Copy QrCode as image + download

This commit is contained in:
Fransolet Thomas 2023-04-26 15:42:42 +02:00
parent 9de38c2cfc
commit 3585a67ee2
8 changed files with 78 additions and 10 deletions

View File

@ -1,4 +1,11 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:manager_app/Components/check_input_container.dart';
import 'package:manager_app/Components/confirmation_dialog.dart';
import 'package:manager_app/Components/fetch_section_icon.dart';
@ -25,6 +32,9 @@ import 'SubSection/Menu/menu_config.dart';
import 'SubSection/Quizz/quizz_config.dart';
import 'SubSection/Slider/slider_config.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:pasteboard/pasteboard.dart';
import 'dart:html' as html;
class SectionDetailScreen extends StatefulWidget {
final String id;
@ -41,13 +51,15 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
final appContext = Provider.of<AppContext>(context);
Size size = MediaQuery.of(context).size;
GlobalKey globalKey = new GlobalKey();
return FutureBuilder(
future: getSection(widget.id, (appContext.getContext() as ManagerAppContext).clientAPI!),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Stack(
children: [
bodySection(snapshot.data, size, appContext, context),
bodySection(snapshot.data, size, appContext, context, globalKey),
Align(
alignment: AlignmentDirectional.bottomCenter,
child: Container(
@ -71,7 +83,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
);
}
Widget bodySection(SectionDTO? sectionDTO, Size size, AppContext appContext, BuildContext context) {
Widget bodySection(SectionDTO? sectionDTO, Size size, AppContext appContext, BuildContext context, GlobalKey globalKey) {
return SingleChildScrollView(
child: Column(
//mainAxisAlignment: MainAxisAlignment.spaceAround,
@ -157,16 +169,26 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
InkWell(
onTap: () async {
var image = await _captureAndSharePng(globalKey, sectionDTO!.id!);
await readAndWriteFiles(image);
showNotification(kSuccess, kWhite, 'Ce QR code a été copié dans le presse papier', context, null);
},
child: Container(
width: size.width *0.1,
height: 125,
child: RepaintBoundary(
key: globalKey,
child: QrImage(
padding: EdgeInsets.only(left: 0.0, top: 5.0, bottom: 5.0),
padding: EdgeInsets.only(left: 5.0, top: 5.0, bottom: 5.0, right: 5.0),
data: sectionDTO!.id!,
version: QrVersions.auto,
size: 50.0,
),
),
),
),
SelectableText(sectionDTO.id!, style: new TextStyle(fontSize: 15))
],
),
@ -435,3 +457,29 @@ Future<SectionDTO?> getSection(String sectionId, Client client) async {
//print(section);
return section;
}
Future<Uint8List?> _captureAndSharePng(GlobalKey globalKey, String sectionId) async {
try {
RenderRepaintBoundary ? boundary = globalKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
var image = await boundary.toImage();
ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
final base64data = base64.encode(pngBytes);
final a = html.AnchorElement(href: 'data:image/jpeg;base64,$base64data');
a.download = '$sectionId.jpg';
a.click();
return pngBytes;
} catch(e) {
print(e.toString());
return null;
}
}
Future<void> readAndWriteFiles(Uint8List? image) async {
await Pasteboard.writeImage(image);
final files = await Pasteboard.files();
print(files);
}

View File

@ -6,6 +6,10 @@
#include "generated_plugin_registrant.h"
#include <pasteboard/pasteboard_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) pasteboard_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "PasteboardPlugin");
pasteboard_plugin_register_with_registrar(pasteboard_registrar);
}

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
pasteboard
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@ -7,10 +7,12 @@ import Foundation
import audio_session
import just_audio
import pasteboard
import path_provider_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
}

View File

@ -551,6 +551,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.2"
pasteboard:
dependency: "direct main"
description:
name: pasteboard
sha256: "1c8b6a8b3f1d12e55d4e9404433cda1b4abe66db6b17bc2d2fb5965772c04674"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
path:
dependency: transitive
description:

View File

@ -52,6 +52,7 @@ dependencies:
# ref: 927f8cbc09b35d85245c095f2db8df9b186f6618
password_credential: ^0.3.1
diacritic: ^0.1.3
pasteboard: ^0.2.0
manager_api_new:
path: manager_api_new

View File

@ -6,6 +6,9 @@
#include "generated_plugin_registrant.h"
#include <pasteboard/pasteboard_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
PasteboardPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PasteboardPlugin"));
}

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
pasteboard
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST