💄 Optimize post editors
This commit is contained in:
parent
a2d2ce4d38
commit
fe028860e9
@ -166,9 +166,9 @@
|
|||||||
"postPosted": "Post has been posted.",
|
"postPosted": "Post has been posted.",
|
||||||
"postPublishedAt": "Published At",
|
"postPublishedAt": "Published At",
|
||||||
"postPublishedUntil": "Published Until",
|
"postPublishedUntil": "Published Until",
|
||||||
"postEditingNotice": "You're about to editing a post that posted {}.",
|
"postEditingNotice": "You're about to editing a post that posted by {}.",
|
||||||
"postReplyingNotice": "You're about to reply to a post that posted {}.",
|
"postReplyingNotice": "You're about to reply to a post that posted by {}.",
|
||||||
"postRepostingNotice": "You're about to repost a post that posted {}.",
|
"postRepostingNotice": "You're about to repost a post that posted by {}.",
|
||||||
"postReact": "React",
|
"postReact": "React",
|
||||||
"postReactions": "Reactions of Post",
|
"postReactions": "Reactions of Post",
|
||||||
"postReactionUpvote": {
|
"postReactionUpvote": {
|
||||||
|
@ -125,6 +125,16 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showPublisherPopup() {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => _PostPublisherPopup(
|
||||||
|
controller: _writeController,
|
||||||
|
publishers: _publishers,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_writeController.dispose();
|
_writeController.dispose();
|
||||||
@ -198,156 +208,42 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
DropdownButtonHideUnderline(
|
if (_writeController.editingPost != null)
|
||||||
child: DropdownButton2<SnPublisher>(
|
Container(
|
||||||
isExpanded: true,
|
padding: const EdgeInsets.only(top: 4, bottom: 4, left: 20, right: 20),
|
||||||
hint: Text(
|
decoration: BoxDecoration(
|
||||||
'fieldPostPublisher',
|
border: Border(
|
||||||
style: TextStyle(
|
bottom: BorderSide(
|
||||||
fontSize: 14,
|
color: Theme.of(context).dividerColor,
|
||||||
color: Theme.of(context).hintColor,
|
width: 1 / MediaQuery.of(context).devicePixelRatio,
|
||||||
),
|
|
||||||
).tr(),
|
|
||||||
items: <DropdownMenuItem<SnPublisher>>[
|
|
||||||
...(_publishers?.map(
|
|
||||||
(item) => DropdownMenuItem<SnPublisher>(
|
|
||||||
enabled: _writeController.editingPost == null,
|
|
||||||
value: item,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
AccountImage(content: item.avatar, radius: 16),
|
|
||||||
const Gap(8),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(item.nick).textStyle(Theme.of(context).textTheme.bodyMedium!),
|
|
||||||
Text('@${item.name}')
|
|
||||||
.textStyle(Theme.of(context).textTheme.bodySmall!)
|
|
||||||
.fontSize(12),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
) ??
|
|
||||||
[]),
|
|
||||||
DropdownMenuItem<SnPublisher>(
|
|
||||||
value: null,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
CircleAvatar(
|
|
||||||
radius: 16,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
foregroundColor: Theme.of(context).colorScheme.onSurface,
|
|
||||||
child: const Icon(Symbols.add),
|
|
||||||
),
|
|
||||||
const Gap(8),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text('publishersNew').tr().textStyle(Theme.of(context).textTheme.bodyMedium!),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
value: _writeController.publisher,
|
|
||||||
onChanged: (SnPublisher? value) {
|
|
||||||
if (value == null) {
|
|
||||||
GoRouter.of(context).pushNamed('accountPublisherNew').then((value) {
|
|
||||||
if (value == true) {
|
|
||||||
_publishers = null;
|
|
||||||
_fetchPublishers();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
_writeController.setPublisher(value);
|
|
||||||
final config = context.read<ConfigProvider>();
|
|
||||||
config.prefs.setInt('int_last_publisher_id', value.id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
buttonStyleData: const ButtonStyleData(
|
|
||||||
padding: EdgeInsets.only(right: 16),
|
|
||||||
height: 48,
|
|
||||||
),
|
),
|
||||||
menuItemStyleData: const MenuItemStyleData(
|
child: Row(
|
||||||
height: 48,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.edit, size: 16),
|
||||||
|
const Gap(10),
|
||||||
|
Text('postEditingNotice').tr(args: ['@${_writeController.editingPost!.publisher.name}']),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const Divider(height: 1),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
SingleChildScrollView(
|
SingleChildScrollView(
|
||||||
padding: EdgeInsets.only(bottom: 160),
|
padding: EdgeInsets.only(bottom: 160),
|
||||||
child: Column(
|
child: switch (_writeController.mode) {
|
||||||
spacing: 8,
|
'stories' => _PostStoryEditor(
|
||||||
children: [
|
controller: _writeController,
|
||||||
// Replying Notice
|
onTapPublisher: _showPublisherPopup,
|
||||||
if (_writeController.replyingPost != null)
|
),
|
||||||
Column(
|
'articles' => _PostArticleEditor(
|
||||||
children: [
|
controller: _writeController,
|
||||||
ExpansionTile(
|
onTapPublisher: _showPublisherPopup,
|
||||||
minTileHeight: 48,
|
),
|
||||||
leading: const Icon(Symbols.reply).padding(left: 4),
|
_ => const Placeholder(),
|
||||||
title: Text('postReplyingNotice')
|
},
|
||||||
.fontSize(15)
|
|
||||||
.tr(args: ['@${_writeController.replyingPost!.publisher.name}']),
|
|
||||||
children: <Widget>[PostItem(data: _writeController.replyingPost!)],
|
|
||||||
),
|
|
||||||
const Divider(height: 1),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
// Reposting Notice
|
|
||||||
if (_writeController.repostingPost != null)
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
ExpansionTile(
|
|
||||||
minTileHeight: 48,
|
|
||||||
leading: const Icon(Symbols.forward).padding(left: 4),
|
|
||||||
title: Text('postRepostingNotice')
|
|
||||||
.fontSize(15)
|
|
||||||
.tr(args: ['@${_writeController.repostingPost!.publisher.name}']),
|
|
||||||
children: <Widget>[
|
|
||||||
PostItem(
|
|
||||||
data: _writeController.repostingPost!,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const Divider(height: 1),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
// Editing Notice
|
|
||||||
if (_writeController.editingPost != null)
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
ExpansionTile(
|
|
||||||
minTileHeight: 48,
|
|
||||||
leading: const Icon(Symbols.edit_note).padding(left: 4),
|
|
||||||
title: Text('postEditingNotice')
|
|
||||||
.fontSize(15)
|
|
||||||
.tr(args: ['@${_writeController.editingPost!.publisher.name}']),
|
|
||||||
children: <Widget>[PostItem(data: _writeController.editingPost!)],
|
|
||||||
),
|
|
||||||
const Divider(height: 1),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
// Content Input Area
|
|
||||||
switch (_writeController.mode) {
|
|
||||||
'stories' => _PostStoryEditor(controller: _writeController),
|
|
||||||
'articles' => _PostArticleEditor(controller: _writeController),
|
|
||||||
_ => const Placeholder(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (_writeController.attachments.isNotEmpty || _writeController.thumbnail != null)
|
if (_writeController.attachments.isNotEmpty || _writeController.thumbnail != null)
|
||||||
Positioned(
|
Positioned(
|
||||||
@ -492,28 +388,89 @@ class _PostEditorActionScrollBehavior extends MaterialScrollBehavior {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _PostPublisherPopup extends StatelessWidget {
|
||||||
|
final PostWriteController controller;
|
||||||
|
final List<SnPublisher>? publishers;
|
||||||
|
|
||||||
|
const _PostPublisherPopup({required this.controller, this.publishers});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.face, size: 24),
|
||||||
|
const Gap(16),
|
||||||
|
Text('accountPublishers', style: Theme.of(context).textTheme.titleLarge).tr(),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 20, top: 16, bottom: 12),
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: publishers?.length ?? 0,
|
||||||
|
itemBuilder: (context, idx) {
|
||||||
|
final publisher = publishers![idx];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(publisher.nick),
|
||||||
|
subtitle: Text('@${publisher.name}'),
|
||||||
|
leading: AccountImage(content: publisher.avatar, radius: 18),
|
||||||
|
onTap: () {
|
||||||
|
controller.setPublisher(publisher);
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _PostStoryEditor extends StatelessWidget {
|
class _PostStoryEditor extends StatelessWidget {
|
||||||
final PostWriteController controller;
|
final PostWriteController controller;
|
||||||
|
final Function? onTapPublisher;
|
||||||
|
|
||||||
const _PostStoryEditor({required this.controller});
|
const _PostStoryEditor({required this.controller, this.onTapPublisher});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
constraints: const BoxConstraints(maxWidth: 640),
|
constraints: const BoxConstraints(maxWidth: 640),
|
||||||
child: TextField(
|
child: Row(
|
||||||
controller: controller.contentController,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
maxLines: null,
|
children: [
|
||||||
decoration: InputDecoration(
|
Material(
|
||||||
hintText: 'fieldPostContent'.tr(),
|
elevation: 1,
|
||||||
hintStyle: TextStyle(fontSize: 14),
|
borderRadius: const BorderRadius.all(Radius.circular(24)),
|
||||||
isCollapsed: true,
|
child: GestureDetector(
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
onTap: () {
|
||||||
horizontal: 16,
|
onTapPublisher?.call();
|
||||||
|
},
|
||||||
|
child: AccountImage(
|
||||||
|
content: controller.publisher?.avatar,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
border: InputBorder.none,
|
Expanded(
|
||||||
),
|
child: TextField(
|
||||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
controller: controller.contentController,
|
||||||
|
maxLines: null,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'fieldPostContent'.tr(),
|
||||||
|
hintStyle: TextStyle(fontSize: 14),
|
||||||
|
isCollapsed: true,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
).padding(top: 4),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -521,60 +478,121 @@ class _PostStoryEditor extends StatelessWidget {
|
|||||||
|
|
||||||
class _PostArticleEditor extends StatelessWidget {
|
class _PostArticleEditor extends StatelessWidget {
|
||||||
final PostWriteController controller;
|
final PostWriteController controller;
|
||||||
|
final Function? onTapPublisher;
|
||||||
|
|
||||||
const _PostArticleEditor({required this.controller});
|
const _PostArticleEditor({required this.controller, this.onTapPublisher});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final editorWidgets = <Widget>[
|
||||||
|
Material(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
child: InkWell(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
AccountImage(content: controller.publisher?.avatar, radius: 20),
|
||||||
|
const Gap(8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(controller.publisher?.nick ?? 'loading'.tr()).bold(),
|
||||||
|
Text('@${controller.publisher?.name}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 12, vertical: 8),
|
||||||
|
onTap: () {
|
||||||
|
onTapPublisher?.call();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(4),
|
||||||
|
TextField(
|
||||||
|
controller: controller.titleController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'fieldPostTitle'.tr(),
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
).padding(horizontal: 16),
|
||||||
|
const Gap(4),
|
||||||
|
TextField(
|
||||||
|
controller: controller.descriptionController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'fieldPostDescription'.tr(),
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
maxLines: null,
|
||||||
|
keyboardType: TextInputType.multiline,
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
).padding(horizontal: 16),
|
||||||
|
const Gap(8),
|
||||||
|
];
|
||||||
|
|
||||||
if (ResponsiveBreakpoints.of(context).largerThan(MOBILE)) {
|
if (ResponsiveBreakpoints.of(context).largerThan(MOBILE)) {
|
||||||
return Container(
|
return Container(
|
||||||
constraints: const BoxConstraints(maxWidth: 640 * 2 + 8),
|
constraints: const BoxConstraints(maxWidth: 640 * 2 + 8),
|
||||||
child: Row(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
...editorWidgets,
|
||||||
child: TextField(
|
Row(
|
||||||
controller: controller.contentController,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
maxLines: null,
|
children: [
|
||||||
decoration: InputDecoration(
|
Expanded(
|
||||||
hintText: 'fieldPostContent'.tr(),
|
child: TextField(
|
||||||
hintStyle: TextStyle(fontSize: 14),
|
controller: controller.contentController,
|
||||||
isCollapsed: true,
|
maxLines: null,
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
decoration: InputDecoration(
|
||||||
horizontal: 16,
|
hintText: 'fieldPostContent'.tr(),
|
||||||
|
hintStyle: TextStyle(fontSize: 14),
|
||||||
|
isCollapsed: true,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
border: InputBorder.none,
|
|
||||||
),
|
),
|
||||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
const Gap(8),
|
||||||
),
|
Expanded(
|
||||||
),
|
child: MarkdownTextContent(
|
||||||
const Gap(8),
|
content: controller.contentController.text,
|
||||||
Expanded(
|
).padding(horizontal: 24),
|
||||||
child: MarkdownTextContent(
|
),
|
||||||
content: controller.contentController.text,
|
],
|
||||||
).padding(horizontal: 24),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Container(
|
return Column(
|
||||||
constraints: const BoxConstraints(maxWidth: 640),
|
children: [
|
||||||
child: TextField(
|
...editorWidgets,
|
||||||
controller: controller.contentController,
|
Container(
|
||||||
maxLines: null,
|
padding: const EdgeInsets.only(top: 8),
|
||||||
decoration: InputDecoration(
|
constraints: const BoxConstraints(maxWidth: 640),
|
||||||
hintText: 'fieldPostContent'.tr(),
|
child: TextField(
|
||||||
hintStyle: TextStyle(fontSize: 14),
|
controller: controller.contentController,
|
||||||
isCollapsed: true,
|
maxLines: null,
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
decoration: InputDecoration(
|
||||||
horizontal: 16,
|
hintText: 'fieldPostContent'.tr(),
|
||||||
|
hintStyle: TextStyle(fontSize: 14),
|
||||||
|
isCollapsed: true,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
border: InputBorder.none,
|
|
||||||
),
|
),
|
||||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
],
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +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:gap/gap.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
@ -96,10 +98,14 @@ class _AccountSelectState extends State<AccountSelect> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Row(
|
||||||
widget.title,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
children: [
|
||||||
).padding(left: 24, right: 24, top: 16, bottom: 16),
|
const Icon(Symbols.group, size: 24),
|
||||||
|
const Gap(16),
|
||||||
|
Text(widget.title, style: Theme.of(context).textTheme.titleLarge),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 20, top: 16, bottom: 12),
|
||||||
Container(
|
Container(
|
||||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
@ -336,6 +336,7 @@ class ChatMessageInputState extends State<ChatMessageInput> {
|
|||||||
: 'fieldChatMessage'.tr(args: [widget.controller.channel?.name ?? 'loading'.tr()]),
|
: 'fieldChatMessage'.tr(args: [widget.controller.channel?.name ?? 'loading'.tr()]),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
),
|
),
|
||||||
|
textInputAction: TextInputAction.send,
|
||||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
onSubmitted: (_) {
|
onSubmitted: (_) {
|
||||||
if (_isBusy) return;
|
if (_isBusy) return;
|
||||||
|
@ -833,7 +833,7 @@ class _PostContentHeader extends StatelessWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => _PostGetInsightSheet(postId: data.id),
|
builder: (context) => _PostGetInsightPopup(postId: data.id),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -1292,16 +1292,16 @@ class _PostAbuseReportDialogState extends State<_PostAbuseReportDialog> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PostGetInsightSheet extends StatefulWidget {
|
class _PostGetInsightPopup extends StatefulWidget {
|
||||||
final int postId;
|
final int postId;
|
||||||
|
|
||||||
const _PostGetInsightSheet({required this.postId});
|
const _PostGetInsightPopup({required this.postId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<_PostGetInsightSheet> createState() => _PostGetInsightSheetState();
|
State<_PostGetInsightPopup> createState() => _PostGetInsightPopupState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PostGetInsightSheetState extends State<_PostGetInsightSheet> {
|
class _PostGetInsightPopupState extends State<_PostGetInsightPopup> {
|
||||||
String? _response;
|
String? _response;
|
||||||
String? _thinkingProcess;
|
String? _thinkingProcess;
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ class PostMediaPendingList extends StatelessWidget {
|
|||||||
constraints: const BoxConstraints(maxHeight: 120),
|
constraints: const BoxConstraints(maxHeight: 120),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const Gap(8),
|
const Gap(16),
|
||||||
if (thumbnail != null)
|
if (thumbnail != null)
|
||||||
ContextMenuArea(
|
ContextMenuArea(
|
||||||
contextMenu: _createContextMenu(context, -1, thumbnail!),
|
contextMenu: _createContextMenu(context, -1, thumbnail!),
|
||||||
@ -337,15 +337,10 @@ class _PostMediaPendingItem extends StatelessWidget {
|
|||||||
|
|
||||||
final sn = context.read<SnNetworkProvider>();
|
final sn = context.read<SnNetworkProvider>();
|
||||||
|
|
||||||
return Container(
|
return Material(
|
||||||
decoration: BoxDecoration(
|
elevation: 4,
|
||||||
border: Border.all(
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
color: Theme.of(context).dividerColor,
|
borderRadius: BorderRadius.circular(8),
|
||||||
width: 1,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
|
||||||
),
|
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
@ -19,6 +19,7 @@ const Map<int, String> kPostVisibilityLevel = {
|
|||||||
|
|
||||||
class PostMetaEditor extends StatelessWidget {
|
class PostMetaEditor extends StatelessWidget {
|
||||||
final PostWriteController controller;
|
final PostWriteController controller;
|
||||||
|
|
||||||
const PostMetaEditor({super.key, required this.controller});
|
const PostMetaEditor({super.key, required this.controller});
|
||||||
|
|
||||||
Future<DateTime?> _selectDate(
|
Future<DateTime?> _selectDate(
|
||||||
@ -87,26 +88,14 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom + 8),
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom + 8),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
if (controller.mode == 'stories')
|
||||||
controller: controller.titleController,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'fieldPostTitle'.tr(),
|
|
||||||
border: UnderlineInputBorder(),
|
|
||||||
),
|
|
||||||
onTapOutside: (_) =>
|
|
||||||
FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
).padding(horizontal: 24),
|
|
||||||
if (controller.mode == 'articles') const Gap(4),
|
|
||||||
if (controller.mode == 'articles')
|
|
||||||
TextField(
|
TextField(
|
||||||
controller: controller.descriptionController,
|
controller: controller.titleController,
|
||||||
maxLines: null,
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'fieldPostDescription'.tr(),
|
labelText: 'fieldPostTitle'.tr(),
|
||||||
border: UnderlineInputBorder(),
|
border: UnderlineInputBorder(),
|
||||||
),
|
),
|
||||||
onTapOutside: (_) =>
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
).padding(horizontal: 24),
|
).padding(horizontal: 24),
|
||||||
const Gap(4),
|
const Gap(4),
|
||||||
PostTagsField(
|
PostTagsField(
|
||||||
@ -133,8 +122,7 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
helperMaxLines: 2,
|
helperMaxLines: 2,
|
||||||
border: UnderlineInputBorder(),
|
border: UnderlineInputBorder(),
|
||||||
),
|
),
|
||||||
onTapOutside: (_) =>
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
).padding(horizontal: 24),
|
).padding(horizontal: 24),
|
||||||
const Gap(12),
|
const Gap(12),
|
||||||
ListTile(
|
ListTile(
|
||||||
@ -182,8 +170,7 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
leading: Icon(Symbols.person),
|
leading: Icon(Symbols.person),
|
||||||
trailing: Icon(Symbols.chevron_right),
|
trailing: Icon(Symbols.chevron_right),
|
||||||
title: Text('postVisibleUsers').tr(),
|
title: Text('postVisibleUsers').tr(),
|
||||||
subtitle: Text('postSelectedUsers')
|
subtitle: Text('postSelectedUsers').plural(controller.visibleUsers.length),
|
||||||
.plural(controller.visibleUsers.length),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_selectVisibleUser(context);
|
_selectVisibleUser(context);
|
||||||
},
|
},
|
||||||
@ -194,8 +181,7 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
leading: Icon(Symbols.person),
|
leading: Icon(Symbols.person),
|
||||||
trailing: Icon(Symbols.chevron_right),
|
trailing: Icon(Symbols.chevron_right),
|
||||||
title: Text('postInvisibleUsers').tr(),
|
title: Text('postInvisibleUsers').tr(),
|
||||||
subtitle: Text('postSelectedUsers')
|
subtitle: Text('postSelectedUsers').plural(controller.invisibleUsers.length),
|
||||||
.plural(controller.invisibleUsers.length),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_selectInvisibleUser(context);
|
_selectInvisibleUser(context);
|
||||||
},
|
},
|
||||||
@ -204,9 +190,7 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
leading: const Icon(Symbols.event_available),
|
leading: const Icon(Symbols.event_available),
|
||||||
title: Text('postPublishedAt').tr(),
|
title: Text('postPublishedAt').tr(),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
controller.publishedAt != null
|
controller.publishedAt != null ? dateFormatter.format(controller.publishedAt!) : 'unset'.tr(),
|
||||||
? dateFormatter.format(controller.publishedAt!)
|
|
||||||
: 'unset'.tr(),
|
|
||||||
),
|
),
|
||||||
trailing: controller.publishedAt != null
|
trailing: controller.publishedAt != null
|
||||||
? IconButton(
|
? IconButton(
|
||||||
@ -230,9 +214,7 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
leading: const Icon(Symbols.event_busy),
|
leading: const Icon(Symbols.event_busy),
|
||||||
title: Text('postPublishedUntil').tr(),
|
title: Text('postPublishedUntil').tr(),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
controller.publishedUntil != null
|
controller.publishedUntil != null ? dateFormatter.format(controller.publishedUntil!) : 'unset'.tr(),
|
||||||
? dateFormatter.format(controller.publishedUntil!)
|
|
||||||
: 'unset'.tr(),
|
|
||||||
),
|
),
|
||||||
trailing: controller.publishedUntil != null
|
trailing: controller.publishedUntil != null
|
||||||
? IconButton(
|
? IconButton(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user