Better attachment preview progress

This commit is contained in:
2026-01-11 13:40:35 +08:00
parent 826238a374
commit b7d5aa5dfb
4 changed files with 272 additions and 272 deletions

View File

@@ -325,6 +325,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
isCompact: true,
item: attachments[idx],
progress: progressMap[idx],
isUploading: progressMap.containsKey(idx),
onRequestUpload: () async {
final config =
await showModalBottomSheet<

View File

@@ -458,6 +458,10 @@ class ChatInput extends HookConsumerWidget {
item: attachments[idx],
progress:
attachmentProgress['chat-upload']?[idx],
isUploading:
attachmentProgress['chat-upload']
?.containsKey(idx) ??
false,
onRequestUpload: () => onUploadAttachment(idx),
onDelete: () => onDeleteAttachment(idx),
onUpdate: (value) {

View File

@@ -14,13 +14,12 @@ import 'package:island/services/file_uploader.dart';
import 'package:island/utils/format.dart';
import 'package:island/widgets/alert.dart';
import 'package:island/widgets/content/cloud_files.dart';
import 'package:island/widgets/content/sensitive.dart';
import 'package:island/widgets/content/sheet.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:super_context_menu/super_context_menu.dart';
import 'sensitive.dart';
class SensitiveMarksSelector extends StatefulWidget {
final List<int> initial;
final ValueChanged<List<int>>? onChanged;
@@ -85,6 +84,7 @@ class SensitiveMarksSelectorState extends State<SensitiveMarksSelector> {
class AttachmentPreview extends HookConsumerWidget {
final UniversalFile item;
final double? progress;
final bool isUploading;
final Function(int)? onMove;
final Function? onDelete;
final Function? onInsert;
@@ -96,6 +96,7 @@ class AttachmentPreview extends HookConsumerWidget {
super.key,
required this.item,
this.progress,
this.isUploading = false,
this.onRequestUpload,
this.onMove,
this.onDelete,
@@ -125,8 +126,7 @@ class AttachmentPreview extends HookConsumerWidget {
context: context,
isScrollControlled: true,
useRootNavigator: true,
builder:
(context) => SheetScaffold(
builder: (context) => SheetScaffold(
heightFactor: 0.6,
titleText: 'rename'.tr(),
child: Column(
@@ -134,10 +134,7 @@ class AttachmentPreview extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 24,
),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 24),
child: TextField(
controller: nameController,
decoration: InputDecoration(
@@ -174,10 +171,7 @@ class AttachmentPreview extends HookConsumerWidget {
final newData = item.data;
newData.name = newName;
onUpdate?.call(
item.copyWith(
data: newData,
displayName: newName,
),
item.copyWith(data: newData, displayName: newName),
);
if (context.mounted) Navigator.pop(context);
} catch (err) {
@@ -205,8 +199,7 @@ class AttachmentPreview extends HookConsumerWidget {
await showModalBottomSheet(
context: context,
isScrollControlled: true,
builder:
(context) => SheetScaffold(
builder: (context) => SheetScaffold(
heightFactor: 0.6,
titleText: 'markAsSensitive'.tr(),
child: Column(
@@ -214,17 +207,13 @@ class AttachmentPreview extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 24,
),
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 24),
child: Column(
children: [
// Sensitive categories checklist
SensitiveMarksSelector(
key: _sensitiveSelectorKey,
initial:
(item.data.sensitiveMarks ?? [])
initial: (item.data.sensitiveMarks ?? [])
.map((e) => e as int)
.cast<int>()
.toList(),
@@ -253,8 +242,7 @@ class AttachmentPreview extends HookConsumerWidget {
showLoadingModal(context);
final apiClient = ref.watch(apiClientProvider);
// Use the current selections from stateful selector via GlobalKey
final selectorState =
_sensitiveSelectorKey.currentState;
final selectorState = _sensitiveSelectorKey.currentState;
final marks = selectorState?.current ?? <int>[];
await apiClient.put(
'/drive/files/${item.data.id}/marks',
@@ -284,8 +272,7 @@ class AttachmentPreview extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
var ratio =
item.isOnCloud
var ratio = item.isOnCloud
? (item.data.fileMeta?['ratio'] is num
? item.data.fileMeta!['ratio'].toDouble()
: 1.0)
@@ -387,7 +374,7 @@ class AttachmentPreview extends HookConsumerWidget {
return Placeholder();
},
),
if (progress != null)
if (isUploading && progress != null && (progress ?? 0) > 0)
Positioned.fill(
child: Container(
color: Colors.black.withOpacity(0.3),
@@ -399,15 +386,9 @@ class AttachmentPreview extends HookConsumerWidget {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (progress != null)
Text(
'${(progress! * 100).toStringAsFixed(2)}%',
style: TextStyle(color: Colors.white),
)
else
Text(
'uploading'.tr(),
style: TextStyle(color: Colors.white),
),
Gap(6),
Center(
@@ -417,6 +398,28 @@ class AttachmentPreview extends HookConsumerWidget {
),
),
),
if (isUploading && (progress == null || progress == 0))
Positioned.fill(
child: Container(
color: Colors.black.withOpacity(0.3),
padding: EdgeInsets.symmetric(
horizontal: 40,
vertical: 16,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'processing'.tr(),
style: TextStyle(color: Colors.white),
),
Gap(6),
Center(child: LinearProgressIndicator(value: null)),
],
),
),
),
],
),
).center(),
@@ -497,8 +500,9 @@ class AttachmentPreview extends HookConsumerWidget {
if (onRequestUpload != null)
InkWell(
borderRadius: BorderRadius.circular(8),
onTap:
item.isOnCloud ? null : () => onRequestUpload?.call(),
onTap: item.isOnCloud
? null
: () => onRequestUpload?.call(),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Container(
@@ -507,8 +511,7 @@ class AttachmentPreview extends HookConsumerWidget {
horizontal: 8,
vertical: 4,
),
child:
(item.isOnCloud)
child: (item.isOnCloud)
? Row(
mainAxisSize: MainAxisSize.min,
children: [
@@ -552,8 +555,7 @@ class AttachmentPreview extends HookConsumerWidget {
);
return ContextMenuWidget(
menuProvider:
(MenuRequest request) => Menu(
menuProvider: (MenuRequest request) => Menu(
children: [
if (item.isOnDevice && item.type == UniversalFileType.image)
MenuAction(

View File

@@ -71,13 +71,13 @@ class ComposeAttachments extends ConsumerWidget {
isCompact: isCompact,
item: state.attachments.value[idx],
progress: progressMap[idx],
isUploading: progressMap.containsKey(idx),
onRequestUpload: () async {
final config = await showModalBottomSheet<AttachmentUploadConfig>(
context: ref.context,
isScrollControlled: true,
useRootNavigator: true,
builder:
(context) =>
builder: (context) =>
AttachmentUploaderSheet(ref: ref, state: state, index: idx),
);
if (config != null) {
@@ -146,14 +146,16 @@ class ArticleComposeAttachments extends ConsumerWidget {
isCompact: true,
item: attachments[idx],
progress: progressMap[idx],
isUploading: progressMap.containsKey(idx),
onRequestUpload: () async {
final config = await showModalBottomSheet<
final config =
await showModalBottomSheet<
AttachmentUploadConfig
>(
context: context,
isScrollControlled: true,
builder:
(context) => AttachmentUploaderSheet(
builder: (context) =>
AttachmentUploaderSheet(
ref: ref,
state: state,
index: idx,
@@ -168,24 +170,15 @@ class ArticleComposeAttachments extends ConsumerWidget {
);
}
},
onUpdate:
(value) => ComposeLogic.updateAttachment(
onUpdate: (value) => ComposeLogic.updateAttachment(
state,
value,
idx,
),
onDelete:
() => ComposeLogic.deleteAttachment(
ref,
state,
idx,
),
onInsert:
() => ComposeLogic.insertAttachment(
ref,
state,
idx,
),
onDelete: () =>
ComposeLogic.deleteAttachment(ref, state, idx),
onInsert: () =>
ComposeLogic.insertAttachment(ref, state, idx),
),
),
],