312 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			312 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'dart:convert';
 | 
						|
 | 
						|
import 'package:easy_localization/easy_localization.dart';
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
import 'package:flutter/services.dart';
 | 
						|
import 'package:island/models/file.dart';
 | 
						|
import 'package:island/utils/format.dart';
 | 
						|
import 'package:island/widgets/alert.dart';
 | 
						|
import 'package:island/widgets/content/sheet.dart';
 | 
						|
import 'package:material_symbols_icons/symbols.dart';
 | 
						|
import 'package:styled_widget/styled_widget.dart';
 | 
						|
import 'package:url_launcher/url_launcher_string.dart';
 | 
						|
 | 
						|
class FileInfoSheet extends StatelessWidget {
 | 
						|
  final SnCloudFile item;
 | 
						|
 | 
						|
  const FileInfoSheet({super.key, required this.item});
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final theme = Theme.of(context);
 | 
						|
    final exifData = item.fileMeta?['exif'] as Map<String, dynamic>? ?? {};
 | 
						|
 | 
						|
    return SheetScaffold(
 | 
						|
      titleText: 'fileInfoTitle'.tr(),
 | 
						|
      child: SingleChildScrollView(
 | 
						|
        child: Column(
 | 
						|
          crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
          children: [
 | 
						|
            Row(
 | 
						|
              children: [
 | 
						|
                Expanded(
 | 
						|
                  child: Column(
 | 
						|
                    crossAxisAlignment: CrossAxisAlignment.center,
 | 
						|
                    mainAxisSize: MainAxisSize.min,
 | 
						|
                    children: [
 | 
						|
                      Text('mimeType').tr(),
 | 
						|
                      Text(
 | 
						|
                        item.mimeType ?? 'unknown'.tr(),
 | 
						|
                        maxLines: 1,
 | 
						|
                        overflow: TextOverflow.ellipsis,
 | 
						|
                        style: theme.textTheme.titleMedium?.copyWith(
 | 
						|
                          fontWeight: FontWeight.bold,
 | 
						|
                        ),
 | 
						|
                      ),
 | 
						|
                    ],
 | 
						|
                  ),
 | 
						|
                ),
 | 
						|
                SizedBox(height: 28, child: const VerticalDivider()),
 | 
						|
                Expanded(
 | 
						|
                  child: Column(
 | 
						|
                    crossAxisAlignment: CrossAxisAlignment.center,
 | 
						|
                    mainAxisSize: MainAxisSize.min,
 | 
						|
                    children: [
 | 
						|
                      Text('fileSize').tr(),
 | 
						|
                      Text(
 | 
						|
                        formatFileSize(item.size),
 | 
						|
                        style: theme.textTheme.titleMedium?.copyWith(
 | 
						|
                          fontWeight: FontWeight.bold,
 | 
						|
                        ),
 | 
						|
                      ),
 | 
						|
                    ],
 | 
						|
                  ),
 | 
						|
                ),
 | 
						|
                if (item.hash != null)
 | 
						|
                  SizedBox(height: 28, child: const VerticalDivider()),
 | 
						|
                if (item.hash != null)
 | 
						|
                  Expanded(
 | 
						|
                    child: GestureDetector(
 | 
						|
                      child: Column(
 | 
						|
                        crossAxisAlignment: CrossAxisAlignment.center,
 | 
						|
                        mainAxisSize: MainAxisSize.min,
 | 
						|
                        children: [
 | 
						|
                          Text('fileHash').tr(),
 | 
						|
                          Text(
 | 
						|
                            '${item.hash!.substring(0, 6)}...',
 | 
						|
                            style: theme.textTheme.titleMedium?.copyWith(
 | 
						|
                              fontWeight: FontWeight.bold,
 | 
						|
                            ),
 | 
						|
                          ),
 | 
						|
                        ],
 | 
						|
                      ),
 | 
						|
                      onLongPress: () {
 | 
						|
                        Clipboard.setData(ClipboardData(text: item.hash!));
 | 
						|
                        showSnackBar('fileHashCopied'.tr());
 | 
						|
                      },
 | 
						|
                    ),
 | 
						|
                  ),
 | 
						|
              ],
 | 
						|
            ).padding(horizontal: 24, vertical: 16),
 | 
						|
            const Divider(height: 1),
 | 
						|
            ListTile(
 | 
						|
              leading: const Icon(Symbols.tag),
 | 
						|
              title: Text('ID').tr(),
 | 
						|
              subtitle: Text(
 | 
						|
                item.id,
 | 
						|
                maxLines: 1,
 | 
						|
                overflow: TextOverflow.ellipsis,
 | 
						|
              ),
 | 
						|
              contentPadding: EdgeInsets.symmetric(horizontal: 24),
 | 
						|
              trailing: IconButton(
 | 
						|
                icon: const Icon(Icons.copy),
 | 
						|
                onPressed: () {
 | 
						|
                  Clipboard.setData(ClipboardData(text: item.id));
 | 
						|
                  showSnackBar('fileIdCopied'.tr());
 | 
						|
                },
 | 
						|
              ),
 | 
						|
            ),
 | 
						|
            ListTile(
 | 
						|
              leading: const Icon(Symbols.file_present),
 | 
						|
              title: Text('Name').tr(),
 | 
						|
              subtitle: Text(
 | 
						|
                item.name,
 | 
						|
                maxLines: 1,
 | 
						|
                overflow: TextOverflow.ellipsis,
 | 
						|
              ),
 | 
						|
              contentPadding: EdgeInsets.symmetric(horizontal: 24),
 | 
						|
              trailing: IconButton(
 | 
						|
                icon: const Icon(Icons.copy),
 | 
						|
                onPressed: () {
 | 
						|
                  Clipboard.setData(ClipboardData(text: item.name));
 | 
						|
                  showSnackBar('fileNameCopied'.tr());
 | 
						|
                },
 | 
						|
              ),
 | 
						|
            ),
 | 
						|
            if (item.pool != null)
 | 
						|
              ListTile(
 | 
						|
                leading: const Icon(Symbols.calendar_today),
 | 
						|
                title: Text('File Pool').tr(),
 | 
						|
                subtitle: Text(
 | 
						|
                  item.pool!.name,
 | 
						|
                  maxLines: 1,
 | 
						|
                  overflow: TextOverflow.ellipsis,
 | 
						|
                ),
 | 
						|
                contentPadding: EdgeInsets.symmetric(horizontal: 24),
 | 
						|
                trailing: IconButton(
 | 
						|
                  icon: const Icon(Icons.copy),
 | 
						|
                  onPressed: () {
 | 
						|
                    Clipboard.setData(ClipboardData(text: item.pool!.id));
 | 
						|
                    showSnackBar('fileNameCopied'.tr());
 | 
						|
                  },
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
            ListTile(
 | 
						|
              leading: const Icon(Symbols.launch),
 | 
						|
              title: Text('openInBrowser').tr(),
 | 
						|
              subtitle: Text('https://solian.app/files/${item.id}'),
 | 
						|
              contentPadding: EdgeInsets.symmetric(horizontal: 24),
 | 
						|
              onTap: () {
 | 
						|
                launchUrlString(
 | 
						|
                  'https://solian.app/files/${item.id}',
 | 
						|
                  mode: LaunchMode.externalApplication,
 | 
						|
                );
 | 
						|
              },
 | 
						|
            ),
 | 
						|
            if (exifData.isNotEmpty) ...[
 | 
						|
              const Divider(height: 1),
 | 
						|
              Theme(
 | 
						|
                data: theme.copyWith(dividerColor: Colors.transparent),
 | 
						|
                child: ExpansionTile(
 | 
						|
                  tilePadding: const EdgeInsets.symmetric(horizontal: 24),
 | 
						|
                  title: Text(
 | 
						|
                    'exifData'.tr(),
 | 
						|
                    style: theme.textTheme.titleMedium?.copyWith(
 | 
						|
                      fontWeight: FontWeight.bold,
 | 
						|
                    ),
 | 
						|
                  ),
 | 
						|
                  children: [
 | 
						|
                    Column(
 | 
						|
                      crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
                      children: [
 | 
						|
                        ...exifData.entries.map(
 | 
						|
                          (entry) => ListTile(
 | 
						|
                            dense: true,
 | 
						|
                            contentPadding: EdgeInsets.symmetric(
 | 
						|
                              horizontal: 24,
 | 
						|
                            ),
 | 
						|
                            title:
 | 
						|
                                Text(
 | 
						|
                                  entry.key.contains('-')
 | 
						|
                                      ? entry.key.split('-').last
 | 
						|
                                      : entry.key,
 | 
						|
                                  style: theme.textTheme.bodyMedium?.copyWith(
 | 
						|
                                    fontWeight: FontWeight.w500,
 | 
						|
                                  ),
 | 
						|
                                ).bold(),
 | 
						|
                            subtitle: Text(
 | 
						|
                              '${entry.value}'.isNotEmpty
 | 
						|
                                  ? '${entry.value}'
 | 
						|
                                  : 'N/A',
 | 
						|
                              style: theme.textTheme.bodyMedium,
 | 
						|
                            ),
 | 
						|
                            onTap: () {
 | 
						|
                              Clipboard.setData(
 | 
						|
                                ClipboardData(text: '${entry.value}'),
 | 
						|
                              );
 | 
						|
                              showSnackBar('valueCopied'.tr());
 | 
						|
                            },
 | 
						|
                          ),
 | 
						|
                        ),
 | 
						|
                      ],
 | 
						|
                    ),
 | 
						|
                  ],
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
            ],
 | 
						|
            if (item.fileMeta != null && item.fileMeta!.isNotEmpty) ...[
 | 
						|
              const Divider(height: 1),
 | 
						|
              Theme(
 | 
						|
                data: theme.copyWith(dividerColor: Colors.transparent),
 | 
						|
                child: ExpansionTile(
 | 
						|
                  tilePadding: const EdgeInsets.symmetric(horizontal: 24),
 | 
						|
                  title: Text(
 | 
						|
                    'fileMetadata'.tr(),
 | 
						|
                    style: theme.textTheme.titleMedium?.copyWith(
 | 
						|
                      fontWeight: FontWeight.bold,
 | 
						|
                    ),
 | 
						|
                  ),
 | 
						|
                  children: [
 | 
						|
                    Column(
 | 
						|
                      crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
                      children: [
 | 
						|
                        ...item.fileMeta!.entries.map(
 | 
						|
                          (entry) => ListTile(
 | 
						|
                            dense: true,
 | 
						|
                            contentPadding: EdgeInsets.symmetric(
 | 
						|
                              horizontal: 24,
 | 
						|
                            ),
 | 
						|
                            title:
 | 
						|
                                Text(
 | 
						|
                                  entry.key,
 | 
						|
                                  style: theme.textTheme.bodyMedium?.copyWith(
 | 
						|
                                    fontWeight: FontWeight.w500,
 | 
						|
                                  ),
 | 
						|
                                ).bold(),
 | 
						|
                            subtitle: Text(
 | 
						|
                              jsonEncode(entry.value),
 | 
						|
                              style: theme.textTheme.bodyMedium,
 | 
						|
                              maxLines: 3,
 | 
						|
                              overflow: TextOverflow.ellipsis,
 | 
						|
                            ),
 | 
						|
                            onTap: () {
 | 
						|
                              Clipboard.setData(
 | 
						|
                                ClipboardData(text: jsonEncode(entry.value)),
 | 
						|
                              );
 | 
						|
                              showSnackBar('valueCopied'.tr());
 | 
						|
                            },
 | 
						|
                          ),
 | 
						|
                        ),
 | 
						|
                      ],
 | 
						|
                    ),
 | 
						|
                  ],
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
            ],
 | 
						|
            if (item.userMeta != null && item.userMeta!.isNotEmpty) ...[
 | 
						|
              const Divider(height: 1),
 | 
						|
              Theme(
 | 
						|
                data: theme.copyWith(dividerColor: Colors.transparent),
 | 
						|
                child: ExpansionTile(
 | 
						|
                  tilePadding: const EdgeInsets.symmetric(horizontal: 24),
 | 
						|
                  title: Text(
 | 
						|
                    'userMetadata'.tr(),
 | 
						|
                    style: theme.textTheme.titleMedium?.copyWith(
 | 
						|
                      fontWeight: FontWeight.bold,
 | 
						|
                    ),
 | 
						|
                  ),
 | 
						|
                  children: [
 | 
						|
                    Column(
 | 
						|
                      crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
                      children: [
 | 
						|
                        ...item.userMeta!.entries.map(
 | 
						|
                          (entry) => ListTile(
 | 
						|
                            dense: true,
 | 
						|
                            contentPadding: EdgeInsets.symmetric(
 | 
						|
                              horizontal: 24,
 | 
						|
                            ),
 | 
						|
                            title:
 | 
						|
                                Text(
 | 
						|
                                  entry.key,
 | 
						|
                                  style: theme.textTheme.bodyMedium?.copyWith(
 | 
						|
                                    fontWeight: FontWeight.w500,
 | 
						|
                                  ),
 | 
						|
                                ).bold(),
 | 
						|
                            subtitle: Text(
 | 
						|
                              jsonEncode(entry.value),
 | 
						|
                              style: theme.textTheme.bodyMedium,
 | 
						|
                              maxLines: 3,
 | 
						|
                              overflow: TextOverflow.ellipsis,
 | 
						|
                            ),
 | 
						|
                            onTap: () {
 | 
						|
                              Clipboard.setData(
 | 
						|
                                ClipboardData(text: jsonEncode(entry.value)),
 | 
						|
                              );
 | 
						|
                              showSnackBar('valueCopied'.tr());
 | 
						|
                            },
 | 
						|
                          ),
 | 
						|
                        ),
 | 
						|
                      ],
 | 
						|
                    ),
 | 
						|
                  ],
 | 
						|
                ),
 | 
						|
              ),
 | 
						|
            ],
 | 
						|
            const SizedBox(height: 16),
 | 
						|
          ],
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |