Setting of attachment thumbnail

This commit is contained in:
2024-09-10 21:36:10 +08:00
parent 1210cda998
commit c5a975b5ed
7 changed files with 218 additions and 34 deletions

View File

@ -37,6 +37,7 @@ class _AttachmentAttrEditorDialogState
widget.item.id,
_altController.value.text,
isMature: _isMature,
metadata: widget.item.metadata ?? {},
);
Get.find<AttachmentProvider>().clearCache(id: widget.item.rid);

View File

@ -20,6 +20,7 @@ import 'package:solian/providers/attachment_uploader.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/providers/content/attachment.dart';
import 'package:solian/widgets/attachments/attachment_attr_editor.dart';
import 'package:solian/widgets/attachments/attachment_editor_thumbnail.dart';
import 'package:solian/widgets/attachments/attachment_fullscreen.dart';
class AttachmentEditorPopup extends StatefulWidget {
@ -264,6 +265,21 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
);
}
void _showAttachmentThumbnailEditor(Attachment element, int idx) {
showDialog(
context: context,
builder: (context) => AttachmentEditorThumbnailDialog(
item: element,
pool: widget.pool,
initialItem: element.metadata?['thumbnail'],
onUpdate: (value) {
_attachments[idx]!.metadata ??= {};
_attachments[idx]!.metadata!['thumbnail'] = value;
},
),
);
}
void _showEdit(Attachment element, int index) {
showDialog(
context: context,
@ -455,11 +471,12 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
);
}
Widget _buildListEntry(Attachment element, int index) {
Widget _buildListEntry(Attachment element, int idx) {
var fileType = element.mimetype.split('/').firstOrNull;
fileType ??= 'unknown';
final canBePreview = fileType.toLowerCase() == 'image';
final canHasThumbnail = fileType.toLowerCase() != 'image';
return Container(
padding: const EdgeInsets.only(left: 16, right: 8, bottom: 16),
@ -491,14 +508,23 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
],
),
),
IconButton(
color: Colors.teal,
icon: const Icon(Icons.preview),
visualDensity: const VisualDensity(horizontal: -4),
onPressed: canBePreview
? () => _showAttachmentPreview(element)
: null,
),
if (canBePreview)
IconButton(
color: Colors.teal,
icon: const Icon(Icons.preview),
visualDensity: const VisualDensity(horizontal: -4),
onPressed: () => _showAttachmentPreview(element),
),
if (canHasThumbnail)
IconButton(
color: Colors.teal,
icon: const Icon(Icons.add_photo_alternate),
visualDensity: const VisualDensity(horizontal: -4),
onPressed: () => _showAttachmentThumbnailEditor(
element,
idx,
),
),
PopupMenuButton(
icon: const Icon(Icons.more_horiz),
iconColor: Theme.of(context).colorScheme.primary,
@ -514,7 +540,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
horizontal: 8,
),
),
onTap: () => _showEdit(element, index),
onTap: () => _showEdit(element, idx),
),
PopupMenuItem(
child: ListTile(
@ -527,7 +553,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
onTap: () {
_deleteAttachment(element).then((_) {
widget.onRemove(element.rid);
setState(() => _attachments.removeAt(index));
setState(() => _attachments.removeAt(idx));
});
},
),
@ -541,7 +567,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
),
onTap: () {
widget.onRemove(element.rid);
setState(() => _attachments.removeAt(index));
setState(() => _attachments.removeAt(idx));
},
),
],

View File

@ -0,0 +1,144 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/exts.dart';
import 'package:solian/models/attachment.dart';
import 'package:solian/providers/content/attachment.dart';
import 'package:solian/widgets/attachments/attachment_editor.dart';
class AttachmentEditorThumbnailDialog extends StatefulWidget {
final Attachment item;
final String pool;
final String? initialItem;
final Function(String? id) onUpdate;
const AttachmentEditorThumbnailDialog({
super.key,
required this.item,
required this.pool,
required this.initialItem,
required this.onUpdate,
});
@override
State<AttachmentEditorThumbnailDialog> createState() =>
_AttachmentEditorThumbnailDialogState();
}
class _AttachmentEditorThumbnailDialogState
extends State<AttachmentEditorThumbnailDialog> {
bool _isLoading = false;
final TextEditingController _attachmentController = TextEditingController();
void _promptUploadNewAttachment() {
showModalBottomSheet(
context: context,
builder: (context) => AttachmentEditorPopup(
pool: widget.pool,
singleMode: true,
imageOnly: true,
autoUpload: true,
onAdd: (value) {
widget.onUpdate(value);
_attachmentController.text = value;
},
initialAttachments: const [],
onRemove: (_) {},
),
);
}
Future<void> _updateAttachment() async {
setState(() => _isLoading = true);
final AttachmentProvider attach = Get.find();
widget.item.metadata ??= {};
widget.item.metadata!['thumbnail'] = _attachmentController.text;
try {
await attach.updateAttachment(
widget.item.id,
widget.item.alt,
isMature: widget.item.isMature,
metadata: widget.item.metadata!,
);
Get.find<AttachmentProvider>().clearCache(id: widget.item.rid);
} catch (e) {
context.showErrorDialog(e);
} finally {
setState(() => _isLoading = false);
}
}
@override
void initState() {
if (widget.initialItem != null) {
_attachmentController.text = widget.initialItem!;
}
super.initState();
}
@override
void dispose() {
_attachmentController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('postThumbnail'.tr),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Card(
margin: EdgeInsets.zero,
child: ListTile(
title: Text('postThumbnailAttachmentNew'.tr),
contentPadding: const EdgeInsets.only(left: 12, right: 9),
trailing: const Icon(Icons.chevron_right),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
onTap: () {
_promptUploadNewAttachment();
},
),
),
const Row(children: <Widget>[
Expanded(child: Divider()),
Text('OR'),
Expanded(child: Divider()),
]).paddingOnly(top: 12, bottom: 16, left: 16, right: 16),
TextField(
controller: _attachmentController,
decoration: InputDecoration(
isDense: true,
border: const OutlineInputBorder(),
prefixText: '#',
labelText: 'postThumbnailAttachment'.tr,
),
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
),
],
),
actions: [
TextButton(
onPressed: _isLoading
? null
: () {
_updateAttachment().then((_) {
widget.onUpdate(_attachmentController.text);
if (mounted) {
Navigator.pop(context);
}
});
},
child: Text('confirm'.tr),
),
],
);
}
}

View File

@ -299,14 +299,14 @@ class _PostItemState extends State<PostItem> {
return AttachmentList(
parentId: widget.item.id.toString(),
attachmentsId: attachments,
autoload: true,
autoload: false,
isGrid: true,
).paddingOnly(left: 36, top: 4, bottom: 4);
} else if (attachments.length > 1) {
return AttachmentList(
parentId: widget.item.id.toString(),
attachmentsId: attachments,
autoload: true,
autoload: false,
isColumn: true,
).paddingOnly(left: 60, right: 24);
} else {
@ -314,7 +314,7 @@ class _PostItemState extends State<PostItem> {
flatMaxHeight: MediaQuery.of(context).size.width,
parentId: widget.item.id.toString(),
attachmentsId: attachments,
autoload: true,
autoload: false,
);
}
}