♻️ Refactor the way to set thumbnail
This commit is contained in:
parent
95f257c47a
commit
30184d08b1
@ -670,5 +670,6 @@
|
|||||||
"attachmentBillingUploaded": "Used space",
|
"attachmentBillingUploaded": "Used space",
|
||||||
"attachmentBillingDiscount": "Free space",
|
"attachmentBillingDiscount": "Free space",
|
||||||
"attachmentBillingRatio": "Usage",
|
"attachmentBillingRatio": "Usage",
|
||||||
"attachmentBillingHint": "Sliding Window Pricing®\nFees will only apply if the size of the file uploaded within 24 hours exceeds the free space."
|
"attachmentBillingHint": "Sliding Window Pricing®\nFees will only apply if the size of the file uploaded within 24 hours exceeds the free space.",
|
||||||
|
"postThumbnail": "Post Thumbnail"
|
||||||
}
|
}
|
||||||
|
@ -668,5 +668,6 @@
|
|||||||
},
|
},
|
||||||
"attachmentBillingUploaded": "已占用的字节数",
|
"attachmentBillingUploaded": "已占用的字节数",
|
||||||
"attachmentBillingDiscount": "免费的字节数",
|
"attachmentBillingDiscount": "免费的字节数",
|
||||||
"attachmentBillingHint": "滑动窗口计价®\n在24小时内上传的文件大小超出免费空间才会适用扣费。"
|
"attachmentBillingHint": "滑动窗口计价®\n在24小时内上传的文件大小超出免费空间才会适用扣费。",
|
||||||
|
"postThumbnail": "帖子缩略图"
|
||||||
}
|
}
|
||||||
|
@ -668,5 +668,6 @@
|
|||||||
},
|
},
|
||||||
"attachmentBillingUploaded": "已佔用的字節數",
|
"attachmentBillingUploaded": "已佔用的字節數",
|
||||||
"attachmentBillingDiscount": "免費的字節數",
|
"attachmentBillingDiscount": "免費的字節數",
|
||||||
"attachmentBillingHint": "滑動窗口計價®\n在24小時內上傳的文件大小超出免費空間才會適用扣費。"
|
"attachmentBillingHint": "滑動窗口計價®\n在24小時內上傳的文件大小超出免費空間才會適用扣費。",
|
||||||
|
"postThumbnail": "帖子縮略圖"
|
||||||
}
|
}
|
||||||
|
@ -668,5 +668,6 @@
|
|||||||
},
|
},
|
||||||
"attachmentBillingUploaded": "已佔用的字節數",
|
"attachmentBillingUploaded": "已佔用的字節數",
|
||||||
"attachmentBillingDiscount": "免費的字節數",
|
"attachmentBillingDiscount": "免費的字節數",
|
||||||
"attachmentBillingHint": "滑動窗口計價®\n在24小時內上傳的文件大小超出免費空間才會適用扣費。"
|
"attachmentBillingHint": "滑動窗口計價®\n在24小時內上傳的文件大小超出免費空間才會適用扣費。",
|
||||||
|
"postThumbnail": "帖子縮略圖"
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,8 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
ContentInsertionConfiguration get contentInsertionConfiguration => ContentInsertionConfiguration(
|
ContentInsertionConfiguration get contentInsertionConfiguration => ContentInsertionConfiguration(
|
||||||
onContentInserted: (KeyboardInsertedContent content) {
|
onContentInserted: (KeyboardInsertedContent content) {
|
||||||
if (content.hasData) {
|
if (content.hasData) {
|
||||||
addAttachments([PostWriteMedia.fromBytes(content.data!, 'attachmentInsertedImage'.tr(), SnMediaType.image)]);
|
addAttachments(
|
||||||
|
[PostWriteMedia.fromBytes(content.data!, 'attachmentInsertedImage'.tr(), SnMediaType.image)]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -571,17 +572,8 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setThumbnail(int? idx) {
|
void setThumbnail(SnAttachment? value) {
|
||||||
if (idx == null) {
|
thumbnail = value == null ? null : PostWriteMedia(value);
|
||||||
attachments.add(thumbnail!);
|
|
||||||
thumbnail = null;
|
|
||||||
} else {
|
|
||||||
if (thumbnail != null) {
|
|
||||||
attachments.add(thumbnail!);
|
|
||||||
}
|
|
||||||
thumbnail = attachments[idx];
|
|
||||||
attachments.removeAt(idx);
|
|
||||||
}
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +161,20 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showThumbnailEditorDialog() async {
|
||||||
|
final attachment = await showDialog<SnAttachment?>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AttachmentInputDialog(
|
||||||
|
title: 'postThumbnail'.tr(),
|
||||||
|
pool: 'interactive',
|
||||||
|
mediaType: SnMediaType.image,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (!context.mounted) return;
|
||||||
|
if (attachment == null) return;
|
||||||
|
_writeController.setThumbnail(attachment);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_writeController.dispose();
|
_writeController.dispose();
|
||||||
@ -344,15 +358,11 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: PostMediaPendingList(
|
child: PostMediaPendingList(
|
||||||
thumbnail: _writeController.thumbnail,
|
|
||||||
attachments: _writeController.attachments,
|
attachments: _writeController.attachments,
|
||||||
isBusy: _writeController.isBusy,
|
isBusy: _writeController.isBusy,
|
||||||
onUpload: (int idx) async {
|
onUpload: (int idx) async {
|
||||||
await _writeController.uploadSingleAttachment(context, idx);
|
await _writeController.uploadSingleAttachment(context, idx);
|
||||||
},
|
},
|
||||||
onPostSetThumbnail: (int? idx) {
|
|
||||||
_writeController.setThumbnail(idx);
|
|
||||||
},
|
|
||||||
onInsertLink: (int idx) async {
|
onInsertLink: (int idx) async {
|
||||||
_writeController.contentController.text +=
|
_writeController.contentController.text +=
|
||||||
'\n';
|
'\n';
|
||||||
@ -453,6 +463,22 @@ class _PostEditorScreenState extends State<PostEditorScreen> {
|
|||||||
_showPollEditorDialog();
|
_showPollEditorDialog();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (_writeController.mode == 'articles')
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Symbols.image, color: Theme.of(context).colorScheme.primary),
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: _writeController.thumbnail == null
|
||||||
|
? null
|
||||||
|
: WidgetStatePropertyAll(Theme.of(context).colorScheme.surfaceContainer),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
if (_writeController.thumbnail != null) {
|
||||||
|
_writeController.setThumbnail(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_showThumbnailEditorDialog();
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -668,7 +694,24 @@ class _PostArticleEditor extends StatelessWidget {
|
|||||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
contentInsertionConfiguration: controller.contentInsertionConfiguration,
|
contentInsertionConfiguration: controller.contentInsertionConfiguration,
|
||||||
).padding(horizontal: 16),
|
).padding(horizontal: 16),
|
||||||
const Gap(4),
|
if (controller.thumbnail != null)
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.only(left: 12, right: 12, top: 8, bottom: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
border: Border.all(color: Theme.of(context).dividerColor),
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 16 / 9,
|
||||||
|
child: AttachmentItem(
|
||||||
|
data: controller.thumbnail!.attachment!,
|
||||||
|
heroTag: "post-editor-thumbnail-preview",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (ResponsiveBreakpoints.of(context).largerThan(MOBILE)) {
|
if (ResponsiveBreakpoints.of(context).largerThan(MOBILE)) {
|
||||||
|
@ -30,25 +30,21 @@ import 'package:surface/widgets/universal_image.dart';
|
|||||||
import '../attachment/pending_attachment_compress.dart';
|
import '../attachment/pending_attachment_compress.dart';
|
||||||
|
|
||||||
class PostMediaPendingList extends StatelessWidget {
|
class PostMediaPendingList extends StatelessWidget {
|
||||||
final PostWriteMedia? thumbnail;
|
|
||||||
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 Future<void> Function(int idx)? onUpload;
|
final Future<void> Function(int idx)? onUpload;
|
||||||
final void Function(int? idx)? onPostSetThumbnail;
|
|
||||||
final void Function(int idx)? onInsertLink;
|
final void Function(int idx)? onInsertLink;
|
||||||
final void Function(bool state)? onUpdateBusy;
|
final void Function(bool state)? onUpdateBusy;
|
||||||
|
|
||||||
const PostMediaPendingList({
|
const PostMediaPendingList({
|
||||||
super.key,
|
super.key,
|
||||||
this.thumbnail,
|
|
||||||
required this.attachments,
|
required this.attachments,
|
||||||
required this.isBusy,
|
required this.isBusy,
|
||||||
this.onUpdate,
|
this.onUpdate,
|
||||||
this.onRemove,
|
this.onRemove,
|
||||||
this.onUpload,
|
this.onUpload,
|
||||||
this.onPostSetThumbnail,
|
|
||||||
this.onInsertLink,
|
this.onInsertLink,
|
||||||
this.onUpdateBusy,
|
this.onUpdateBusy,
|
||||||
});
|
});
|
||||||
@ -116,7 +112,7 @@ class PostMediaPendingList extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _deleteAttachment(BuildContext context, int idx) async {
|
Future<void> _deleteAttachment(BuildContext context, int idx) async {
|
||||||
final media = idx == -1 ? thumbnail! : attachments[idx];
|
final media = attachments[idx];
|
||||||
if (media.attachment == null) return;
|
if (media.attachment == null) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -212,22 +208,6 @@ class PostMediaPendingList extends StatelessWidget {
|
|||||||
onSelected: () {
|
onSelected: () {
|
||||||
onUpload!(idx);
|
onUpload!(idx);
|
||||||
}),
|
}),
|
||||||
if (media.attachment != null && media.type == SnMediaType.image && onPostSetThumbnail != null && idx != -1)
|
|
||||||
MenuItem(
|
|
||||||
label: 'attachmentSetAsPostThumbnail'.tr(),
|
|
||||||
icon: Symbols.gallery_thumbnail,
|
|
||||||
onSelected: () {
|
|
||||||
onPostSetThumbnail!(idx);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
else if (media.attachment != null && media.type == SnMediaType.image && onPostSetThumbnail != null)
|
|
||||||
MenuItem(
|
|
||||||
label: 'attachmentUnsetAsPostThumbnail'.tr(),
|
|
||||||
icon: Symbols.cancel,
|
|
||||||
onSelected: () {
|
|
||||||
onPostSetThumbnail!(null);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (media.attachment != null && onInsertLink != null)
|
if (media.attachment != null && onInsertLink != null)
|
||||||
MenuItem(
|
MenuItem(
|
||||||
label: 'attachmentInsertLink'.tr(),
|
label: 'attachmentInsertLink'.tr(),
|
||||||
@ -291,23 +271,9 @@ class PostMediaPendingList extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
constraints: const BoxConstraints(maxHeight: 120),
|
constraints: const BoxConstraints(maxHeight: 120),
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Gap(16),
|
|
||||||
if (thumbnail != null)
|
|
||||||
ContextMenuArea(
|
|
||||||
contextMenu: _createContextMenu(context, -1, thumbnail!),
|
|
||||||
child: _PostMediaPendingItem(media: thumbnail!),
|
|
||||||
),
|
|
||||||
if (thumbnail != null)
|
|
||||||
const VerticalDivider(width: 1, thickness: 1).padding(
|
|
||||||
horizontal: 12,
|
|
||||||
vertical: 16,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
padding: const EdgeInsets.only(right: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
separatorBuilder: (context, index) => const Gap(8),
|
separatorBuilder: (context, index) => const Gap(8),
|
||||||
itemCount: attachments.length,
|
itemCount: attachments.length,
|
||||||
itemBuilder: (context, idx) {
|
itemBuilder: (context, idx) {
|
||||||
@ -318,9 +284,6 @@ class PostMediaPendingList extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user