Browse Source

harbour: Warn users when up-/downloading big files

pull/27/head
jld3103 2 years ago
parent
commit
f3823dc1a3
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 25
      packages/harbour/lib/l10n/en.arb
  2. 30
      packages/harbour/lib/l10n/localizations.dart
  3. 19
      packages/harbour/lib/l10n/localizations_en.dart
  4. 1
      packages/harbour/lib/src/apps/files/app.dart
  5. 46
      packages/harbour/lib/src/apps/files/dialogs/choose_create.dart
  6. 41
      packages/harbour/lib/src/apps/files/options.dart
  7. 14
      packages/harbour/lib/src/apps/files/pages/main.dart
  8. 12
      packages/harbour/lib/src/apps/files/widgets/browser_view.dart

25
packages/harbour/lib/l10n/en.arb

@ -42,6 +42,7 @@
"retry": "Retry", "retry": "Retry",
"showSlashHide": "Show/Hide", "showSlashHide": "Show/Hide",
"exit": "Exit", "exit": "Exit",
"disabled": "Disabled",
"settings": "Settings", "settings": "Settings",
"settingsForApp": "Settings - {name}", "settingsForApp": "Settings - {name}",
"@settingsForApp": { "@settingsForApp": {
@ -135,9 +136,33 @@
"filesChooseFolder": "Choose folder", "filesChooseFolder": "Choose folder",
"filesAddToFavorites": "Add to favorites", "filesAddToFavorites": "Add to favorites",
"filesRemoveFromFavorites": "Remove from favorites", "filesRemoveFromFavorites": "Remove from favorites",
"filesConfirmUploadSizeWarning": "Are you sure you want to upload a file that is bigger than {warningSize} ({actualSize})?",
"@filesConfirmUploadSizeWarning": {
"placeholders": {
"warningSize": {
"type": "String"
},
"actualSize": {
"type": "String"
}
}
},
"filesConfirmDownloadSizeWarning": "Are you sure you want to download a file that is bigger than {warningSize} ({actualSize})?",
"@filesConfirmDownloadSizeWarning": {
"placeholders": {
"warningSize": {
"type": "String"
},
"actualSize": {
"type": "String"
}
}
},
"filesOptionsShowPreviews": "Show previews for files", "filesOptionsShowPreviews": "Show previews for files",
"filesOptionsUploadQueueParallelism": "Upload queue parallelism", "filesOptionsUploadQueueParallelism": "Upload queue parallelism",
"filesOptionsDownloadQueueParallelism": "Download queue parallelism", "filesOptionsDownloadQueueParallelism": "Download queue parallelism",
"filesOptionsUploadSizeWarning": "Upload size warning",
"filesOptionsDownloadSizeWarning": "Download size warning",
"newsName": "News", "newsName": "News",
"newsAddFeed": "Add feed", "newsAddFeed": "Add feed",
"newsFolder": "Folder", "newsFolder": "Folder",

30
packages/harbour/lib/l10n/localizations.dart

@ -257,6 +257,12 @@ abstract class AppLocalizations {
/// **'Exit'** /// **'Exit'**
String get exit; String get exit;
/// No description provided for @disabled.
///
/// In en, this message translates to:
/// **'Disabled'**
String get disabled;
/// No description provided for @settings. /// No description provided for @settings.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@ -569,6 +575,18 @@ abstract class AppLocalizations {
/// **'Remove from favorites'** /// **'Remove from favorites'**
String get filesRemoveFromFavorites; String get filesRemoveFromFavorites;
/// No description provided for @filesConfirmUploadSizeWarning.
///
/// In en, this message translates to:
/// **'Are you sure you want to upload a file that is bigger than {warningSize} ({actualSize})?'**
String filesConfirmUploadSizeWarning(String warningSize, String actualSize);
/// No description provided for @filesConfirmDownloadSizeWarning.
///
/// In en, this message translates to:
/// **'Are you sure you want to download a file that is bigger than {warningSize} ({actualSize})?'**
String filesConfirmDownloadSizeWarning(String warningSize, String actualSize);
/// No description provided for @filesOptionsShowPreviews. /// No description provided for @filesOptionsShowPreviews.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@ -587,6 +605,18 @@ abstract class AppLocalizations {
/// **'Download queue parallelism'** /// **'Download queue parallelism'**
String get filesOptionsDownloadQueueParallelism; String get filesOptionsDownloadQueueParallelism;
/// No description provided for @filesOptionsUploadSizeWarning.
///
/// In en, this message translates to:
/// **'Upload size warning'**
String get filesOptionsUploadSizeWarning;
/// No description provided for @filesOptionsDownloadSizeWarning.
///
/// In en, this message translates to:
/// **'Download size warning'**
String get filesOptionsDownloadSizeWarning;
/// No description provided for @newsName. /// No description provided for @newsName.
/// ///
/// In en, this message translates to: /// In en, this message translates to:

19
packages/harbour/lib/l10n/localizations_en.dart

@ -95,6 +95,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get exit => 'Exit'; String get exit => 'Exit';
@override
String get disabled => 'Disabled';
@override @override
String get settings => 'Settings'; String get settings => 'Settings';
@ -261,6 +264,16 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get filesRemoveFromFavorites => 'Remove from favorites'; String get filesRemoveFromFavorites => 'Remove from favorites';
@override
String filesConfirmUploadSizeWarning(String warningSize, String actualSize) {
return 'Are you sure you want to upload a file that is bigger than $warningSize ($actualSize)?';
}
@override
String filesConfirmDownloadSizeWarning(String warningSize, String actualSize) {
return 'Are you sure you want to download a file that is bigger than $warningSize ($actualSize)?';
}
@override @override
String get filesOptionsShowPreviews => 'Show previews for files'; String get filesOptionsShowPreviews => 'Show previews for files';
@ -270,6 +283,12 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get filesOptionsDownloadQueueParallelism => 'Download queue parallelism'; String get filesOptionsDownloadQueueParallelism => 'Download queue parallelism';
@override
String get filesOptionsUploadSizeWarning => 'Upload size warning';
@override
String get filesOptionsDownloadSizeWarning => 'Download size warning';
@override @override
String get newsName => 'News'; String get newsName => 'News';

1
packages/harbour/lib/src/apps/files/app.dart

@ -17,6 +17,7 @@ import 'package:image_picker/image_picker.dart';
import 'package:intersperse/intersperse.dart'; import 'package:intersperse/intersperse.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/nextcloud.dart';
import 'package:path/path.dart' as p;
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
import 'package:settings/settings.dart'; import 'package:settings/settings.dart';

46
packages/harbour/lib/src/apps/files/dialogs/choose_create.dart

@ -1,6 +1,6 @@
part of '../app.dart'; part of '../app.dart';
class FilesChooseCreateDialog extends StatelessWidget { class FilesChooseCreateDialog extends StatefulWidget {
const FilesChooseCreateDialog({ const FilesChooseCreateDialog({
required this.bloc, required this.bloc,
required this.basePath, required this.basePath,
@ -10,18 +10,42 @@ class FilesChooseCreateDialog extends StatelessWidget {
final FilesBloc bloc; final FilesBloc bloc;
final List<String> basePath; final List<String> basePath;
Future upload(final FileType type) async { @override
State<FilesChooseCreateDialog> createState() => _FilesChooseCreateDialogState();
}
class _FilesChooseCreateDialogState extends State<FilesChooseCreateDialog> {
Future uploadFromPick(final FileType type) async {
final result = await FilePicker.platform.pickFiles( final result = await FilePicker.platform.pickFiles(
allowMultiple: true, allowMultiple: true,
type: type, type: type,
); );
if (result != null) { if (result != null) {
for (final file in result.files) { for (final file in result.files) {
bloc.uploadFile([...basePath, file.name], file.path!); await upload(File(file.path!));
} }
} }
} }
Future upload(final File file) async {
final sizeWarning = widget.bloc.options.uploadSizeWarning.value;
if (sizeWarning != null) {
final stat = file.statSync();
if (stat.size > sizeWarning) {
if (!(await showConfirmationDialog(
context,
AppLocalizations.of(context).filesConfirmUploadSizeWarning(
filesize(sizeWarning),
filesize(stat.size),
),
))) {
return;
}
}
}
widget.bloc.uploadFile([...widget.basePath, p.basename(file.path)], file.path);
}
@override @override
Widget build(final BuildContext context) => CustomDialog( Widget build(final BuildContext context) => CustomDialog(
children: [ children: [
@ -32,9 +56,11 @@ class FilesChooseCreateDialog extends StatelessWidget {
), ),
title: Text(AppLocalizations.of(context).filesUploadFiles), title: Text(AppLocalizations.of(context).filesUploadFiles),
onTap: () async { onTap: () async {
Navigator.of(context).pop(); await uploadFromPick(FileType.any);
await upload(FileType.any); if (mounted) {
Navigator.of(context).pop();
}
}, },
), ),
ListTile( ListTile(
@ -44,9 +70,11 @@ class FilesChooseCreateDialog extends StatelessWidget {
), ),
title: Text(AppLocalizations.of(context).filesUploadImages), title: Text(AppLocalizations.of(context).filesUploadImages),
onTap: () async { onTap: () async {
Navigator.of(context).pop(); await uploadFromPick(FileType.image);
await upload(FileType.image); if (mounted) {
Navigator.of(context).pop();
}
}, },
), ),
if (Provider.of<HarbourPlatform>(context, listen: false).canUseCamera) ...[ if (Provider.of<HarbourPlatform>(context, listen: false).canUseCamera) ...[
@ -62,7 +90,7 @@ class FilesChooseCreateDialog extends StatelessWidget {
final picker = ImagePicker(); final picker = ImagePicker();
final result = await picker.pickImage(source: ImageSource.camera); final result = await picker.pickImage(source: ImageSource.camera);
if (result != null) { if (result != null) {
bloc.uploadFile([...basePath, result.name], result.path); await upload(File(result.path));
} }
}, },
), ),
@ -81,7 +109,7 @@ class FilesChooseCreateDialog extends StatelessWidget {
builder: (final context) => const FilesCreateFolderDialog(), builder: (final context) => const FilesCreateFolderDialog(),
); );
if (result != null) { if (result != null) {
bloc.browser.createFolder([...basePath, ...result]); widget.bloc.browser.createFolder([...widget.basePath, ...result]);
} }
}, },
), ),

41
packages/harbour/lib/src/apps/files/options.dart

@ -9,6 +9,8 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
showPreviewsOption, showPreviewsOption,
uploadQueueParallelism, uploadQueueParallelism,
downloadQueueParallelism, downloadQueueParallelism,
uploadSizeWarning,
downloadSizeWarning,
]; ];
} }
@ -25,7 +27,7 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
); );
late final uploadQueueParallelism = SelectOption<int>( late final uploadQueueParallelism = SelectOption<int>(
storage: super.storage, storage: storage,
category: generalCategory, category: generalCategory,
key: 'upload-queue-parallelism', key: 'upload-queue-parallelism',
label: (final context) => AppLocalizations.of(context).filesOptionsUploadQueueParallelism, label: (final context) => AppLocalizations.of(context).filesOptionsUploadQueueParallelism,
@ -38,7 +40,7 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
); );
late final downloadQueueParallelism = SelectOption<int>( late final downloadQueueParallelism = SelectOption<int>(
storage: super.storage, storage: storage,
category: generalCategory, category: generalCategory,
key: 'download-queue-parallelism', key: 'download-queue-parallelism',
label: (final context) => AppLocalizations.of(context).filesOptionsDownloadQueueParallelism, label: (final context) => AppLocalizations.of(context).filesOptionsDownloadQueueParallelism,
@ -49,4 +51,39 @@ class FilesAppSpecificOptions extends NextcloudAppSpecificOptions {
}, },
}), }),
); );
late final _sizeWarningValues = <int?, String Function(BuildContext)>{
null: (final context) => AppLocalizations.of(context).disabled,
for (final i in [
1,
10,
100,
1024,
2 * 2024,
6 * 1024,
10 * 1024,
]) ...{
_mb(i): (final _) => filesize(_mb(i)),
},
};
int _mb(final int i) => i * 1024 * 1024;
late final uploadSizeWarning = SelectOption<int?>(
storage: storage,
category: generalCategory,
key: 'upload-size-warning',
label: (final context) => AppLocalizations.of(context).filesOptionsUploadSizeWarning,
defaultValue: BehaviorSubject.seeded(_mb(10)),
values: BehaviorSubject.seeded(_sizeWarningValues),
);
late final downloadSizeWarning = SelectOption<int?>(
storage: storage,
category: generalCategory,
key: 'download-size-warning',
label: (final context) => AppLocalizations.of(context).filesOptionsDownloadSizeWarning,
defaultValue: BehaviorSubject.seeded(_mb(10)),
values: BehaviorSubject.seeded(_sizeWarningValues),
);
} }

14
packages/harbour/lib/src/apps/files/pages/main.dart

@ -26,7 +26,19 @@ class _FilesMainPageState extends State<FilesMainPage> {
Widget build(BuildContext context) => FilesBrowserView( Widget build(BuildContext context) => FilesBrowserView(
bloc: widget.bloc.browser, bloc: widget.bloc.browser,
filesBloc: widget.bloc, filesBloc: widget.bloc,
onPickFile: (final details) { onPickFile: (final details) async {
final sizeWarning = widget.bloc.options.downloadSizeWarning.value;
if (sizeWarning != null && details.size > sizeWarning) {
if (!(await showConfirmationDialog(
context,
AppLocalizations.of(context).filesConfirmDownloadSizeWarning(
filesize(sizeWarning),
filesize(details.size),
),
))) {
return;
}
}
widget.bloc.openFile(details.path, details.etag!, details.mimeType); widget.bloc.openFile(details.path, details.etag!, details.mimeType);
}, },
); );

12
packages/harbour/lib/src/apps/files/widgets/browser_view.dart

@ -425,6 +425,18 @@ class _FilesBrowserViewState extends State<FilesBrowserView> {
} }
break; break;
case _FileAction.sync: case _FileAction.sync:
final sizeWarning = widget.bloc.options.downloadSizeWarning.value;
if (sizeWarning != null && details.size > sizeWarning) {
if (!(await showConfirmationDialog(
context,
AppLocalizations.of(context).filesConfirmDownloadSizeWarning(
filesize(sizeWarning),
filesize(details.size),
),
))) {
return;
}
}
widget.filesBloc.syncFile(details.path); widget.filesBloc.syncFile(details.path);
break; break;
case _FileAction.delete: case _FileAction.delete:

Loading…
Cancel
Save