✨ Setting of attachment thumbnail
This commit is contained in:
@ -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);
|
||||
|
@ -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));
|
||||
},
|
||||
),
|
||||
],
|
||||
|
144
lib/widgets/attachments/attachment_editor_thumbnail.dart
Normal file
144
lib/widgets/attachments/attachment_editor_thumbnail.dart
Normal 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),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user