Compare commits
3 Commits
0303ef4a93
...
f92cfafda4
| Author | SHA1 | Date | |
|---|---|---|---|
|
f92cfafda4
|
|||
|
fa208b44d7
|
|||
|
94adecafbb
|
@@ -258,6 +258,24 @@ class UploadTasksNotifier extends StateNotifier<List<DriveTask>> {
|
|||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateDownloadProgress(
|
||||||
|
String taskId,
|
||||||
|
int downloadedBytes,
|
||||||
|
int totalBytes,
|
||||||
|
) {
|
||||||
|
state =
|
||||||
|
state.map((task) {
|
||||||
|
if (task.taskId == taskId) {
|
||||||
|
return task.copyWith(
|
||||||
|
fileSize: totalBytes,
|
||||||
|
uploadedBytes: downloadedBytes,
|
||||||
|
updatedAt: DateTime.now(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return task;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
void removeTask(String taskId) {
|
void removeTask(String taskId) {
|
||||||
state = state.where((task) => task.taskId != taskId).toList();
|
state = state.where((task) => task.taskId != taskId).toList();
|
||||||
}
|
}
|
||||||
@@ -291,6 +309,27 @@ class UploadTasksNotifier extends StateNotifier<List<DriveTask>> {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String addLocalDownloadTask(SnCloudFile item) {
|
||||||
|
final taskId =
|
||||||
|
'download-${item.id}-${DateTime.now().millisecondsSinceEpoch}';
|
||||||
|
final task = DriveTask(
|
||||||
|
id: taskId,
|
||||||
|
taskId: taskId,
|
||||||
|
fileName: item.name,
|
||||||
|
contentType: item.mimeType ?? '',
|
||||||
|
fileSize: 0,
|
||||||
|
uploadedBytes: 0,
|
||||||
|
totalChunks: 1,
|
||||||
|
uploadedChunks: 0,
|
||||||
|
status: DriveTaskStatus.inProgress,
|
||||||
|
createdAt: DateTime.now(),
|
||||||
|
updatedAt: DateTime.now(),
|
||||||
|
type: 'FileDownload',
|
||||||
|
);
|
||||||
|
state = [...state, task];
|
||||||
|
return taskId;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_websocketSubscription?.cancel();
|
_websocketSubscription?.cancel();
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/pods/upload_tasks.dart';
|
||||||
|
import 'package:island/models/drive_task.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@@ -76,7 +78,7 @@ class FileDetailScreen extends HookConsumerWidget {
|
|||||||
}, [animationController]);
|
}, [animationController]);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
isNoBackground: true,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
@@ -86,26 +88,47 @@ class FileDetailScreen extends HookConsumerWidget {
|
|||||||
title: Text(item.name.isEmpty ? 'File Details' : item.name),
|
title: Text(item.name.isEmpty ? 'File Details' : item.name),
|
||||||
actions: _buildAppBarActions(context, ref, showInfoSheet),
|
actions: _buildAppBarActions(context, ref, showInfoSheet),
|
||||||
),
|
),
|
||||||
body: AnimatedBuilder(
|
body: LayoutBuilder(
|
||||||
animation: animation,
|
builder: (context, constraints) {
|
||||||
builder: (context, child) {
|
return AnimatedBuilder(
|
||||||
return Row(
|
animation: animation,
|
||||||
children: [
|
builder: (context, child) {
|
||||||
// Main content area
|
return Stack(
|
||||||
Expanded(child: _buildContent(context, ref, serverUrl)),
|
children: [
|
||||||
// Animated drawer panel
|
// Main content area - resizes with animation
|
||||||
if (isWide)
|
Positioned(
|
||||||
SizedBox(
|
left: 0,
|
||||||
height: double.infinity,
|
top: 0,
|
||||||
width: animation.value * 400, // Max width of 400px
|
bottom: 0,
|
||||||
child: Container(
|
width: constraints.maxWidth - animation.value * 400,
|
||||||
child:
|
child: _buildContent(context, ref, serverUrl),
|
||||||
animation.value > 0.1
|
|
||||||
? FileInfoSheet(item: item, onClose: showInfoSheet)
|
|
||||||
: const SizedBox.shrink(),
|
|
||||||
),
|
),
|
||||||
),
|
// Animated drawer panel - overlays
|
||||||
],
|
if (isWide)
|
||||||
|
Positioned(
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
width: 400,
|
||||||
|
child: Transform.translate(
|
||||||
|
offset: Offset((1 - animation.value) * 400, 0),
|
||||||
|
child: SizedBox(
|
||||||
|
width: 400,
|
||||||
|
child: Material(
|
||||||
|
color:
|
||||||
|
Theme.of(context).colorScheme.surfaceContainer,
|
||||||
|
elevation: 8,
|
||||||
|
child: FileInfoSheet(
|
||||||
|
item: item,
|
||||||
|
onClose: showInfoSheet,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -187,6 +210,9 @@ class FileDetailScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _downloadFile(WidgetRef ref) async {
|
Future<void> _downloadFile(WidgetRef ref) async {
|
||||||
|
final taskId = ref
|
||||||
|
.read(uploadTasksProvider.notifier)
|
||||||
|
.addLocalDownloadTask(item);
|
||||||
try {
|
try {
|
||||||
showSnackBar('Downloading file...');
|
showSnackBar('Downloading file...');
|
||||||
|
|
||||||
@@ -202,14 +228,34 @@ class FileDetailScreen extends HookConsumerWidget {
|
|||||||
'/drive/files/${item.id}',
|
'/drive/files/${item.id}',
|
||||||
filePath,
|
filePath,
|
||||||
queryParameters: {'original': true},
|
queryParameters: {'original': true},
|
||||||
|
onReceiveProgress: (count, total) {
|
||||||
|
if (total > 0) {
|
||||||
|
ref
|
||||||
|
.read(uploadTasksProvider.notifier)
|
||||||
|
.updateDownloadProgress(taskId, count, total);
|
||||||
|
ref
|
||||||
|
.read(uploadTasksProvider.notifier)
|
||||||
|
.updateTransmissionProgress(taskId, count / total);
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
await FileSaver.instance.saveFile(
|
await FileSaver.instance.saveFile(
|
||||||
name: item.name.isEmpty ? '${item.id}.$extName' : item.name,
|
name: item.name.isEmpty ? '${item.id}.$extName' : item.name,
|
||||||
file: File(filePath),
|
file: File(filePath),
|
||||||
);
|
);
|
||||||
|
ref
|
||||||
|
.read(uploadTasksProvider.notifier)
|
||||||
|
.updateTaskStatus(taskId, DriveTaskStatus.completed);
|
||||||
showSnackBar('File saved to downloads');
|
showSnackBar('File saved to downloads');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
ref
|
||||||
|
.read(uploadTasksProvider.notifier)
|
||||||
|
.updateTaskStatus(
|
||||||
|
taskId,
|
||||||
|
DriveTaskStatus.failed,
|
||||||
|
errorMessage: e.toString(),
|
||||||
|
);
|
||||||
showErrorAlert(e);
|
showErrorAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ class AccountName extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
account.nick,
|
textOverride ?? account.nick,
|
||||||
style: nameStyle,
|
style: nameStyle,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:file_saver/file_saver.dart';
|
import 'package:file_saver/file_saver.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
@@ -266,68 +266,57 @@ class GenericFileContent extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(
|
child: Column(
|
||||||
margin: const EdgeInsets.all(32),
|
mainAxisSize: MainAxisSize.min,
|
||||||
padding: const EdgeInsets.all(32),
|
children: [
|
||||||
decoration: BoxDecoration(
|
Icon(
|
||||||
border: Border.all(
|
Symbols.insert_drive_file,
|
||||||
color: Theme.of(context).colorScheme.outline,
|
size: 64,
|
||||||
width: 1,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(16),
|
const Gap(16),
|
||||||
),
|
Text(
|
||||||
child: Column(
|
item.name,
|
||||||
mainAxisSize: MainAxisSize.min,
|
style: TextStyle(
|
||||||
children: [
|
fontSize: 20,
|
||||||
Icon(
|
fontWeight: FontWeight.bold,
|
||||||
Symbols.insert_drive_file,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
size: 64,
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
Text(
|
||||||
|
formatFileSize(item.size),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
const Gap(16),
|
),
|
||||||
Text(
|
const Gap(24),
|
||||||
item.name,
|
Row(
|
||||||
style: TextStyle(
|
mainAxisSize: MainAxisSize.min,
|
||||||
fontSize: 20,
|
children: [
|
||||||
fontWeight: FontWeight.bold,
|
FilledButton.icon(
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
onPressed: downloadFile,
|
||||||
|
icon: const Icon(Symbols.download),
|
||||||
|
label: Text('download').tr(),
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
const Gap(16),
|
||||||
),
|
OutlinedButton.icon(
|
||||||
const Gap(8),
|
onPressed: () {
|
||||||
Text(
|
showModalBottomSheet(
|
||||||
formatFileSize(item.size),
|
useRootNavigator: true,
|
||||||
style: TextStyle(
|
context: context,
|
||||||
fontSize: 16,
|
isScrollControlled: true,
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
builder: (context) => FileInfoSheet(item: item),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.info),
|
||||||
|
label: Text('info').tr(),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const Gap(24),
|
),
|
||||||
Row(
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
FilledButton.icon(
|
|
||||||
onPressed: downloadFile,
|
|
||||||
icon: const Icon(Symbols.download),
|
|
||||||
label: Text('download'),
|
|
||||||
),
|
|
||||||
const Gap(16),
|
|
||||||
OutlinedButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
useRootNavigator: true,
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (context) => FileInfoSheet(item: item),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.info),
|
|
||||||
label: Text('info'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:island/pods/network.dart';
|
|
||||||
import 'package:island/talker.dart';
|
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
import 'package:media_kit_video/media_kit_video.dart';
|
import 'package:media_kit_video/media_kit_video.dart';
|
||||||
|
|
||||||
@@ -28,28 +25,12 @@ class _UniversalVideoState extends ConsumerState<UniversalVideo> {
|
|||||||
VideoController? _videoController;
|
VideoController? _videoController;
|
||||||
|
|
||||||
void _openVideo() async {
|
void _openVideo() async {
|
||||||
final url = widget.uri;
|
|
||||||
MediaKit.ensureInitialized();
|
MediaKit.ensureInitialized();
|
||||||
|
|
||||||
_player = Player();
|
_player = Player();
|
||||||
_videoController = VideoController(_player!);
|
_videoController = VideoController(_player!);
|
||||||
|
|
||||||
String? uri;
|
_player!.open(Media(widget.uri), play: widget.autoplay);
|
||||||
final inCacheInfo = await DefaultCacheManager().getFileFromCache(url);
|
|
||||||
if (inCacheInfo == null) {
|
|
||||||
talker.info('[MediaPlayer] Miss cache: $url');
|
|
||||||
final token = ref.watch(tokenProvider)?.token;
|
|
||||||
DefaultCacheManager().downloadFile(
|
|
||||||
url,
|
|
||||||
authHeaders: {'Authorization': 'AtField $token'},
|
|
||||||
);
|
|
||||||
uri = url;
|
|
||||||
} else {
|
|
||||||
uri = inCacheInfo.file.path;
|
|
||||||
talker.info('[MediaPlayer] Hit cache: $url');
|
|
||||||
}
|
|
||||||
|
|
||||||
_player!.open(Media(uri), play: widget.autoplay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
@@ -31,7 +30,6 @@ class UploadOverlay extends HookConsumerWidget {
|
|||||||
|
|
||||||
final isVisibleOverride = useState<bool?>(null);
|
final isVisibleOverride = useState<bool?>(null);
|
||||||
final pendingHide = useState(false);
|
final pendingHide = useState(false);
|
||||||
final hideTimer = useState<Timer?>(null);
|
|
||||||
final isVisible =
|
final isVisible =
|
||||||
(isVisibleOverride.value ?? activeTasks.isNotEmpty) &&
|
(isVisibleOverride.value ?? activeTasks.isNotEmpty) &&
|
||||||
!pendingHide.value;
|
!pendingHide.value;
|
||||||
@@ -53,24 +51,6 @@ class UploadOverlay extends HookConsumerWidget {
|
|||||||
return null;
|
return null;
|
||||||
}, [isVisible]);
|
}, [isVisible]);
|
||||||
|
|
||||||
// Handle hide delay when tasks complete
|
|
||||||
useEffect(() {
|
|
||||||
if (activeTasks.isEmpty && (isVisibleOverride.value ?? false) == false) {
|
|
||||||
// No active tasks and not manually visible (not expanded)
|
|
||||||
hideTimer.value = Timer(const Duration(seconds: 2), () {
|
|
||||||
pendingHide.value = true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Cancel any pending hide and reset
|
|
||||||
hideTimer.value?.cancel();
|
|
||||||
hideTimer.value = null;
|
|
||||||
pendingHide.value = false;
|
|
||||||
}
|
|
||||||
return () {
|
|
||||||
hideTimer.value?.cancel();
|
|
||||||
};
|
|
||||||
}, [activeTasks.length, isVisibleOverride.value]);
|
|
||||||
|
|
||||||
if (!isVisible && slideController.status == AnimationStatus.dismissed) {
|
if (!isVisible && slideController.status == AnimationStatus.dismissed) {
|
||||||
// If not visible and animation is complete (back to start), don't show anything
|
// If not visible and animation is complete (back to start), don't show anything
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@@ -86,7 +66,6 @@ class UploadOverlay extends HookConsumerWidget {
|
|||||||
position: slideAnimation,
|
position: slideAnimation,
|
||||||
child: _UploadOverlayContent(
|
child: _UploadOverlayContent(
|
||||||
activeTasks: activeTasks,
|
activeTasks: activeTasks,
|
||||||
onVisibilityChanged: (bool? v) => isVisibleOverride.value = v,
|
|
||||||
).padding(bottom: 16 + MediaQuery.of(context).padding.bottom),
|
).padding(bottom: 16 + MediaQuery.of(context).padding.bottom),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -95,15 +74,12 @@ class UploadOverlay extends HookConsumerWidget {
|
|||||||
|
|
||||||
class _UploadOverlayContent extends HookConsumerWidget {
|
class _UploadOverlayContent extends HookConsumerWidget {
|
||||||
final List<DriveTask> activeTasks;
|
final List<DriveTask> activeTasks;
|
||||||
final void Function(bool?) onVisibilityChanged;
|
|
||||||
|
|
||||||
const _UploadOverlayContent({
|
const _UploadOverlayContent({required this.activeTasks});
|
||||||
required this.activeTasks,
|
|
||||||
required this.onVisibilityChanged,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final isExpanded = useState(false);
|
||||||
final animationController = useAnimationController(
|
final animationController = useAnimationController(
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
initialValue: 0.0,
|
initialValue: 0.0,
|
||||||
@@ -117,15 +93,12 @@ class _UploadOverlayContent extends HookConsumerWidget {
|
|||||||
CurvedAnimation(parent: animationController, curve: Curves.easeInOut),
|
CurvedAnimation(parent: animationController, curve: Curves.easeInOut),
|
||||||
);
|
);
|
||||||
|
|
||||||
final isExpanded = useState(false);
|
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
if (isExpanded.value) {
|
if (isExpanded.value) {
|
||||||
animationController.forward();
|
animationController.forward();
|
||||||
} else {
|
} else {
|
||||||
animationController.reverse();
|
animationController.reverse();
|
||||||
}
|
}
|
||||||
onVisibilityChanged.call(isExpanded.value);
|
|
||||||
return null;
|
return null;
|
||||||
}, [isExpanded.value]);
|
}, [isExpanded.value]);
|
||||||
|
|
||||||
@@ -349,6 +322,7 @@ class _UploadOverlayContent extends HookConsumerWidget {
|
|||||||
IconData _getOverallStatusIcon(List<DriveTask> tasks) {
|
IconData _getOverallStatusIcon(List<DriveTask> tasks) {
|
||||||
if (tasks.isEmpty) return Symbols.upload;
|
if (tasks.isEmpty) return Symbols.upload;
|
||||||
|
|
||||||
|
final hasDownload = tasks.any((task) => task.type == 'FileDownload');
|
||||||
final hasInProgress = tasks.any(
|
final hasInProgress = tasks.any(
|
||||||
(task) => task.status == DriveTaskStatus.inProgress,
|
(task) => task.status == DriveTaskStatus.inProgress,
|
||||||
);
|
);
|
||||||
@@ -370,6 +344,9 @@ class _UploadOverlayContent extends HookConsumerWidget {
|
|||||||
|
|
||||||
// Priority order: in progress > pending > paused > failed > completed
|
// Priority order: in progress > pending > paused > failed > completed
|
||||||
if (hasInProgress) {
|
if (hasInProgress) {
|
||||||
|
if (hasDownload) {
|
||||||
|
return Symbols.download;
|
||||||
|
}
|
||||||
return Symbols.upload;
|
return Symbols.upload;
|
||||||
} else if (hasPending) {
|
} else if (hasPending) {
|
||||||
return Symbols.schedule;
|
return Symbols.schedule;
|
||||||
@@ -387,6 +364,7 @@ class _UploadOverlayContent extends HookConsumerWidget {
|
|||||||
String _getOverallStatusText(List<DriveTask> tasks) {
|
String _getOverallStatusText(List<DriveTask> tasks) {
|
||||||
if (tasks.isEmpty) return '0 tasks';
|
if (tasks.isEmpty) return '0 tasks';
|
||||||
|
|
||||||
|
final hasDownload = tasks.any((task) => task.type == 'FileDownload');
|
||||||
final hasInProgress = tasks.any(
|
final hasInProgress = tasks.any(
|
||||||
(task) => task.status == DriveTaskStatus.inProgress,
|
(task) => task.status == DriveTaskStatus.inProgress,
|
||||||
);
|
);
|
||||||
@@ -408,7 +386,11 @@ class _UploadOverlayContent extends HookConsumerWidget {
|
|||||||
|
|
||||||
// Priority order: in progress > pending > paused > failed > completed
|
// Priority order: in progress > pending > paused > failed > completed
|
||||||
if (hasInProgress) {
|
if (hasInProgress) {
|
||||||
return '${tasks.length} ${'uploading'.tr()}';
|
if (hasDownload) {
|
||||||
|
return '${tasks.length} ${'downloading'.tr()}';
|
||||||
|
} else {
|
||||||
|
return '${tasks.length} ${'uploading'.tr()}';
|
||||||
|
}
|
||||||
} else if (hasPending) {
|
} else if (hasPending) {
|
||||||
return '${tasks.length} ${'pending'.tr()}';
|
return '${tasks.length} ${'pending'.tr()}';
|
||||||
} else if (hasPaused) {
|
} else if (hasPaused) {
|
||||||
@@ -550,7 +532,10 @@ class _UploadTaskTileState extends State<UploadTaskTile>
|
|||||||
color = Theme.of(context).colorScheme.secondary;
|
color = Theme.of(context).colorScheme.secondary;
|
||||||
break;
|
break;
|
||||||
case DriveTaskStatus.inProgress:
|
case DriveTaskStatus.inProgress:
|
||||||
icon = Symbols.upload;
|
icon =
|
||||||
|
widget.task.type == 'FileDownload'
|
||||||
|
? Symbols.download
|
||||||
|
: Symbols.upload;
|
||||||
color = Theme.of(context).colorScheme.primary;
|
color = Theme.of(context).colorScheme.primary;
|
||||||
break;
|
break;
|
||||||
case DriveTaskStatus.paused:
|
case DriveTaskStatus.paused:
|
||||||
|
|||||||
Reference in New Issue
Block a user