[client] Show file type

This commit is contained in:
Abhishek Shroff
2025-06-03 02:45:04 +05:30
parent 6f812adf64
commit 64e4185dd8
3 changed files with 161 additions and 48 deletions
@@ -0,0 +1,92 @@
String mimeTypeName(String mimeType) {
final index = mimeType.indexOf(';');
if (index > 0) {
mimeType = mimeType.substring(0, index);
}
final name = _fullTypeNames[mimeType];
if (name != null) return name;
final parts = mimeType.split('/');
return _categoryNames[parts[0]] ?? 'Unknown';
}
const _categoryNames = <String, String>{
'application': 'Other',
'text': 'Text',
'audio': 'Audio',
'video': 'Video',
'image': 'Image',
};
const _fullTypeNames = <String, String>{
// Application
'application/epub+zip': 'EPUB E-Book',
'application/json': 'JSON',
'application/manifest+json': 'Web Manifest',
'application/msword': 'Word Document (Legacy)',
'application/octet-stream': 'Binary Data',
'application/pdf': 'PDF Document',
'application/postscript': 'PostScript Document',
'application/vnd.android.package-archive': 'Android Application Package',
'application/vnd.ms-excel': 'Excel Spreadsheet (Legacy)',
'application/vnd.ms-powerpoint': 'PowerPoint Presentation (Legacy)',
'application/vnd.oasis.opendocument.presentation': 'OpenOffice Presentation',
'application/vnd.oasis.opendocument.spreadsheet': 'OpenOffice Spreadsheet',
'application/vnd.oasis.opendocument.text': 'OpenOffice Text Document',
'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'PowerPoint Presentation',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'Excel Spreadsheet',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'Word Document',
'application/x-bzip': 'BZip Archive',
'application/x-bzip2': 'BZip Archive',
'application/x-latex': 'LaTeX Document',
'application/x-msdownload': 'Windows Application',
'application/x-rar-compressed': 'RAR Archive',
'application/x-tex': 'TeX Document',
'application/x-sh': 'Shell Script',
'application/x-sql': 'SQL Script',
'application/xml': 'XML',
'application/zip': 'Zip Archive',
// Audio
'audio/aac': 'AAC Audio',
'audio/mpeg': 'MPEG Audio',
'audio/mp4': 'MP4 Audio',
'audio/ogg': 'OGG Audio',
'audio/webm': 'WEBM Audio',
'audio/x-flac': 'FLAC Audio',
'audio/x-wav': 'WAV Audio',
// Image
'image/bmp': 'Bitmap Image',
'image/gif': 'GIF Image',
'image/heic': 'HEIC Image',
'image/heif': 'HEIF Image',
'image/jpeg': 'JPEG Image',
'image/png': 'PNG Image',
'image/svg+xml': 'SVG Image',
'image/vnd.adobe.photoshop': 'Photoshop Image',
'image/webp': 'WebP Image',
'image/x-icon': 'Favicon Image',
// Text
'text/css': 'CSS Source Code',
'text/csv': 'Comma-Separated Values',
'text/html': 'HTML Source Code',
'text/ics': 'Calendar Invite',
'text/javascript': 'JS Source Code',
'text/markdown': 'Markdown',
'text/plain': 'Plain Text',
'text/vnd.dvb.subtitle': 'Subtitles',
'text/x-c': 'C/C++ Source Code',
'text/x-dart': 'Dart Source Code',
'text/x-vcard': 'vCard',
// Video
'video/mp4': 'MP4 Video',
'video/mpeg': 'MPEG Video',
'video/quicktime': 'MOV Video',
'video/webm': 'WEBM Video',
'video/x-matroska': 'MKV Video',
'video/x-msvideo': 'AVI Video',
'video/x-ms-wmv': 'WMV Video',
};
@@ -3,7 +3,7 @@ import 'package:phylum/libphylum/db/db.dart';
import 'package:phylum/libphylum/phylum_account.dart';
const IconData folderIcon = Icons.folder;
const IconData fileIcon = Icons.insert_drive_file;
const IconData defaultFileIcon = Icons.insert_drive_file;
extension ResourceIconExtension on Resource {
Widget getIcon(PhylumAccount account) {
@@ -28,6 +28,6 @@ extension ResourceVersionIconExtension on ResourceVersion {
} else if (mimeType.startsWith("text")) {
return const Icon(Icons.article);
}
return const Icon(fileIcon);
return const Icon(defaultFileIcon);
}
}
+67 -46
View File
@@ -1,7 +1,6 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:offtheline/offtheline.dart';
import 'package:phylum/libphylum/actions/action_resource.dart';
import 'package:phylum/libphylum/db/db.dart';
@@ -9,6 +8,7 @@ import 'package:phylum/libphylum/phylum_account.dart';
import 'package:phylum/ui/common/responsive_dialog.dart';
import 'package:phylum/ui/explorer/explorer_controller.dart';
import 'package:phylum/libphylum/phylum_api_types.dart';
import 'package:phylum/ui/explorer/mime_type_names.dart';
import 'package:phylum/ui/explorer/resource_permissions_view.dart';
import 'package:phylum/ui/explorer/resource_publinks_view.dart';
import 'package:phylum/ui/explorer/resource_sync_state.dart';
@@ -80,15 +80,7 @@ class ResourceInfoView extends StatelessWidget {
title: Text('Type'),
subtitle: Text('Folder'),
)
: StreamBuilder(
stream: account.db.latestVersion(resource.id).watchSingleOrNull(),
builder: (context, snapshot) {
return ListTile(
leading: snapshot.data?.getIcon() ?? Icon(Icons.insert_drive_file),
title: const Text('Type'),
subtitle: Text(snapshot.data?.mimeType ?? '<unknown>'),
);
}),
: LatestVersionInfoView(resourceId: resource.id),
ListTile(
leading: const Icon(Icons.event),
title: const Text('Created'),
@@ -125,50 +117,79 @@ class ResourceInfoView extends StatelessWidget {
},
);
}),
if (!resource.dir)
StreamBuilder(
stream: account.db.latestVersion(resource.id).watchSingleOrNull(),
builder: (context, snapshot) {
final data = snapshot.data;
// if (!resource.dir)
// StreamBuilder(
// stream: account.db.latestVersion(resource.id).watchSingleOrNull(),
// builder: (context, snapshot) {
// final data = snapshot.data;
if (data == null) {
return SizedBox();
}
// if (data == null) {
// return SizedBox();
// }
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.storage),
title: const Text('Size'),
subtitle: Text('${data.size.formatForDisplay()} (${data.size} B)'),
),
ListTile(
leading: const Icon(Icons.shield),
title: const Text('SHA-256'),
onLongPress: () {
Clipboard.setData(ClipboardData(text: data.sha256));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('SHA-256 checksum copied to clipboard'),
duration: const Duration(seconds: 2),
));
},
subtitle: Text(
data.sha256,
maxLines: 1,
softWrap: false,
overflow: TextOverflow.fade,
),
),
],
);
}),
// return Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// ListTile(
// leading: const Icon(Icons.storage),
// title: const Text('Size'),
// subtitle: Text('${data.size.formatForDisplay()} (${data.size} B)'),
// ),
// ListTile(
// leading: const Icon(Icons.shield),
// title: const Text('SHA-256'),
// onLongPress: () {
// Clipboard.setData(ClipboardData(text: data.sha256));
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(
// content: Text('SHA-256 checksum copied to clipboard'),
// duration: const Duration(seconds: 2),
// ));
// },
// subtitle: Text(
// data.sha256,
// maxLines: 1,
// softWrap: false,
// overflow: TextOverflow.fade,
// ),
// ),
// ],
// );
// }),
],
),
);
}
}
class LatestVersionInfoView extends StatelessWidget {
final String resourceId;
const LatestVersionInfoView({super.key, required this.resourceId});
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: context.read<PhylumAccount>().db.latestVersion(resourceId).watchSingleOrNull(),
builder: (context, snapshot) {
final data = snapshot.data;
if (data == null) {
return const ListTile(
leading: Icon(defaultFileIcon),
title: Text('Type'),
subtitle: Text(''),
);
}
return ListTile(
leading: data.getIcon(),
title: Text('Type'),
subtitle: Text('${mimeTypeName(data.mimeType)} \u2022 ${data.size.formatForDisplay()}'),
);
});
}
}
class PendingActionsTile extends StatefulWidget {
final String resourceId;