💄 Better post quick reply

This commit is contained in:
2025-10-12 22:26:37 +08:00
parent 1be33916af
commit 67def56ad1
3 changed files with 98 additions and 100 deletions

View File

@@ -490,14 +490,13 @@ class PostDetailScreen extends HookConsumerWidget {
), ),
if (user.value != null) if (user.value != null)
Positioned( Positioned(
bottom: 0, bottom: 16 + MediaQuery.of(context).padding.bottom,
left: 0, left: 16,
right: 0, right: 16,
child: Material( child:
elevation: 2, ConstrainedBox(
color: Theme.of(context).colorScheme.surfaceContainer, constraints: BoxConstraints(maxWidth: 660),
child: postState child: postState.when(
.when(
data: data:
(post) => PostQuickReply( (post) => PostQuickReply(
parent: post!, parent: post!,
@@ -509,13 +508,8 @@ class PostDetailScreen extends HookConsumerWidget {
), ),
loading: () => const SizedBox.shrink(), loading: () => const SizedBox.shrink(),
error: (_, _) => const SizedBox.shrink(), error: (_, _) => const SizedBox.shrink(),
)
.padding(
bottom: MediaQuery.of(context).padding.bottom + 8,
top: 8,
horizontal: 16,
), ),
), ).center(),
), ),
], ],
); );

View File

@@ -1,6 +1,7 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart'; import 'package:island/models/post.dart';
@@ -69,79 +70,86 @@ class PostQuickReply extends HookConsumerWidget {
return publishers.when( return publishers.when(
data: data:
(data) => Row( (data) => Material(
spacing: 8, elevation: 2,
children: [ color: Theme.of(context).colorScheme.surfaceContainerHighest,
GestureDetector( borderRadius: BorderRadius.circular(20),
child: ProfilePictureWidget( child: Padding(
fileId: currentPublisher.value?.picture?.id, padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 8),
radius: 16, child: Row(
), crossAxisAlignment: CrossAxisAlignment.start,
onTap: () { children: [
showModalBottomSheet( GestureDetector(
isScrollControlled: true, child: ProfilePictureWidget(
context: context, fileId: currentPublisher.value?.picture?.id,
builder: (context) => PublisherModal(), radius: 16,
).then((value) { ),
if (value is SnPublisher) currentPublisher.value = value; onTap: () {
}); showModalBottomSheet(
}, isScrollControlled: true,
).padding(right: 4), context: context,
Expanded( builder: (context) => PublisherModal(),
child: TextField( ).then((value) {
controller: contentController, if (value is SnPublisher) {
decoration: InputDecoration( currentPublisher.value = value;
hintText: 'postReplyPlaceholder'.tr(), }
border: InputBorder.none, });
isDense: true, },
isCollapsed: true, ).padding(right: 12),
contentPadding: EdgeInsets.symmetric( Expanded(
horizontal: 12, child: TextField(
vertical: 8, controller: contentController,
decoration: InputDecoration(
hintText: 'postReplyPlaceholder'.tr(),
border: InputBorder.none,
isDense: true,
isCollapsed: true,
contentPadding: EdgeInsets.symmetric(
horizontal: 12,
vertical: 9,
),
),
style: TextStyle(fontSize: 14),
maxLines: null,
onTapOutside:
(_) => FocusManager.instance.primaryFocus?.unfocus(),
), ),
), ),
style: TextStyle(fontSize: 14), const Gap(8),
maxLines: null, IconButton(
onTapOutside: onPressed: () {
(_) => FocusManager.instance.primaryFocus?.unfocus(), onLaunch?.call();
), GoRouter.of(context)
.pushNamed(
'postCompose',
extra: PostComposeInitialState(
content: contentController.text,
replyingTo: parent,
),
)
.then((value) {
if (value != null) onPosted?.call();
});
},
icon: const Icon(Symbols.launch, size: 20),
visualDensity: VisualDensity.compact,
),
IconButton(
icon:
submitting.value
? SizedBox(
width: 28,
height: 28,
child: CircularProgressIndicator(strokeWidth: 3),
)
: Icon(Symbols.send, size: 20),
color: Theme.of(context).colorScheme.primary,
onPressed: submitting.value ? null : performAction,
visualDensity: VisualDensity.compact,
),
],
), ),
IconButton( ),
onPressed: () {
onLaunch?.call();
GoRouter.of(context)
.pushNamed(
'postCompose',
extra: PostComposeInitialState(
content: contentController.text,
replyingTo: parent,
),
)
.then((value) {
if (value != null) onPosted?.call();
});
},
icon: const Icon(Symbols.launch, size: 20),
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
constraints: const BoxConstraints(),
),
IconButton(
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
icon:
submitting.value
? SizedBox(
width: 28,
height: 28,
child: CircularProgressIndicator(strokeWidth: 3),
)
: Icon(Symbols.send, size: 20),
color: Theme.of(context).colorScheme.primary,
onPressed: submitting.value ? null : performAction,
constraints: const BoxConstraints(),
),
],
), ),
loading: () => const SizedBox.shrink(), loading: () => const SizedBox.shrink(),
error: (e, _) => const SizedBox.shrink(), error: (e, _) => const SizedBox.shrink(),

View File

@@ -36,22 +36,18 @@ class PostRepliesSheet extends HookConsumerWidget {
), ),
// Quick reply section // Quick reply section
if (user.value != null) if (user.value != null)
Material( PostQuickReply(
elevation: 2, parent: post,
color: Theme.of(context).colorScheme.surfaceContainerHigh, onPosted: () {
child: PostQuickReply( ref.invalidate(postRepliesNotifierProvider(post.id));
parent: post, },
onPosted: () { onLaunch: () {
ref.invalidate(postRepliesNotifierProvider(post.id)); Navigator.of(context).pop();
}, },
onLaunch: () { ).padding(
Navigator.of(context).pop(); bottom: MediaQuery.of(context).padding.bottom + 16,
}, top: 8,
).padding( horizontal: 16,
bottom: MediaQuery.of(context).padding.bottom + 8,
top: 8,
horizontal: 16,
),
), ),
], ],
), ),