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/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/check_input_container.dart';
import 'package:manager_app/Components/confirmation_dialog.dart'; import 'package:manager_app/Components/confirmation_dialog.dart';
import 'package:manager_app/Components/fetch_section_icon.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/Quizz/quizz_config.dart';
import 'SubSection/Slider/slider_config.dart'; import 'SubSection/Slider/slider_config.dart';
import 'package:qr_flutter/qr_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart';
import 'package:pasteboard/pasteboard.dart';
import 'dart:html' as html;
class SectionDetailScreen extends StatefulWidget { class SectionDetailScreen extends StatefulWidget {
final String id; final String id;
@ -41,13 +51,15 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
final appContext = Provider.of<AppContext>(context); final appContext = Provider.of<AppContext>(context);
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
GlobalKey globalKey = new GlobalKey();
return FutureBuilder( return FutureBuilder(
future: getSection(widget.id, (appContext.getContext() as ManagerAppContext).clientAPI!), future: getSection(widget.id, (appContext.getContext() as ManagerAppContext).clientAPI!),
builder: (context, AsyncSnapshot<dynamic> snapshot) { builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) { if (snapshot.connectionState == ConnectionState.done) {
return Stack( return Stack(
children: [ children: [
bodySection(snapshot.data, size, appContext, context), bodySection(snapshot.data, size, appContext, context, globalKey),
Align( Align(
alignment: AlignmentDirectional.bottomCenter, alignment: AlignmentDirectional.bottomCenter,
child: Container( 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( return SingleChildScrollView(
child: Column( child: Column(
//mainAxisAlignment: MainAxisAlignment.spaceAround, //mainAxisAlignment: MainAxisAlignment.spaceAround,
@ -157,14 +169,24 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Container( InkWell(
width: size.width *0.1, onTap: () async {
height: 125, var image = await _captureAndSharePng(globalKey, sectionDTO!.id!);
child: QrImage( await readAndWriteFiles(image);
padding: EdgeInsets.only(left: 0.0, top: 5.0, bottom: 5.0), showNotification(kSuccess, kWhite, 'Ce QR code a été copié dans le presse papier', context, null);
data: sectionDTO!.id!, },
version: QrVersions.auto, child: Container(
size: 50.0, width: size.width *0.1,
height: 125,
child: RepaintBoundary(
key: globalKey,
child: QrImage(
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)) SelectableText(sectionDTO.id!, style: new TextStyle(fontSize: 15))
@ -435,3 +457,29 @@ Future<SectionDTO?> getSection(String sectionId, Client client) async {
//print(section); //print(section);
return 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 "generated_plugin_registrant.h"
#include <pasteboard/pasteboard_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { 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 list(APPEND FLUTTER_PLUGIN_LIST
pasteboard
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

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

View File

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

View File

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

View File

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

View File

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