Enhance file download functionality with snackbar notifications and authentication token handling
This commit is contained in:
@@ -10,6 +10,8 @@ import '../blocs/file_browser/file_browser_state.dart';
|
||||
import '../blocs/permission/permission_bloc.dart';
|
||||
import '../blocs/permission/permission_event.dart';
|
||||
import '../blocs/permission/permission_state.dart';
|
||||
import '../blocs/session/session_bloc.dart';
|
||||
import '../blocs/session/session_state.dart';
|
||||
import '../blocs/upload/upload_bloc.dart';
|
||||
import '../blocs/upload/upload_event.dart';
|
||||
import '../blocs/upload/upload_state.dart';
|
||||
@@ -282,15 +284,59 @@ class _FileExplorerState extends State<FileExplorer> {
|
||||
}
|
||||
|
||||
void _downloadFile(FileItem file) async {
|
||||
// Show download starting snackbar
|
||||
ScaffoldFeatureController<SnackBar, SnackBarClosedReason>? snackController;
|
||||
if (context.mounted) {
|
||||
snackController = ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: AppTheme.accentColor,
|
||||
backgroundColor: AppTheme.accentColor.withValues(alpha: 0.3),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Preparing download: ${file.name}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(color: AppTheme.primaryText),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
duration: const Duration(seconds: 3),
|
||||
backgroundColor: AppTheme.primaryBackground,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
final fileService = getIt<FileService>();
|
||||
|
||||
// Get token from SessionBloc for authentication
|
||||
final sessionState = context.read<SessionBloc>().state;
|
||||
String? token;
|
||||
if (sessionState is SessionActive) {
|
||||
token = sessionState.token;
|
||||
}
|
||||
|
||||
if (token == null) {
|
||||
throw Exception('Not authenticated');
|
||||
}
|
||||
|
||||
final downloadUrl = await fileService.getDownloadUrl(
|
||||
widget.orgId,
|
||||
file.path,
|
||||
);
|
||||
|
||||
// For web, use the download URL with the ApiClient base URL (from DI)
|
||||
final fullUrl = '${fileService.baseUrl}$downloadUrl';
|
||||
// Build full URL with token for authentication (anchor elements can't send headers)
|
||||
final fullUrl = '${fileService.baseUrl}$downloadUrl&token=${Uri.encodeComponent(token)}';
|
||||
|
||||
// Trigger download via anchor element
|
||||
final anchor = web.HTMLAnchorElement()
|
||||
@@ -298,16 +344,50 @@ class _FileExplorerState extends State<FileExplorer> {
|
||||
..download = file.name;
|
||||
anchor.click();
|
||||
|
||||
// Dismiss preparing snackbar and show success
|
||||
snackController?.close();
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Downloading ${file.name}')));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
const Icon(Icons.download_done, color: AppTheme.accentColor, size: 20),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Downloaded ${file.name}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(color: AppTheme.primaryText),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: AppTheme.primaryBackground,
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
snackController?.close();
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Download failed: $e')));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
const Icon(Icons.error_outline, color: Colors.red, size: 20),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Download failed: $e',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(color: AppTheme.primaryText),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
backgroundColor: AppTheme.primaryBackground,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user