From 02d9d82575c8ed89b70de114014193f67e241f87 Mon Sep 17 00:00:00 2001 From: ImBenji Date: Thu, 1 Jan 2026 07:45:17 +0000 Subject: [PATCH] initial --- .gitea/workflows/android-build.yml | 3 + android/app/src/main/AndroidManifest.xml | 1 + ios/Podfile.lock | 20 + lib/main.dart | 10 +- lib/pages/home/page.dart | 674 ++++++++++++------ linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 6 + pubspec.lock | 200 ++++++ pubspec.yaml | 3 + .../flutter/generated_plugin_registrant.cc | 6 + windows/flutter/generated_plugins.cmake | 2 + 12 files changed, 700 insertions(+), 230 deletions(-) diff --git a/.gitea/workflows/android-build.yml b/.gitea/workflows/android-build.yml index 92124df..e96f548 100644 --- a/.gitea/workflows/android-build.yml +++ b/.gitea/workflows/android-build.yml @@ -26,6 +26,9 @@ jobs: distribution: "zulu" java-version: "17" + - name: Install jq + run: apt-get update && apt-get install -y jq + - name: Setup Flutter uses: subosito/flutter-action@v2 with: diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 98c2714..e058d67 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,5 @@ + { "avatar_image": null, "post_image": null, }; - - + + Uint8List? postPreviewImage; + final TextEditingController _displayNameController = TextEditingController(); + final TextEditingController _handleController = TextEditingController(); + final TextEditingController _contentController = TextEditingController(); + + @override + void initState() { + super.initState(); + _loadFormData(); + } + + @override + void dispose() { + _displayNameController.dispose(); + _handleController.dispose(); + _contentController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { @@ -43,252 +66,345 @@ class _HomePageState extends State { double bottomPadding = MediaQuery.of(context).padding.bottom; return Scaffold( - child: Column( - children: [ - - Gap(max(topPadding, 14)), - - AspectRatio( - aspectRatio: 1, - child: OutlinedContainer( - backgroundColor: Colors.black, - child: postPreviewImage == null ? Center( - child: CircularProgressIndicator( - color: Colors.white, - strokeWidth: 3, + child: SingleChildScrollView( + child: Column( + children: [ + + Gap(max(topPadding, 14)), + + AspectRatio( + aspectRatio: 1, + child: OutlinedContainer( + backgroundColor: Colors.black, + child: postPreviewImage == null ? Center( + child: CircularProgressIndicator( + color: Colors.white, + strokeWidth: 3, + ), + ) : Stack( + children: [ + Image.memory( + postPreviewImage!, + fit: BoxFit.cover, + ), + + Align( + alignment: Alignment.bottomRight, + child: IconButton.secondary( + icon: Icon( + Icons.share, + ), + onPressed: () async { + await shareImage(); + } + ) + ).withPadding( + all: 12 + ) + ], ), - ) : Image.memory( - postPreviewImage!, - fit: BoxFit.cover, - ), - ) - ).withPadding( - horizontal: 14 - ), - - Gap(14), - - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Display Name" - ).xSmall.semiBold, - - Gap(6), - - TextField( - placeholder: Text( - "e.g. John Doe" - ), - onChanged: (value) { - setState(() { - formData["display_name"] = value; - }); - onSubmit(); - }, - ), - ], - ), - ), - - Gap(14), - - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Handle" - ).xSmall.semiBold, - - Gap(6), - - TextField( - placeholder: Text( - "e.g. @johndoe" - ), - onChanged: (value) { - setState(() { - formData["handle"] = value; - }); - onSubmit(); - }, - ), - ], - ), - ), - ], - ), - - Gap(10), - - SizedBox( - height: 96, - child: Row( + ) + ).withPadding( + horizontal: 14 + ), + + Gap(14), + + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Row( children: [ Expanded( child: Column( - children: [ - SizedBox( - width: double.infinity, - child: OutlineButton( - child: Text("Select Avatar Image"), - onPressed: () async { - FilePickerResult? result = await FilePicker.platform.pickFiles( - type: FileType.image, - allowMultiple: false, - ); - - if (result != null) { - Uint8List? imageBytes; - - // on web, bytes is availble directly - if (result.files.single.bytes != null) { - imageBytes = result.files.single.bytes!; - } - // on mobile (iOS/Android), need to raed from path - else if (result.files.single.path != null) { - File file = File(result.files.single.path!); - imageBytes = await file.readAsBytes(); - } - - if (imageBytes != null) { - // compression disabled for testing - // Uint8List? compressedBytes = await compressImage(imageBytes, maxWidth: 400); - - if (!mounted) return; - setState(() { - formData["avatar_image"] = imageBytes; - }); - onSubmit(); - } - } - }, - ), + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Display Name" + ).xSmall.semiBold, + + Gap(6), + + TextField( + controller: _displayNameController, + placeholder: Text( + "e.g. John Doe" ), - - Gap(6), - - SizedBox( - width: double.infinity, - child: OutlineButton( - child: Text("Select Post Image"), - onPressed: () async { - FilePickerResult? result = await FilePicker.platform.pickFiles( - type: FileType.image, - allowMultiple: false, - ); - - if (result != null) { - Uint8List? imageBytes; - - // on web, bytes is availble directly - if (result.files.single.bytes != null) { - imageBytes = result.files.single.bytes!; - } - // on mobile (iOS/Android), need to raed from path - else if (result.files.single.path != null) { - File file = File(result.files.single.path!); - imageBytes = await file.readAsBytes(); - } - - if (imageBytes != null) { - if (!mounted) return; - setState(() { - formData["post_image"] = imageBytes; - }); - onSubmit(); - } - } - }, - ), - ), - ] + onChanged: (value) { + setState(() { + formData["display_name"] = value; + }); + _saveFormData(); + onSubmit(); + }, + ), + ], ), ), - - Gap(10), - - AspectRatio( - aspectRatio: 1, - child: ClipRRect( - borderRadius: BorderRadius.circular(1000), - child: formData["avatar_image"] != null ? Image.memory( - formData["avatar_image"], - width: 50, - height: 50, - fit: BoxFit.cover, - ) : OutlinedContainer( - borderRadius: BorderRadius.circular(1000), - child: Center( - child: Text( - formData["display_name"].isNotEmpty ? formData["display_name"][0].toUpperCase() : "P", - ) + + Gap(14), + + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Handle" + ).xSmall.semiBold, + + Gap(6), + + TextField( + controller: _handleController, + placeholder: Text( + "e.g. @johndoe" + ), + onChanged: (value) { + setState(() { + formData["handle"] = value; + }); + _saveFormData(); + onSubmit(); + }, ), - ), - ) + ], + ), ), ], ), - ), + + Gap(10), + + SizedBox( + height: 132, + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: double.infinity, + child: OutlineButton( + child: Text("Select Avatar Image"), + onPressed: () async { + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.image, + allowMultiple: false, + ); + + if (result != null) { + Uint8List? imageBytes; + + // on web, bytes is availble directly + if (result.files.single.bytes != null) { + imageBytes = result.files.single.bytes!; + } + // on mobile (iOS/Android), need to raed from path + else if (result.files.single.path != null) { + File file = File(result.files.single.path!); + imageBytes = await file.readAsBytes(); + } + + if (imageBytes != null) { + // downscale avatar image + Uint8List? resizedBytes = await compressImage(imageBytes, maxWidth: 400); - Gap(10), + if (!mounted) return; + setState(() { + formData["avatar_image"] = resizedBytes ?? imageBytes; + }); + _saveFormData(); + onSubmit(); + } + } + }, + ), + ), + + Gap(8), + - Text( - "Content" - ).xSmall.semiBold, - - Gap(6), - - TextArea( - onChanged: (value) { - setState(() { - formData["content"] = value; - }); - onSubmit(); - }, - ), - - Gap(10), - - Text( - "Timestamp" - ).xSmall.semiBold, - - Gap(6), - - SizedBox( - width: double.infinity, - child: DatePicker( - value: DateTime.now(), - onChanged: (DateTime? date) { + + Divider(), + + Gap(6), + + Text( + "Timestamp" + ).xSmall.semiBold, + + Gap(6), + + SizedBox( + width: double.infinity, + child: DatePicker( + value: formData["timestamp"] > 0 + ? DateTime.fromMillisecondsSinceEpoch(formData["timestamp"]) + : DateTime.now(), + onChanged: (DateTime? date) { + setState(() { + formData["timestamp"] = date!.millisecondsSinceEpoch; + }); + _saveFormData(); + onSubmit(); + } + ) + ).withPadding( + right: 10 + ), + ] + ), + ), + + // Gap(10), + + VerticalDivider().withPadding( + top: 54 + ), + + Gap(10), + + AspectRatio( + aspectRatio: 1, + child: ClipRRect( + borderRadius: BorderRadius.circular(1000), + child: formData["avatar_image"] != null ? Image.memory( + formData["avatar_image"], + width: 50, + height: 50, + fit: BoxFit.cover, + ) : OutlinedContainer( + borderRadius: BorderRadius.circular(1000), + child: Center( + child: Text( + formData["display_name"].isNotEmpty ? formData["display_name"][0].toUpperCase() : "P", + ) + ), + ), + ) + ), + ], + ), + ), + + Gap(10), + + Text( + "Content" + ).xSmall.semiBold, + + Gap(6), + + TextArea( + controller: _contentController, + onChanged: (value) { setState(() { - formData["timestamp"] = date!.millisecondsSinceEpoch; + formData["content"] = value; }); + _saveFormData(); onSubmit(); - } - ) - ), + }, + ), + + Gap(10), - ], - ).withPadding( - horizontal: 14 - ) + Divider(), - ], + Gap(10), + + if (formData["post_image"] != null)...[ + OutlinedContainer( + child: formData["post_image"] != null ? Image.memory( + formData["post_image"], + width: double.infinity, + // height: 200, + fit: BoxFit.cover, + ) : Center( + child: Text( + "No Post Image Selected", + ).small.semiBold, + ), + ), + + Gap(10), + ], + + Row( + children: [ + Expanded( + child: SizedBox( + width: double.infinity, + child: OutlineButton( + child: formData["post_image"] == null ? Text("Select Post Image") : Text("Change Post Image"), + onPressed: () async { + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.image, + allowMultiple: false, + ); + + if (result != null) { + Uint8List? imageBytes; + + // on web, bytes is availble directly + if (result.files.single.bytes != null) { + imageBytes = result.files.single.bytes!; + } + // on mobile (iOS/Android), need to raed from path + else if (result.files.single.path != null) { + File file = File(result.files.single.path!); + imageBytes = await file.readAsBytes(); + } + + if (imageBytes != null) { + if (!mounted) return; + setState(() { + formData["post_image"] = imageBytes; + }); + _saveFormData(); + onSubmit(); + } + } + }, + ), + ), + ), + + if (formData["post_image"] != null)...[ + Gap(10), + + IconButton.destructive( + icon: Icon( + Icons.delete, + ), + onPressed: () { + if (!mounted) return; + setState(() { + formData["post_image"] = null; + }); + _saveFormData(); + onSubmit(); + }, + ) + ] + ], + ), + + Gap(bottomPadding) + + ], + ).withPadding( + horizontal: 14 + ) + + ], + ), ), ); } - // compress and resize image to reduce payload size + // resize image to reduce payload size without comression Future compressImage(Uint8List bytes, {int maxWidth = 800, int quality = 85}) async { try { img.Image? image = img.decodeImage(bytes); @@ -299,10 +415,10 @@ class _HomePageState extends State { image = img.copyResize(image, width: maxWidth); } - // encode as JPEG with compression - return Uint8List.fromList(img.encodeJpg(image, quality: quality)); + // encode as PNG (lossles, no compression) + return Uint8List.fromList(img.encodePng(image)); } catch (e) { - print("Error compresing image: $e"); + print("Error resizng image: $e"); return null; } } @@ -345,4 +461,104 @@ class _HomePageState extends State { }); } + + Future shareImage() async { + if (postPreviewImage == null) { + print("No image to share"); + return; + } + + try { + // get temporary directry + final tempDir = await getTemporaryDirectory(); + + // create a unique filename with timestmp + final fileName = "quote_${DateTime.now().millisecondsSinceEpoch}.png"; + final filePath = path.join(tempDir.path, fileName); + + // write the image bytes to a temporry file + final file = File(filePath); + await file.writeAsBytes(postPreviewImage!); + + + // Share the file using the systm share dialog + final result = await Share.shareXFiles( + [XFile(filePath)], + text: "Check out this quote!", + ); + + // optinal: log share result + if (result.status == ShareResultStatus.success) { + print("Share succesful"); + } + + } catch (e) { + print("Error sharin image: $e"); + } + } + + // load form data from shared preferences + Future _loadFormData() async { + try { + final prefs = await SharedPreferences.getInstance(); + + setState(() { + // load text fields + formData["display_name"] = prefs.getString("display_name") ?? ""; + formData["handle"] = prefs.getString("handle") ?? ""; + formData["content"] = prefs.getString("content") ?? ""; + formData["timestamp"] = prefs.getInt("timestamp") ?? 0; + + // load images from base64 + String? avatarBase64 = prefs.getString("avatar_image"); + if (avatarBase64 != null && avatarBase64.isNotEmpty) { + formData["avatar_image"] = base64Decode(avatarBase64); + } + + String? postBase64 = prefs.getString("post_image"); + if (postBase64 != null && postBase64.isNotEmpty) { + formData["post_image"] = base64Decode(postBase64); + } + + // update controllers + _displayNameController.text = formData["display_name"]; + _handleController.text = formData["handle"]; + _contentController.text = formData["content"]; + }); + + // regenerate preview if we have data + if (formData["display_name"].isNotEmpty || formData["content"].isNotEmpty) { + onSubmit(); + } + } catch (e) { + print("Error loading form data: $e"); + } + } + + // save form data to shared preferences + Future _saveFormData() async { + try { + final prefs = await SharedPreferences.getInstance(); + + // save text felds + await prefs.setString("display_name", formData["display_name"]); + await prefs.setString("handle", formData["handle"]); + await prefs.setString("content", formData["content"]); + await prefs.setInt("timestamp", formData["timestamp"]); + + // save images as base64 + if (formData["avatar_image"] != null) { + String avatarBase64 = base64Encode(formData["avatar_image"]); + await prefs.setString("avatar_image", avatarBase64); + } + + if (formData["post_image"] != null) { + String postBase64 = base64Encode(formData["post_image"]); + await prefs.setString("post_image", postBase64); + } + + } catch (e) { + print("Error savin form data: $e"); + } + } } \ No newline at end of file diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d..f6f23bf 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87..f16b4c3 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 774a6b8..f12d843 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,7 +6,13 @@ import FlutterMacOS import Foundation import file_picker +import path_provider_foundation +import share_plus +import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 7a62c3c..628936c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -137,6 +137,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" file_picker: dependency: "direct main" description: @@ -145,6 +153,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.3.7" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -296,6 +312,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" path: dependency: transitive description: @@ -304,6 +328,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e + url: "https://pub.dev" + source: hosted + version: "2.2.22" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4" + url: "https://pub.dev" + source: hosted + version: "2.5.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" petitparser: dependency: transitive description: @@ -320,6 +392,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.4" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -360,6 +440,78 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.47" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da + url: "https://pub.dev" + source: hosted + version: "10.1.4" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b + url: "https://pub.dev" + source: hosted + version: "5.0.2" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "83af5c682796c0f7719c2bbf74792d113e40ae97981b8f266fa84574573556bc" + url: "https://pub.dev" + source: hosted + version: "2.4.18" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" skeletonizer: dependency: transitive description: @@ -429,6 +581,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + uuid: + dependency: transitive + description: + name: uuid + sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8 + url: "https://pub.dev" + source: hosted + version: "4.5.2" vector_math: dependency: transitive description: @@ -461,6 +653,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.15.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f5e18be..98b3252 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,9 @@ dependencies: http: ^1.2.2 file_picker: ^8.1.6 image: ^4.3.0 + share_plus: ^10.1.4 + path_provider: ^2.1.5 + shared_preferences: ^2.3.4 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d468..c3384ec 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,12 @@ #include "generated_plugin_registrant.h" +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + SharePlusWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b93c4c3..01d3836 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,8 @@ # list(APPEND FLUTTER_PLUGIN_LIST + share_plus + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST