💄 Optimize the article editor
This commit is contained in:
@@ -201,6 +201,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
color: colorScheme.surface,
|
||||||
border: Border.all(color: colorScheme.outline.withOpacity(0.3)),
|
border: Border.all(color: colorScheme.outline.withOpacity(0.3)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
@@ -225,19 +226,14 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(child: widgetItem),
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
child: widgetItem,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildEditorPane() {
|
Widget buildEditorPane() {
|
||||||
return Center(
|
final editorContent = Center(
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxWidth: 560),
|
constraints: const BoxConstraints(maxWidth: 560),
|
||||||
child: Column(
|
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(
|
return PopScope(
|
||||||
@@ -325,7 +335,9 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
Tooltip(
|
Tooltip(
|
||||||
message: 'togglePreview'.tr(),
|
message: 'togglePreview'.tr(),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: Icon(showPreview.value ? Symbols.edit : Symbols.preview),
|
icon: Icon(
|
||||||
|
showPreview.value ? Symbols.preview_off : Symbols.preview,
|
||||||
|
),
|
||||||
onPressed: () => showPreview.value = !showPreview.value,
|
onPressed: () => showPreview.value = !showPreview.value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -395,12 +407,25 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
switchOutCurve: Curves.easeOutCubic,
|
switchOutCurve: Curves.easeOutCubic,
|
||||||
transitionBuilder:
|
transitionBuilder:
|
||||||
(Widget child, Animation<double> animation) {
|
(Widget child, Animation<double> animation) {
|
||||||
return FadeTransition(
|
final isWide = isWideScreen(context);
|
||||||
opacity: animation,
|
if (isWide) {
|
||||||
child: SlideTransition(
|
// 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:
|
position:
|
||||||
Tween<Offset>(
|
Tween<Offset>(
|
||||||
begin: const Offset(0, 0.05),
|
begin: const Offset(0.05, 0),
|
||||||
end: Offset.zero,
|
end: Offset.zero,
|
||||||
).animate(
|
).animate(
|
||||||
CurvedAnimation(
|
CurvedAnimation(
|
||||||
@@ -409,8 +434,8 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: child,
|
child: child,
|
||||||
),
|
);
|
||||||
);
|
}
|
||||||
},
|
},
|
||||||
child: isWideScreen(context)
|
child: isWideScreen(context)
|
||||||
? Row(
|
? Row(
|
||||||
@@ -439,4 +464,4 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class ResponsiveSidebar extends HookConsumerWidget {
|
|||||||
showDrawer.value = true;
|
showDrawer.value = true;
|
||||||
animationController.forward();
|
animationController.forward();
|
||||||
} else if (!showSidebar.value && showDrawer.value) {
|
} else if (!showSidebar.value && showDrawer.value) {
|
||||||
showDrawer.value = false;
|
// Don't set showDrawer.value = false here - let animation complete first
|
||||||
animationController.reverse();
|
animationController.reverse();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -121,11 +121,10 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
content: composeState.contentController.text,
|
content: composeState.contentController.text,
|
||||||
visibility: composeState.visibility.value,
|
visibility: composeState.visibility.value,
|
||||||
type: composeState.postType,
|
type: composeState.postType,
|
||||||
attachments:
|
attachments: composeState.attachments.value
|
||||||
composeState.attachments.value
|
.where((e) => e.isOnCloud)
|
||||||
.where((e) => e.isOnCloud)
|
.map((e) => e.data as SnCloudFile)
|
||||||
.map((e) => e.data as SnCloudFile)
|
.toList(),
|
||||||
.toList(),
|
|
||||||
publisher: composeState.currentPublisher.value!,
|
publisher: composeState.currentPublisher.value!,
|
||||||
updatedAt: DateTime.now(),
|
updatedAt: DateTime.now(),
|
||||||
);
|
);
|
||||||
@@ -218,27 +217,25 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
onPressed:
|
onPressed:
|
||||||
(composeState.submitting.value ||
|
(composeState.submitting.value ||
|
||||||
composeState.currentPublisher.value == null)
|
composeState.currentPublisher.value == null)
|
||||||
? null
|
? null
|
||||||
: performSubmit,
|
: performSubmit,
|
||||||
icon:
|
icon: composeState.submitting.value
|
||||||
composeState.submitting.value
|
? SizedBox(
|
||||||
? SizedBox(
|
width: 24,
|
||||||
width: 24,
|
height: 24,
|
||||||
height: 24,
|
child: const CircularProgressIndicator(
|
||||||
child: const CircularProgressIndicator(
|
strokeWidth: 2,
|
||||||
strokeWidth: 2,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Icon(
|
|
||||||
originalPost != null
|
|
||||||
? Symbols.edit
|
|
||||||
: Symbols.upload,
|
|
||||||
),
|
),
|
||||||
tooltip:
|
)
|
||||||
originalPost != null
|
: Icon(
|
||||||
? 'postUpdate'.tr()
|
originalPost != null
|
||||||
: 'postPublish'.tr(),
|
? Symbols.edit
|
||||||
|
: Symbols.upload,
|
||||||
|
),
|
||||||
|
tooltip: originalPost != null
|
||||||
|
? 'postUpdate'.tr()
|
||||||
|
: 'postPublish'.tr(),
|
||||||
visualDensity: const VisualDensity(
|
visualDensity: const VisualDensity(
|
||||||
horizontal: -4,
|
horizontal: -4,
|
||||||
vertical: -2,
|
vertical: -2,
|
||||||
@@ -268,13 +265,10 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
builder:
|
builder: (context) => SheetScaffold(
|
||||||
(context) => SheetScaffold(
|
titleText: 'Post Preview',
|
||||||
titleText: 'Post Preview',
|
child: SingleChildScrollView(child: PostItem(item: post)),
|
||||||
child: SingleChildScrollView(
|
),
|
||||||
child: PostItem(item: post),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -283,16 +277,15 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: KeyboardListener(
|
child: KeyboardListener(
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
onKeyEvent:
|
onKeyEvent: (event) => ComposeLogic.handleKeyPress(
|
||||||
(event) => ComposeLogic.handleKeyPress(
|
event,
|
||||||
event,
|
composeState,
|
||||||
composeState,
|
ref,
|
||||||
ref,
|
context,
|
||||||
context,
|
originalPost: originalPost,
|
||||||
originalPost: originalPost,
|
repliedPost: repliedPost,
|
||||||
repliedPost: repliedPost,
|
forwardedPost: forwardedPost,
|
||||||
forwardedPost: forwardedPost,
|
),
|
||||||
),
|
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
@@ -304,17 +297,16 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
// Publisher profile picture
|
// Publisher profile picture
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: ProfilePictureWidget(
|
child: ProfilePictureWidget(
|
||||||
fileId:
|
fileId: composeState
|
||||||
composeState
|
.currentPublisher
|
||||||
.currentPublisher
|
.value
|
||||||
.value
|
?.picture
|
||||||
?.picture
|
?.id,
|
||||||
?.id,
|
|
||||||
radius: 20,
|
radius: 20,
|
||||||
fallbackIcon:
|
fallbackIcon:
|
||||||
composeState.currentPublisher.value == null
|
composeState.currentPublisher.value == null
|
||||||
? Symbols.question_mark
|
? Symbols.question_mark
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (composeState.currentPublisher.value == null) {
|
if (composeState.currentPublisher.value == null) {
|
||||||
@@ -326,8 +318,8 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
builder:
|
builder: (context) =>
|
||||||
(context) => const NewPublisherScreen(),
|
const NewPublisherScreen(),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
composeState.currentPublisher.value =
|
composeState.currentPublisher.value =
|
||||||
@@ -370,9 +362,8 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
builder:
|
builder: (context) =>
|
||||||
(context) =>
|
const NewPublisherScreen(),
|
||||||
const NewPublisherScreen(),
|
|
||||||
).then((value) {
|
).then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
composeState.currentPublisher.value =
|
composeState.currentPublisher.value =
|
||||||
@@ -388,8 +379,8 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder: (context) =>
|
||||||
(context) => const PublisherModal(),
|
const PublisherModal(),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
composeState.currentPublisher.value =
|
composeState.currentPublisher.value =
|
||||||
@@ -415,19 +406,16 @@ class PostComposeCard extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Bottom toolbar
|
// Bottom toolbar
|
||||||
SizedBox(
|
ClipRRect(
|
||||||
height: 65,
|
borderRadius: const BorderRadius.only(
|
||||||
child: ClipRRect(
|
bottomLeft: Radius.circular(8),
|
||||||
borderRadius: const BorderRadius.only(
|
bottomRight: Radius.circular(8),
|
||||||
bottomLeft: Radius.circular(8),
|
),
|
||||||
bottomRight: Radius.circular(8),
|
child: ComposeToolbar(
|
||||||
),
|
state: composeState,
|
||||||
child: ComposeToolbar(
|
originalPost: originalPost,
|
||||||
state: composeState,
|
isCompact: true,
|
||||||
originalPost: originalPost,
|
useSafeArea: isContained,
|
||||||
isCompact: true,
|
|
||||||
useSafeArea: isContained,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user