♻️ Better file icons

This commit is contained in:
2025-11-15 13:36:00 +08:00
parent 7957e4894a
commit 4607b77355
2 changed files with 64 additions and 41 deletions

View File

@@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';
import '../models/file.dart';
import '../widgets/content/cloud_files.dart';
/// Returns an appropriate icon widget for the given file based on its MIME type
Widget getFileIcon(SnCloudFile file, {required double size}) {
final itemType = file.mimeType?.split('/').firstOrNull;
final mimeType = file.mimeType ?? '';
final extension = file.name.split('.').lastOrNull?.toLowerCase() ?? '';
// For images, show the actual image thumbnail
if (itemType == 'image') {
return CloudImageWidget(file: file);
}
// Return icon based on MIME type or file extension
final icon = switch ((itemType, mimeType, extension)) {
('audio', _, _) => Symbols.audio_file,
('video', _, _) => Symbols.video_file,
('application', 'application/pdf', _) => Symbols.picture_as_pdf,
('application', 'application/zip', _) => Symbols.archive,
('application', 'application/x-rar-compressed', _) => Symbols.archive,
(
'application',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
_,
) ||
('application', 'application/msword', _) => Symbols.description,
(
'application',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
_,
) ||
('application', 'application/vnd.ms-excel', _) => Symbols.table_chart,
(
'application',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
_,
) ||
('application', 'application/vnd.ms-powerpoint', _) => Symbols.slideshow,
('text', _, _) => Symbols.article,
('application', _, 'js') ||
('application', _, 'dart') ||
('application', _, 'py') ||
('application', _, 'java') ||
('application', _, 'cpp') ||
('application', _, 'c') ||
('application', _, 'cs') => Symbols.code,
('application', _, 'json') ||
('application', _, 'xml') => Symbols.data_object,
(_, _, 'md') => Symbols.article,
(_, _, 'html') => Symbols.web,
(_, _, 'css') => Symbols.css,
_ => Symbols.description, // Default icon
};
return Icon(icon, size: size, fill: 1).center();
}

View File

@@ -10,9 +10,9 @@ import 'package:island/models/file.dart';
import 'package:island/pods/file_list.dart'; import 'package:island/pods/file_list.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/services/file_uploader.dart'; import 'package:island/services/file_uploader.dart';
import 'package:island/utils/file_icon_utils.dart';
import 'package:island/utils/format.dart'; import 'package:island/utils/format.dart';
import 'package:island/widgets/alert.dart'; import 'package:island/widgets/alert.dart';
import 'package:island/widgets/content/cloud_files.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
@@ -81,8 +81,6 @@ class FileListView extends HookConsumerWidget {
}, },
unindexedFile: (unindexedFileItem) { unindexedFile: (unindexedFileItem) {
final file = unindexedFileItem.file; final file = unindexedFileItem.file;
final itemType =
file.mimeType?.split('/').firstOrNull;
return ListTile( return ListTile(
leading: ClipRRect( leading: ClipRRect(
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(
@@ -91,24 +89,7 @@ class FileListView extends HookConsumerWidget {
child: SizedBox( child: SizedBox(
height: 48, height: 48,
width: 48, width: 48,
child: switch (itemType) { child: getFileIcon(file, size: 24),
'image' => CloudImageWidget(file: file),
'audio' =>
const Icon(
Symbols.audio_file,
fill: 1,
).center(),
'video' =>
const Icon(
Symbols.video_file,
fill: 1,
).center(),
_ =>
const Icon(
Symbols.body_system,
fill: 1,
).center(),
},
), ),
), ),
title: title:
@@ -179,8 +160,6 @@ class FileListView extends HookConsumerWidget {
return item.map( return item.map(
file: (fileItem) { file: (fileItem) {
final file = fileItem.fileIndex.file; final file = fileItem.fileIndex.file;
final itemType =
file.mimeType?.split('/').firstOrNull;
return ListTile( return ListTile(
leading: ClipRRect( leading: ClipRRect(
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(
@@ -189,24 +168,7 @@ class FileListView extends HookConsumerWidget {
child: SizedBox( child: SizedBox(
height: 48, height: 48,
width: 48, width: 48,
child: switch (itemType) { child: getFileIcon(file, size: 24),
'image' => CloudImageWidget(file: file),
'audio' =>
const Icon(
Symbols.audio_file,
fill: 1,
).center(),
'video' =>
const Icon(
Symbols.video_file,
fill: 1,
).center(),
_ =>
const Icon(
Symbols.body_system,
fill: 1,
).center(),
},
), ),
), ),
title: title: