⬆️ Support new attachments system

This commit is contained in:
2024-08-18 22:51:52 +08:00
parent 98749f42c0
commit 49f73f5f04
19 changed files with 154 additions and 151 deletions

View File

@ -24,7 +24,6 @@ class AccountAvatar extends StatelessWidget {
if (content is String) {
direct = content.startsWith('http');
if (!isEmpty) isEmpty = content.isEmpty;
if (!isEmpty) isEmpty = content.endsWith('/attachments/0');
}
final url = direct

View File

@ -16,10 +16,12 @@ class AttachmentAttrEditorDialog extends StatefulWidget {
});
@override
State<AttachmentAttrEditorDialog> createState() => _AttachmentAttrEditorDialogState();
State<AttachmentAttrEditorDialog> createState() =>
_AttachmentAttrEditorDialogState();
}
class _AttachmentAttrEditorDialogState extends State<AttachmentAttrEditorDialog> {
class _AttachmentAttrEditorDialogState
extends State<AttachmentAttrEditorDialog> {
final _altController = TextEditingController();
bool _isBusy = false;
@ -33,7 +35,6 @@ class _AttachmentAttrEditorDialogState extends State<AttachmentAttrEditorDialog>
final resp = await provider.updateAttachment(
widget.item.id,
_altController.value.text,
widget.item.usage,
isMature: _isMature,
);
@ -109,7 +110,7 @@ class _AttachmentAttrEditorDialogState extends State<AttachmentAttrEditorDialog>
TextButton(
style: TextButton.styleFrom(
foregroundColor:
Theme.of(context).colorScheme.onSurfaceVariant),
Theme.of(context).colorScheme.onSurfaceVariant),
onPressed: () => Navigator.pop(context),
child: Text('cancel'.tr),
),

View File

@ -22,19 +22,19 @@ import 'package:solian/widgets/attachments/attachment_attr_editor.dart';
import 'package:solian/widgets/attachments/attachment_fullscreen.dart';
class AttachmentEditorPopup extends StatefulWidget {
final String usage;
final String pool;
final bool singleMode;
final bool imageOnly;
final bool autoUpload;
final double? imageMaxWidth;
final double? imageMaxHeight;
final List<int>? initialAttachments;
final void Function(int) onAdd;
final void Function(int) onRemove;
final List<String>? initialAttachments;
final void Function(String) onAdd;
final void Function(String) onRemove;
const AttachmentEditorPopup({
super.key,
required this.usage,
required this.pool,
required this.onAdd,
required this.onRemove,
this.singleMode = false,
@ -73,7 +73,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
_enqueueTaskBatch(medias.map((x) {
final file = File(x.path);
return AttachmentUploadTask(file: file, usage: widget.usage);
return AttachmentUploadTask(file: file, usage: widget.pool);
}));
} else {
final media = await _imagePicker.pickMedia(
@ -83,7 +83,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
if (media == null) return;
_enqueueTask(
AttachmentUploadTask(file: File(media.path), usage: widget.usage),
AttachmentUploadTask(file: File(media.path), usage: widget.pool),
);
}
}
@ -97,7 +97,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
final file = File(media.path);
_enqueueTask(
AttachmentUploadTask(file: file, usage: widget.usage),
AttachmentUploadTask(file: file, usage: widget.pool),
);
}
@ -113,7 +113,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
List<File> files = result.paths.map((path) => File(path!)).toList();
_enqueueTaskBatch(files.map((x) {
return AttachmentUploadTask(file: x, usage: widget.usage);
return AttachmentUploadTask(file: x, usage: widget.pool);
}));
}
@ -131,7 +131,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
final file = File(media.path);
_enqueueTask(
AttachmentUploadTask(file: file, usage: widget.usage),
AttachmentUploadTask(file: file, usage: widget.pool),
);
}
@ -181,13 +181,11 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
WidgetsBinding.instance.addPostFrameCallback((_) => controller.dispose());
if (input == null || input.isEmpty) return;
final value = int.tryParse(input);
if (value == null) return;
final AttachmentProvider attach = Get.find();
final result = await attach.getMetadata(value);
final result = await attach.getMetadata(input);
if (result != null) {
widget.onAdd(result.id);
widget.onAdd(result.rid);
setState(() => _attachments.add(result));
if (widget.singleMode) Navigator.pop(context);
}
@ -202,11 +200,11 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
_uploadController.uploadAttachmentWithCallback(
data,
'Pasted Image',
widget.usage,
widget.pool,
null,
(item) {
if (item == null) return;
widget.onAdd(item.id);
widget.onAdd(item.rid);
if (mounted) {
setState(() => _attachments.add(item));
if (widget.singleMode) Navigator.pop(context);
@ -413,11 +411,11 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
: () {
_uploadController
.performSingleTask(index)
.then((r) {
if (r == null) return;
widget.onAdd(r.id);
.then((out) {
if (out == null) return;
widget.onAdd(out.rid);
if (mounted) {
setState(() => _attachments.add(r));
setState(() => _attachments.add(out));
if (widget.singleMode) {
Navigator.pop(context);
}
@ -515,7 +513,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
),
onTap: () {
_deleteAttachment(element).then((_) {
widget.onRemove(element.id);
widget.onRemove(element.rid);
setState(() => _attachments.removeAt(index));
});
},
@ -529,7 +527,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
),
),
onTap: () {
widget.onRemove(element.id);
widget.onRemove(element.rid);
setState(() => _attachments.removeAt(index));
},
),
@ -560,7 +558,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
void _startUploading() {
_uploadController.performUploadQueue(onData: (r) {
widget.onAdd(r.id);
widget.onAdd(r.rid);
if (mounted) {
setState(() => _attachments.add(r));
if (widget.singleMode) Navigator.pop(context);
@ -584,7 +582,7 @@ class _AttachmentEditorPopupState extends State<AttachmentEditorPopup> {
if (_uploadController.isUploading.value) return;
_enqueueTaskBatch(detail.files.map((x) {
final file = File(x.path);
return AttachmentUploadTask(file: file, usage: widget.usage);
return AttachmentUploadTask(file: file, usage: widget.pool);
}));
},
child: Column(

View File

@ -67,9 +67,10 @@ class _AttachmentFullScreenState extends State<AttachmentFullScreen> {
Future<void> _saveToAlbum() async {
final url = ServiceFinder.buildUrl(
'files',
'/attachments/${widget.item.id}',
'/attachments/${widget.item.rid}',
);
print(url);
if (PlatformInfo.isWeb || PlatformInfo.isDesktop) {
await launchUrlString(url);
return;
@ -258,7 +259,7 @@ class _AttachmentFullScreenState extends State<AttachmentFullScreen> {
spacing: 6,
children: [
Text(
'#${widget.item.id}',
'#${widget.item.rid}',
style: metaTextStyle,
),
if (widget.item.metadata?['width'] != null &&

View File

@ -91,7 +91,7 @@ class _AttachmentItemState extends State<AttachmentItem> {
launchUrlString(
ServiceFinder.buildUrl(
'files',
'/attachments/${widget.item.id}',
'/attachments/${widget.item.rid}',
),
);
},
@ -135,7 +135,7 @@ class _AttachmentItemImage extends StatelessWidget {
fit: fit,
imageUrl: ServiceFinder.buildUrl(
'files',
'/attachments/${item.id}',
'/attachments/${item.rid}',
),
progressIndicatorBuilder: (context, url, downloadProgress) {
return Center(
@ -240,7 +240,7 @@ class _AttachmentItemVideoState extends State<_AttachmentItemVideo> {
final ratio = widget.item.metadata?['ratio'] ?? 16 / 9;
_playerController = VideoPlayerController.networkUrl(
Uri.parse(
ServiceFinder.buildUrl('files', '/attachments/${widget.item.id}'),
ServiceFinder.buildUrl('files', '/attachments/${widget.item.rid}'),
),
);
_playerController!.initialize();

View File

@ -14,7 +14,7 @@ import 'package:solian/widgets/sized_container.dart';
class AttachmentList extends StatefulWidget {
final String parentId;
final List<int> attachmentsId;
final List<String> attachmentsId;
final bool isGrid;
final bool isForceGrid;
final bool autoload;
@ -334,13 +334,13 @@ class AttachmentListEntry extends StatelessWidget {
}
class AttachmentSelfContainedEntry extends StatefulWidget {
final int id;
final String rid;
final String parentId;
final bool isDense;
const AttachmentSelfContainedEntry({
super.key,
required this.id,
required this.rid,
required this.parentId,
this.isDense = false,
});
@ -359,10 +359,12 @@ class _AttachmentSelfContainedEntryState
final AttachmentProvider attachments = Get.find();
return FutureBuilder(
future: attachments.getMetadata(widget.id),
future: attachments.getMetadata(widget.rid),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Text('Loading...');
return const Center(
child: CircularProgressIndicator(),
);
}
return AttachmentListEntry(

View File

@ -39,8 +39,8 @@ class ChatEvent extends StatelessWidget {
Widget _buildAttachment(BuildContext context, {bool isMinimal = false}) {
final attachments = item.body['attachments'] != null
? List<int>.from(item.body['attachments'].map((x) => x))
: List<int>.empty();
? List<String>.from(item.body['attachments'].map((x) => x))
: List<String>.empty();
if (attachments.isEmpty) return const SizedBox();

View File

@ -59,7 +59,7 @@ class _ChatMessageInputState extends State<ChatMessageInput> {
final TextEditingController _textController = TextEditingController();
final FocusNode _focusNode = FocusNode();
final List<int> _attachments = List.empty(growable: true);
final List<String> _attachments = List.empty(growable: true);
Event? _editTo;
Event? _replyTo;
@ -68,7 +68,7 @@ class _ChatMessageInputState extends State<ChatMessageInput> {
showModalBottomSheet(
context: context,
builder: (context) => AttachmentEditorPopup(
usage: 'm.attachment',
pool: 'messaging',
initialAttachments: _attachments,
onAdd: (value) {
setState(() {
@ -103,7 +103,7 @@ class _ChatMessageInputState extends State<ChatMessageInput> {
final AttachmentUploaderController uploader = Get.find();
if (uploader.queueOfUpload.any(
((x) => x.usage == 'm.attachment' && x.isUploading),
((x) => x.isUploading),
)) {
context.showErrorDialog('attachmentUploadInProgress'.tr);
return;

View File

@ -131,7 +131,7 @@ class MarkdownTextContent extends StatelessWidget {
child: AttachmentSelfContainedEntry(
isDense: true,
parentId: parentId,
id: int.parse(segments[1]),
rid: segments[1],
),
),
).paddingSymmetric(vertical: 4);

View File

@ -20,7 +20,7 @@ class _PostEditorThumbnailDialogState extends State<PostEditorThumbnailDialog> {
showModalBottomSheet(
context: context,
builder: (context) => AttachmentEditorPopup(
usage: 'i.attachment',
pool: 'interactive',
singleMode: true,
imageOnly: true,
autoUpload: true,
@ -84,8 +84,7 @@ class _PostEditorThumbnailDialogState extends State<PostEditorThumbnailDialog> {
actions: [
TextButton(
onPressed: () {
widget.controller.thumbnail.value =
int.tryParse(_attachmentController.text);
widget.controller.thumbnail.value = _attachmentController.text;
Navigator.pop(context);
},
child: Text('confirm'.tr),

View File

@ -87,7 +87,7 @@ class _PostItemState extends State<PostItem> {
child: AspectRatio(
aspectRatio: 16 / 9,
child: AttachmentSelfContainedEntry(
id: widget.item.body['thumbnail'],
rid: widget.item.body['thumbnail'],
parentId: 'p${item.id}-thumbnail',
),
),
@ -292,8 +292,8 @@ class _PostItemState extends State<PostItem> {
@override
Widget build(BuildContext context) {
final List<int> attachments = item.body['attachments'] is List
? item.body['attachments']?.cast<int>()
final List<String> attachments = item.body['attachments'] is List
? item.body['attachments']?.cast<String>()
: List.empty();
final hasAttachment = attachments.isNotEmpty;

View File

@ -29,7 +29,7 @@ class _StickerUploadDialogState extends State<StickerUploadDialog> {
showModalBottomSheet(
context: context,
builder: (context) => AttachmentEditorPopup(
usage: 'sticker',
pool: 'sticker',
singleMode: true,
imageOnly: true,
autoUpload: true,