From 3417c51a3b20bc42c599f0e4958c3ca48702c17e Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Mon, 1 Sep 2025 00:34:55 +0800 Subject: [PATCH] :sparkles: Preview for SND files --- assets/i18n/en-US.json | 4 +-- assets/i18n/zh-CN.json | 3 +- lib/widgets/content/cloud_files.dart | 53 +++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 0ddf5667..a9e81f37 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -951,7 +951,6 @@ "chatBreak15m": "15m", "chatBreak30m": "30m", "chatBreakCustomMinutes": "Custom (minutes)", - "chatBreakEnterMinutes": "Enter minutes", "errorGeneric": "Error: {}", "searchMessages": "Search Messages", "messagesCount": "{} messages", @@ -960,5 +959,6 @@ "searchMessagesHint": "Search messages...", "searchLinks": "Links", "searchAttachments": "Attachments", - "noMessagesFound": "No messages found" + "noMessagesFound": "No messages found", + "openInBrowser": "Open in Browser" } \ No newline at end of file diff --git a/assets/i18n/zh-CN.json b/assets/i18n/zh-CN.json index 4473fc18..2adc7e7f 100644 --- a/assets/i18n/zh-CN.json +++ b/assets/i18n/zh-CN.json @@ -857,5 +857,6 @@ "expiresIn": "过期时间(秒)", "isOidc": "OIDC 兼容", "statusPresent": "至今", - "accountAutomated": "机器人" + "accountAutomated": "机器人", + "openInBrowser": "在浏览器中打开" } diff --git a/lib/widgets/content/cloud_files.dart b/lib/widgets/content/cloud_files.dart index da9d9fb1..6717e2ba 100644 --- a/lib/widgets/content/cloud_files.dart +++ b/lib/widgets/content/cloud_files.dart @@ -1,8 +1,10 @@ import 'dart:math' as math; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/models/file.dart'; import 'package:island/pods/config.dart'; @@ -10,6 +12,7 @@ import 'package:island/services/time.dart'; import 'package:island/widgets/content/audio.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:styled_widget/styled_widget.dart'; +import 'package:url_launcher/url_launcher_string.dart'; import 'image.dart'; import 'video.dart'; @@ -32,6 +35,16 @@ class CloudFileWidget extends HookConsumerWidget { final serverUrl = ref.watch(serverUrlProvider); final uri = '$serverUrl/drive/files/${item.id}'; + String formatFileSize(int bytes) { + if (bytes <= 0) return '0 B'; + if (bytes < 1024) return '$bytes B'; + if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(2)} KB'; + if (bytes < 1024 * 1024 * 1024) { + return '${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB'; + } + return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB'; + } + var ratio = item.fileMeta?['ratio'] is num ? item.fileMeta!['ratio'].toDouble() @@ -60,7 +73,45 @@ class CloudFileWidget extends HookConsumerWidget { child: UniversalAudio(uri: uri, filename: item.name), ), ), - _ => Text('Unable render for ${item.mimeType}'), + _ => Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Symbols.insert_drive_file, + size: 48, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const Gap(8), + Text( + item.name, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 14, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + Text( + formatFileSize(item.size), + style: TextStyle( + fontSize: 12, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const Gap(8), + TextButton.icon( + onPressed: () { + launchUrlString( + 'https://fs.solian.app/files/${item.id}', + mode: LaunchMode.externalApplication, + ); + }, + icon: const Icon(Symbols.launch), + label: Text('openInBrowser').tr(), + ), + ], + ).padding(all: 8), }; if (heroTag != null) {