Compare commits

...

3 Commits

Author SHA1 Message Date
6e442c144e Chat shell resizable 2024-10-14 00:13:01 +08:00
8bbd964026 🐛 Fix share as image on iPad 2024-10-14 00:10:13 +08:00
0b8a5a3303 💄 Optimize share as image 2024-10-14 00:03:45 +08:00
7 changed files with 82 additions and 24 deletions

View File

@ -484,5 +484,5 @@
"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",
"shareImage": "Share as image",
"shareImageFooter": "See more interesting posts on Solar Network"
"shareImageFooter": "Only on the Solar Network"
}

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_resizable_container/flutter_resizable_container.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:gap/gap.dart';
import 'package:get/get.dart';
@ -42,14 +43,20 @@ class ChatListShell extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RootContainer(
child: Row(
child: ResizableContainer(
direction: Axis.horizontal,
divider: ResizableDivider(
thickness: 0.3,
color: Theme.of(context).dividerColor,
),
children: [
const SizedBox(
width: 360,
const ResizableChild(
minSize: 280,
maxSize: 520,
size: ResizableSize.pixels(320),
child: ChatList(),
),
const VerticalDivider(thickness: 0.3, width: 0.3),
Expanded(child: child ?? const EmptyPagePlaceholder()),
ResizableChild(child: child ?? const EmptyPagePlaceholder()),
],
),
);

View File

@ -89,10 +89,25 @@ class _PostActionState extends State<PostAction> {
}
Future<void> _shareImage() async {
final List<String> attachments = widget.item.body['attachments'] is List
? List.from(widget.item.body['attachments']?.whereType<String>())
: List.empty();
final hasAttachment = attachments.isNotEmpty;
final screenshot = ScreenshotController();
final image = await screenshot.captureFromWidget(
PostShareImage(item: widget.item),
final image = await screenshot.captureFromLongWidget(
MediaQuery(
data: MediaQuery.of(context),
child: PostShareImage(item: widget.item),
),
context: context,
pixelRatio: 2,
constraints: BoxConstraints(
minWidth: 480,
maxWidth: hasAttachment ? 480 : 640,
minHeight: 640,
maxHeight: double.infinity,
),
);
final directory = await getApplicationDocumentsDirectory();
final imageFile = await File(
@ -100,8 +115,16 @@ class _PostActionState extends State<PostAction> {
).create();
await imageFile.writeAsBytes(image);
final box = context.findRenderObject() as RenderBox?;
final file = XFile(imageFile.path);
await Share.shareXFiles([file]);
await Share.shareXFiles(
[file],
subject: 'postShareSubject'.trParams({
'username': widget.item.author.nick,
}),
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
);
await imageFile.delete();
}

View File

@ -31,6 +31,7 @@ class PostItem extends StatefulWidget {
final bool isOverrideEmbedClickable;
final bool isFullDate;
final bool isContentSelectable;
final bool isNonScrollAttachment;
final bool showFeaturedReply;
final String? attachmentParent;
@ -49,6 +50,7 @@ class PostItem extends StatefulWidget {
this.isOverrideEmbedClickable = false,
this.isFullDate = false,
this.isContentSelectable = false,
this.isNonScrollAttachment = false,
this.showFeaturedReply = false,
this.attachmentParent,
this.padding,
@ -214,6 +216,7 @@ class _PostItemState extends State<PostItem> {
_PostAttachmentWidget(
item: item,
padding: widget.padding,
isNonScrollAttachment: widget.isNonScrollAttachment,
),
if (widget.showFeaturedReply)
_PostFeaturedReplyWidget(item: item).paddingSymmetric(
@ -380,8 +383,13 @@ class _PostFeaturedReplyWidget extends StatelessWidget {
class _PostAttachmentWidget extends StatelessWidget {
final Post item;
final EdgeInsets? padding;
final bool isNonScrollAttachment;
const _PostAttachmentWidget({required this.item, required this.padding});
const _PostAttachmentWidget({
required this.item,
required this.padding,
required this.isNonScrollAttachment,
});
@override
Widget build(BuildContext context) {
@ -401,14 +409,6 @@ class _PostAttachmentWidget extends StatelessWidget {
autoload: false,
isFullWidth: true,
);
} else if (attachments.length == 1) {
return AttachmentList(
parentId: item.id.toString(),
attachmentIds: item.preload == null ? attachments : null,
attachments: item.preload?.attachments,
autoload: false,
isColumn: true,
).paddingSymmetric(horizontal: (padding?.horizontal ?? 0) + 14);
} else if (attachments.length > 1 &&
attachments.length % 3 == 0 &&
!isLargeScreen) {
@ -419,6 +419,14 @@ class _PostAttachmentWidget extends StatelessWidget {
autoload: false,
isGrid: true,
).paddingSymmetric(horizontal: (padding?.horizontal ?? 0) + 14);
} else if (attachments.length == 1 || isNonScrollAttachment) {
return AttachmentList(
parentId: item.id.toString(),
attachmentIds: item.preload == null ? attachments : null,
attachments: item.preload?.attachments,
autoload: false,
isColumn: true,
).paddingSymmetric(horizontal: (padding?.horizontal ?? 0) + 14);
} else {
return AttachmentList(
parentId: item.id.toString(),

View File

@ -15,14 +15,15 @@ class PostShareImage extends StatelessWidget {
Widget build(BuildContext context) {
final textColor = Theme.of(context).colorScheme.onSurface.withOpacity(0.3);
return RootContainer(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
child: Wrap(
alignment: WrapAlignment.spaceBetween,
runAlignment: WrapAlignment.center,
children: [
const Gap(24),
const SizedBox(height: 40),
Material(
color: Colors.transparent,
child: Card(
margin: EdgeInsets.zero,
child: PostItem(
item: item,
isShowEmbed: true,
@ -30,11 +31,15 @@ class PostShareImage extends StatelessWidget {
showFeaturedReply: false,
isReactable: false,
isShowReply: false,
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
isNonScrollAttachment: true,
padding: const EdgeInsets.symmetric(
horizontal: 4,
vertical: 16,
),
onComment: () {},
),
),
),
).paddingOnly(bottom: 24),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@ -80,6 +85,12 @@ class PostShareImage extends StatelessWidget {
version: QrVersions.auto,
padding: const EdgeInsets.all(4),
size: 48,
dataModuleStyle: QrDataModuleStyle(
color: Theme.of(context).colorScheme.onSurface,
),
eyeStyle: QrEyeStyle(
color: Theme.of(context).colorScheme.onSurface,
),
),
),
),

View File

@ -803,6 +803,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.23"
flutter_resizable_container:
dependency: "direct main"
description:
name: flutter_resizable_container
sha256: "5b15c79c6cc338ed79640c706bb5176baa3333d92fd3627ad279aa3e25d2f0e7"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
flutter_secure_storage:
dependency: "direct main"
description:

View File

@ -87,6 +87,7 @@ dependencies:
timeline_tile: ^2.0.0
screenshot: ^3.0.0
qr_flutter: ^4.1.0
flutter_resizable_container: ^3.0.0
dev_dependencies:
flutter_test: