💄 Optimize attachment in article

This commit is contained in:
2025-08-17 13:02:52 +08:00
parent 5d4b896f70
commit 466e354679
4 changed files with 103 additions and 76 deletions

View File

@@ -89,6 +89,9 @@ class ArticleComposeScreen extends HookConsumerWidget {
}, [state]);
final showPreview = useState(false);
final isAttachmentsExpanded = useState(
true,
); // New state for attachments section
// Initialize publisher once when data is available
useEffect(() {
@@ -297,71 +300,86 @@ class ArticleComposeScreen extends HookConsumerWidget {
valueListenable: state.attachments,
builder: (context, attachments, _) {
if (attachments.isEmpty) return const SizedBox.shrink();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Gap(16),
Text(
'articleAttachmentHint'.tr(),
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
).padding(bottom: 8),
ValueListenableBuilder<Map<int, double>>(
valueListenable: state.attachmentProgress,
builder: (context, progressMap, _) {
return Wrap(
runSpacing: 8,
spacing: 8,
children: [
for (var idx = 0; idx < attachments.length; idx++)
SizedBox(
width: 280,
height: 280,
child: AttachmentPreview(
item: attachments[idx],
progress: progressMap[idx],
onRequestUpload:
() => ComposeLogic.uploadAttachment(
ref,
state,
idx,
),
onUpdate:
(value) =>
ComposeLogic.updateAttachment(
state,
value,
idx,
),
onDelete:
() => ComposeLogic.deleteAttachment(
ref,
state,
idx,
),
onMove: (delta) {
state
.attachments
.value = ComposeLogic.moveAttachment(
state.attachments.value,
idx,
delta,
);
},
onInsert:
() => ComposeLogic.insertAttachment(
ref,
state,
idx,
),
),
),
],
);
},
return Theme(
data: Theme.of(
context,
).copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
initiallyExpanded: isAttachmentsExpanded.value,
onExpansionChanged: (expanded) {
isAttachmentsExpanded.value = expanded;
},
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('attachments').tr(),
Text(
'articleAttachmentHint'.tr(),
style: Theme.of(
context,
).textTheme.bodySmall?.copyWith(
color:
Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
],
),
],
children: [
ValueListenableBuilder<Map<int, double>>(
valueListenable: state.attachmentProgress,
builder: (context, progressMap, _) {
return Wrap(
runSpacing: 8,
spacing: 8,
children: [
for (
var idx = 0;
idx < attachments.length;
idx++
)
SizedBox(
width: 180,
height: 180,
child: AttachmentPreview(
isCompact: true,
item: attachments[idx],
progress: progressMap[idx],
onRequestUpload:
() => ComposeLogic.uploadAttachment(
ref,
state,
idx,
),
onUpdate:
(value) =>
ComposeLogic.updateAttachment(
state,
value,
idx,
),
onDelete:
() => ComposeLogic.deleteAttachment(
ref,
state,
idx,
),
onInsert:
() => ComposeLogic.insertAttachment(
ref,
state,
idx,
),
),
),
],
);
},
),
Gap(16),
],
),
);
},
),

View File

@@ -88,6 +88,7 @@ class AttachmentPreview extends HookConsumerWidget {
final Function? onInsert;
final Function(UniversalFile)? onUpdate;
final Function? onRequestUpload;
final bool isCompact;
const AttachmentPreview({
super.key,
@@ -98,6 +99,7 @@ class AttachmentPreview extends HookConsumerWidget {
this.onDelete,
this.onUpdate,
this.onInsert,
this.isCompact = false,
});
// GlobalKey for selector
@@ -458,11 +460,12 @@ class AttachmentPreview extends HookConsumerWidget {
size: 16,
color: Colors.white,
),
const Gap(8),
Text(
'On-cloud',
style: TextStyle(color: Colors.white),
),
if (!isCompact) const Gap(8),
if (!isCompact)
Text(
'attachmentOnCloud'.tr(),
style: TextStyle(color: Colors.white),
),
],
)
: Row(
@@ -473,11 +476,12 @@ class AttachmentPreview extends HookConsumerWidget {
size: 16,
color: Colors.white,
),
const Gap(8),
Text(
'On-device',
style: TextStyle(color: Colors.white),
),
if (!isCompact) const Gap(8),
if (!isCompact)
Text(
'attachmentOnDevice'.tr(),
style: TextStyle(color: Colors.white),
),
],
),
),