💫 Optimize transition of pages

This commit is contained in:
LittleSheep 2024-11-23 17:32:48 +08:00
parent 5d6a52494e
commit b8a1e5b5c0
4 changed files with 73 additions and 109 deletions

View File

@ -48,7 +48,8 @@ final _appRoutes = [
GoRoute( GoRoute(
path: '/post/write/:mode', path: '/post/write/:mode',
name: 'postEditor', name: 'postEditor',
pageBuilder: (context, state) => CustomTransitionPage( builder: (context, state) => AppBackground(
isLessOptimization: true,
child: PostEditorScreen( child: PostEditorScreen(
mode: state.pathParameters['mode']!, mode: state.pathParameters['mode']!,
postEditId: int.tryParse( postEditId: int.tryParse(
@ -61,34 +62,17 @@ final _appRoutes = [
state.uri.queryParameters['reposting'] ?? '', state.uri.queryParameters['reposting'] ?? '',
), ),
), ),
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
return FadeThroughTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
fillColor: Colors.transparent,
child: AppBackground(isLessOptimization: true, child: child),
);
},
), ),
), ),
GoRoute( GoRoute(
path: '/post/:slug', path: '/post/:slug',
name: 'postDetail', name: 'postDetail',
pageBuilder: (context, state) => CustomTransitionPage( builder: (context, state) => AppBackground(
isLessOptimization: true,
child: PostDetailScreen( child: PostDetailScreen(
slug: state.pathParameters['slug']!, slug: state.pathParameters['slug']!,
preload: state.extra as SnPost?, preload: state.extra as SnPost?,
), ),
transitionsBuilder:
(context, animation, secondaryAnimation, child) {
return FadeThroughTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
fillColor: Colors.transparent,
child: AppBackground(isLessOptimization: true, child: child),
);
},
), ),
), ),
], ],

View File

@ -354,7 +354,25 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
), ),
if (_writeController.attachments.isNotEmpty) if (_writeController.attachments.isNotEmpty)
PostMediaPendingList( PostMediaPendingList(
controller: _writeController, attachments: _writeController.attachments,
isBusy: _writeController.isBusy,
onUpdate: (int idx, PostWriteMedia updatedMedia) async {
_writeController.setIsBusy(true);
try {
_writeController.setAttachmentAt(idx, updatedMedia);
} finally {
_writeController.setIsBusy(false);
}
},
onRemove: (int idx) async {
_writeController.setIsBusy(true);
try {
_writeController.removeAttachmentAt(idx);
} finally {
_writeController.setIsBusy(false);
}
},
onUpdateBusy: (state) => _writeController.setIsBusy(state),
).padding(bottom: 8), ).padding(bottom: 8),
Material( Material(
elevation: 2, elevation: 2,

View File

@ -175,7 +175,7 @@ class ChatMessageInputState extends State<ChatMessageInput> {
padding: _attachments.isNotEmpty padding: _attachments.isNotEmpty
? const EdgeInsets.only(top: 8) ? const EdgeInsets.only(top: 8)
: EdgeInsets.zero, : EdgeInsets.zero,
child: PostMediaPendingListRaw( child: PostMediaPendingList(
attachments: _attachments, attachments: _attachments,
isBusy: _isBusy, isBusy: _isBusy,
onUpdate: (idx, updatedMedia) async { onUpdate: (idx, updatedMedia) async {

View File

@ -17,53 +17,13 @@ import 'package:surface/widgets/attachment/attachment_detail.dart';
import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/dialog.dart';
class PostMediaPendingList extends StatelessWidget { class PostMediaPendingList extends StatelessWidget {
final PostWriteController controller;
const PostMediaPendingList({super.key, required this.controller});
Future<void> _handleUpdate(int idx, PostWriteMedia updatedMedia) async {
controller.setIsBusy(true);
try {
controller.setAttachmentAt(idx, updatedMedia);
} finally {
controller.setIsBusy(false);
}
}
Future<void> _handleRemove(int idx) async {
controller.setIsBusy(true);
try {
controller.removeAttachmentAt(idx);
} finally {
controller.setIsBusy(false);
}
}
@override
Widget build(BuildContext context) {
return ListenableBuilder(
listenable: controller,
builder: (context, _) {
return PostMediaPendingListRaw(
attachments: controller.attachments,
isBusy: controller.isBusy,
onUpdate: (idx, updatedMedia) => _handleUpdate(idx, updatedMedia),
onRemove: (idx) => _handleRemove(idx),
onUpdateBusy: (state) => controller.setIsBusy(state),
);
},
);
}
}
class PostMediaPendingListRaw extends StatelessWidget {
final List<PostWriteMedia> attachments; final List<PostWriteMedia> attachments;
final bool isBusy; final bool isBusy;
final Future<void> Function(int idx, PostWriteMedia updatedMedia)? onUpdate; final Future<void> Function(int idx, PostWriteMedia updatedMedia)? onUpdate;
final Future<void> Function(int idx)? onRemove; final Future<void> Function(int idx)? onRemove;
final void Function(bool state)? onUpdateBusy; final void Function(bool state)? onUpdateBusy;
const PostMediaPendingListRaw({ const PostMediaPendingList({
super.key, super.key,
required this.attachments, required this.attachments,
required this.isBusy, required this.isBusy,
@ -122,6 +82,53 @@ class PostMediaPendingListRaw extends StatelessWidget {
} }
} }
ContextMenu _buildContextMenu(
BuildContext context, int idx, PostWriteMedia media) {
return ContextMenu(
entries: [
if (media.type == PostWriteMediaType.image && media.attachment != null)
MenuItem(
label: 'preview'.tr(),
icon: Symbols.preview,
onSelected: () {
context.pushTransparentRoute(
AttachmentDetailPopup(data: media.attachment!),
rootNavigator: true,
);
},
),
if (media.type == PostWriteMediaType.image && media.attachment == null)
MenuItem(
label: 'crop'.tr(),
icon: Symbols.crop,
onSelected: () => _cropImage(context, idx),
),
if (media.attachment != null && onRemove != null)
MenuItem(
label: 'delete'.tr(),
icon: Symbols.delete,
onSelected: isBusy ? null : () => _deleteAttachment(context, idx),
),
if (media.attachment == null && onRemove != null)
MenuItem(
label: 'delete'.tr(),
icon: Symbols.delete,
onSelected: () {
onRemove!(idx);
},
)
else if (onRemove != null)
MenuItem(
label: 'unlink'.tr(),
icon: Symbols.link_off,
onSelected: () {
onRemove!(idx);
},
),
],
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
@ -136,52 +143,7 @@ class PostMediaPendingListRaw extends StatelessWidget {
itemBuilder: (context, idx) { itemBuilder: (context, idx) {
final media = attachments[idx]; final media = attachments[idx];
return ContextMenuRegion( return ContextMenuRegion(
contextMenu: ContextMenu( contextMenu: _buildContextMenu(context, idx, media),
entries: [
if (media.type == PostWriteMediaType.image &&
media.attachment != null)
MenuItem(
label: 'preview'.tr(),
icon: Symbols.preview,
onSelected: () {
context.pushTransparentRoute(
AttachmentDetailPopup(data: media.attachment!),
rootNavigator: true,
);
},
),
if (media.type == PostWriteMediaType.image &&
media.attachment == null)
MenuItem(
label: 'crop'.tr(),
icon: Symbols.crop,
onSelected: () => _cropImage(context, idx),
),
if (media.attachment != null && onRemove != null)
MenuItem(
label: 'delete'.tr(),
icon: Symbols.delete,
onSelected:
isBusy ? null : () => _deleteAttachment(context, idx),
),
if (media.attachment == null && onRemove != null)
MenuItem(
label: 'delete'.tr(),
icon: Symbols.delete,
onSelected: () {
onRemove!(idx);
},
)
else if (onRemove != null)
MenuItem(
label: 'unlink'.tr(),
icon: Symbols.link_off,
onSelected: () {
onRemove!(idx);
},
),
],
),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( border: Border.all(