💄 Optimize the article editor

This commit is contained in:
2026-01-17 14:50:16 +08:00
parent 09767e113f
commit c5d667ecf3
3 changed files with 99 additions and 86 deletions

View File

@@ -201,6 +201,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
return Container(
decoration: BoxDecoration(
color: colorScheme.surface,
border: Border.all(color: colorScheme.outline.withOpacity(0.3)),
borderRadius: BorderRadius.circular(8),
),
@@ -225,19 +226,14 @@ class ArticleComposeScreen extends HookConsumerWidget {
],
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: widgetItem,
),
),
Expanded(child: widgetItem),
],
),
);
}
Widget buildEditorPane() {
return Center(
final editorContent = Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 560),
child: Column(
@@ -267,6 +263,20 @@ class ArticleComposeScreen extends HookConsumerWidget {
),
),
);
// Add background color for mobile editor pane
if (!isWideScreen(context)) {
return Container(
decoration: BoxDecoration(
color: colorScheme.surface,
borderRadius: BorderRadius.circular(8),
),
margin: const EdgeInsets.symmetric(vertical: 8),
child: editorContent,
);
}
return editorContent;
}
return PopScope(
@@ -325,7 +335,9 @@ class ArticleComposeScreen extends HookConsumerWidget {
Tooltip(
message: 'togglePreview'.tr(),
child: IconButton(
icon: Icon(showPreview.value ? Symbols.edit : Symbols.preview),
icon: Icon(
showPreview.value ? Symbols.preview_off : Symbols.preview,
),
onPressed: () => showPreview.value = !showPreview.value,
),
),
@@ -395,12 +407,25 @@ class ArticleComposeScreen extends HookConsumerWidget {
switchOutCurve: Curves.easeOutCubic,
transitionBuilder:
(Widget child, Animation<double> animation) {
return FadeTransition(
opacity: animation,
child: SlideTransition(
final isWide = isWideScreen(context);
if (isWide) {
// Desktop: scale animation
return ScaleTransition(
scale: Tween<double>(begin: 0.95, end: 1.0)
.animate(
CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic,
),
),
child: child,
);
} else {
// Mobile: horizontal slide animation
return SlideTransition(
position:
Tween<Offset>(
begin: const Offset(0, 0.05),
begin: const Offset(0.05, 0),
end: Offset.zero,
).animate(
CurvedAnimation(
@@ -409,8 +434,8 @@ class ArticleComposeScreen extends HookConsumerWidget {
),
),
child: child,
),
);
}
},
child: isWideScreen(context)
? Row(

View File

@@ -44,7 +44,7 @@ class ResponsiveSidebar extends HookConsumerWidget {
showDrawer.value = true;
animationController.forward();
} else if (!showSidebar.value && showDrawer.value) {
showDrawer.value = false;
// Don't set showDrawer.value = false here - let animation complete first
animationController.reverse();
}
} else {

View File

@@ -121,8 +121,7 @@ class PostComposeCard extends HookConsumerWidget {
content: composeState.contentController.text,
visibility: composeState.visibility.value,
type: composeState.postType,
attachments:
composeState.attachments.value
attachments: composeState.attachments.value
.where((e) => e.isOnCloud)
.map((e) => e.data as SnCloudFile)
.toList(),
@@ -221,8 +220,7 @@ class PostComposeCard extends HookConsumerWidget {
composeState.currentPublisher.value == null)
? null
: performSubmit,
icon:
composeState.submitting.value
icon: composeState.submitting.value
? SizedBox(
width: 24,
height: 24,
@@ -235,8 +233,7 @@ class PostComposeCard extends HookConsumerWidget {
? Symbols.edit
: Symbols.upload,
),
tooltip:
originalPost != null
tooltip: originalPost != null
? 'postUpdate'.tr()
: 'postPublish'.tr(),
visualDensity: const VisualDensity(
@@ -268,12 +265,9 @@ class PostComposeCard extends HookConsumerWidget {
context: context,
isScrollControlled: true,
useRootNavigator: true,
builder:
(context) => SheetScaffold(
builder: (context) => SheetScaffold(
titleText: 'Post Preview',
child: SingleChildScrollView(
child: PostItem(item: post),
),
child: SingleChildScrollView(child: PostItem(item: post)),
),
);
},
@@ -283,8 +277,7 @@ class PostComposeCard extends HookConsumerWidget {
Expanded(
child: KeyboardListener(
focusNode: FocusNode(),
onKeyEvent:
(event) => ComposeLogic.handleKeyPress(
onKeyEvent: (event) => ComposeLogic.handleKeyPress(
event,
composeState,
ref,
@@ -304,8 +297,7 @@ class PostComposeCard extends HookConsumerWidget {
// Publisher profile picture
GestureDetector(
child: ProfilePictureWidget(
fileId:
composeState
fileId: composeState
.currentPublisher
.value
?.picture
@@ -326,8 +318,8 @@ class PostComposeCard extends HookConsumerWidget {
context: context,
isScrollControlled: true,
useRootNavigator: true,
builder:
(context) => const NewPublisherScreen(),
builder: (context) =>
const NewPublisherScreen(),
).then((value) {
if (value != null) {
composeState.currentPublisher.value =
@@ -370,8 +362,7 @@ class PostComposeCard extends HookConsumerWidget {
context: context,
isScrollControlled: true,
useRootNavigator: true,
builder:
(context) =>
builder: (context) =>
const NewPublisherScreen(),
).then((value) {
if (value != null) {
@@ -388,8 +379,8 @@ class PostComposeCard extends HookConsumerWidget {
isScrollControlled: true,
useRootNavigator: true,
context: context,
builder:
(context) => const PublisherModal(),
builder: (context) =>
const PublisherModal(),
).then((value) {
if (value != null) {
composeState.currentPublisher.value =
@@ -415,9 +406,7 @@ class PostComposeCard extends HookConsumerWidget {
),
// Bottom toolbar
SizedBox(
height: 65,
child: ClipRRect(
ClipRRect(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
@@ -429,7 +418,6 @@ class PostComposeCard extends HookConsumerWidget {
useSafeArea: isContained,
),
),
),
],
),
),