💫 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,24 +82,11 @@ class PostMediaPendingListRaw extends StatelessWidget {
} }
} }
@override ContextMenu _buildContextMenu(
Widget build(BuildContext context) { BuildContext context, int idx, PostWriteMedia media) {
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio; return ContextMenu(
return Container(
constraints: const BoxConstraints(maxHeight: 120),
child: ListView.separated(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 8),
separatorBuilder: (context, index) => const Gap(8),
itemCount: attachments.length,
itemBuilder: (context, idx) {
final media = attachments[idx];
return ContextMenuRegion(
contextMenu: ContextMenu(
entries: [ entries: [
if (media.type == PostWriteMediaType.image && if (media.type == PostWriteMediaType.image && media.attachment != null)
media.attachment != null)
MenuItem( MenuItem(
label: 'preview'.tr(), label: 'preview'.tr(),
icon: Symbols.preview, icon: Symbols.preview,
@ -150,8 +97,7 @@ class PostMediaPendingListRaw extends StatelessWidget {
); );
}, },
), ),
if (media.type == PostWriteMediaType.image && if (media.type == PostWriteMediaType.image && media.attachment == null)
media.attachment == null)
MenuItem( MenuItem(
label: 'crop'.tr(), label: 'crop'.tr(),
icon: Symbols.crop, icon: Symbols.crop,
@ -161,8 +107,7 @@ class PostMediaPendingListRaw extends StatelessWidget {
MenuItem( MenuItem(
label: 'delete'.tr(), label: 'delete'.tr(),
icon: Symbols.delete, icon: Symbols.delete,
onSelected: onSelected: isBusy ? null : () => _deleteAttachment(context, idx),
isBusy ? null : () => _deleteAttachment(context, idx),
), ),
if (media.attachment == null && onRemove != null) if (media.attachment == null && onRemove != null)
MenuItem( MenuItem(
@ -181,7 +126,24 @@ class PostMediaPendingListRaw extends StatelessWidget {
}, },
), ),
], ],
), );
}
@override
Widget build(BuildContext context) {
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
return Container(
constraints: const BoxConstraints(maxHeight: 120),
child: ListView.separated(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 8),
separatorBuilder: (context, index) => const Gap(8),
itemCount: attachments.length,
itemBuilder: (context, idx) {
final media = attachments[idx];
return ContextMenuRegion(
contextMenu: _buildContextMenu(context, idx, media),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( border: Border.all(