Share post as image on web

This commit is contained in:
LittleSheep 2024-10-14 20:51:56 +08:00
parent a6b17f2c05
commit 1abc65f8fa
8 changed files with 76 additions and 62 deletions

View File

@ -484,5 +484,6 @@
"authMaximumAuthStepsDesc": "The maximum number of authentication steps when logging in, higher value is more secure, lower value is more convenient; default is 2", "authMaximumAuthStepsDesc": "The maximum number of authentication steps when logging in, higher value is more secure, lower value is more convenient; default is 2",
"auditLog": "Audit log", "auditLog": "Audit log",
"shareImage": "Share as image", "shareImage": "Share as image",
"shareImageFooter": "Only on the Solar Network" "shareImageFooter": "Only on the Solar Network",
"fileSavedAt": "File saved at @path"
} }

View File

@ -480,5 +480,6 @@
"authMaximumAuthStepsDesc": "登陆时最多的验证步数,值越高则越安全,反之则会相对方便;默认设置为 2", "authMaximumAuthStepsDesc": "登陆时最多的验证步数,值越高则越安全,反之则会相对方便;默认设置为 2",
"auditLog": "活动日志", "auditLog": "活动日志",
"shareImage": "分享图片", "shareImage": "分享图片",
"shareImageFooter": "上 Solar Network 看更多有趣帖子" "shareImageFooter": "上 Solar Network 看更多有趣帖子",
"fileSavedAt": "文件保存于 @path"
} }

View File

@ -49,6 +49,7 @@ class _AttachmentListState extends State<AttachmentList> {
bool _isLoading = true; bool _isLoading = true;
bool _showMature = false; bool _showMature = false;
// ignore: unused_field
double _aspectRatio = 1; double _aspectRatio = 1;
List<Attachment?> _attachments = List.empty(); List<Attachment?> _attachments = List.empty();

View File

@ -1,4 +1,3 @@
import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:file_saver/file_saver.dart'; import 'package:file_saver/file_saver.dart';
@ -7,9 +6,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_animate/flutter_animate.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:screenshot/screenshot.dart'; import 'package:screenshot/screenshot.dart';
import 'package:share_plus/share_plus.dart'; import 'package:share_plus/share_plus.dart';
import 'package:solian/exts.dart'; import 'package:solian/exts.dart';
@ -113,16 +109,17 @@ class _PostActionState extends State<PostAction> {
maxHeight: double.infinity, maxHeight: double.infinity,
), ),
); );
final directory = await getApplicationDocumentsDirectory();
final imageFile = await File( final filename = 'share_post#${widget.item.id}';
'${directory.path}/share_image_${DateFormat('yyyy-MM-dd-HH-mm-ss').format(DateTime.now())}.png',
).create();
await imageFile.writeAsBytes(image);
if (PlatformInfo.isAndroid || PlatformInfo.isIOS) { if (PlatformInfo.isAndroid || PlatformInfo.isIOS) {
final box = context.findRenderObject() as RenderBox?; final box = context.findRenderObject() as RenderBox?;
final file = XFile(imageFile.path); final file = XFile.fromData(
image,
mimeType: 'image/png',
name: filename,
);
await Share.shareXFiles( await Share.shareXFiles(
[file], [file],
subject: 'postShareSubject'.trParams({ subject: 'postShareSubject'.trParams({
@ -132,15 +129,14 @@ class _PostActionState extends State<PostAction> {
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
); );
} else { } else {
await FileSaver.instance.saveAs( final filepath = await FileSaver.instance.saveFile(
name: path.basename(imageFile.path), name: filename,
ext: path.extension(imageFile.path), ext: 'png',
mimeType: MimeType.png, mimeType: MimeType.png,
file: imageFile, bytes: image,
); );
context.showSnackbar('fileSavedAt'.trParams({'path': filepath}));
} }
await imageFile.delete();
} }
@override @override

View File

@ -1,3 +1,4 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
@ -73,9 +74,30 @@ class PostListEntryWidget extends StatelessWidget {
required this.onUpdate, required this.onUpdate,
}); });
void _openActions(BuildContext context) {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) return;
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) => PostAction(item: item),
).then((value) {
if (value is Future) {
value.then((_) {
onUpdate();
});
} else if (value != null) {
onUpdate();
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return TapRegion(
child: GestureDetector(
onLongPress: () => _openActions(context),
child: PostItem( child: PostItem(
key: Key('p${item.id}'), key: Key('p${item.id}'),
item: item, item: item,
@ -100,23 +122,11 @@ class PostListEntryWidget extends StatelessWidget {
}); });
}, },
).paddingSymmetric(vertical: 8), ).paddingSymmetric(vertical: 8),
onLongPress: () { ),
final AuthProvider auth = Get.find(); onTapInside: (event) {
if (auth.isAuthorized.isFalse) return; if (event.buttons == kSecondaryMouseButton) {
_openActions(context);
showModalBottomSheet(
useRootNavigator: true,
context: context,
builder: (context) => PostAction(item: item),
).then((value) {
if (value is Future) {
value.then((_) {
onUpdate();
});
} else if (value != null) {
onUpdate();
} }
});
}, },
); );
} }

View File

@ -6,6 +6,8 @@ PODS:
- FlutterMacOS - FlutterMacOS
- device_info_plus (0.0.1): - device_info_plus (0.0.1):
- FlutterMacOS - FlutterMacOS
- file_saver (0.0.1):
- FlutterMacOS
- file_selector_macos (0.0.1): - file_selector_macos (0.0.1):
- FlutterMacOS - FlutterMacOS
- Firebase/Analytics (11.2.0): - Firebase/Analytics (11.2.0):
@ -230,6 +232,7 @@ DEPENDENCIES:
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/darwin`) - connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/darwin`)
- desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`) - desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- file_saver (from `Flutter/ephemeral/.symlinks/plugins/file_saver/macos`)
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`) - file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
- firebase_analytics (from `Flutter/ephemeral/.symlinks/plugins/firebase_analytics/macos`) - firebase_analytics (from `Flutter/ephemeral/.symlinks/plugins/firebase_analytics/macos`)
- firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`) - firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`)
@ -288,6 +291,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos :path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos
device_info_plus: device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos :path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
file_saver:
:path: Flutter/ephemeral/.symlinks/plugins/file_saver/macos
file_selector_macos: file_selector_macos:
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos :path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
firebase_analytics: firebase_analytics:
@ -349,6 +354,7 @@ SPEC CHECKSUMS:
connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db
desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898 desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898
device_info_plus: f1aae8670672f75c4c8850ecbe0b2ddef62b0a22 device_info_plus: f1aae8670672f75c4c8850ecbe0b2ddef62b0a22
file_saver: 44e6fbf666677faf097302460e214e977fdd977b
file_selector_macos: cc3858c981fe6889f364731200d6232dac1d812d file_selector_macos: cc3858c981fe6889f364731200d6232dac1d812d
Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c
firebase_analytics: 30ff72f6d4847ff0b479d8edd92fc8582e719072 firebase_analytics: 30ff72f6d4847ff0b479d8edd92fc8582e719072

View File

@ -2,7 +2,7 @@ name: solian
description: "The Solar Network App" description: "The Solar Network App"
publish_to: "none" publish_to: "none"
version: 1.3.7+12 version: 1.3.8+12
environment: environment:
sdk: ">=3.3.4 <4.0.0" sdk: ">=3.3.4 <4.0.0"

View File

@ -111,14 +111,13 @@
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
</head> </head>
<body> <body oncontextmenu="return false;">
<picture id="splash"> <picture id="splash">
<source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x" media="(prefers-color-scheme: light)"> <source srcset="splash/img/light-1x.png 1x, splash/img/light-2x.png 2x, splash/img/light-3x.png 3x, splash/img/light-4x.png 4x" media="(prefers-color-scheme: light)">
<source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x" media="(prefers-color-scheme: dark)"> <source srcset="splash/img/dark-1x.png 1x, splash/img/dark-2x.png 2x, splash/img/dark-3x.png 3x, splash/img/dark-4x.png 4x" media="(prefers-color-scheme: dark)">
<img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt=""> <img class="center" aria-hidden="true" src="splash/img/light-1x.png" alt="">
</picture> </picture>
<script src="flutter_bootstrap.js" async=""></script> <script src="flutter_bootstrap.js" async=""></script>