This commit is contained in:
@@ -26,6 +26,9 @@ jobs:
|
|||||||
distribution: "zulu"
|
distribution: "zulu"
|
||||||
java-version: "17"
|
java-version: "17"
|
||||||
|
|
||||||
|
- name: Install jq
|
||||||
|
run: apt-get update && apt-get install -y jq
|
||||||
|
|
||||||
- name: Setup Flutter
|
- name: Setup Flutter
|
||||||
uses: subosito/flutter-action@v2
|
uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<application
|
<application
|
||||||
android:label="quotegen_client"
|
android:label="quotegen_client"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
|
|||||||
@@ -34,14 +34,25 @@ PODS:
|
|||||||
- DKImagePickerController/PhotoGallery
|
- DKImagePickerController/PhotoGallery
|
||||||
- Flutter
|
- Flutter
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
|
- path_provider_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- SDWebImage (5.21.1):
|
- SDWebImage (5.21.1):
|
||||||
- SDWebImage/Core (= 5.21.1)
|
- SDWebImage/Core (= 5.21.1)
|
||||||
- SDWebImage/Core (5.21.1)
|
- SDWebImage/Core (5.21.1)
|
||||||
|
- share_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- shared_preferences_foundation (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- SwiftyGif (5.4.5)
|
- SwiftyGif (5.4.5)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
|
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||||
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
@@ -55,13 +66,22 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/file_picker/ios"
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
|
path_provider_foundation:
|
||||||
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
|
share_plus:
|
||||||
|
:path: ".symlinks/plugins/share_plus/ios"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
|
file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
|
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
|
||||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||||
|
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
|
||||||
|
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
||||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
|
|
||||||
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:quotegen_client/pages/home/page.dart';
|
import 'package:quotegen_client/pages/home/page.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
@@ -16,6 +16,14 @@ class MyApp extends StatelessWidget {
|
|||||||
return ShadcnApp.router(
|
return ShadcnApp.router(
|
||||||
title: 'Flutter Demo',
|
title: 'Flutter Demo',
|
||||||
routerConfig: _router,
|
routerConfig: _router,
|
||||||
|
scaling: defaultTargetPlatform == TargetPlatform.android ? AdaptiveScaling.only(
|
||||||
|
sizeScaling: 1,
|
||||||
|
textScaling: 1.1,
|
||||||
|
radiusScaling: 1.1
|
||||||
|
) : null,
|
||||||
|
theme: ThemeData(
|
||||||
|
colorScheme: ColorSchemes.darkBlue,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
@@ -9,6 +10,10 @@ import 'package:go_router/go_router.dart';
|
|||||||
import 'package:image/image.dart' as img;
|
import 'package:image/image.dart' as img;
|
||||||
import 'package:quotegen_client/services/quote_api.dart';
|
import 'package:quotegen_client/services/quote_api.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class HomePage extends StatefulWidget {
|
class HomePage extends StatefulWidget {
|
||||||
|
|
||||||
@@ -31,11 +36,29 @@ class _HomePageState extends State<HomePage> {
|
|||||||
"avatar_image": null,
|
"avatar_image": null,
|
||||||
"post_image": null,
|
"post_image": null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Uint8List? postPreviewImage;
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
@@ -43,252 +66,345 @@ class _HomePageState extends State<HomePage> {
|
|||||||
double bottomPadding = MediaQuery.of(context).padding.bottom;
|
double bottomPadding = MediaQuery.of(context).padding.bottom;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
child: Column(
|
child: SingleChildScrollView(
|
||||||
children: [
|
child: Column(
|
||||||
|
children: [
|
||||||
Gap(max(topPadding, 14)),
|
|
||||||
|
Gap(max(topPadding, 14)),
|
||||||
AspectRatio(
|
|
||||||
aspectRatio: 1,
|
AspectRatio(
|
||||||
child: OutlinedContainer(
|
aspectRatio: 1,
|
||||||
backgroundColor: Colors.black,
|
child: OutlinedContainer(
|
||||||
child: postPreviewImage == null ? Center(
|
backgroundColor: Colors.black,
|
||||||
child: CircularProgressIndicator(
|
child: postPreviewImage == null ? Center(
|
||||||
color: Colors.white,
|
child: CircularProgressIndicator(
|
||||||
strokeWidth: 3,
|
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!,
|
).withPadding(
|
||||||
fit: BoxFit.cover,
|
horizontal: 14
|
||||||
),
|
),
|
||||||
)
|
|
||||||
).withPadding(
|
Gap(14),
|
||||||
horizontal: 14
|
|
||||||
),
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Gap(14),
|
children: [
|
||||||
|
|
||||||
Column(
|
Row(
|
||||||
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(
|
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
SizedBox(
|
children: [
|
||||||
width: double.infinity,
|
Text(
|
||||||
child: OutlineButton(
|
"Display Name"
|
||||||
child: Text("Select Avatar Image"),
|
).xSmall.semiBold,
|
||||||
onPressed: () async {
|
|
||||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
Gap(6),
|
||||||
type: FileType.image,
|
|
||||||
allowMultiple: false,
|
TextField(
|
||||||
);
|
controller: _displayNameController,
|
||||||
|
placeholder: Text(
|
||||||
if (result != null) {
|
"e.g. John Doe"
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
onChanged: (value) {
|
||||||
Gap(6),
|
setState(() {
|
||||||
|
formData["display_name"] = value;
|
||||||
SizedBox(
|
});
|
||||||
width: double.infinity,
|
_saveFormData();
|
||||||
child: OutlineButton(
|
onSubmit();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
Gap(10),
|
Gap(14),
|
||||||
|
|
||||||
AspectRatio(
|
Expanded(
|
||||||
aspectRatio: 1,
|
child: Column(
|
||||||
child: ClipRRect(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
borderRadius: BorderRadius.circular(1000),
|
children: [
|
||||||
child: formData["avatar_image"] != null ? Image.memory(
|
Text(
|
||||||
formData["avatar_image"],
|
"Handle"
|
||||||
width: 50,
|
).xSmall.semiBold,
|
||||||
height: 50,
|
|
||||||
fit: BoxFit.cover,
|
Gap(6),
|
||||||
) : OutlinedContainer(
|
|
||||||
borderRadius: BorderRadius.circular(1000),
|
TextField(
|
||||||
child: Center(
|
controller: _handleController,
|
||||||
child: Text(
|
placeholder: Text(
|
||||||
formData["display_name"].isNotEmpty ? formData["display_name"][0].toUpperCase() : "P",
|
"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"
|
Divider(),
|
||||||
).xSmall.semiBold,
|
|
||||||
|
Gap(6),
|
||||||
Gap(6),
|
|
||||||
|
Text(
|
||||||
TextArea(
|
"Timestamp"
|
||||||
onChanged: (value) {
|
).xSmall.semiBold,
|
||||||
setState(() {
|
|
||||||
formData["content"] = value;
|
Gap(6),
|
||||||
});
|
|
||||||
onSubmit();
|
SizedBox(
|
||||||
},
|
width: double.infinity,
|
||||||
),
|
child: DatePicker(
|
||||||
|
value: formData["timestamp"] > 0
|
||||||
Gap(10),
|
? DateTime.fromMillisecondsSinceEpoch(formData["timestamp"])
|
||||||
|
: DateTime.now(),
|
||||||
Text(
|
onChanged: (DateTime? date) {
|
||||||
"Timestamp"
|
setState(() {
|
||||||
).xSmall.semiBold,
|
formData["timestamp"] = date!.millisecondsSinceEpoch;
|
||||||
|
});
|
||||||
Gap(6),
|
_saveFormData();
|
||||||
|
onSubmit();
|
||||||
SizedBox(
|
}
|
||||||
width: double.infinity,
|
)
|
||||||
child: DatePicker(
|
).withPadding(
|
||||||
value: DateTime.now(),
|
right: 10
|
||||||
onChanged: (DateTime? date) {
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 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(() {
|
setState(() {
|
||||||
formData["timestamp"] = date!.millisecondsSinceEpoch;
|
formData["content"] = value;
|
||||||
});
|
});
|
||||||
|
_saveFormData();
|
||||||
onSubmit();
|
onSubmit();
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
),
|
|
||||||
|
Gap(10),
|
||||||
|
|
||||||
],
|
Divider(),
|
||||||
).withPadding(
|
|
||||||
horizontal: 14
|
|
||||||
)
|
|
||||||
|
|
||||||
],
|
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<Uint8List?> compressImage(Uint8List bytes, {int maxWidth = 800, int quality = 85}) async {
|
Future<Uint8List?> compressImage(Uint8List bytes, {int maxWidth = 800, int quality = 85}) async {
|
||||||
try {
|
try {
|
||||||
img.Image? image = img.decodeImage(bytes);
|
img.Image? image = img.decodeImage(bytes);
|
||||||
@@ -299,10 +415,10 @@ class _HomePageState extends State<HomePage> {
|
|||||||
image = img.copyResize(image, width: maxWidth);
|
image = img.copyResize(image, width: maxWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode as JPEG with compression
|
// encode as PNG (lossles, no compression)
|
||||||
return Uint8List.fromList(img.encodeJpg(image, quality: quality));
|
return Uint8List.fromList(img.encodePng(image));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Error compresing image: $e");
|
print("Error resizng image: $e");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,4 +461,104 @@ class _HomePageState extends State<HomePage> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> 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<void> _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<void> _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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
@@ -6,7 +6,13 @@ import FlutterMacOS
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import file_picker
|
import file_picker
|
||||||
|
import path_provider_foundation
|
||||||
|
import share_plus
|
||||||
|
import shared_preferences_foundation
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
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"))
|
||||||
}
|
}
|
||||||
|
|||||||
200
pubspec.lock
200
pubspec.lock
@@ -137,6 +137,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.1"
|
||||||
file_picker:
|
file_picker:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -145,6 +153,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.3.7"
|
version: "8.3.7"
|
||||||
|
fixnum:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fixnum
|
||||||
|
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.1"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -296,6 +312,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.0"
|
version: "1.17.0"
|
||||||
|
mime:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mime
|
||||||
|
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -304,6 +328,54 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.1"
|
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:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -320,6 +392,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.4"
|
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:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -360,6 +440,78 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.47"
|
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:
|
skeletonizer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -429,6 +581,46 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
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:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -461,6 +653,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.15.0"
|
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:
|
xml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ dependencies:
|
|||||||
http: ^1.2.2
|
http: ^1.2.2
|
||||||
file_picker: ^8.1.6
|
file_picker: ^8.1.6
|
||||||
image: ^4.3.0
|
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.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
|||||||
@@ -6,6 +6,12 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
||||||
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
|
SharePlusWindowsPluginCApiRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
|
||||||
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
share_plus
|
||||||
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
Reference in New Issue
Block a user