From c39ffab3eababd53d0b16d16da163a2fcfd0a027 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Fri, 14 Jul 2023 21:36:41 +0200 Subject: [PATCH 01/13] :memo: Fixed linting warnings --- test/file_encrypt_and_decrypt_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/file_encrypt_and_decrypt_test.dart b/test/file_encrypt_and_decrypt_test.dart index dfbb7d0..9bd5ea7 100644 --- a/test/file_encrypt_and_decrypt_test.dart +++ b/test/file_encrypt_and_decrypt_test.dart @@ -53,8 +53,10 @@ void main() async { await completer.future; for(int i = 0; i < fileLength; i++) { + //ignore: avoid_print print('$i : ${fullFileDecryption.elementAtOrNull(i) ?? 'NOT FOUND'} : ${i - fileStart < 0 ? 'NOT FOUND' : partialFileDecryption.elementAtOrNull(i - fileStart) ?? 'NOT FOUND'}'); } + //ignore: avoid_print print('Full length: ${fullFileDecryption.length} Partial length: ${partialFileDecryption.length} File Start: $fileStart}'); expect(listEquals(fullFileDecryption.sublist(fileStart), partialFileDecryption), isTrue); From 86be7c97b9ad7ab6b7d436600375c3dae127c5db Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Fri, 14 Jul 2023 22:20:42 +0200 Subject: [PATCH 02/13] :sparkles: Added all the confirmations --- lib/file_explorer/file_explorer.dart | 162 ++++++++++++++++++--------- lib/generated/intl/messages_en.dart | 26 +++-- lib/generated/intl/messages_fr.dart | 27 +++-- lib/generated/l10n.dart | 38 ++++++- lib/l10n/intl_en.arb | 19 +++- lib/l10n/intl_fr.arb | 5 +- lib/main.dart | 135 +++++++++++++++------- 7 files changed, 296 insertions(+), 116 deletions(-) diff --git a/lib/file_explorer/file_explorer.dart b/lib/file_explorer/file_explorer.dart index e1d6458..82372a3 100644 --- a/lib/file_explorer/file_explorer.dart +++ b/lib/file_explorer/file_explorer.dart @@ -19,7 +19,14 @@ import 'package:life_chest/vault.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; -typedef FileExportArgs = (String thumbnailFilePath, List encryptionKey, Map data, List fileContent, String unlockMechanismType, Map additionalUnlockData); +typedef FileExportArgs = ( + String thumbnailFilePath, + List encryptionKey, + Map data, + List fileContent, + String unlockMechanismType, + Map additionalUnlockData +); /// The file reader, this enable the user to see file and to browse between them while keeping a cache of them class FileReader extends StatefulWidget { @@ -440,29 +447,34 @@ class FileExplorerState extends State { final receivePort = ReceivePort(); - Isolate.spawn(exportEncryptedThumbnails, - (receivePort.sendPort, List.generate(filesToExport.length, - (index) { - FileThumbnail fileToExport = - filesToExport[index]; - return ( - fileToExport.localPath, - encryptionKey, - fileToExport.data, - fileToExport.file.readAsBytesSync(), - widget.vault.unlockMechanismType, - widget.vault.additionalUnlockData - ); - }))); + Isolate.spawn(exportEncryptedThumbnails, ( + receivePort.sendPort, + List.generate( + filesToExport.length, (index) { + FileThumbnail fileToExport = + filesToExport[index]; + return ( + fileToExport.localPath, + encryptionKey, + fileToExport.data, + fileToExport.file.readAsBytesSync(), + widget.vault.unlockMechanismType, + widget.vault.additionalUnlockData + ); + }) + )); List decryptedFiles = []; - await for(List decryptedFile in receivePort) { - decryptedFiles.add(Uint8List.fromList(decryptedFile)); + await for (List decryptedFile + in receivePort) { + decryptedFiles + .add(Uint8List.fromList(decryptedFile)); setState(() { loaderCurrentLoad = decryptedFiles.length; }); - if(loaderTarget == loaderCurrentLoad) break; + if (loaderTarget == loaderCurrentLoad) + break; } setState(() { @@ -470,17 +482,26 @@ class FileExplorerState extends State { loaderCurrentLoad = null; }); - DocumentFileSavePlus().saveMultipleFiles( - dataList: decryptedFiles, - fileNameList: [for (FileThumbnail thumbnail in filesToExport) setExtension(basenameWithoutExtension(thumbnail.data['name']), '.lcef')], - mimeTypeList: List.filled(filesToExport.length, 'plain') - ).then((value) { + DocumentFileSavePlus() + .saveMultipleFiles( + dataList: decryptedFiles, + fileNameList: [ + for (FileThumbnail thumbnail + in filesToExport) + setExtension( + basenameWithoutExtension( + thumbnail.data['name']), + '.lcef') + ], + mimeTypeList: List.filled( + filesToExport.length, 'plain')) + .then((value) { if (context.mounted) { ScaffoldMessenger.of(context) .showSnackBar(SnackBar( - content: Text(S - .of(context) - .savedToFolder))); + content: Text(S + .of(context) + .savedToFolder))); } }); } @@ -549,40 +570,78 @@ class FileExplorerState extends State { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text(S.of(context).savedToFolder))); + content: + Text(S.of(context).savedToFolder))); } }, child: Text(S.of(context).exportAsCleartext)), PopupMenuItem( onTap: () async { + List filesToDelete = []; + for (FileThumbnail thumbnail in thumbnails) { if (thumbnail.isSelected) { - if (thumbnail.file.existsSync()) { - thumbnail.file.deleteSync(); - } - if(thumbnail.placeholder == FileThumbnailsPlaceholder.folder) { - for (MapEntry innerRawThumbnail in List.from(map.entries)) { - if(isWithin(thumbnail.fullLocalPath, innerRawThumbnail.value['name'])) { - File innerRawThumbnailFile = File(join(widget.vault.path, innerRawThumbnail.key)); - if(innerRawThumbnailFile.existsSync()) { - innerRawThumbnailFile.deleteSync(); + filesToDelete.add(thumbnail); + } + } + + WidgetsBinding.instance + .addPostFrameCallback((timeStamp) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(S + .of(context) + .areYouSureDeleteFiles( + filesToDelete.length)), + content: Text(S + .of(context) + .lostDataContBeRecovered), + actions: [ + TextButton( + onPressed: () => Navigator.pop( + context, false), + child: Text(S.of(context).no)), + TextButton( + onPressed: () => Navigator.pop( + context, true), + child: Text(S.of(context).yes)) + ])).then((value) async { + for (FileThumbnail thumbnail in filesToDelete) { + if (thumbnail.file.existsSync()) { + thumbnail.file.deleteSync(); + } + if (thumbnail.placeholder == + FileThumbnailsPlaceholder.folder) { + for (MapEntry innerRawThumbnail + in List.from(map.entries)) { + if (isWithin(thumbnail.fullLocalPath, + innerRawThumbnail.value['name'])) { + File innerRawThumbnailFile = File(join( + widget.vault.path, + innerRawThumbnail.key)); + if (innerRawThumbnailFile + .existsSync()) { + innerRawThumbnailFile.deleteSync(); + } + map.remove(innerRawThumbnail.key); } - map.remove(innerRawThumbnail.key); } } + map.remove(thumbnail.localPath); } - map.remove(thumbnail.localPath); - } - } - List encryptedMap = - (await VaultsManager.encryptMap( - widget.vault, map))!; - setState(() { - // TODO: Forensic should be made to see if iOS/Android keeps any of the file data in storage, if yes fill the file with null bytes and then delete it. - File(join(widget.vault.path, '.map')) - .writeAsBytesSync(encryptedMap); - isSelectionMode = false; - thumbnailCollector = reloadThumbnails(); + List encryptedMap = + (await VaultsManager.encryptMap( + widget.vault, map))!; + setState(() { + // TODO: Forensic should be made to see if iOS/Android keeps any of the file data in storage, if yes fill the file with null bytes and then delete it. + File(join(widget.vault.path, '.map')) + .writeAsBytesSync(encryptedMap); + isSelectionMode = false; + thumbnailCollector = reloadThumbnails(); + }); + }); }); }, child: Text(S.of(context).delete)), @@ -677,8 +736,8 @@ class FileExplorerState extends State { child: LinearProgressIndicator( value: loaderCurrentLoad! / loaderTarget!)), backgroundColor: isSelectionMode - ? Theme.of(context).colorScheme.primaryContainer - : null), + ? Theme.of(context).colorScheme.primaryContainer + : null), floatingActionButton: GestureDetector( onLongPress: () { saveFolder(context); @@ -943,6 +1002,7 @@ class FileExplorerState extends State { return; } } + /// A helper method to know if an entity is 1 level deeper in the tree than a local path so that whe can know if the UI should draw it static bool shouldThumbnailBeShown( String fileLocalPath, String currentLocalPath) { diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index ca55d8b..20e86db 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -21,13 +21,18 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'en'; static String m0(count) => + "Are you sure to delete ${count} ${Intl.plural(count, one: 'file', other: 'files')} ?"; + + static String m1(vaultName) => "Are you sure to delete \"${vaultName}\"?"; + + static String m2(count) => "We detected ${Intl.plural(count, one: 'a file', other: 'multiple files')} that come from a vault. To access ${Intl.plural(count, one: 'its', other: 'their')} content, you must unlock them."; - static String m1(groupID) => "Group n.${groupID}"; + static String m3(groupID) => "Group n.${groupID}"; - static String m2(count) => "${count} selected"; + static String m4(count) => "${count} selected"; - static String m3(unlockName) => + static String m5(unlockName) => "This group can be unlocked with: ${unlockName}."; final messages = _notInlinedMessages(_notInlinedMessages); @@ -36,7 +41,10 @@ class MessageLookup extends MessageLookupByLibrary { "addFiles": MessageLookupByLibrary.simpleMessage("Add files"), "appLegalese": MessageLookupByLibrary.simpleMessage( "The application \"Life Chest\" has been made by Theskyblockman with a ❤️ and a 🖥️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri"), - "areYouSure": MessageLookupByLibrary.simpleMessage("Are you sure?"), + "areYouSureClearVaults": MessageLookupByLibrary.simpleMessage( + "Are you sure to delete all vaults?"), + "areYouSureDeleteFiles": m0, + "areYouSureDeleteVault": m1, "biometrics": MessageLookupByLibrary.simpleMessage("Biometrics"), "biometricsAreLocal": MessageLookupByLibrary.simpleMessage( "Biometrics-locked chests can only be unlocked on the device it has been created on. Encrypted file export is unavailable."), @@ -60,7 +68,7 @@ class MessageLookup extends MessageLookupByLibrary { "delete": MessageLookupByLibrary.simpleMessage("Delete"), "deleteAllChests": MessageLookupByLibrary.simpleMessage("Delete all the chests"), - "detectedExportedFile": m0, + "detectedExportedFile": m2, "doNothing": MessageLookupByLibrary.simpleMessage("Do nothing"), "enterTheChestPassword": MessageLookupByLibrary.simpleMessage( "Please enter the password of this chest"), @@ -102,7 +110,7 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Export as an encrypted file"), "exportedFileDescription": MessageLookupByLibrary.simpleMessage( "A file exported from the Life Chest app and who needs to be unlocked to get more information about it."), - "group": m1, + "group": m3, "ignore": MessageLookupByLibrary.simpleMessage("Ignore"), "import": MessageLookupByLibrary.simpleMessage("Import"), "internalError": MessageLookupByLibrary.simpleMessage("Internal Error"), @@ -118,6 +126,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Loading elements"), "loadingImage": MessageLookupByLibrary.simpleMessage("Loading image"), "loadingVideo": MessageLookupByLibrary.simpleMessage("Loading video"), + "lostDataContBeRecovered": MessageLookupByLibrary.simpleMessage( + "This action is irreversible! All lost data can\'t be recovered."), "nameSortName": MessageLookupByLibrary.simpleMessage("Alphabetical order"), "newFolder": MessageLookupByLibrary.simpleMessage("New folder"), @@ -143,9 +153,9 @@ class MessageLookup extends MessageLookupByLibrary { "We successfully saved the file(s)"), "scheme": MessageLookupByLibrary.simpleMessage("Pattern"), "selectAll": MessageLookupByLibrary.simpleMessage("Select all"), - "selected": m2, + "selected": m4, "sortBy": MessageLookupByLibrary.simpleMessage("Sort by..."), - "unlockAbleBy": m3, + "unlockAbleBy": m5, "unlockChest": MessageLookupByLibrary.simpleMessage("Unlock the chest"), "unlockFile": MessageLookupByLibrary.simpleMessage("Unlock the file"), "unlockWizard": MessageLookupByLibrary.simpleMessage("Unlock wizard"), diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index 8d485e3..d50551f 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -21,14 +21,20 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'fr'; static String m0(count) => - "Nous avons détecté ${Intl.plural(count, one: 'un fichier', other: 'des fichiers')} provenant d\'un coffre. Pour accéder à ${Intl.plural(count, one: 'son', other: 'leur')} contenu, vous devez ${Intl.plural(count, one: 'le', other: 'les')} déverrouiller."; + "Êtes-vous sûr de supprimer ${count} ${Intl.plural(count, one: 'fichier', other: 'fichiers')}?"; - static String m1(groupID) => "Groupe n°${groupID}"; + static String m1(vaultName) => + "Êtes-vous sûr de supprimer \"${vaultName}\" ?"; static String m2(count) => + "Nous avons détecté ${Intl.plural(count, one: 'un fichier', other: 'des fichiers')} provenant d\'un coffre. Pour accéder à ${Intl.plural(count, one: 'son', other: 'leur')} contenu, vous devez ${Intl.plural(count, one: 'le', other: 'les')} déverrouiller."; + + static String m3(groupID) => "Groupe n°${groupID}"; + + static String m4(count) => "${count} ${Intl.plural(count, one: 'fichier sélectionné', other: 'fichiers sélectionnés')}"; - static String m3(unlockName) => + static String m5(unlockName) => "Ce groupe peut être débloquer grâce à : ${unlockName}."; final messages = _notInlinedMessages(_notInlinedMessages); @@ -38,7 +44,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Ajouter des fichiers"), "appLegalese": MessageLookupByLibrary.simpleMessage( "L\'application \"Life Chest\" a été créée par Theskyblockman avec ❤️ et un 🖥️ sous la licence MIT, Nous ne donnons aucune garantie, veuillez voir la license MIT pour plus d\'informations ©️ 2023 Haroun El Omri"), - "areYouSure": MessageLookupByLibrary.simpleMessage("Êtes-vous sûr ?"), + "areYouSureClearVaults": MessageLookupByLibrary.simpleMessage( + "Êtes-vous sûr de supprimer tous les coffres ?"), + "areYouSureDeleteFiles": m0, + "areYouSureDeleteVault": m1, "biometrics": MessageLookupByLibrary.simpleMessage("Empreinte digitale"), "biometricsAreLocal": MessageLookupByLibrary.simpleMessage( @@ -65,7 +74,7 @@ class MessageLookup extends MessageLookupByLibrary { "delete": MessageLookupByLibrary.simpleMessage("Supprimer"), "deleteAllChests": MessageLookupByLibrary.simpleMessage("Supprimer tous les coffres"), - "detectedExportedFile": m0, + "detectedExportedFile": m2, "doNothing": MessageLookupByLibrary.simpleMessage("Ne rien faire"), "enterTheChestPassword": MessageLookupByLibrary.simpleMessage( "Veuillez entrer le mot de passe de ce coffre"), @@ -107,7 +116,7 @@ class MessageLookup extends MessageLookupByLibrary { "Exporter en tant que fichier chiffré"), "exportedFileDescription": MessageLookupByLibrary.simpleMessage( "Um fichier exporté depuis Life Chest qui est chiffré et qui a donc besoin d\'être déchiffré pour être lu."), - "group": m1, + "group": m3, "ignore": MessageLookupByLibrary.simpleMessage("Ignorer"), "import": MessageLookupByLibrary.simpleMessage("Importer"), "internalError": MessageLookupByLibrary.simpleMessage("Erreur interne"), @@ -125,6 +134,8 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Chargement de l\'image"), "loadingVideo": MessageLookupByLibrary.simpleMessage("Chargement de la vidéo"), + "lostDataContBeRecovered": MessageLookupByLibrary.simpleMessage( + "Cette action est irréversible ! Toutes les données perdues ne pourront pas être récupérées"), "nameSortName": MessageLookupByLibrary.simpleMessage("Ordre alphabétique"), "newFolder": MessageLookupByLibrary.simpleMessage("Nouveau dossier"), @@ -150,9 +161,9 @@ class MessageLookup extends MessageLookupByLibrary { "Le(s) fichier(s) a/ont été sauvegardé(s)."), "scheme": MessageLookupByLibrary.simpleMessage("Modèle"), "selectAll": MessageLookupByLibrary.simpleMessage("Tout sélectionner"), - "selected": m2, + "selected": m4, "sortBy": MessageLookupByLibrary.simpleMessage("Trier par..."), - "unlockAbleBy": m3, + "unlockAbleBy": m5, "unlockChest": MessageLookupByLibrary.simpleMessage( "Veuillez déverrouiller le coffre"), "unlockFile": diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 08aecaa..d16e31e 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -520,11 +520,41 @@ class S { ); } - /// `Are you sure?` - String get areYouSure { + /// `Are you sure to delete all vaults?` + String get areYouSureClearVaults { return Intl.message( - 'Are you sure?', - name: 'areYouSure', + 'Are you sure to delete all vaults?', + name: 'areYouSureClearVaults', + desc: '', + args: [], + ); + } + + /// `Are you sure to delete "{vaultName}"?` + String areYouSureDeleteVault(String vaultName) { + return Intl.message( + 'Are you sure to delete "$vaultName"?', + name: 'areYouSureDeleteVault', + desc: '', + args: [vaultName], + ); + } + + /// `Are you sure to delete {count} {count, plural, =1{file} other{files}} ?` + String areYouSureDeleteFiles(int count) { + return Intl.message( + 'Are you sure to delete $count ${Intl.plural(count, one: 'file', other: 'files')} ?', + name: 'areYouSureDeleteFiles', + desc: '', + args: [count], + ); + } + + /// `This action is irreversible! All lost data can't be recovered.` + String get lostDataContBeRecovered { + return Intl.message( + 'This action is irreversible! All lost data can\'t be recovered.', + name: 'lostDataContBeRecovered', desc: '', args: [], ); diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 2e0d69f..35450f4 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -54,7 +54,24 @@ "wrongPassword": "Wrong password", "cancel": "Cancel", "ok": "OK", - "areYouSure": "Are you sure?", + "areYouSureClearVaults": "Are you sure to delete all vaults?", + "@areYouSureDeleteVault": { + "placeholders": { + "vaultName": { + "type": "String" + } + } + }, + "areYouSureDeleteVault": "Are you sure to delete \"{vaultName}\"?", + "@areYouSureDeleteFiles": { + "placeholders": { + "count": { + "type": "int" + } + } + }, + "areYouSureDeleteFiles": "Are you sure to delete {count} {count, plural, =1{file} other{files}} ?", + "lostDataContBeRecovered": "This action is irreversible! All lost data can't be recovered.", "yes": "Yes", "no": "No", "closeChestNotificationTitle": "You still have a chest opened", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 72cae49..4ec112b 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -48,7 +48,10 @@ "wrongPassword": "Mauvais mot de passe", "cancel": "Annuler", "ok": "OK", - "areYouSure": "Êtes-vous sûr ?", + "areYouSureClearVaults": "Êtes-vous sûr de supprimer tous les coffres ?", + "areYouSureDeleteVault": "Êtes-vous sûr de supprimer \"{vaultName}\" ?", + "areYouSureDeleteFiles": "Êtes-vous sûr de supprimer {count} {count, plural, =1{fichier} other{fichiers}}?", + "lostDataContBeRecovered": "Cette action est irréversible ! Toutes les données perdues ne pourront pas être récupérées", "yes": "Oui", "no": "Non", "closeChestNotificationTitle": "Vous avez toujours un coffre ouvert", diff --git a/lib/main.dart b/lib/main.dart index da998d9..7367cfd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -57,27 +57,28 @@ class LifeChestApp extends StatelessWidget { return DynamicColorBuilder(builder: (lightDynamic, darkDynamic) { ThemeData lightTheme = ThemeData( useMaterial3: true, - colorScheme: kDebugMode ? lightColorScheme : lightDynamic ?? lightColorScheme, + colorScheme: + kDebugMode ? lightColorScheme : lightDynamic ?? lightColorScheme, ); ThemeData darkTheme = ThemeData( useMaterial3: true, - colorScheme: kDebugMode ? darkColorScheme : darkDynamic ?? darkColorScheme, + colorScheme: + kDebugMode ? darkColorScheme : darkDynamic ?? darkColorScheme, ); return MaterialApp( - title: 'Life Chest', - localizationsDelegates: const [ - S.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - DefaultCupertinoLocalizations.delegate - ], - supportedLocales: S.delegate.supportedLocales, - theme: lightTheme, - darkTheme: darkTheme, - home: firstLaunch ? const WelcomePage() : const ChestMainPage() - ); + title: 'Life Chest', + localizationsDelegates: const [ + S.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + DefaultCupertinoLocalizations.delegate + ], + supportedLocales: S.delegate.supportedLocales, + theme: lightTheme, + darkTheme: darkTheme, + home: firstLaunch ? const WelcomePage() : const ChestMainPage()); }); } } @@ -117,7 +118,12 @@ class ChestMainPageState extends State { showDialog( context: context, builder: (context) => AlertDialog( - title: Text(S.of(context).areYouSure), + title: Text(S + .of(context) + .areYouSureClearVaults), + content: Text(S + .of(context) + .lostDataContBeRecovered), actions: [ TextButton( onPressed: () => Navigator.pop( @@ -143,8 +149,8 @@ class ChestMainPageState extends State { child: Text(S.of(context).deleteAllChests)), PopupMenuItem( onTap: () async { - - PackageInfo packageInfo = await PackageInfo.fromPlatform(); + PackageInfo packageInfo = + await PackageInfo.fromPlatform(); WidgetsBinding.instance .addPostFrameCallback((timeStamp) { @@ -152,7 +158,7 @@ class ChestMainPageState extends State { context: context, applicationVersion: packageInfo.version, applicationIcon: - Image.asset('logo.png', height: 64, width: 64), + Image.asset('logo.png', height: 64, width: 64), applicationLegalese: S.of(context).appLegalese, ); }); @@ -188,17 +194,19 @@ class ChestMainPageState extends State { body: VaultsManager.storedVaults.isEmpty ? Center( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.lock_outline, size: 128, color: Theme.of(context).colorScheme.outline), - Text( - S.of(context).noChestsCreatedYet, - textScaleFactor: 2.5, - textAlign: TextAlign.center, - style: TextStyle(color: Theme.of(context).colorScheme.outline), - ) - ], - )) + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.lock_outline, + size: 128, color: Theme.of(context).colorScheme.outline), + Text( + S.of(context).noChestsCreatedYet, + textScaleFactor: 2.5, + textAlign: TextAlign.center, + style: + TextStyle(color: Theme.of(context).colorScheme.outline), + ) + ], + )) : ListView.builder( itemBuilder: (context, index) { Vault chest = VaultsManager.storedVaults[index]; @@ -209,14 +217,17 @@ class ChestMainPageState extends State { UnlockTester tester = UnlockTester( chest.unlockMechanismType, chest.additionalUnlockData, - onKeyIssued: (issuedKey, didPushed, mechanismUsed) => - onKeyIssued(chest, issuedKey, didPushed, mechanismUsed)); + onKeyIssued: + (issuedKey, didPushed, mechanismUsed) => + onKeyIssued(chest, issuedKey, didPushed, + mechanismUsed)); if (tester.shouldUseChooser(context)) { Navigator.push( context, MaterialPageRoute( builder: (context) => UnlockChooser( - onKeyIssued: (issuedKey, didPushed, mechanismUsed) => + onKeyIssued: (issuedKey, didPushed, + mechanismUsed) => onKeyIssued(chest, issuedKey, didPushed, mechanismUsed)))); } @@ -234,9 +245,41 @@ class ChestMainPageState extends State { onTap: () { WidgetsBinding.instance .addPostFrameCallback((timeStamp) { - setState(() { - VaultsManager.deleteVault(chest); - VaultsManager.loadVaults(); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(S + .of(context) + .areYouSureDeleteVault( + chest.name)), + content: Text(S + .of(context) + .lostDataContBeRecovered), + actions: [ + TextButton( + onPressed: () => + Navigator.pop( + context, + false), + child: Text(S + .of(context) + .no)), + TextButton( + onPressed: () => + Navigator.pop( + context, + true), + child: Text(S + .of(context) + .yes)) + ])).then((value) { + if (value == true) { + setState(() { + VaultsManager.deleteVault( + chest); + VaultsManager.loadVaults(); + }); + } }); }); }, @@ -275,24 +318,30 @@ class ChestMainPageState extends State { child: Text(S.of(context).rename), ) ]; - }) - ), + })), )); }, itemCount: VaultsManager.storedVaults.length)); } - void onKeyIssued(Vault chest, SecretKey issuedKey, bool didPush, UnlockMechanism mechanismUsed) async { + void onKeyIssued(Vault chest, SecretKey issuedKey, bool didPush, + UnlockMechanism mechanismUsed) async { chest.encryptionKey = issuedKey; chest.locked = !(await VaultsManager.testVaultKey(chest)); if (!chest.locked) { if (context.mounted) { if (didPush) { - Navigator.pushReplacement(context, - MaterialPageRoute(builder: (context) => FileExplorer(chest, mechanismUsed.isEncryptedExportAllowed()))); + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => FileExplorer( + chest, mechanismUsed.isEncryptedExportAllowed()))); } else { - Navigator.push(context, - MaterialPageRoute(builder: (context) => FileExplorer(chest, mechanismUsed.isEncryptedExportAllowed()))); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => FileExplorer( + chest, mechanismUsed.isEncryptedExportAllowed()))); } } } From a109aaf76b9099c533bf3f7de00eb773c0001877 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Fri, 14 Jul 2023 22:26:41 +0200 Subject: [PATCH 03/13] :bug: Fixed the file deletion working even if no is pressed. --- lib/file_explorer/file_explorer.dart | 61 +++++++++++++++------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/lib/file_explorer/file_explorer.dart b/lib/file_explorer/file_explorer.dart index 82372a3..73391ab 100644 --- a/lib/file_explorer/file_explorer.dart +++ b/lib/file_explorer/file_explorer.dart @@ -607,40 +607,43 @@ class FileExplorerState extends State { context, true), child: Text(S.of(context).yes)) ])).then((value) async { - for (FileThumbnail thumbnail in filesToDelete) { - if (thumbnail.file.existsSync()) { - thumbnail.file.deleteSync(); - } - if (thumbnail.placeholder == - FileThumbnailsPlaceholder.folder) { - for (MapEntry innerRawThumbnail - in List.from(map.entries)) { - if (isWithin(thumbnail.fullLocalPath, - innerRawThumbnail.value['name'])) { - File innerRawThumbnailFile = File(join( - widget.vault.path, - innerRawThumbnail.key)); - if (innerRawThumbnailFile - .existsSync()) { - innerRawThumbnailFile.deleteSync(); + if (value == true) { + for (FileThumbnail thumbnail + in filesToDelete) { + if (thumbnail.file.existsSync()) { + thumbnail.file.deleteSync(); + } + if (thumbnail.placeholder == + FileThumbnailsPlaceholder.folder) { + for (MapEntry innerRawThumbnail + in List.from(map.entries)) { + if (isWithin(thumbnail.fullLocalPath, + innerRawThumbnail.value['name'])) { + File innerRawThumbnailFile = File( + join(widget.vault.path, + innerRawThumbnail.key)); + if (innerRawThumbnailFile + .existsSync()) { + innerRawThumbnailFile.deleteSync(); + } + map.remove(innerRawThumbnail.key); } - map.remove(innerRawThumbnail.key); } } + map.remove(thumbnail.localPath); } - map.remove(thumbnail.localPath); + List encryptedMap = + (await VaultsManager.encryptMap( + widget.vault, map))!; + setState(() { + // TODO: Forensic should be made to see if iOS/Android keeps any of the file data in storage, if yes fill the file with null bytes and then delete it. + File(join(widget.vault.path, '.map')) + .writeAsBytesSync(encryptedMap); + isSelectionMode = false; + thumbnailCollector = reloadThumbnails(); + }); } - List encryptedMap = - (await VaultsManager.encryptMap( - widget.vault, map))!; - setState(() { - // TODO: Forensic should be made to see if iOS/Android keeps any of the file data in storage, if yes fill the file with null bytes and then delete it. - File(join(widget.vault.path, '.map')) - .writeAsBytesSync(encryptedMap); - isSelectionMode = false; - thumbnailCollector = reloadThumbnails(); - }); }); }); }, From 708485b82a4344a45d442fe370dd08113d45e21a Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Fri, 14 Jul 2023 22:31:10 +0200 Subject: [PATCH 04/13] Update flutter.yml to make passing tests easier --- .github/workflows/flutter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml index c688d8e..5552b68 100644 --- a/.github/workflows/flutter.yml +++ b/.github/workflows/flutter.yml @@ -29,5 +29,5 @@ jobs: channel: 'stable' cache: true - run: flutter pub get - - run: flutter analyze + - run: flutter analyze --no-fatal-infos --no-fatal-warnings - run: flutter test From 92190f3dd08da613678f2fe3cc1bad508c82c18f Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Fri, 14 Jul 2023 22:48:10 +0200 Subject: [PATCH 05/13] Update PRIVACY.md to be more specific --- PRIVACY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PRIVACY.md b/PRIVACY.md index 8854270..52c5a37 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -1 +1 @@ -The application, Life Chest does not collect, use or receive any user data. The user's privacy is our priority. All possible data we harvest is how many people have downloaded our application. +The application, Life Chest does not collect, use nor store any user personal data. The user's privacy is our priority. All possible data we harvest is provided by Google LLC and only monitors the application growth (installation success rate, total downloads, impressions and other metrics all in this same scope) for statistical purpose. From 27d4f1652af798ad5bdb1a9998bc78b11813cf39 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Sat, 15 Jul 2023 22:07:41 +0200 Subject: [PATCH 06/13] :building_construction: Introducing nonces and MACs to encrypt data more safely, transition script needs to be made. (Like a banner to upgrade the chest) --- lib/file_explorer/file_explorer.dart | 37 +++---- lib/file_explorer/file_unlock_wizard.dart | 5 +- lib/file_recovery/file_exporter.dart | 18 ++-- .../single_threaded_recovery.dart | 96 +++++++++++-------- lib/file_viewers/audio.dart | 5 +- lib/file_viewers/documents.dart | 3 +- lib/file_viewers/image.dart | 5 +- lib/file_viewers/video.dart | 3 +- lib/generated/intl/messages_en.dart | 2 + lib/generated/intl/messages_fr.dart | 4 +- lib/generated/l10n.dart | 10 ++ lib/l10n/intl_en.arb | 1 + lib/l10n/intl_fr.arb | 3 +- lib/main.dart | 4 + lib/vault.dart | 22 +++-- pubspec.lock | 72 ++++++++++---- pubspec.yaml | 3 +- test/file_encrypt_and_decrypt_test.dart | 6 +- test/test_file_to_encrypt_backup.txt | 7 -- 19 files changed, 199 insertions(+), 107 deletions(-) delete mode 100644 test/test_file_to_encrypt_backup.txt diff --git a/lib/file_explorer/file_explorer.dart b/lib/file_explorer/file_explorer.dart index e1d6458..8f8df0a 100644 --- a/lib/file_explorer/file_explorer.dart +++ b/lib/file_explorer/file_explorer.dart @@ -440,20 +440,24 @@ class FileExplorerState extends State { final receivePort = ReceivePort(); + List dataToExport = []; + + for(FileThumbnail fileToExport in filesToExport) { + String unsafeData = (await VaultsManager.nonceStorage.read(key: fileToExport.localPath))!; + Map unsafeDataClone = Map.from(fileToExport.data); + unsafeDataClone['nonce'] = unsafeData; + dataToExport.add(( + fileToExport.localPath, + encryptionKey, + unsafeDataClone, + fileToExport.file.readAsBytesSync(), + widget.vault.unlockMechanismType, + widget.vault.additionalUnlockData + )); + } + Isolate.spawn(exportEncryptedThumbnails, - (receivePort.sendPort, List.generate(filesToExport.length, - (index) { - FileThumbnail fileToExport = - filesToExport[index]; - return ( - fileToExport.localPath, - encryptionKey, - fileToExport.data, - fileToExport.file.readAsBytesSync(), - widget.vault.unlockMechanismType, - widget.vault.additionalUnlockData - ); - }))); + (receivePort.sendPort, dataToExport)); List decryptedFiles = []; @@ -480,7 +484,7 @@ class FileExplorerState extends State { .showSnackBar(SnackBar( content: Text(S .of(context) - .savedToFolder))); + .savedToFolderWarning, style: const TextStyle(color: Colors.amber)))); } }); } @@ -536,9 +540,10 @@ class FileExplorerState extends State { for (FileThumbnail thumbnail in filesToExport) { Stream> exportedFile = - SingleThreadedRecovery.loadAndDecryptFile( + await SingleThreadedRecovery.loadAndDecryptFile( widget.vault.encryptionKey!, - thumbnail.file); + thumbnail.file, + Mac(thumbnail.data['mac'])); File fileToSaveTo = File(join(saveLocation.path, thumbnail.name)); diff --git a/lib/file_explorer/file_unlock_wizard.dart b/lib/file_explorer/file_unlock_wizard.dart index 6983dc2..153a2bb 100644 --- a/lib/file_explorer/file_unlock_wizard.dart +++ b/lib/file_explorer/file_unlock_wizard.dart @@ -26,15 +26,16 @@ class FileUnlockWizardState extends State { Future<(Map metadata, List data)> getOrUnlockFile( List fileToUnlock, SecretKey key) async { + print(unlockedMap); for (List unlockedFile in List.from(unlockedMap.keys)) { if (listEquals(fileToUnlock, unlockedFile)) { return unlockedMap[unlockedFile]!; } } - + print(unlockedMap); unlockedMap[fileToUnlock] = (await FileExporter.importFile(fileToUnlock, key))!; - + print(unlockedMap); return unlockedMap[fileToUnlock]!; } diff --git a/lib/file_recovery/file_exporter.dart b/lib/file_recovery/file_exporter.dart index de07990..e71a6bc 100644 --- a/lib/file_recovery/file_exporter.dart +++ b/lib/file_recovery/file_exporter.dart @@ -54,10 +54,10 @@ class FileExporter { // Signature finalExportedFile.addAll('Life Chest Encrypted File'.codeUnits); String encodedMetadata = jsonEncode(fileMapData); - List encryptedMetadata = (await VaultsManager.cipher.encrypt( + List encryptedMetadata = (await VaultsManager.secondaryCipher.encrypt( utf8.encode(encodedMetadata), secretKey: encryptionKey, - nonce: Uint8List(VaultsManager.cipher.nonceLength))) + nonce: Uint8List(VaultsManager.secondaryCipher.nonceLength))) .cipherText; // The hash of the key to check if 2 files were encrypted using the same key (Always 64 chars long) finalExportedFile.addAll(sha256 @@ -79,7 +79,7 @@ class FileExporter { // The file fake name used internally by the app to identify it without giving its clear name, logically this isn't sensitive information so we can give the encrypted and clear file fake name so the app can say if a file is valid or not by detecting the "|" char and dividing the file name length by 2. finalExportedFile.addAll(fileFakeName.codeUnits); - finalExportedFile.addAll((await VaultsManager.cipher.encrypt( + finalExportedFile.addAll((await VaultsManager.secondaryCipher.encrypt( fileFakeName.codeUnits, secretKey: encryptionKey, nonce: Uint8List(VaultsManager.cipher.nonceLength))) @@ -131,9 +131,9 @@ class FileExporter { _splitListBySeparator(exportedFile, '|'.codeUnits[0], 4); // No need to round, the length is even whatever happening because of the source multiplication by 2 rule SecretBox encryptedName = SecretBox(List.from(elements[3].sublist(32, 64)), - nonce: Uint8List(VaultsManager.cipher.nonceLength), mac: Mac.empty); + nonce: Uint8List(VaultsManager.secondaryCipher.nonceLength), mac: Mac.empty); return listEquals( - await VaultsManager.cipher + await VaultsManager.secondaryCipher .decrypt(encryptedName, secretKey: encryptionKey), elements[3].sublist(0, 32)); } @@ -150,18 +150,20 @@ class FileExporter { int metadataLength = int.parse(String.fromCharCodes(elements[2])); Map metadata = jsonDecode(String.fromCharCodes(utf8 - .decode(await VaultsManager.cipher.decrypt( + .decode(await VaultsManager.secondaryCipher.decrypt( SecretBox(elements[3].sublist(64, 64 + metadataLength), - nonce: Uint8List(VaultsManager.cipher.nonceLength), + nonce: Uint8List(VaultsManager.secondaryCipher.nonceLength), mac: Mac.empty), secretKey: encryptionKey)) .codeUnits)); List fileData = await VaultsManager.cipher.decrypt( SecretBox(elements[3].sublist(64 + metadataLength), - nonce: Uint8List(VaultsManager.cipher.nonceLength), mac: Mac.empty), + nonce: metadata.containsKey('nonce') ? base64Decode(metadata['nonce']) : Uint8List(VaultsManager.secondaryCipher.nonceLength), mac: Mac(List.from(metadata['mac']))), secretKey: encryptionKey); + metadata.remove('nonce'); + return (metadata, fileData); } diff --git a/lib/file_recovery/single_threaded_recovery.dart b/lib/file_recovery/single_threaded_recovery.dart index e6d734c..00c67d8 100644 --- a/lib/file_recovery/single_threaded_recovery.dart +++ b/lib/file_recovery/single_threaded_recovery.dart @@ -4,11 +4,10 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:cryptography/cryptography.dart'; -import 'package:ffmpeg_kit_flutter/ffprobe_kit.dart'; -import 'package:ffmpeg_kit_flutter/media_information_session.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/services.dart'; import 'package:flutter_media_metadata/flutter_media_metadata.dart'; +import 'package:flutter_video_info/flutter_video_info.dart'; import 'package:life_chest/vault.dart'; import 'package:mime/mime.dart'; import 'package:path/path.dart'; @@ -18,20 +17,20 @@ import '../file_explorer/file_placeholder.dart'; class SingleThreadedRecovery { /// Loads in memory the full decrypted content of [fileToRead] with [encryptionKey] and returns the decrypted data all at once static Future loadAndDecryptFullFile( - SecretKey encryptionKey, File fileToRead) async { - return Uint8List.fromList(await VaultsManager.cipher.decrypt( + SecretKey encryptionKey, File fileToRead, Mac mac, [Chacha20? cipher, bool isTesting = false]) async { + return Uint8List.fromList(await (cipher ?? VaultsManager.cipher).decrypt( SecretBox(fileToRead.readAsBytesSync(), - nonce: Uint8List(VaultsManager.cipher.nonceLength), mac: Mac.empty), + nonce: isTesting ? Uint8List((cipher ?? VaultsManager.cipher).nonceLength) : base64Decode((await VaultsManager.nonceStorage.read(key: basename(fileToRead.path)))!), mac: mac), secretKey: encryptionKey)); } /// Loads in memory the full decrypted content of [fileToRead] with [encryptionKey] and returns the decrypted data incrementally by data chunks - static Stream> loadAndDecryptFile( - SecretKey encryptionKey, File fileToRead) { - return VaultsManager.cipher.decryptStream(fileToRead.openRead(), + static Future>> loadAndDecryptFile( + SecretKey encryptionKey, File fileToRead, Mac mac, [Chacha20? cipher, bool isTesting = false]) async { + return (cipher ?? VaultsManager.cipher).decryptStream(fileToRead.openRead(), secretKey: encryptionKey, - nonce: Uint8List(VaultsManager.cipher.nonceLength), - mac: Mac.empty); + nonce: isTesting ? Uint8List((cipher ?? VaultsManager.cipher).nonceLength) : base64Decode((await VaultsManager.nonceStorage.read(key: basename(fileToRead.path)))!), + mac: mac); } /// Selects the portion to decrypt and decrypts it (maybe the file reading part could be worked on) @@ -39,12 +38,14 @@ class SingleThreadedRecovery { SecretKey encryptionKey, File fileToRead, int startByte, - int endByte) { + int endByte, + Mac mac, + [Chacha20? cipher, bool isTesting = false]) { int currentLength = startByte; return fileToRead.openRead(startByte, endByte).asyncMap((event) async { currentLength += event.length; - return await VaultsManager.cipher - .decrypt(SecretBox(event, nonce: Uint8List(VaultsManager.cipher.nonceLength), mac: Mac.empty), secretKey: encryptionKey, keyStreamIndex: currentLength - event.length); + return await (cipher ?? VaultsManager.cipher) + .decrypt(SecretBox(event, nonce: isTesting ? Uint8List((cipher ?? VaultsManager.cipher).nonceLength) : base64Decode((await VaultsManager.nonceStorage.read(key: basename(fileToRead.path)))!), mac: mac), secretKey: encryptionKey, keyStreamIndex: currentLength - event.length); }); } @@ -55,33 +56,18 @@ class SingleThreadedRecovery { String localPath, String? rootFolderPath, {File? createdFile, - (Map metadata, List data)? importedFile}) async { + (Map metadata, List data)? importedFile, bool isTesting = false}) async { String fileName = md5RandomFileName(); File fileToCreate = File(join(vaultPath, fileName)); await fileToCreate.create(recursive: true); - if (createdFile != null) { - IOSink fileToCreateSink = fileToCreate.openWrite(); - try { - final clearTextStream = createdFile.openRead(); - final encryptedStream = VaultsManager.cipher.encryptStream( - clearTextStream, - secretKey: encryptionKey, - nonce: Uint8List(VaultsManager.cipher.nonceLength), - onMac: (Mac mac) {}); - await fileToCreateSink.addStream(encryptedStream); - } finally { - fileToCreateSink.close(); - } - } else { - fileToCreate.writeAsBytesSync( - (await VaultsManager.cipher.encrypt( - importedFile!.$2, - secretKey: encryptionKey, - nonce: Uint8List(VaultsManager.cipher.nonceLength), - )).cipherText - ); + Uint8List nonce = Uint8List.fromList(List.generate(VaultsManager.cipher.nonceLength, (index) => SecureRandom.safe.nextInt(256))); + if(!isTesting) { + await VaultsManager.nonceStorage.write(key: fileName, value: base64Encode(nonce)); } + + Completer> macReceiver = Completer(); + String? type; if (createdFile != null) { @@ -120,21 +106,53 @@ class SingleThreadedRecovery { } } else if (placeholder == FileThumbnailsPlaceholder.videos) { if (createdFile != null) { - MediaInformationSession result = await FFprobeKit.getMediaInformation(createdFile.absolute.path); - - finalData['videoData'] = result.getMediaInformation()!.getAllProperties(); - + VideoData result = (await FlutterVideoInfo().getVideoInfo(createdFile.absolute.path))!; + finalData['videoData'] = {}; + finalData['videoData']['width'] = result.width!; + finalData['videoData']['height'] = result.height!; + finalData['type'] = result.mimetype!; } else { finalData['videoData'] = importedFile!.$1.containsKey('videoData') ? importedFile.$1['videoData'] : {}; } } + if (createdFile != null) { + IOSink fileToCreateSink = fileToCreate.openWrite(); + try { + final clearTextStream = createdFile.openRead(); + final encryptedStream = VaultsManager.cipher.encryptStream( + clearTextStream, + secretKey: encryptionKey, + nonce: nonce, + onMac: (Mac mac) async { + macReceiver.complete(mac.bytes); + }); + await fileToCreateSink.addStream(encryptedStream); + } finally { + fileToCreateSink.close(); + } + } else { + SecretBox encryptedData = await VaultsManager.cipher.encrypt( + importedFile!.$2, + secretKey: encryptionKey, + nonce: nonce, + ); + fileToCreate.writeAsBytesSync( + encryptedData.cipherText + ); + macReceiver.complete(encryptedData.mac.bytes); + } + + List mac = await macReceiver.future; + try { createdFile?.deleteSync(recursive: true); } catch (e) { // Ignore } + finalData['mac'] = mac; + return (fileName, finalData); } diff --git a/lib/file_viewers/audio.dart b/lib/file_viewers/audio.dart index 18b76e7..178e861 100644 --- a/lib/file_viewers/audio.dart +++ b/lib/file_viewers/audio.dart @@ -12,6 +12,7 @@ import 'package:flutter/material.dart'; import 'package:life_chest/generated/l10n.dart'; import 'package:life_chest/file_recovery/single_threaded_recovery.dart'; import 'package:life_chest/file_viewers/file_viewer.dart'; +import 'package:life_chest/vault.dart'; import 'package:path/path.dart' as p; import 'package:rxdart/rxdart.dart'; @@ -350,8 +351,8 @@ class EncryptedAudioSource extends StreamAudioSource { contentLength: (end ?? fileByteLength) - (start ?? 0), offset: start ?? 0, stream: start == null && end == null ? - SingleThreadedRecovery.loadAndDecryptFile(encryptionKey, fileToRead) : - SingleThreadedRecovery.loadAndDecryptPartialFile(encryptionKey, fileToRead, start ?? 0, end ?? fileByteLength), + await SingleThreadedRecovery.loadAndDecryptFile(encryptionKey, fileToRead, Mac.empty) : + SingleThreadedRecovery.loadAndDecryptPartialFile(encryptionKey, fileToRead, start ?? 0, end ?? fileByteLength, Mac.empty, VaultsManager.secondaryCipher), contentType: mimeType, rangeRequestsSupported: true); } diff --git a/lib/file_viewers/documents.dart b/lib/file_viewers/documents.dart index 968ee7e..addf81c 100644 --- a/lib/file_viewers/documents.dart +++ b/lib/file_viewers/documents.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cryptography/cryptography.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; @@ -52,7 +53,7 @@ class DocumentViewer extends FileViewer { ? DocumentType.pdf : DocumentType.plainText; loadedDocument = await SingleThreadedRecovery.loadAndDecryptFullFile( - fileVault.encryptionKey!, fileToRead); + fileVault.encryptionKey!, fileToRead, Mac(List.from(fileData['mac']))); return true; } diff --git a/lib/file_viewers/image.dart b/lib/file_viewers/image.dart index 90458a6..dd6a7fc 100644 --- a/lib/file_viewers/image.dart +++ b/lib/file_viewers/image.dart @@ -1,3 +1,4 @@ +import 'package:cryptography/cryptography.dart'; import 'package:flutter/material.dart'; import 'package:life_chest/generated/l10n.dart'; import 'package:life_chest/file_explorer/file_explorer.dart'; @@ -36,7 +37,7 @@ class ImageViewer extends FileViewer { Future load(BuildContext context) async { loadedImage = Image.memory( await SingleThreadedRecovery.loadAndDecryptFullFile( - fileVault.encryptionKey!, fileToRead)); + fileVault.encryptionKey!, fileToRead, Mac(List.from(fileData['mac'])))); return true; } @@ -52,7 +53,7 @@ class ImageViewer extends FileViewer { Future onFocus() async { loadedImage = Image.memory( await SingleThreadedRecovery.loadAndDecryptFullFile( - fileVault.encryptionKey!, fileToRead)); + fileVault.encryptionKey!, fileToRead, Mac(List.from(fileData['mac'])))); } @override diff --git a/lib/file_viewers/video.dart b/lib/file_viewers/video.dart index 56643e8..1d3c0d6 100644 --- a/lib/file_viewers/video.dart +++ b/lib/file_viewers/video.dart @@ -1,4 +1,5 @@ import 'package:better_player/better_player.dart'; +import 'package:cryptography/cryptography.dart'; import 'package:flutter/material.dart'; import 'package:life_chest/file_recovery/single_threaded_recovery.dart'; import 'package:life_chest/file_viewers/file_viewer.dart'; @@ -31,7 +32,7 @@ class VideoViewer extends FileViewer { Future load(BuildContext context) async { dataSource = BetterPlayerDataSource(BetterPlayerDataSourceType.memory, '', bytes: await SingleThreadedRecovery.loadAndDecryptFullFile( - fileVault.encryptionKey!, fileToRead), videoExtension: extension(fileName)); + fileVault.encryptionKey!, fileToRead, Mac(List.from(fileData['mac']))), videoExtension: extension(fileName)); // ignore: use_build_context_synchronously if(!context.mounted) return false; diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index ca55d8b..171b576 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -141,6 +141,8 @@ class MessageLookup extends MessageLookupByLibrary { "rename": MessageLookupByLibrary.simpleMessage("Rename"), "savedToFolder": MessageLookupByLibrary.simpleMessage( "We successfully saved the file(s)"), + "savedToFolderWarning": MessageLookupByLibrary.simpleMessage( + "We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors or its contributor cannot be held liable for any divulged data."), "scheme": MessageLookupByLibrary.simpleMessage("Pattern"), "selectAll": MessageLookupByLibrary.simpleMessage("Select all"), "selected": m2, diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index 8d485e3..c95181e 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -147,7 +147,9 @@ class MessageLookup extends MessageLookupByLibrary { "Veuillez utiliser votre empreinte digitale pour déverrouiller le coffre"), "rename": MessageLookupByLibrary.simpleMessage("Renommer"), "savedToFolder": MessageLookupByLibrary.simpleMessage( - "Le(s) fichier(s) a/ont été sauvegardé(s)."), + "Nous avons enregistré avec succès le(s) fichier(s)."), + "savedToFolderWarning": MessageLookupByLibrary.simpleMessage( + "Nous avons enregistré avec succès le(s) fichier(s). ATTENTION! Ces fichiers chiffrés sont plus vulnérables dans ce format, ne les distribuez pas publiquement. Life Chest, ses auteurs ou son contributeur ne peuvent être tenus responsables des données divulguées."), "scheme": MessageLookupByLibrary.simpleMessage("Modèle"), "selectAll": MessageLookupByLibrary.simpleMessage("Tout sélectionner"), "selected": m2, diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 08aecaa..cb39dbb 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -840,6 +840,16 @@ class S { ); } + /// `We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors or its contributor cannot be held liable for any divulged data.` + String get savedToFolderWarning { + return Intl.message( + 'We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors or its contributor cannot be held liable for any divulged data.', + name: 'savedToFolderWarning', + desc: '', + args: [], + ); + } + /// `Import` String get import { return Intl.message( diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 2e0d69f..67800f1 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -93,6 +93,7 @@ "ignore": "Ignore", "lifeChestBulkSave": "Life Chest bulk file export", "savedToFolder": "We successfully saved the file(s)", + "savedToFolderWarning": "We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors or its contributor cannot be held liable for any divulged data.", "import": "Import", "@group": { "placeholders": { diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 72cae49..f42b18c 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -78,7 +78,8 @@ "exportAsCleartext": "Exporter en tant que fichier lisible (fichier non chiffré)", "exportAsEncrypted": "Exporter en tant que fichier chiffré", "lifeChestBulkSave": "Sauvegarde de fichiers en masse", - "savedToFolder": "Le(s) fichier(s) a/ont été sauvegardé(s).", + "savedToFolder": "Nous avons enregistré avec succès le(s) fichier(s).", + "savedToFolderWarning": "Nous avons enregistré avec succès le(s) fichier(s). ATTENTION! Ces fichiers chiffrés sont plus vulnérables dans ce format, ne les distribuez pas publiquement. Life Chest, ses auteurs ou son contributeur ne peuvent être tenus responsables des données divulguées.", "import": "Importer", "group": "Groupe n°{groupID}", "unlockAbleBy": "Ce groupe peut être débloquer grâce à : {unlockName}.", diff --git a/lib/main.dart b/lib/main.dart index da998d9..1d1446e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:life_chest/color_schemes.g.dart'; import 'package:life_chest/file_explorer/file_explorer.dart'; import 'package:life_chest/file_viewers/audio.dart'; @@ -27,6 +28,9 @@ void main() async { VaultsManager.appFolder = appDocuments.path; VaultsManager.mainConfigFile = File('${VaultsManager.appFolder}/.config'); VaultsManager.packageInfo = await PackageInfo.fromPlatform(); + VaultsManager.nonceStorage = const FlutterSecureStorage(aOptions: AndroidOptions( + encryptedSharedPreferences: true, + ), iOptions: IOSOptions(groupId: 'fr.theskyblockman')); bool firstLaunch = !VaultsManager.mainConfigFile.existsSync() || kDebugMode; if (firstLaunch) { VaultsManager.mainConfigFile.createSync(); diff --git a/lib/vault.dart b/lib/vault.dart index bd68988..f845e3f 100644 --- a/lib/vault.dart +++ b/lib/vault.dart @@ -5,6 +5,7 @@ import 'dart:math'; import 'package:crypto/crypto.dart' as crypto; import 'package:cryptography/cryptography.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:life_chest/file_explorer/file_explorer.dart'; import 'package:life_chest/file_explorer/file_sort_methods.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -25,9 +26,11 @@ class VaultsManager { static late final String appFolder; static late final File mainConfigFile; static late final PackageInfo packageInfo; - static final cipher = Chacha20(macAlgorithm: MacAlgorithm.empty); + static final cipher = Chacha20.poly1305Aead(); + static final secondaryCipher = Chacha20(macAlgorithm: MacAlgorithm.empty); // Mainly used for file exportation so that no MAC is required. static bool shouldUpdateVaultList = false; static Map globalAdditionalUnlockData = {}; + static late final FlutterSecureStorage nonceStorage; static void saveVaults() { mainConfigFile.writeAsStringSync(jsonEncode({ @@ -77,6 +80,8 @@ class VaultsManager { secretKey: cryptKey, nonce: Uint8List(cipher.nonceLength)); + await nonceStorage.write(key: keyFile.absolute.path, value: base64Encode(encryptedWitnessFile.mac.bytes)); + File witnessFile = File(p.join(path, '.witness')); witnessFile.createSync(recursive: true); witnessFile.writeAsBytesSync(encryptedWitnessFile.cipherText); @@ -117,7 +122,7 @@ class VaultsManager { String decryptedWitnessFile = utf8.decode( await cipher.decrypt( SecretBox(witnessFile.readAsBytesSync(), - nonce: Uint8List(cipher.nonceLength), mac: Mac.empty), + nonce: Uint8List(cipher.nonceLength), mac: Mac(base64Decode((await nonceStorage.read(key: witnessFile.absolute.path))!))), secretKey: vault.encryptionKey!), allowMalformed: true); return decryptedWitnessFile == @@ -152,10 +157,13 @@ class VaultsManager { Vault vault, Map initialMap) async { if (vault.encryptionKey == null) return null; - return (await cipher.encrypt(utf8.encode(jsonEncode(initialMap)), - secretKey: vault.encryptionKey!, - nonce: Uint8List(cipher.nonceLength))) - .cipherText; + SecretBox encryptedMap = (await cipher.encrypt(utf8.encode(jsonEncode(initialMap)), + secretKey: vault.encryptionKey!, + nonce: Uint8List(cipher.nonceLength))); + + await nonceStorage.write(key: vault.filesMetadataBankPath, value: base64Encode(encryptedMap.mac.bytes)); + + return encryptedMap.cipherText; } static Future?> decryptMap( @@ -164,7 +172,7 @@ class VaultsManager { Map decryptedMap = jsonDecode(utf8.decode( await cipher.decrypt( SecretBox(encryptedMap, - nonce: Uint8List(cipher.nonceLength), mac: Mac.empty), + nonce: Uint8List(cipher.nonceLength), mac: Mac(base64Decode((await nonceStorage.read(key: vault.filesMetadataBankPath))!))), secretKey: vault.encryptionKey!))); return decryptedMap; diff --git a/pubspec.lock b/pubspec.lock index 7d1fb56..c07c035 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -250,22 +250,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" - ffmpeg_kit_flutter: - dependency: "direct main" - description: - name: ffmpeg_kit_flutter - sha256: "2b13913a5850d5c0149fe5a322770e72b107e0941d112a5334bce71d91051134" - url: "https://pub.dev" - source: hosted - version: "5.1.0-LTS" - ffmpeg_kit_flutter_platform_interface: - dependency: transitive - description: - name: ffmpeg_kit_flutter_platform_interface - sha256: addf046ae44e190ad0101b2fde2ad909a3cd08a2a109f6106d2f7048b7abedee - url: "https://pub.dev" - source: hosted - version: "0.2.1" file: dependency: transitive description: @@ -340,11 +324,67 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.15" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: "98352186ee7ad3639ccc77ad7924b773ff6883076ab952437d20f18a61f0a7c5" + url: "https://pub.dev" + source: hosted + version: "8.0.0" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "0912ae29a572230ad52d8a4697e5518d7f0f429052fd51df7e5a7952c7efe2a3" + url: "https://pub.dev" + source: hosted + version: "1.1.3" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: "083add01847fc1c80a07a08e1ed6927e9acd9618a35e330239d4422cd2a58c50" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: b3773190e385a3c8a382007893d678ae95462b3c2279e987b55d140d3b0cb81b + url: "https://pub.dev" + source: hosted + version: "1.0.1" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: "42938e70d4b872e856e678c423cc0e9065d7d294f45bc41fc1981a4eb4beaffe" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: fc2910ec9b28d60598216c29ea763b3a96c401f0ce1d13cdf69ccb0e5c93c3ee + url: "https://pub.dev" + source: hosted + version: "2.0.0" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_video_info: + dependency: "direct main" + description: + name: flutter_video_info + sha256: "0fd0c7dec11feda0174f77dc12274bd024d31937376804b98d95c161d7cdf12b" + url: "https://pub.dev" + source: hosted + version: "1.3.1" flutter_web_plugins: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index b7ac905..eb1df15 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,7 +38,8 @@ dependencies: flutter_pdfview: ^1.3.1 package_info_plus: ^3.1.2 document_file_save_plus: ^2.0.0 - ffmpeg_kit_flutter: 5.1.0-LTS + flutter_secure_storage: ^8.0.0 + flutter_video_info: ^1.3.1 dev_dependencies: flutter_test: diff --git a/test/file_encrypt_and_decrypt_test.dart b/test/file_encrypt_and_decrypt_test.dart index 9bd5ea7..fad3c48 100644 --- a/test/file_encrypt_and_decrypt_test.dart +++ b/test/file_encrypt_and_decrypt_test.dart @@ -23,7 +23,7 @@ void main() async { clonedFile.writeAsBytesSync(fileToClone.readAsBytesSync()); - savedData = await SingleThreadedRecovery.saveFile(secretKey, './test/assets/', '', '/', createdFile: clonedFile); + savedData = await SingleThreadedRecovery.saveFile(secretKey, './test/assets/', '', '/', createdFile: clonedFile, isTesting: true); }); @@ -38,7 +38,7 @@ void main() async { File savedFile = File(join('test', 'assets', savedData!.$1)); - List fullFileDecryption = await SingleThreadedRecovery.loadAndDecryptFullFile(secretKey, savedFile); + List fullFileDecryption = await SingleThreadedRecovery.loadAndDecryptFullFile(secretKey, savedFile, Mac.empty, Chacha20(macAlgorithm: MacAlgorithm.empty), true); List partialFileDecryption = List.empty(growable: true); Completer completer = Completer(); @@ -46,7 +46,7 @@ void main() async { int fileLength = savedFile.lengthSync(); int fileStart = Random().nextInt(fileLength); fileStart = fileStart == 0 ? 1 : fileStart; - SingleThreadedRecovery.loadAndDecryptPartialFile(secretKey, savedFile, fileStart, savedFile.lengthSync()).listen((event) { + SingleThreadedRecovery.loadAndDecryptPartialFile(secretKey, savedFile, fileStart, savedFile.lengthSync(), Mac.empty, Chacha20(macAlgorithm: MacAlgorithm.empty), true).listen((event) { partialFileDecryption.addAll(event); }, onDone: () => completer.complete()); diff --git a/test/test_file_to_encrypt_backup.txt b/test/test_file_to_encrypt_backup.txt deleted file mode 100644 index 40ce9b2..0000000 --- a/test/test_file_to_encrypt_backup.txt +++ /dev/null @@ -1,7 +0,0 @@ -Copyright 2023 Haroun El Omri - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file From 18c704ac46e6638ae619442b69c344451fe895e3 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Sat, 15 Jul 2023 22:44:35 +0200 Subject: [PATCH 07/13] :building_construction: Fixed the audio player --- lib/file_recovery/single_threaded_recovery.dart | 9 +++++---- lib/file_viewers/audio.dart | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/file_recovery/single_threaded_recovery.dart b/lib/file_recovery/single_threaded_recovery.dart index 00c67d8..77ce998 100644 --- a/lib/file_recovery/single_threaded_recovery.dart +++ b/lib/file_recovery/single_threaded_recovery.dart @@ -44,8 +44,9 @@ class SingleThreadedRecovery { int currentLength = startByte; return fileToRead.openRead(startByte, endByte).asyncMap((event) async { currentLength += event.length; - return await (cipher ?? VaultsManager.cipher) - .decrypt(SecretBox(event, nonce: isTesting ? Uint8List((cipher ?? VaultsManager.cipher).nonceLength) : base64Decode((await VaultsManager.nonceStorage.read(key: basename(fileToRead.path)))!), mac: mac), secretKey: encryptionKey, keyStreamIndex: currentLength - event.length); + return (cipher ?? VaultsManager.cipher).decrypt(SecretBox(event, nonce: isTesting ? Uint8List((cipher ?? VaultsManager.cipher).nonceLength) : base64Decode((await VaultsManager.nonceStorage.read(key: basename(fileToRead.path)))!), mac: mac), + secretKey: encryptionKey, + keyStreamIndex: currentLength - event.length); }); } @@ -120,7 +121,7 @@ class SingleThreadedRecovery { IOSink fileToCreateSink = fileToCreate.openWrite(); try { final clearTextStream = createdFile.openRead(); - final encryptedStream = VaultsManager.cipher.encryptStream( + final encryptedStream = (placeholder == FileThumbnailsPlaceholder.audio ? VaultsManager.secondaryCipher : VaultsManager.cipher).encryptStream( clearTextStream, secretKey: encryptionKey, nonce: nonce, @@ -132,7 +133,7 @@ class SingleThreadedRecovery { fileToCreateSink.close(); } } else { - SecretBox encryptedData = await VaultsManager.cipher.encrypt( + SecretBox encryptedData = await (placeholder == FileThumbnailsPlaceholder.audio ? VaultsManager.secondaryCipher : VaultsManager.cipher).encrypt( importedFile!.$2, secretKey: encryptionKey, nonce: nonce, diff --git a/lib/file_viewers/audio.dart b/lib/file_viewers/audio.dart index 178e861..52d90ee 100644 --- a/lib/file_viewers/audio.dart +++ b/lib/file_viewers/audio.dart @@ -351,7 +351,7 @@ class EncryptedAudioSource extends StreamAudioSource { contentLength: (end ?? fileByteLength) - (start ?? 0), offset: start ?? 0, stream: start == null && end == null ? - await SingleThreadedRecovery.loadAndDecryptFile(encryptionKey, fileToRead, Mac.empty) : + await SingleThreadedRecovery.loadAndDecryptFile(encryptionKey, fileToRead, Mac.empty, VaultsManager.secondaryCipher) : SingleThreadedRecovery.loadAndDecryptPartialFile(encryptionKey, fileToRead, start ?? 0, end ?? fileByteLength, Mac.empty, VaultsManager.secondaryCipher), contentType: mimeType, rangeRequestsSupported: true); From 0f4fc9cc38fdf3280f32de62bf0390655e3e5c80 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Tue, 18 Jul 2023 11:38:11 +0200 Subject: [PATCH 08/13] Update README.md Fixed a lot of typos and rephrased/added some lines --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 28b0675..73a597d 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ # Life chest -An app to securely store your data locally +An app to securely store your data locally. -## Legal disclamer (MIT License) +## Legal disclaimer (MIT License) THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Features - Singlethreaded ChaCha20 encryption/decryption (Natively implemented) -- Chest/Vault system (name to determine) +- Chest system - See images - View documents - On-boarding - Localization -- Remaking file cards in the ``GridView`` -- Chaining file players with a ``PageView`` +- File explorer in ``GridView`` +- File explorer in ``PageView`` - File renaming - Lazy loading - Export files/vaults to their original file or to a new file format (.lcef or Life Chest Encrypted @@ -23,10 +23,10 @@ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR I - Audio playing ## Credits -- Thanks to Syncfusion to let us use their software with their Open Source Community License. +- Thanks to Syncfusion for letting us use their software with their Open Source Community License. (NOTE: We are not using their software anymore because of their proprietary license) ## Support -I develop the Life Chest application ib my free time, if you want me to work more on it, you can buy me a coffee! +I develop the Life Chest application in my free time, to support what I am doing, you can buy me a coffee! [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/N4N6N222N) From 230624f61c2e505eb2050aee8806594ff0099c3a Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Tue, 18 Jul 2023 12:53:04 +0200 Subject: [PATCH 09/13] :globe_with_meridians: Heavily edited localization phrasing --- .gitignore | 3 +- lib/generated/intl/messages_en.dart | 31 ++++++------- lib/generated/intl/messages_fr.dart | 70 ++++++++++++++--------------- lib/generated/l10n.dart | 60 ++++++++++++------------- lib/l10n/intl_en.arb | 32 ++++++------- lib/l10n/intl_fr.arb | 67 +++++++++++++-------------- 6 files changed, 133 insertions(+), 130 deletions(-) diff --git a/.gitignore b/.gitignore index ab05fd2..80ac2a7 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,5 @@ app.*.map.json /android/app/release # For missing translations -/missingTranslations.json \ No newline at end of file +/missingTranslations.json +/test/assets/* diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index a5f8af8..154ae0f 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -21,9 +21,10 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'en'; static String m0(count) => - "Are you sure to delete ${count} ${Intl.plural(count, one: 'file', other: 'files')} ?"; + "Are you sure you want to delete ${count} ${Intl.plural(count, one: 'file', other: 'files')}?"; - static String m1(vaultName) => "Are you sure to delete \"${vaultName}\"?"; + static String m1(vaultName) => + "Are you sure you want to delete \"${vaultName}\"?"; static String m2(count) => "We detected ${Intl.plural(count, one: 'a file', other: 'multiple files')} that come from a vault. To access ${Intl.plural(count, one: 'its', other: 'their')} content, you must unlock them."; @@ -40,17 +41,17 @@ class MessageLookup extends MessageLookupByLibrary { "about": MessageLookupByLibrary.simpleMessage("About..."), "addFiles": MessageLookupByLibrary.simpleMessage("Add files"), "appLegalese": MessageLookupByLibrary.simpleMessage( - "The application \"Life Chest\" has been made by Theskyblockman with a ❤️ and a 🖥️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri"), + "The application \"Life Chest\" has been made by Theskyblockman with ❤️ and a 🖥️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri"), "areYouSureClearVaults": MessageLookupByLibrary.simpleMessage( - "Are you sure to delete all vaults?"), + "Are you sure you want to delete all vaults?"), "areYouSureDeleteFiles": m0, "areYouSureDeleteVault": m1, "biometrics": MessageLookupByLibrary.simpleMessage("Biometrics"), "biometricsAreLocal": MessageLookupByLibrary.simpleMessage( "Biometrics-locked chests can only be unlocked on the device it has been created on. Encrypted file export is unavailable."), "cancel": MessageLookupByLibrary.simpleMessage("Cancel"), - "chestName": MessageLookupByLibrary.simpleMessage("Chest name"), - "chestPassword": MessageLookupByLibrary.simpleMessage("Chest password"), + "chestName": MessageLookupByLibrary.simpleMessage("Chest Name"), + "chestPassword": MessageLookupByLibrary.simpleMessage("Chest Password"), "chestPinCode": MessageLookupByLibrary.simpleMessage("Chest PIN code"), "closeChest": MessageLookupByLibrary.simpleMessage("Close the chest"), "closeChestNotificationContent": MessageLookupByLibrary.simpleMessage( @@ -58,11 +59,11 @@ class MessageLookup extends MessageLookupByLibrary { "closeChestNotificationTitle": MessageLookupByLibrary.simpleMessage( "You still have a chest opened"), "createANewChest": - MessageLookupByLibrary.simpleMessage("Create a new chest"), + MessageLookupByLibrary.simpleMessage("Create a New Chest"), "createANewFolder": MessageLookupByLibrary.simpleMessage("Create a new folder"), "createTheNewChest": - MessageLookupByLibrary.simpleMessage("Create the chest"), + MessageLookupByLibrary.simpleMessage("Create the Chest"), "defineScheme": MessageLookupByLibrary.simpleMessage("Define the scheme"), "delete": MessageLookupByLibrary.simpleMessage("Delete"), @@ -80,7 +81,7 @@ class MessageLookup extends MessageLookupByLibrary { "The chest name must not be empty"), "errorChestPasswordMoreCharacters": MessageLookupByLibrary.simpleMessage( - "The password must be 8 characters or more"), + "The password must be at least 8 characters long"), "errorChestPasswordMoreDigits": MessageLookupByLibrary.simpleMessage( "The password must contain at least one digit"), "errorChestPasswordMoreLowercaseLetter": @@ -109,7 +110,7 @@ class MessageLookup extends MessageLookupByLibrary { "exportAsEncrypted": MessageLookupByLibrary.simpleMessage("Export as an encrypted file"), "exportedFileDescription": MessageLookupByLibrary.simpleMessage( - "A file exported from the Life Chest app and who needs to be unlocked to get more information about it."), + "A file exported from the Life Chest app and needs to be unlocked to get more information about it."), "group": m3, "ignore": MessageLookupByLibrary.simpleMessage("Ignore"), "import": MessageLookupByLibrary.simpleMessage("Import"), @@ -152,7 +153,7 @@ class MessageLookup extends MessageLookupByLibrary { "savedToFolder": MessageLookupByLibrary.simpleMessage( "We successfully saved the file(s)"), "savedToFolderWarning": MessageLookupByLibrary.simpleMessage( - "We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors or its contributor cannot be held liable for any divulged data."), + "We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors, or its contributors cannot be held liable for any divulged data."), "scheme": MessageLookupByLibrary.simpleMessage("Pattern"), "selectAll": MessageLookupByLibrary.simpleMessage("Select all"), "selected": m4, @@ -166,17 +167,17 @@ class MessageLookup extends MessageLookupByLibrary { "validate": MessageLookupByLibrary.simpleMessage("Validate"), "welcomeNext": MessageLookupByLibrary.simpleMessage("Next"), "welcomePage1Content": MessageLookupByLibrary.simpleMessage( - "Welcome to your life chest! Here you will be able to create chests to store your data privately without compromising over usability."), + "Welcome to your Life Chest! Here, you will be able to create chests to store your data securely without compromising usability."), "welcomePage1Title": MessageLookupByLibrary.simpleMessage("Hello there!"), "welcomePage2Content": MessageLookupByLibrary.simpleMessage( - "We use an encryption system called Chacha20, so trying to access your files without your password will take about 200 trillions of trillions of trillions times the age of the universe! And to prove it, we are 100% open-source!"), + "We use an encryption system called Chacha20, which means attempting to access your files without your password would take about 200 trillions of trillions of trillions times the age of the universe! And to prove it, we are 100% open-source!"), "welcomePage2Title": MessageLookupByLibrary.simpleMessage( - "Here, our main priority is your security"), + "Your Security is Our Main Priority"), "welcomePage3Content": MessageLookupByLibrary.simpleMessage( "You\'ll see, it\'s fast, easy, and secure!"), "welcomePage3Title": MessageLookupByLibrary.simpleMessage( - "Let\'s create your first chest!"), + "Let\'s Create Your First Chest!"), "welcomeSkip": MessageLookupByLibrary.simpleMessage("Skip"), "whatShouldBeDoneAfterUnfocus": MessageLookupByLibrary.simpleMessage( "What should we do when the application is paused"), diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index a48f250..65acb4c 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -21,10 +21,10 @@ class MessageLookup extends MessageLookupByLibrary { String get localeName => 'fr'; static String m0(count) => - "Êtes-vous sûr de supprimer ${count} ${Intl.plural(count, one: 'fichier', other: 'fichiers')}?"; + "Êtes-vous sûr de vouloir supprimer ${count} ${Intl.plural(count, one: 'fichier', other: 'fichiers')}?"; static String m1(vaultName) => - "Êtes-vous sûr de supprimer \"${vaultName}\" ?"; + "Êtes-vous sûr de vouloir supprimer \"${vaultName}\" ?"; static String m2(count) => "Nous avons détecté ${Intl.plural(count, one: 'un fichier', other: 'des fichiers')} provenant d\'un coffre. Pour accéder à ${Intl.plural(count, one: 'son', other: 'leur')} contenu, vous devez ${Intl.plural(count, one: 'le', other: 'les')} déverrouiller."; @@ -34,8 +34,7 @@ class MessageLookup extends MessageLookupByLibrary { static String m4(count) => "${count} ${Intl.plural(count, one: 'fichier sélectionné', other: 'fichiers sélectionnés')}"; - static String m5(unlockName) => - "Ce groupe peut être débloquer grâce à : ${unlockName}."; + static String m5(unlockName) => "Déverouillable grâce à : ${unlockName}."; final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { @@ -43,9 +42,9 @@ class MessageLookup extends MessageLookupByLibrary { "addFiles": MessageLookupByLibrary.simpleMessage("Ajouter des fichiers"), "appLegalese": MessageLookupByLibrary.simpleMessage( - "L\'application \"Life Chest\" a été créée par Theskyblockman avec ❤️ et un 🖥️ sous la licence MIT, Nous ne donnons aucune garantie, veuillez voir la license MIT pour plus d\'informations ©️ 2023 Haroun El Omri"), + "L\'application \"Life Chest\" a été créée par Theskyblockman avec ❤️ et un 🖥️ sous la licence MIT. Nous ne donnons aucune garantie, veuillez consulter la licence MIT pour plus d\'informations ©️ 2023 Haroun El Omri"), "areYouSureClearVaults": MessageLookupByLibrary.simpleMessage( - "Êtes-vous sûr de supprimer tous les coffres ?"), + "Êtes-vous sûr de vouloir supprimer tous les coffres ?"), "areYouSureDeleteFiles": m0, "areYouSureDeleteVault": m1, "biometrics": @@ -60,17 +59,17 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Code PIN du coffre"), "closeChest": MessageLookupByLibrary.simpleMessage("Fermer le coffre"), "closeChestNotificationContent": MessageLookupByLibrary.simpleMessage( - "Appuyez sur le bouton ci-dessous pour le fermer"), + "Cliquez sur le bouton ci-dessous pour le fermer"), "closeChestNotificationTitle": MessageLookupByLibrary.simpleMessage( - "Vous avez toujours un coffre ouvert"), + "Vous avez encore un coffre ouvert"), "createANewChest": MessageLookupByLibrary.simpleMessage("Créer un nouveau coffre"), "createANewFolder": MessageLookupByLibrary.simpleMessage("Créer un nouveau dossier"), "createTheNewChest": MessageLookupByLibrary.simpleMessage("Créer le coffre"), - "defineScheme": - MessageLookupByLibrary.simpleMessage("Définir le modèle"), + "defineScheme": MessageLookupByLibrary.simpleMessage( + "Définir le modèle de déverrouillage"), "delete": MessageLookupByLibrary.simpleMessage("Supprimer"), "deleteAllChests": MessageLookupByLibrary.simpleMessage("Supprimer tous les coffres"), @@ -79,11 +78,11 @@ class MessageLookup extends MessageLookupByLibrary { "enterTheChestPassword": MessageLookupByLibrary.simpleMessage( "Veuillez entrer le mot de passe de ce coffre"), "enterTheChestScheme": MessageLookupByLibrary.simpleMessage( - "Veuillez entrer le modèle du coffre"), + "Veuillez entrer le modèle de déverrouillage de ce coffre"), "enterThePinCode": MessageLookupByLibrary.simpleMessage( - "Veuillez entrer le code PIN du coffre"), + "Veuillez entrer le code PIN de ce coffre"), "errorChestNameShouldNotBeEmpty": MessageLookupByLibrary.simpleMessage( - "Le nom du coffre ne doit pas être vide"), + "Le nom du coffre ne peut pas être vide"), "errorChestPasswordMoreCharacters": MessageLookupByLibrary.simpleMessage( "Le mot de passe doit contenir au moins 8 caractères"), @@ -97,33 +96,33 @@ class MessageLookup extends MessageLookupByLibrary { "Le mot de passe doit contenir au moins une lettre majuscule"), "errorChestPasswordShouldNotBeEmpty": MessageLookupByLibrary.simpleMessage( - "Le mot de passe ne doit pas être vide"), + "Le mot de passe ne peut pas être vide"), "errorChestPinCodeMoreCharacters": MessageLookupByLibrary.simpleMessage( "Le code PIN doit contenir au moins 4 caractères"), "errorChestPinCodeShouldNotBeEmpty": MessageLookupByLibrary.simpleMessage( - "Le code PIN ne doit pas être vide"), + "Le code PIN ne peut pas être vide"), "errorChestSchemeShouldNotBeEmpty": MessageLookupByLibrary.simpleMessage( - "Le schéma ne doit pas être vide"), + "Le modèle ne peut pas être vide"), "errorDurationMustBeFormatted": MessageLookupByLibrary.simpleMessage( "La durée doit être au format HH:MM"), "errorDurationMustNotBeEmpty": MessageLookupByLibrary.simpleMessage( - "La durée ne doit pas être vide"), + "La durée ne peut pas être vide"), "exportAsCleartext": MessageLookupByLibrary.simpleMessage( - "Exporter en tant que fichier lisible (fichier non chiffré)"), + "Exporter en tant que fichier lisible (non chiffré)"), "exportAsEncrypted": MessageLookupByLibrary.simpleMessage( "Exporter en tant que fichier chiffré"), "exportedFileDescription": MessageLookupByLibrary.simpleMessage( - "Um fichier exporté depuis Life Chest qui est chiffré et qui a donc besoin d\'être déchiffré pour être lu."), + "Un fichier exporté depuis l\'application Life Chest et qui nécessite d\'être déverrouillé pour accéder à ses informations."), "group": m3, "ignore": MessageLookupByLibrary.simpleMessage("Ignorer"), "import": MessageLookupByLibrary.simpleMessage("Importer"), "internalError": MessageLookupByLibrary.simpleMessage("Erreur interne"), "lifeChestBulkSave": MessageLookupByLibrary.simpleMessage( - "Sauvegarde de fichiers en masse"), + "Exportation en masse de fichiers Life Chest"), "linkCopied": MessageLookupByLibrary.simpleMessage( - "Le lien a été placé dans le presse-papier"), + "Le lien a été copié dans votre presse-papiers."), "loadingAudioTrack": MessageLookupByLibrary.simpleMessage( "Chargement de la piste audio"), "loadingDocuments": @@ -135,7 +134,7 @@ class MessageLookup extends MessageLookupByLibrary { "loadingVideo": MessageLookupByLibrary.simpleMessage("Chargement de la vidéo"), "lostDataContBeRecovered": MessageLookupByLibrary.simpleMessage( - "Cette action est irréversible ! Toutes les données perdues ne pourront pas être récupérées"), + "Cette action est irréversible ! Toutes les données perdues ne pourront pas être récupérées."), "nameSortName": MessageLookupByLibrary.simpleMessage("Ordre alphabétique"), "newFolder": MessageLookupByLibrary.simpleMessage("Nouveau dossier"), @@ -150,9 +149,9 @@ class MessageLookup extends MessageLookupByLibrary { "ok": MessageLookupByLibrary.simpleMessage("OK"), "password": MessageLookupByLibrary.simpleMessage("Mot de passe"), "pickFilesDialogTitle": MessageLookupByLibrary.simpleMessage( - "Choisissez les fichiers que vous voulez ajouter"), + "Sélectionnez les fichiers que vous souhaitez ajouter"), "pickFolderDialogTitle": MessageLookupByLibrary.simpleMessage( - "Choisissez le dossier que vous voulez ajouter"), + "Sélectionnez le dossier que vous souhaitez ajouter"), "pinCode": MessageLookupByLibrary.simpleMessage("Code PIN"), "pleaseUseBiometrics": MessageLookupByLibrary.simpleMessage( "Veuillez utiliser votre empreinte digitale pour déverrouiller le coffre"), @@ -160,14 +159,14 @@ class MessageLookup extends MessageLookupByLibrary { "savedToFolder": MessageLookupByLibrary.simpleMessage( "Nous avons enregistré avec succès le(s) fichier(s)."), "savedToFolderWarning": MessageLookupByLibrary.simpleMessage( - "Nous avons enregistré avec succès le(s) fichier(s). ATTENTION! Ces fichiers chiffrés sont plus vulnérables dans ce format, ne les distribuez pas publiquement. Life Chest, ses auteurs ou son contributeur ne peuvent être tenus responsables des données divulguées."), - "scheme": MessageLookupByLibrary.simpleMessage("Modèle"), + "Nous avons enregistré avec succès le(s) fichier(s). ATTENTION! Ces fichiers chiffrés sont plus vulnérables dans ce format, ne les distribuez pas publiquement. Life Chest, ses auteurs ou ses contributeurs ne peuvent être tenus responsables des données divulguées."), + "scheme": MessageLookupByLibrary.simpleMessage("Schéma"), "selectAll": MessageLookupByLibrary.simpleMessage("Tout sélectionner"), "selected": m4, "sortBy": MessageLookupByLibrary.simpleMessage("Trier par..."), "unlockAbleBy": m5, - "unlockChest": MessageLookupByLibrary.simpleMessage( - "Veuillez déverrouiller le coffre"), + "unlockChest": + MessageLookupByLibrary.simpleMessage("Déverrouiller le coffre"), "unlockFile": MessageLookupByLibrary.simpleMessage("Déverrouiller le fichier"), "unlockWizard": @@ -177,23 +176,24 @@ class MessageLookup extends MessageLookupByLibrary { "validate": MessageLookupByLibrary.simpleMessage("Valider"), "welcomeNext": MessageLookupByLibrary.simpleMessage("Suivant"), "welcomePage1Content": MessageLookupByLibrary.simpleMessage( - "Bienvenue dans votre coffre de vie ! Ici, vous pourrez créer des coffres pour stocker vos données en toute sécurité sans compromettre leur utilisation."), - "welcomePage1Title": MessageLookupByLibrary.simpleMessage("Bonjour !"), + "Bienvenue dans votre coffre-fort Life Chest ! Ici, vous pourrez créer des coffres pour stocker vos données en toute sécurité sans compromettre la convivialité."), + "welcomePage1Title": + MessageLookupByLibrary.simpleMessage("Bienvenue !"), "welcomePage2Content": MessageLookupByLibrary.simpleMessage( - "Nous utilisons un système de cryptage appelé Chacha20, donc essayer d\'accéder à vos fichiers sans votre mot de passe prendra environ 200 billions de billions de billions de fois l\'âge de l\'univers ! Et pour le prouver, nous sommes 100 % open-source !"), + "Nous utilisons un système de chiffrement appelé Chacha20, ce qui signifie que toute tentative d\'accès à vos fichiers sans votre mot de passe prendrait environ 200 trillions de trillions de trillions de fois l\'âge de l\'univers ! Et pour le prouver, nous sommes 100 % open-source !"), "welcomePage2Title": MessageLookupByLibrary.simpleMessage( - "Ici, notre priorité principale est votre sécurité"), + "Votre sécurité est notre priorité"), "welcomePage3Content": MessageLookupByLibrary.simpleMessage( "Vous verrez, c\'est rapide, facile et sécurisé !"), "welcomePage3Title": MessageLookupByLibrary.simpleMessage( "Créons votre premier coffre !"), "welcomeSkip": MessageLookupByLibrary.simpleMessage("Passer"), "whatShouldBeDoneAfterUnfocus": MessageLookupByLibrary.simpleMessage( - "Que devons-nous faire si l\'application est mise en pause"), + "Que devons-nous faire lorsque l\'application est en pause"), "wrongDevice": MessageLookupByLibrary.simpleMessage( - "Mauvais appareil, nous n\'avons pas trouvé les donnés nécessaires pour déverouiller le coffre dans la collection de clés."), + "Mauvais appareil, impossible de trouver les données de déverrouillage dans le téléphone."), "wrongPassword": - MessageLookupByLibrary.simpleMessage("Mauvais mot de passe"), + MessageLookupByLibrary.simpleMessage("Mot de passe incorrect"), "wrongPinCode": MessageLookupByLibrary.simpleMessage("Code PIN incorrect"), "yes": MessageLookupByLibrary.simpleMessage("Oui") diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 38fee03..32187af 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -60,40 +60,40 @@ class S { ); } - /// `Welcome to your life chest! Here you will be able to create chests to store your data privately without compromising over usability.` + /// `Welcome to your Life Chest! Here, you will be able to create chests to store your data securely without compromising usability.` String get welcomePage1Content { return Intl.message( - 'Welcome to your life chest! Here you will be able to create chests to store your data privately without compromising over usability.', + 'Welcome to your Life Chest! Here, you will be able to create chests to store your data securely without compromising usability.', name: 'welcomePage1Content', desc: '', args: [], ); } - /// `Here, our main priority is your security` + /// `Your Security is Our Main Priority` String get welcomePage2Title { return Intl.message( - 'Here, our main priority is your security', + 'Your Security is Our Main Priority', name: 'welcomePage2Title', desc: '', args: [], ); } - /// `We use an encryption system called Chacha20, so trying to access your files without your password will take about 200 trillions of trillions of trillions times the age of the universe! And to prove it, we are 100% open-source!` + /// `We use an encryption system called Chacha20, which means attempting to access your files without your password would take about 200 trillions of trillions of trillions times the age of the universe! And to prove it, we are 100% open-source!` String get welcomePage2Content { return Intl.message( - 'We use an encryption system called Chacha20, so trying to access your files without your password will take about 200 trillions of trillions of trillions times the age of the universe! And to prove it, we are 100% open-source!', + 'We use an encryption system called Chacha20, which means attempting to access your files without your password would take about 200 trillions of trillions of trillions times the age of the universe! And to prove it, we are 100% open-source!', name: 'welcomePage2Content', desc: '', args: [], ); } - /// `Let's create your first chest!` + /// `Let's Create Your First Chest!` String get welcomePage3Title { return Intl.message( - 'Let\'s create your first chest!', + 'Let\'s Create Your First Chest!', name: 'welcomePage3Title', desc: '', args: [], @@ -130,20 +130,20 @@ class S { ); } - /// `Create a new chest` + /// `Create a New Chest` String get createANewChest { return Intl.message( - 'Create a new chest', + 'Create a New Chest', name: 'createANewChest', desc: '', args: [], ); } - /// `Chest name` + /// `Chest Name` String get chestName { return Intl.message( - 'Chest name', + 'Chest Name', name: 'chestName', desc: '', args: [], @@ -160,10 +160,10 @@ class S { ); } - /// `Chest password` + /// `Chest Password` String get chestPassword { return Intl.message( - 'Chest password', + 'Chest Password', name: 'chestPassword', desc: '', args: [], @@ -180,10 +180,10 @@ class S { ); } - /// `The password must be 8 characters or more` + /// `The password must be at least 8 characters long` String get errorChestPasswordMoreCharacters { return Intl.message( - 'The password must be 8 characters or more', + 'The password must be at least 8 characters long', name: 'errorChestPasswordMoreCharacters', desc: '', args: [], @@ -290,20 +290,20 @@ class S { ); } - /// `Create the chest` + /// `Create the Chest` String get createTheNewChest { return Intl.message( - 'Create the chest', + 'Create the Chest', name: 'createTheNewChest', desc: '', args: [], ); } - /// `The application "Life Chest" has been made by Theskyblockman with a ❤️ and a 🖥️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri` + /// `The application "Life Chest" has been made by Theskyblockman with ❤️ and a 🖥️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri` String get appLegalese { return Intl.message( - 'The application "Life Chest" has been made by Theskyblockman with a ❤️ and a 🖥️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri', + 'The application "Life Chest" has been made by Theskyblockman with ❤️ and a 🖥️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri', name: 'appLegalese', desc: '', args: [], @@ -520,30 +520,30 @@ class S { ); } - /// `Are you sure to delete all vaults?` + /// `Are you sure you want to delete all vaults?` String get areYouSureClearVaults { return Intl.message( - 'Are you sure to delete all vaults?', + 'Are you sure you want to delete all vaults?', name: 'areYouSureClearVaults', desc: '', args: [], ); } - /// `Are you sure to delete "{vaultName}"?` + /// `Are you sure you want to delete "{vaultName}"?` String areYouSureDeleteVault(String vaultName) { return Intl.message( - 'Are you sure to delete "$vaultName"?', + 'Are you sure you want to delete "$vaultName"?', name: 'areYouSureDeleteVault', desc: '', args: [vaultName], ); } - /// `Are you sure to delete {count} {count, plural, =1{file} other{files}} ?` + /// `Are you sure you want to delete {count} {count, plural, =1{file} other{files}}?` String areYouSureDeleteFiles(int count) { return Intl.message( - 'Are you sure to delete $count ${Intl.plural(count, one: 'file', other: 'files')} ?', + 'Are you sure you want to delete $count ${Intl.plural(count, one: 'file', other: 'files')}?', name: 'areYouSureDeleteFiles', desc: '', args: [count], @@ -870,10 +870,10 @@ class S { ); } - /// `We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors or its contributor cannot be held liable for any divulged data.` + /// `We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors, or its contributors cannot be held liable for any divulged data.` String get savedToFolderWarning { return Intl.message( - 'We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors or its contributor cannot be held liable for any divulged data.', + 'We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors, or its contributors cannot be held liable for any divulged data.', name: 'savedToFolderWarning', desc: '', args: [], @@ -910,10 +910,10 @@ class S { ); } - /// `A file exported from the Life Chest app and who needs to be unlocked to get more information about it.` + /// `A file exported from the Life Chest app and needs to be unlocked to get more information about it.` String get exportedFileDescription { return Intl.message( - 'A file exported from the Life Chest app and who needs to be unlocked to get more information about it.', + 'A file exported from the Life Chest app and needs to be unlocked to get more information about it.', name: 'exportedFileDescription', desc: '', args: [], diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index d9af383..4d16d60 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,19 +1,19 @@ { "@@locale": "en", "welcomePage1Title": "Hello there!", - "welcomePage1Content": "Welcome to your life chest! Here you will be able to create chests to store your data privately without compromising over usability.", - "welcomePage2Title": "Here, our main priority is your security", - "welcomePage2Content": "We use an encryption system called Chacha20, so trying to access your files without your password will take about 200 trillions of trillions of trillions times the age of the universe! And to prove it, we are 100% open-source!", - "welcomePage3Title": "Let's create your first chest!", + "welcomePage1Content": "Welcome to your Life Chest! Here, you will be able to create chests to store your data securely without compromising usability.", + "welcomePage2Title": "Your Security is Our Main Priority", + "welcomePage2Content": "We use an encryption system called Chacha20, which means attempting to access your files without your password would take about 200 trillions of trillions of trillions times the age of the universe! And to prove it, we are 100% open-source!", + "welcomePage3Title": "Let's Create Your First Chest!", "welcomePage3Content": "You'll see, it's fast, easy, and secure!", "welcomeSkip": "Skip", "welcomeNext": "Next", - "createANewChest": "Create a new chest", - "chestName": "Chest name", + "createANewChest": "Create a New Chest", + "chestName": "Chest Name", "errorChestNameShouldNotBeEmpty": "The chest name must not be empty", - "chestPassword": "Chest password", + "chestPassword": "Chest Password", "errorChestPasswordShouldNotBeEmpty": "The password must not be empty", - "errorChestPasswordMoreCharacters": "The password must be 8 characters or more", + "errorChestPasswordMoreCharacters": "The password must be at least 8 characters long", "errorChestPasswordMoreUppercaseLetter": "The password must contain at least one uppercase character", "errorChestPasswordMoreLowercaseLetter": "The password must contain at least one lowercase character", "errorChestPasswordMoreDigits": "The password must contain at least one digit", @@ -24,8 +24,8 @@ "closeChest": "Close the chest", "errorDurationMustNotBeEmpty": "The duration must not be empty", "errorDurationMustBeFormatted": "The duration must be in the HH:MM format", - "createTheNewChest": "Create the chest", - "appLegalese": "The application \"Life Chest\" has been made by Theskyblockman with a ❤️ and a \uD83D\uDDA5️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri", + "createTheNewChest": "Create the Chest", + "appLegalese": "The application \"Life Chest\" has been made by Theskyblockman with ❤️ and a \uD83D\uDDA5️ under the MIT license. We do not provide any warranty, see the MIT license for more information ©️ 2023 Haroun El Omri", "noChestsCreatedYet": "No chests created yet", "noFilesCreatedYet": "No files added yet", "enterTheChestPassword": "Please enter the password of this chest", @@ -54,7 +54,7 @@ "wrongPassword": "Wrong password", "cancel": "Cancel", "ok": "OK", - "areYouSureClearVaults": "Are you sure to delete all vaults?", + "areYouSureClearVaults": "Are you sure you want to delete all vaults?", "@areYouSureDeleteVault": { "placeholders": { "vaultName": { @@ -62,7 +62,7 @@ } } }, - "areYouSureDeleteVault": "Are you sure to delete \"{vaultName}\"?", + "areYouSureDeleteVault": "Are you sure you want to delete \"{vaultName}\"?", "@areYouSureDeleteFiles": { "placeholders": { "count": { @@ -70,7 +70,7 @@ } } }, - "areYouSureDeleteFiles": "Are you sure to delete {count} {count, plural, =1{file} other{files}} ?", + "areYouSureDeleteFiles": "Are you sure you want to delete {count} {count, plural, =1{file} other{files}}?", "lostDataContBeRecovered": "This action is irreversible! All lost data can't be recovered.", "yes": "Yes", "no": "No", @@ -110,7 +110,7 @@ "ignore": "Ignore", "lifeChestBulkSave": "Life Chest bulk file export", "savedToFolder": "We successfully saved the file(s)", - "savedToFolderWarning": "We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors or its contributor cannot be held liable for any divulged data.", + "savedToFolderWarning": "We successfully saved the file(s). WARNING! These encrypted files are more vulnerable in this format, do not publicly distribute them. Life Chest, its authors, or its contributors cannot be held liable for any divulged data.", "import": "Import", "@group": { "placeholders": { @@ -128,9 +128,9 @@ } }, "unlockAbleBy": "This group can be unlocked with: {unlockName}.", - "exportedFileDescription": "A file exported from the Life Chest app and who needs to be unlocked to get more information about it.", + "exportedFileDescription": "A file exported from the Life Chest app and needs to be unlocked to get more information about it.", "internalError": "Internal Error", "wrongDevice": "Wrong device, couldn't find the unlock data in the keystore", "biometricsAreLocal": "Biometrics-locked chests can only be unlocked on the device it has been created on. Encrypted file export is unavailable.", "linkCopied": "The link has been copied to your clipboard." -} +} \ No newline at end of file diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index eafa14f..dc8de39 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -1,32 +1,32 @@ { "@@locale": "fr", - "welcomePage1Title": "Bonjour !", - "welcomePage1Content": "Bienvenue dans votre coffre de vie ! Ici, vous pourrez créer des coffres pour stocker vos données en toute sécurité sans compromettre leur utilisation.", - "welcomePage2Title": "Ici, notre priorité principale est votre sécurité", - "welcomePage2Content": "Nous utilisons un système de cryptage appelé Chacha20, donc essayer d'accéder à vos fichiers sans votre mot de passe prendra environ 200 billions de billions de billions de fois l'âge de l'univers ! Et pour le prouver, nous sommes 100 % open-source !", + "welcomePage1Title": "Bienvenue !", + "welcomePage1Content": "Bienvenue dans votre coffre-fort Life Chest ! Ici, vous pourrez créer des coffres pour stocker vos données en toute sécurité sans compromettre la convivialité.", + "welcomePage2Title": "Votre sécurité est notre priorité", + "welcomePage2Content": "Nous utilisons un système de chiffrement appelé Chacha20, ce qui signifie que toute tentative d'accès à vos fichiers sans votre mot de passe prendrait environ 200 trillions de trillions de trillions de fois l'âge de l'univers ! Et pour le prouver, nous sommes 100 % open-source !", "welcomePage3Title": "Créons votre premier coffre !", "welcomePage3Content": "Vous verrez, c'est rapide, facile et sécurisé !", "welcomeSkip": "Passer", "welcomeNext": "Suivant", "createANewChest": "Créer un nouveau coffre", "chestName": "Nom du coffre", - "errorChestNameShouldNotBeEmpty": "Le nom du coffre ne doit pas être vide", + "errorChestNameShouldNotBeEmpty": "Le nom du coffre ne peut pas être vide", "chestPassword": "Mot de passe du coffre", - "errorChestPasswordShouldNotBeEmpty": "Le mot de passe ne doit pas être vide", + "errorChestPasswordShouldNotBeEmpty": "Le mot de passe ne peut pas être vide", "errorChestPasswordMoreCharacters": "Le mot de passe doit contenir au moins 8 caractères", "errorChestPinCodeMoreCharacters": "Le code PIN doit contenir au moins 4 caractères", "errorChestPasswordMoreUppercaseLetter": "Le mot de passe doit contenir au moins une lettre majuscule", "errorChestPasswordMoreLowercaseLetter": "Le mot de passe doit contenir au moins une lettre minuscule", "errorChestPasswordMoreDigits": "Le mot de passe doit contenir au moins un chiffre", - "errorChestSchemeShouldNotBeEmpty": "Le schéma ne doit pas être vide", - "whatShouldBeDoneAfterUnfocus": "Que devons-nous faire si l'application est mise en pause", + "errorChestSchemeShouldNotBeEmpty": "Le modèle ne peut pas être vide", + "whatShouldBeDoneAfterUnfocus": "Que devons-nous faire lorsque l'application est en pause", "doNothing": "Ne rien faire", "notify": "Vous notifier", "closeChest": "Fermer le coffre", - "errorDurationMustNotBeEmpty": "La durée ne doit pas être vide", + "errorDurationMustNotBeEmpty": "La durée ne peut pas être vide", "errorDurationMustBeFormatted": "La durée doit être au format HH:MM", "createTheNewChest": "Créer le coffre", - "appLegalese": "L'application \"Life Chest\" a été créée par Theskyblockman avec ❤️ et un \uD83D\uDDA5️ sous la licence MIT, Nous ne donnons aucune garantie, veuillez voir la license MIT pour plus d'informations ©️ 2023 Haroun El Omri", + "appLegalese": "L'application \"Life Chest\" a été créée par Theskyblockman avec ❤️ et un \uD83D\uDDA5️ sous la licence MIT. Nous ne donnons aucune garantie, veuillez consulter la licence MIT pour plus d'informations ©️ 2023 Haroun El Omri", "noChestsCreatedYet": "Aucun coffre créé pour le moment", "noFilesCreatedYet": "Aucun fichier ajouté pour le moment", "enterTheChestPassword": "Veuillez entrer le mot de passe de ce coffre", @@ -41,21 +41,21 @@ "loadingImage": "Chargement de l'image", "loadingAudioTrack": "Chargement de la piste audio", "loadingVideo": "Chargement de la vidéo", - "pickFilesDialogTitle": "Choisissez les fichiers que vous voulez ajouter", - "pickFolderDialogTitle": "Choisissez le dossier que vous voulez ajouter", + "pickFilesDialogTitle": "Sélectionnez les fichiers que vous souhaitez ajouter", + "pickFolderDialogTitle": "Sélectionnez le dossier que vous souhaitez ajouter", "selected": "{count} {count, plural, =1{fichier sélectionné} other{fichiers sélectionnés}}", "selectAll": "Tout sélectionner", - "wrongPassword": "Mauvais mot de passe", + "wrongPassword": "Mot de passe incorrect", "cancel": "Annuler", "ok": "OK", - "areYouSureClearVaults": "Êtes-vous sûr de supprimer tous les coffres ?", - "areYouSureDeleteVault": "Êtes-vous sûr de supprimer \"{vaultName}\" ?", - "areYouSureDeleteFiles": "Êtes-vous sûr de supprimer {count} {count, plural, =1{fichier} other{fichiers}}?", - "lostDataContBeRecovered": "Cette action est irréversible ! Toutes les données perdues ne pourront pas être récupérées", + "areYouSureClearVaults": "Êtes-vous sûr de vouloir supprimer tous les coffres ?", + "areYouSureDeleteVault": "Êtes-vous sûr de vouloir supprimer \"{vaultName}\" ?", + "areYouSureDeleteFiles": "Êtes-vous sûr de vouloir supprimer {count} {count, plural, =1{fichier} other{fichiers}}?", + "lostDataContBeRecovered": "Cette action est irréversible ! Toutes les données perdues ne pourront pas être récupérées.", "yes": "Oui", "no": "Non", - "closeChestNotificationTitle": "Vous avez toujours un coffre ouvert", - "closeChestNotificationContent": "Appuyez sur le bouton ci-dessous pour le fermer", + "closeChestNotificationTitle": "Vous avez encore un coffre ouvert", + "closeChestNotificationContent": "Cliquez sur le bouton ci-dessous pour le fermer", "createANewFolder": "Créer un nouveau dossier", "newFolder": "Nouveau dossier", "sortBy": "Trier par...", @@ -63,32 +63,33 @@ "nameSortName": "Ordre alphabétique", "password": "Mot de passe", "pinCode": "Code PIN", - "scheme": "Modèle", + "scheme": "Schéma", "chestPinCode": "Code PIN du coffre", - "enterTheChestScheme": "Veuillez entrer le modèle du coffre", - "enterThePinCode": "Veuillez entrer le code PIN du coffre", + "enterTheChestScheme": "Veuillez entrer le modèle de déverrouillage de ce coffre", + "enterThePinCode": "Veuillez entrer le code PIN de ce coffre", "wrongPinCode": "Code PIN incorrect", "wrongScheme": "Schéma incorrect", - "unlockChest": "Veuillez déverrouiller le coffre", + "unlockChest": "Déverrouiller le coffre", "pleaseUseBiometrics": "Veuillez utiliser votre empreinte digitale pour déverrouiller le coffre", - "defineScheme": "Définir le modèle", - "errorChestPinCodeShouldNotBeEmpty": "Le code PIN ne doit pas être vide", + "defineScheme": "Définir le modèle de déverrouillage", + "errorChestPinCodeShouldNotBeEmpty": "Le code PIN ne peut pas être vide", "biometrics": "Empreinte digitale", - "detectedExportedFile": "Nous avons détecté {count, plural, =1{un fichier} other{des fichiers}} provenant d'un coffre. Pour accéder à {count, plural, =1{son} other{leur}} contenu, vous devez {count, plural, =1{le} other{les}} déverrouiller.", "unlockFile": "Déverrouiller le fichier", + "detectedExportedFile": "Nous avons détecté {count, plural, =1{un fichier} other{des fichiers}} provenant d'un coffre. Pour accéder à {count, plural, =1{son} other{leur}} contenu, vous devez {count, plural, =1{le} other{les}} déverrouiller.", + "unlockFile": "Déverrouiller le fichier", "useUnlockWizard": "Utiliser l'assistant de déverrouillage", "unlockWizard": "Assistant de déverrouillage", "ignore": "Ignorer", - "exportAsCleartext": "Exporter en tant que fichier lisible (fichier non chiffré)", + "exportAsCleartext": "Exporter en tant que fichier lisible (non chiffré)", "exportAsEncrypted": "Exporter en tant que fichier chiffré", - "lifeChestBulkSave": "Sauvegarde de fichiers en masse", + "lifeChestBulkSave": "Exportation en masse de fichiers Life Chest", "savedToFolder": "Nous avons enregistré avec succès le(s) fichier(s).", - "savedToFolderWarning": "Nous avons enregistré avec succès le(s) fichier(s). ATTENTION! Ces fichiers chiffrés sont plus vulnérables dans ce format, ne les distribuez pas publiquement. Life Chest, ses auteurs ou son contributeur ne peuvent être tenus responsables des données divulguées.", + "savedToFolderWarning": "Nous avons enregistré avec succès le(s) fichier(s). ATTENTION! Ces fichiers chiffrés sont plus vulnérables dans ce format, ne les distribuez pas publiquement. Life Chest, ses auteurs ou ses contributeurs ne peuvent être tenus responsables des données divulguées.", "import": "Importer", "group": "Groupe n°{groupID}", - "unlockAbleBy": "Ce groupe peut être débloquer grâce à : {unlockName}.", - "exportedFileDescription": "Um fichier exporté depuis Life Chest qui est chiffré et qui a donc besoin d'être déchiffré pour être lu.", + "unlockAbleBy": "Déverouillable grâce à : {unlockName}.", + "exportedFileDescription": "Un fichier exporté depuis l'application Life Chest et qui nécessite d'être déverrouillé pour accéder à ses informations.", "internalError": "Erreur interne", - "wrongDevice": "Mauvais appareil, nous n'avons pas trouvé les donnés nécessaires pour déverouiller le coffre dans la collection de clés.", + "wrongDevice": "Mauvais appareil, impossible de trouver les données de déverrouillage dans le téléphone.", "biometricsAreLocal": "Les coffres verrouillés par biométrie ne peuvent être déverrouillés que sur l'appareil sur lequel ils ont été créés. L'exportation de fichiers chiffrés n'est pas disponible.", - "linkCopied": "Le lien a été placé dans le presse-papier" + "linkCopied": "Le lien a été copié dans votre presse-papiers." } \ No newline at end of file From e470148290a72341e7736f2dcb97837e075add34 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Tue, 18 Jul 2023 13:06:08 +0200 Subject: [PATCH 10/13] :bug: Aligned normal text with Marquee text in the file explorer thumbnails to look nicer --- lib/file_explorer/file_thumbnail.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/file_explorer/file_thumbnail.dart b/lib/file_explorer/file_thumbnail.dart index 0676c99..bbdaf9d 100644 --- a/lib/file_explorer/file_thumbnail.dart +++ b/lib/file_explorer/file_thumbnail.dart @@ -87,8 +87,12 @@ class FileThumbnail extends StatelessWidget { return Column( children: [ placeholder.gridIcon, - Text(name), - ], + Expanded(child: + Center( + child: Text(name), + ) + ) + ] ); } else { return Column( From 5cf049c87e43ff0d31f104a4eb56819b5f934396 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Tue, 18 Jul 2023 23:06:20 +0200 Subject: [PATCH 11/13] :bricks: Changed the video player. --- lib/file_viewers/video.dart | 82 +++++++++++-------------- lib/generated/intl/messages_en.dart | 2 + lib/generated/intl/messages_fr.dart | 3 + lib/generated/l10n.dart | 20 +++++++ lib/l10n/intl_en.arb | 4 +- lib/l10n/intl_fr.arb | 4 +- lib/new_chest.dart | 2 +- pubspec.lock | 93 +++++++++++++++++++---------- pubspec.yaml | 4 +- 9 files changed, 132 insertions(+), 82 deletions(-) diff --git a/lib/file_viewers/video.dart b/lib/file_viewers/video.dart index 1d3c0d6..229071a 100644 --- a/lib/file_viewers/video.dart +++ b/lib/file_viewers/video.dart @@ -1,10 +1,15 @@ -import 'package:better_player/better_player.dart'; +import 'dart:async'; +import 'dart:io'; + +import 'package:chewie/chewie.dart'; import 'package:cryptography/cryptography.dart'; import 'package:flutter/material.dart'; import 'package:life_chest/file_recovery/single_threaded_recovery.dart'; import 'package:life_chest/file_viewers/file_viewer.dart'; import 'package:life_chest/generated/l10n.dart'; import 'package:path/path.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:video_player/video_player.dart'; class VideoViewer extends FileViewer { VideoViewer( @@ -12,64 +17,51 @@ class VideoViewer extends FileViewer { required super.fileToRead, required super.fileName, required super.fileData}); - late BetterPlayerDataSource dataSource; - - BetterPlayerController? controller; + ChewieController? controller; + late File videoFile; @override Widget build(BuildContext context) { - return ColoredBox(color: Colors.black, child: Center(child: BetterPlayer(controller: controller!))); + return ColoredBox( + color: Colors.black, + child: Center(child: Chewie(controller: controller!))); } @override void dispose() { - controller! - .pause() - .then((value) => controller!.dispose(forceDispose: true)); + controller!.pause().then((value) => controller!.dispose()); + Future.delayed(const Duration(seconds: 30)).then((value) => videoFile.deleteSync()); } @override Future load(BuildContext context) async { - dataSource = BetterPlayerDataSource(BetterPlayerDataSourceType.memory, '', - bytes: await SingleThreadedRecovery.loadAndDecryptFullFile( - fileVault.encryptionKey!, fileToRead, Mac(List.from(fileData['mac']))), videoExtension: extension(fileName)); + videoFile = + File(join((await getTemporaryDirectory()).path, basename(fileName))); + if (!videoFile.existsSync() || + videoFile.statSync().size != fileToRead.statSync().size) { + await videoFile.openWrite().addStream( + await SingleThreadedRecovery.loadAndDecryptFile( + fileVault.encryptionKey!, + fileToRead, + Mac(List.from(fileData['mac'])))); + } // ignore: use_build_context_synchronously - if(!context.mounted) return false; + if (!context.mounted) return false; - controller = BetterPlayerController(BetterPlayerConfiguration( - allowedScreenSleep: false, - autoDetectFullscreenAspectRatio: true, - autoDispose: false, - autoPlay: false, + controller ??= ChewieController( + autoPlay: true, looping: true, - autoDetectFullscreenDeviceOrientation: true, - controlsConfiguration: const BetterPlayerControlsConfiguration(), - aspectRatio: fileData['videoData']['streams'][0]['width'] / fileData['videoData']['streams'][0]['height'], - fit: BoxFit.contain, - translations: [ - BetterPlayerTranslations(), - BetterPlayerTranslations( - languageCode: 'fr', - generalDefaultError: 'La vidéo ne peut pas être jouée', - generalNone: 'Aucun', - generalDefault: 'Défaut', - generalRetry: 'Réessayer', - playlistLoadingNextVideo: "Chargement de la prochaine vidéo", - controlsLive: "DIRECT", - controlsNextVideoIn: "Prochaine vidéo dans", - overflowMenuPlaybackSpeed: "Vitesse de lecture", - overflowMenuSubtitles: "Sous-titres", - overflowMenuQuality: "Qualité", - overflowMenuAudioTracks: "Audio", - qualityAuto: "Auto" - ) - ] - ), - betterPlayerDataSource: dataSource, - betterPlayerPlaylistConfiguration: - const BetterPlayerPlaylistConfiguration( - loopVideos: true, initialStartIndex: 0)); + optionsTranslation: OptionsTranslation( + cancelButtonText: S.of(context).cancel, + subtitlesButtonText: S.of(context).subtitles, + playbackSpeedButtonText: S.of(context).playbackSpeed + ), + aspectRatio: + fileData['videoData']['width'] / fileData['videoData']['height'], + videoPlayerController: VideoPlayerController.file(videoFile, + videoPlayerOptions: VideoPlayerOptions( + allowBackgroundPlayback: false, mixWithOthers: true))); return true; } @@ -80,8 +72,6 @@ class VideoViewer extends FileViewer { @override Future onFocus() async { if (controller != null) { - controller!.setOverriddenAspectRatio( - controller!.videoPlayerController!.value.aspectRatio); controller!.play(); } } diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 154ae0f..95865d7 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -147,6 +147,7 @@ class MessageLookup extends MessageLookupByLibrary { "pickFolderDialogTitle": MessageLookupByLibrary.simpleMessage( "Pick the folder you want to add"), "pinCode": MessageLookupByLibrary.simpleMessage("PIN code"), + "playbackSpeed": MessageLookupByLibrary.simpleMessage("Playback speed"), "pleaseUseBiometrics": MessageLookupByLibrary.simpleMessage( "Please use your biometrics to unlock the chest"), "rename": MessageLookupByLibrary.simpleMessage("Rename"), @@ -158,6 +159,7 @@ class MessageLookup extends MessageLookupByLibrary { "selectAll": MessageLookupByLibrary.simpleMessage("Select all"), "selected": m4, "sortBy": MessageLookupByLibrary.simpleMessage("Sort by..."), + "subtitles": MessageLookupByLibrary.simpleMessage("Subtitles"), "unlockAbleBy": m5, "unlockChest": MessageLookupByLibrary.simpleMessage("Unlock the chest"), "unlockFile": MessageLookupByLibrary.simpleMessage("Unlock the file"), diff --git a/lib/generated/intl/messages_fr.dart b/lib/generated/intl/messages_fr.dart index 65acb4c..ff5533d 100644 --- a/lib/generated/intl/messages_fr.dart +++ b/lib/generated/intl/messages_fr.dart @@ -153,6 +153,8 @@ class MessageLookup extends MessageLookupByLibrary { "pickFolderDialogTitle": MessageLookupByLibrary.simpleMessage( "Sélectionnez le dossier que vous souhaitez ajouter"), "pinCode": MessageLookupByLibrary.simpleMessage("Code PIN"), + "playbackSpeed": + MessageLookupByLibrary.simpleMessage("Vitesse de lecture"), "pleaseUseBiometrics": MessageLookupByLibrary.simpleMessage( "Veuillez utiliser votre empreinte digitale pour déverrouiller le coffre"), "rename": MessageLookupByLibrary.simpleMessage("Renommer"), @@ -164,6 +166,7 @@ class MessageLookup extends MessageLookupByLibrary { "selectAll": MessageLookupByLibrary.simpleMessage("Tout sélectionner"), "selected": m4, "sortBy": MessageLookupByLibrary.simpleMessage("Trier par..."), + "subtitles": MessageLookupByLibrary.simpleMessage("Sous-titres"), "unlockAbleBy": m5, "unlockChest": MessageLookupByLibrary.simpleMessage("Déverrouiller le coffre"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 32187af..a500fb8 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -959,6 +959,26 @@ class S { args: [], ); } + + /// `Subtitles` + String get subtitles { + return Intl.message( + 'Subtitles', + name: 'subtitles', + desc: '', + args: [], + ); + } + + /// `Playback speed` + String get playbackSpeed { + return Intl.message( + 'Playback speed', + name: 'playbackSpeed', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 4d16d60..c816f08 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -132,5 +132,7 @@ "internalError": "Internal Error", "wrongDevice": "Wrong device, couldn't find the unlock data in the keystore", "biometricsAreLocal": "Biometrics-locked chests can only be unlocked on the device it has been created on. Encrypted file export is unavailable.", - "linkCopied": "The link has been copied to your clipboard." + "linkCopied": "The link has been copied to your clipboard.", + "subtitles": "Subtitles", + "playbackSpeed": "Playback speed" } \ No newline at end of file diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index dc8de39..5d6405b 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -91,5 +91,7 @@ "internalError": "Erreur interne", "wrongDevice": "Mauvais appareil, impossible de trouver les données de déverrouillage dans le téléphone.", "biometricsAreLocal": "Les coffres verrouillés par biométrie ne peuvent être déverrouillés que sur l'appareil sur lequel ils ont été créés. L'exportation de fichiers chiffrés n'est pas disponible.", - "linkCopied": "Le lien a été copié dans votre presse-papiers." + "linkCopied": "Le lien a été copié dans votre presse-papiers.", + "subtitles": "Sous-titres", + "playbackSpeed": "Vitesse de lecture" } \ No newline at end of file diff --git a/lib/new_chest.dart b/lib/new_chest.dart index 071ed5e..322d03c 100644 --- a/lib/new_chest.dart +++ b/lib/new_chest.dart @@ -46,7 +46,7 @@ class CreateNewChestPageState extends State { keyboardType: TextInputType.text, textInputAction: TextInputAction.next, onChanged: (value) { - policy.vaultName = value; + policy.vaultName = value.trim(); }, onEditingComplete: () => currentMechanism?.creationFocus(), decoration: InputDecoration( diff --git a/pubspec.lock b/pubspec.lock index c07c035..7a765f4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -81,15 +81,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.16" - better_player: - dependency: "direct main" - description: - path: "." - ref: HEAD - resolved-ref: d59cf112b8e3487a6f417371a083c8cebf9bebf6 - url: "https://github.com/AnonymHK/betterplayer.git" - source: git - version: "0.1.0" boolean_selector: dependency: transitive description: @@ -114,6 +105,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + chewie: + dependency: "direct main" + description: + name: chewie + sha256: "745e81e84c6d7f3835f89f85bb49771c0a66099e4caf8f8e9e9a372bc66fb2c1" + url: "https://pub.dev" + source: hosted + version: "1.5.0" cli_util: dependency: transitive description: @@ -182,10 +181,10 @@ packages: dependency: transitive description: name: csslib - sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" url: "https://pub.dev" source: hosted - version: "0.17.3" + version: "1.0.0" cupertino_icons: dependency: transitive description: @@ -390,14 +389,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_widget_from_html_core: - dependency: transitive - description: - name: flutter_widget_from_html_core - sha256: b733a240388736fcf40692920033dc3a749155dc49c840f6c0e4a732f553908b - url: "https://pub.dev" - source: hosted - version: "0.10.3" frontend_server_client: dependency: transitive description: @@ -406,14 +397,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.0" - fwfh_text_style: - dependency: transitive - description: - name: fwfh_text_style - sha256: f0883ccb64b7bb3f2a7a091542c2e834fc3e2a6aa54158f46b3c43b55675d8f7 - url: "https://pub.dev" - source: hosted - version: "2.22.8+3" glob: dependency: transitive description: @@ -630,6 +613,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" node_preamble: dependency: transitive description: @@ -775,6 +766,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.2.4" + provider: + dependency: transitive + description: + name: provider + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" + source: hosted + version: "6.0.5" pub_semver: dependency: transitive description: @@ -956,14 +955,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - visibility_detector: + video_player: + dependency: "direct main" + description: + name: video_player + sha256: "3fd106c74da32f336dc7feb65021da9b0207cb3124392935f1552834f7cce822" + url: "https://pub.dev" + source: hosted + version: "2.7.0" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: f338a5a396c845f4632959511cad3542cdf3167e1b2a1a948ef07f7123c03608 + url: "https://pub.dev" + source: hosted + version: "2.4.9" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: f5f5b7fe8c865be8a57fe80c2dca130772e1db775b7af4e5c5aa1905069cfc6c + url: "https://pub.dev" + source: hosted + version: "2.4.9" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: "1ca9acd7a0fb15fb1a990cb554e6f004465c6f37c99d2285766f08a4b2802988" + url: "https://pub.dev" + source: hosted + version: "6.2.0" + video_player_web: dependency: transitive description: - name: visibility_detector - sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + name: video_player_web + sha256: "44ce41424d104dfb7cf6982cc6b84af2b007a24d126406025bf40de5d481c74c" url: "https://pub.dev" source: hosted - version: "0.4.0+2" + version: "2.0.16" vm_service: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index eb1df15..269c3e0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,13 +33,13 @@ dependencies: local_auth: ^2.1.6 dynamic_color: ^1.6.6 marquee: ^2.2.3 - better_player: - git: https://github.com/AnonymHK/betterplayer.git flutter_pdfview: ^1.3.1 package_info_plus: ^3.1.2 document_file_save_plus: ^2.0.0 flutter_secure_storage: ^8.0.0 flutter_video_info: ^1.3.1 + video_player: ^2.7.0 + chewie: ^1.0.0 dev_dependencies: flutter_test: From 6c08f59f0d870e308373ed39428176913274c475 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Thu, 20 Jul 2023 21:02:01 +0200 Subject: [PATCH 12/13] Updated graphics to make the shield black --- .../app/src/main/ic_launcher-playstore.png | Bin 0 -> 19523 bytes .../res/drawable/ic_launcher_foreground.xml | 19 ++++++++++++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 +++++ .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 +++++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 2823 -> 1971 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3987 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 1839 -> 1362 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2533 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 3750 -> 2663 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 5669 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 5848 -> 4309 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 9145 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 7662 -> 6126 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 13364 bytes .../res/values/ic_launcher_background.xml | 4 ++++ logo.png | Bin 36945 -> 31989 bytes logo.svg | 12 +++++------ pubspec.yaml | 1 - 18 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 android/app/src/main/ic_launcher-playstore.png create mode 100644 android/app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/values/ic_launcher_background.xml diff --git a/android/app/src/main/ic_launcher-playstore.png b/android/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..df7af64bce658d7ae566491f1b091eee0fddb5a1 GIT binary patch literal 19523 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..79589c7 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 505fa339511c156733a8d11cef1132ca97d97bb4..d51e1a201ad25219fea7199f80a8177aede71efb 100644 GIT binary patch delta 1958 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 S21fM&0000P)`SZ5q;>9lX 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 P00000NkvXXu0mjf0U}BG diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..26fd5052d06d333a1d0864d5538926e56ca1213a GIT binary patch literal 2533 zcmVkv15cM61n&nujsA#?F|`L}wDF+C&`;f}KRiM5<|PGFnO61OdTL zs7Z(#Fud$e&?*YjpzA7;g!(usUH`~tIt=4vj)z%51k1@AhYxqYZ>hPEw_1}~ zKKDDFTdV{9VF0%!1v22noa~N+UrniKH(TGASDmk#It7LU4#_tEy|=~mp*t=o#3&5Zg|9&JNHaS~t#*U?cfB+8kF@`zFKvvXu2l&P!_B6NjU()I3 zDLJZ|GVfW`dTu~bRGxs9EzZoMxJ8R-;)DqVQ^16X2uk|(Qi^}>Io_AYAp=?H__8Z9 zhb}{1Ez{>5m0X=o-kx5Q>1Ai?csOl3s;lW}P7b~N!iy9!Zk&_c-Q&m8lBX6@etJ4} z*Ecxjzpkm_W0-@CEDv4SfGyY*{YY>im3muEbg8Opy^^c5$q|w9t5CN3HXiv9=lmnH ze@2lK@o<(N53}@m>($rDc;Ena)*4juGB5`j$U+CYumM}JDay+L7c6R*v97J`y@GK{ z&I18R5q(qNh`Wuv`YJ;*pb|P}480T=#|kuuzSh^MWV``7(1i`yf=y9I3G4z+w0~Dt zCMh|)98EWyTPh&zE%%{z@6>2!?6_*qU%&=zc?&@1)PCkn<%q#r2yi|iuITmmGofy- z;KL5YL`Tzw6I#`rzkm(c@)iI%k=2IU>aHp(nk5A=(s?X(84O9%b-``nD)D~_z|7Og zfiyCgm#^aifV;c{H|pzmL&%qNf5-sXgQu6}cb~D&Io4;Wquy#gpA+T%34mY6nT>N= zZ61?%Uh&ZazHMkcEenZ?B0L2E(jD6~===*S=)$T5y0+^BjtlV#bnZ9HsUstk`sxOc zSHRx@@bhw2)fpx~c$8{2ny~Mio6jnRhJvR6I#Scf^2p<4`T3*n!R8>N)bTd}q-(~z_LZXVWh%aAR=b{4}ur)a< zO65m{9Kemb`p!?Yvu8L1&=nTm?@s^^#!TZu9M8*h8Na?SpKMS5Qbk%u+k&U4`_mE^ zoqz8Am_3QZxlPfJ2xS0y+qd(hl(*8HoFB7?Si3AFDvEe^!2${n3ZnP7ZF6mMznr0c>8oHu5_^iuf%Uj|5g`Y_p2lCq$Hh%_2EbZK zr@>Gq3yF#%j_ujQFJRG=Cb3(jUNsM*9cdY4oA(P2^hNRjbYTOwD)#JE&5Mw^UDRsz zjB_YwE?tU(E?0e?s}vdvxQIRW&_jIX^3yYLPf^M6bYjnht2?rIUp3EkpbH!G=gjfx zLI`fqYbiZa!1RJScj+n-(0r(Ly(EaMgxBlD-?sjVJD(RD%U0y1YTg^516|mFEpgrr z@Lu3xwaN-VZxcAXTqX9UrpES~%-6ZFm&+XRAKfWV00p>Z?OI}|m`cVIAPXJn!Uk-K zG9s}0xXg7Lj5pFYZk!9wTD}8=*Xgh;pI4vY!d|Y^k_`QQ=U-{`s8JLZ8Oh$NK60B% zA|L}<=!^~t;Wm8Km``a0;Jp_siDInGb$u?l17sjO zDma+dtyrO&cL%om4z~J^@7WQ2aMv!RPms%NrTlvK=Z~=kait+%DV4Z%>NI~z z4-5#P2V!EVXh$Zoi=j#mW0->sWS2hk41L9PMLBnnUnwu1)SZ2J#*7#x=fNNbA{u=n zKmSd9i$THIecXkAeO5_N&!5jfp@fBo(x%mk%-LXJN8OWY@cNKRJUpRLz zyF2ZpZYCq@c|xDr(vOqpT1{=wTN^ek128*a#H1D|J#i;pl4 z_koMYy!X_kCv*tI^wR}JMc=Xe3=E^Fa4w6EZx^r$+wg(3Ig!g({wLtTpSZWuBt--f zgFNi4HQaZfvqrJ*)Xi(wEVq=G8?hTW zp%j6jKKu!0;4hjIaoB=Q^U!NXX8Wh`0bf2BtUpaUgOO5`?~aIw-TUslZ#MnokdD2W zbYTVY1P3W;cU&NS_2V*ls$SLCbTuD3tb+~Mf=$@=dd}Z&!^%ib#xP7`c<{x=ix=-p z%h-CVuyDWmXqg^&miFrE%j^Mk6+r(>o$joq?3f-hkcAG@#g_%x7z3LrDJkkdT>MZC zwIMxN5DdQAgGda+%qdY(a~3}F#DeF4wdiR8eT-pFl7TFA_*<3gVsX`|Q5X`#Bx+zw(5EeyI{ZlU_Ja)}k_ z!LU>p7mw6y=6`UgZdT>x^^8p#NEA(KZ=5cn^9K(jU^308-E-nzR1hJ`gTG>kX}Q(!n$(j zW81fnWDTm-CVXQ_1F8XE78KN^Y}|N1v~z|59tTrX@2!^xw1{fJ<-GjrSJ$lzg?7#` zz;n;$&G*$y16o8gAitm{DK2g-w37z3Bhr8lMjFt;NCP?;X+Q_#76#OvDZ^y|E~;1MIKTi33HAp%Te9+n{ox%~R=fy)_i zv!s+NkL1wn@z2qe2@%xO$43*rIgo=~tb=t?gRk3GxP$>Xj8qpE(c!IcQ0$BubZ5VQ zg2*b~-MT68^Hs1eYM>Tsw)G*(^ah+g@DEzIY=0RA4IL_osb@gnzV!Q;xpZv%4h2kO z9-pTNHBlQq_`c4ipERRw)Y@mqHQ1bNf5QJ0l?cqbe{8<$3e(7bpUVK`pgLznn z9OUxrtDpyZp(lFtbsWJo2Gp>_!3Ud@DJD9a`u6Tko}Qk9Pyk|$4+){fwQ+PY`v~D? z2Y+9S2RX=1T)URSMvrOMRP;n|i~(c8nD|;oF^vJk0|KbKmzN+4=-jz84fFS><#S@_ zczQZjojfJ1-x_edzxL5dr3PxDCTjEj0LFqb@imNM8Us+8=MMIQIXyCxcKkJwDsyt2 z`htmCsEOL>fnI!nz^`W%QyOs3-FH*MAAi?S$(|3IJhnR<^gu84L~s3A_*|oy(tzKw zGZ=n(dx75ivGB`{A`LKzG(Z|)JEQ@|kOmk;8Xyg@9nt_}xU2!S$4}7J7hk5&e!Gw^ z%$-k{Ry|H%??|J%l2QdsV;+_v2f0{>ufrn^XoUecvUBJ{%zUzh{Fute+^3qw4gXLR}T~R>$Gt;UO$HihpSg=-;Q0w&A~d=;y+6l^eN7sbXA&AZ%+n8}SpW zEolC12))&D1l%=PSZ);47;tZ3ptj+Y$Bnajr|Z&+Rn5Q9+Jdd~pC_Ld>ZyGDaWPE_ z3)jXmIw(lUF^Xvnm=Y18ZTOfGBW&KAy?OLQIv+hl6u1S>|6(T9<`)R{RDaMDz149% z{NRH^j!{fw!0OmoZNu?2!^^NeB|1Hjsai?qi?dUWqj z2UAmpoF-uc*Sx!%&P6?>iT}^353|>a-K`QI?Ax+M>51MLL)@Z8LVu1un96{>?K|ju zzP{RCh;#B=trQSkKX^zH9$=bZ-W=$mKmYI5vnLg#r3-oXU@8M@OG;^caEK-Zp4BPL z$Pn^uapOpi0zcmtg}XBvJr@)i9x9!n71Tma)K>eTr!)6{U`hi3 z-k9O(WV8fbyL6$1HEW#mfG%pF7HX>X(F;BKTt_jj0T5~1rhiT3V?8$qI9C5H{yB&K z6R<97=#TrD-nQv4PBE9qv<3iN9)4oM!bTs~z;PNMw!2}+Q`2|~`n6}{8@;}uHr{l# z)l=A}HUNBe{Dg9B)_;(~hwZV?u2@O`J@Ju{-yBy8j?**Cms5A$^(NHBr(w{8&vzE4 zHvnA8FQA`>g?}|N0aqqhblu=yH02O@Y zK-{9mGea!}&QSyK^BbPyN007*y|}nk{)CBbpba##?AupyUtpjgv`b4%v)=$ja&j_$ zq^wt2=KfdkSRZRpTPJ_SM}TQ_8`|JrMrQJst$)zWs-0tDE#f;fGBV_1_K}OY(1k{< z=`H-rvBquQ4;lEqEO!PP41*@nhE02SYFN;!O#-gsMcK#C&#$k)zyF;>h71`vn7Qtb zVB4Vqw16g7ZJfU6Hx+1t^III}(A1rQ2GF8igqI;hh71`pWXN!h_#aR7TMP_($h80f N002ovPDHLkV1mY>Az=Uj literal 3750 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 LNkvXXu0mjf^GX8i literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 4923ad46f03e49460ec0de3a53105444d0624873..6a8cbd5c23b6dd1edcfdf542fb6172e799495cc4 100644 GIT binary patch literal 4309 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 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..68513c70a39e2ab44cd3f6530eb769d50ef548e5 GIT binary patch literal 9145 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 DVvdtV literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 6263c58812aa7c55926deecc221b1ab34d530b92..b21d041d162b78c8deaf010832de80de0f2c572b 100644 GIT binary patch literal 6126 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 literal 7662 zcmcI}^;guv*Z-TP)}@w4IwT|&kd7smSh^bo0T&SIuBE%AKJ-%3pp+nuAfVC$f)Wc- zA`Q~;?C1IZ2hTa*AKve|=ggUzJ2Q9gy|4R<*VR@ffzU$$03cCUQ`X0}egFNy1lYg+ zuUCZF=Ak#-)Z4(#(c90~(*f}F^AmJ>?c(*q*4;tS>jcz6?D8Fr}$0D;WCY>=iyJ zpc?8PuH5SJOJVX2f3}=H7^`ryR!D0YhsF@#xZ!M^4j@Z61Gu@=h8r2PPlCDm4*ViC8Vk&Yax_e@QRgZ@BlKZM?hxBef_I zeBsU%TV|AmVCci}JfHwaPu*$k_gf`$_nU`Mu==?YaacH% z9`i7pKKXNdSGEhGAV7d_l_$u$BQU(%C13lV-s@wq(-|3uxoK+?d*jF^YQF6*L7(2% z{NA+F9Y+n%{33Ah>_yt=4bP6|BkpeHoPP>x;u%zs=r$$1udH#i;4EK+cZk*}d|iTQ zMTJy%2P8jDeoXtF;>~EEL~rOwVtFh%yQ_--Db+wZH8`Du|D@ir9YC;VA(&DTYKjH5 z(6v+J0fH#Ct(La7BFcE>%>j(wRAH z{&$}WHMw50YR&JSv9KzeBL*JT&R)e&w;6#f0ac*B?!i;p0Pg?+Jol%(KXc9#o0Rxy zL5k%)hnkOM@t$^Rb%6pBqTC->w0Jm26QPMn8LF;?2lbpP4oKN!M9A6GPkC67yUc

;UR%)y29lriZZ#g!m7IaQ;}WF2=ZIpk7s@AevSxkr<8f;_qq9 zStyFcb!}(KV?fqARec{`Lux*mcb6g)PCiqbr}-8%%^-0{(lSD# zX2P+AN(iW9{LGwSOt4s^0@$M=0`obzMvr=o+|j&tt>*K-Q5213oMTy@Kqa_8Q!G@6kQug`@n@@~ z4l4~rTGfegEaQPJv?xNa-&e)WXFPduzDhS2z@jos++vgjsA*~v)TCuHS0#M9?TvWy zTz%Mp5pFL3;}Cy(V)b%AobF1Aczu;R#D-!O%C$21MILnf3x=W;v^(V%8LTl0j7WnDU~-Wq5)p>$afBc>EP3V% z*Jy)M7uS6b)bYjT>F?(4n=^XU&lik)o(i_3*tdc?8t^*8^PTa~+2OpunMCr(TqXnS zRr>3n`@1wnQCbl{W&(8?$(ImxXhgl|$28P|GS{^v)0kU{yc5z-w-RQ1F zBo8szlmyuKvXevcT(|ue)O73oxH{hQ1`aW zNeky~U+~jC%4$=cUA-%JZ=^}bbDJc*jjrDAvQBAq&T31hHZtLWuG#A@%$Ll3pc1%~ zqH><~MsDEQu4$L&OTV=tR-`W;a}??~VaDq4riL8F3YPx$`aD=z(M2qude_j1foVp_ znj`+NV{*!gseiN+IA?rdp1Rk&VH!UT7S~K1tz;~6YgU3Um=~^jd~z8~q#gmjN*k^o zwLhj0-Y{Nl)2~*>DTmJ8FjI$8OTBJ{0rd!ma=81wANvxXjys|9lQiO%l9eaKHjyn!T388Wo+h36oacjx`WQ;nqpv1orC%wpsKfei_VcU)+!ql ze6EBf)Z756Dxw{b$crIDl{x+Y6cB@kJmAXm=}MN2@!(#$oZB`L8`c9%6KlnKV2IZU zdgV+f-}U4r&53k8g-v#{j5l|M@XLY%&4OJ)DxIUv6WODe()wcIGI^Sxt%Aljd-q$+ z#JSI|>N0zE_}p=HkL#67C(PbooVsxv)_s?SfJ%_eg&FL&&=?Te)4IUjO_)8y@m=y^=Jk zZKC??2EpVH0*hd7hbBsG2%M|HMYzH8&$-o#omjL}Ly1v4pzLlbwd4-h@GtDt-L@F_ zVT>LKvwTS0+dAgl5d^Py^EGai-zJHP8K9hS)fuP6E9@wcp>OI)7k}0o>=r#C;@J7A zr?tSv2}clBHYr~8S6+pmDe7&o2Z*Ni1meLT&fBfK@qY zux*O`bIq`i|+)qFxp`8tPTqkd?A!{rol|^sEf}>m5M!G z21_8;BbYZt-%8N0WZG9PS-x1lR)^i^k9OzT0pe#VS35vjro-#=zTu1cJ!w?v=%53% zuN%Se|2hOSq^+D7OsDt?Wp$hwu*>w>UL1G0@w(#j1==?|B-@*CVCTnt-Pp}+3#X1? z#RDzWRS((g&#X_DX_MN=uYq`I67i{s#~y1|O65WDYg5LH5QlRYMLeS-=2m8HvG8p-IdPsaO|1A^6EILj5W9(QO&w~g-GTP~~6r!^1==u-x&(*X;s=WHgn!At=yME;bYSLTU>Q47DSJBbg=R{O#}#GWSZUsw5OLbv6n&UG zbYrUsy>k?z>HQ?k(s4Q99MC$8RD1Ug*TF!?ONPFe#<(pG8#TZY&~i!U`XoaQ%FahZ z;E&=izk2DX7yn6TUyh6!SKfZ8I~m#V>_(=jF0edzNc^utqxPi~z;ikM&e36$+qpcdl4njI_1?Db)pIk1B4wwBsZ*GF~WAC9JnAL*uDfwh*u+`E+YP+9h zG!Vn@Xz%UMzZnrETuAQz8h4V!Y+sXSY4B!A6>a)Q_1@e4?`nXQVh}QA!d`f|scA#k zSK_Z*Z?WdMtU!9+W7W_)>_LS5w)&vau&1Z}R+5f+Rm3>vzq?xH`dcB%%vA5jy2GQI zs$o}Hxp^lyddlPVo+oj;oS^X1iZ5iD@b^e!=7X*ibaU2#*BDnIsebNvpVPFLGagabVsu>knq{fA%ITS}EAaP<5xZ-u<>cj|l7^*q#* zl(Ufog-IN_=;KTwR$!>oflm+s@t(vY6_klsuV)8Re2BHK=q(uAl7~6#&WnmPW%*5t zHr{=*4caDSKBtg8QO?yBc%*ny=D(|>8x2fSyov>s4^m=YOxQW;m~89Y}YQ$&Y~4(E?K8vWHSf#9&>1?rs7PD{M! zG$A8rB*X-dkJp58CnlU(_Q|^kccrQfKEF7bk-aI?y>ux4YQ;kpWhtoI zx=aUJWkyr}N}_4myjQLjypj~Q+{cIZ5%KT+NvN~7@t0d=k@uRoGbxOiwAsJuEFHDK znGun77D|5jWBhC<#gG?1z>>!e3&^~@uKQb}Kn-H;BYHKMOeFv?N<&$ih)_^*Iy;@y z8V1ph$L(KCc!-S$VzeiZ-IO+1V!r5fHYf^D(vg%)S~t#zp|ssIvt&i9Q~>0dc!_@E zaw_GpH7t8|hdPi+w{|o$^kakX;3=+vTYKWr0iP`{@BPZ={46PK!^GQK_Dh5_x2*nL z-K!G#GZ2c9bz%X2jtdo@E!)`Hb(ipc*IE}82QGr|N>_7UBy_Sif}#Ijg>vZzseeNv zvqV-tDf~V7=Gc7eG_G*bT$C>P9jgU4!5}jHGciR5l`VlVVG=W`fRa(Wly3)1UVVd0 z*V)%TA8kE<$7kQm8s7C+-6S+tB@C}e9@>^kaK;J;Wn{^=U?;)z4<8d1fv}4}h#7u@`38sDZNz0*aHrBK$Fy!AQD(rhy_M}}LDxMqmFz-91q z!g1+Uy>Dj-311LG!4-t|NpAS}?;jg;>Ptz=NS=5G;-gDh5C>Nq-WGH5xMs%jB6*o@ z$nXsF(9p6vd-`@`*{^b-WFH|mml;!o2iuG-V>u+h!YSR#LPI}S!-1$eYaTh;L!IJK z^ujNZoZ?4A&+rirsw8W%kUYo^UJUuMxDkcj}0wL*@rj@&w@L zkH#dCxA%k?UcL;3qSYLLMd4u3gTZeC^IW ztL^1^Y?9+;U|q@ZlxzB<@#F)W6TG;kX_uu24+hz1wOLI%#P%)-@6g6_r(3p*Lctu3 zwvAlTDt!QNFfkE{hXTEi{)G9tySsZ}?_|=^wd?tMWSeA#g#prQKfNQR+FjP@?;`l~ zujie$-n#PS+?*KBd7g9ZYs0(Y4a+X&NN0SMyW_KgyeF>}Aho4I$Bjrtc^?)Xq z0lmjMQ9I^Cyey&J`?Bbd0#NWxRE4Ylr2Tt52AA7Nt)bFOuUa@Y(O{|y7Wg9LR`K$@ zR!2>8ANFLuwKU`d6t%R*3jAf{lB2}!Ci;&=+?UtecbZ=1>yrivIM!GlWk!9w4p+UC z+zSAQ71`RR8djMDG>Hym=4rJ0)l_3$^wL)#kttf}o}`2-Hy!bE#9XoSmUv|UJ0q<` zn~#dKAXa~wB2_X*37D@f^mhO8DL$7&^FlF4lKviL2_iz~Qi11+axsNp=IE7hH+-zh z8bB(@^=ny@(8?hGO4?r!>hg#(Si?>!G_=prHa^n(kH<>=rfoy#cf4zyH(#1y2jKOt z+#|ibnvpnAsF)Q)vI_0TrG1jRztf-{?~k-ny&oov=F3!5rOyJpONIJrl;B|C7Nw<9 z=3yY1Bb~D*ic{FeJqbBeQmAs~a^O^usZKc_D>(e|bI-TaS#^V~f*lWLr!$x#qDL1t zrFV+I8lw{pcDx9d8_Ll#W(S9;I0)x@v}{Q-ro?6~)<? z!4e@^6JB+Emg_8dzgeClKJ8N4P}W8`V}AXpYjA{rw3-eF+GTyveSLnwLYB%J_=d4c zL18=^`20kq4x+GoFA}WV{Vx;HxixsEt#Oc&K!G*wC6e>2M`PPha9#&{KcOoyx3IXT z;`>?iK$LE4X#HrXB~?~{=Bpmv!Jixznht<*}#fSF;8+Y;~x8NK>a zW8Ab*$6~wg`OAiKqxxx-ocPnH32azw*dokk`1=}z&s-rh`)hjoSXoKw6AH0|9wk|D zKJE+0ouEpD*PP!{=yK^8*~!1Y-|jNgBUUO06jL zTxV?SgaaYrBV>MWgLs`rY*-Gg7M)ZL&X=}c!Bjs8usn#~7okrMQw^_wZf^~LqscYO zvA)3h?WYhsf1#alE<68UJ1sZ_g(5ww#JX~3*H}96_HS7-zitwYAzV|*kwnHx%ggHo zAzWDS&$4-;>(}mC&*uR_$tqJE=wyO?9O;o772_9u`v|*7l`+foel%8pV=MB28k%1{}8qP>tZVZ2mmdA=@nc7U9%A5{fzrGu>zoCG*pjb2kz3l|rOpq|zIl!~ z14W@=+W1KgdJ=C5#$J_0uJ>jMde5-$w|kkpY2j}*I2IA_k}TnOba#6_CL8q6@==Ee zFHm@w$aY$>eQKb^u``GieSLZve6Hb|^Tsd>7@;C;-`eT)JCGw`8@ve62um~i&2cary zREjIBd}u0|<5HE`T5lDez{k4T%Or5Gbiuv%cRVu3qjSk%YIsqw!qvHi7axWKM!HV< z*g#EE)tRKlsGdQlp!0oM{Dyl-#%TGE{2v+_Cz#f_D4_X9g{SLu~ZMdGQAXB3uhe2SknYK}Z!`XRCDU+2>DT&+o?0@g+!46xPI z({!S`D(-Nil-H;9x=8JQ@W!XJD^$(UvgvT}?mg7EO#Qn#H#zx)E~}T_#5XJ9EgtNh zdA(Vb(hJN3V^(iE4e24rm8ZiXN9k_yh zxH4S7uzhU$RH*%Y>uWo$Np-z}5N#e65dO`ny0NjBx&FKp**z*9UtvnVo;qYl#=aDv zhNO`h;25c_)g=BhIGLw}6! zQ*NWRV^#er3J-=Sr`x72QC)AqCF4eFe*Hb`kD7K@H`pd~-|c$TAEcKDV0~G@c6gPXIl;_mEkc|yO6&Jxo)+JwQa$adh>(;OgdXXp=x*T#hey?qC z?`BnOaak>#QxC*Iuw(NfE)2)L3=?y9DRx?k2^*xR?Jo6kC&tlwnhZcQAlVnIO@jiKbmFWp%{J zOCekDy~x$`-~`iq-&44;@h5iQY7Dl@6s6==7A+@D5ibLN`m3h4F9`p-m<$gzgQcUm zSUeI+)*wdOBR~IONcLge|2X||h5uZ+R=85&ng=$S?TtNq_AK~*rmPR2736KYqC$LI zTwh;5Go^R?^v0yl{DGv)^#LVC z!De<^(TW)R#|_Cep=7*wL{%3jX%je)8%8f7f=uo<3+c<=-vP-qP4!?TOcJcU-aUqYwmC=#oFPFKA>8ZXe?Lv5HGR z_Vyu7`5BuXO2T_f5qzhmd}0UBN}BLqNgW&m7nLEUB`NX}xDHi6*5gna1c()hf$yB}PSCF9w%e zpdyZpB~CJcsKSbzmoq6p__Uk86gG51*F0np|8J;m_4JW^%igWX%VDRL&%we)P?38= z68HaC$OmGn1?DmKprWm>_YA|ek3wUpCm(I{Wc`MmX+dA}^CO%mRpg8Oc^YS5w?j#Gs#+xEmuw}B=%oQZdi*N6b;EKVvVUAtlisrmsJ>*6{;$}DGP zVtQsG$&0LYa>i9uM^cOo>ko8~raC&M`e7&^Z#jV!xqcg;}wuTtqoV<6?zFbNApj7r9o*(j9)D`W6G_hRPD3UroUE&72 zz{H-FJ(XFh*wxil!4?{jHpav~I*0KOn$9o@qi1pM`+B8%`>~lB$TLrk<2$GY`i@v( zet*Wy77IC(tc7Y<#!q+CKn0}QXBk%}PE-=4pAflGxpyi>b>-2;W&O>(v-D~6DQ6|G z&F!6W(}#Vkqz{4ElcWm7+c+W&96@U?u}tt~Topog0lSNmTrsxt1ydhMkFOrIigl_} ziO2@ZrN1-fPNN6Bc36O9GaZN*{TssEHK&JZTu@2RrPk#;8$!59>E8j!w3cYSHP;5I z+=~BdlZJUAvUwDIh)WaP8vFsSSC^R@jr#Ge;hkE((q*r%Z)*4Ar%B$LZ<<6BK2J4y z#Rfc6kby1*((}+5L}n~ef$ezr`XXbRZ0rwsu4k!d?K*zH$n7L1{L^<>SyTci!d$>2 zQ#c7BSkK#5QFqO7>Ik_bfj9Yfsb1f!o1%DL#emeL*XRPgGPK=Av%>phu#FZ=NSuHs(rd@zyuEUD`893hv@ueG2Ss#r ztujJeX@Pf(p$^{AsnEtto_cSKcB{HiD?`o`nFR%l^|()x{AYX;=hvlE)_@ zZ5*>QY1*o^`7cz9XMD8zZGY;xw}@%$I?=DfYT72d#j$0`u#yWKc1cjqd7O*Zs5m38 zZ0;BR_&*fMzL)x#S=h_qRuDy26!kC|V8$Ej{f#p>p+;o78x31Ie}7;gtKQ_)c|+YQ zzipDLKr1I^Z}*wu{G2B0`X@a-vIB>IeehOd&th>EMQEb$#|UNpjnh*H4kI2q4n=o~ ze^HV3V~|NuX#beg@=x^2PkxZuI!5e=!-<}|XC^;Cjc)HUS%NOoJz3Md2*w}4sFEPQ z8Kl1y2)tIpQSIN>Z$m?oHbiD6X*YT*EYAn*to}ZCD^lbwJX#|Sb&4B_gem`Vy)-iu znq6JYTYynxI2RiJzGAj37e%}fol>A!0vyYb-HQL9S|8Jki>pF?t_+ezyr?6)te1ai ztB<3w+GT2h50ieO{wgc`9JVgT$Ts=q?;19>AnwODVr)); zw~>`4T<4C=i4SGeQxHfWg`%fN^o8wcOK43j*Ev$)UL6kTWz<#7xZ|Z z^9~_M28I8gvbX0KJrfhmYKuL?7iaDABnY)J9)tV5c^}g%_BHaDL{oQ0RqpdrXGwEY^RKjyB zmVYbdx`{38J>AjW2dGpR`L&!y(`EdNgx`|_Fp^t5w`0|EEH1$Cu)hx;DVEvQwYzgA zE0T;qluWmgqM`ceHV7&Bo3#_)16;Ectr;4Bz6XqoYs2~6R8Q^!hIp~b&HEjGo@2ZO z<c9JLg38gfTFi$<}SV57a_PV{R$EyYL46N4tImY527&!~0G z~6oVwZP!Yt!8p6*7_Zt*rNg-kK>;d z9reGRet7Jf3er$@KO6EgO`3cVrV0IIW^rBZ?gDiV!tIy$@ntd+ya5u_A|(=m$?SOF z(_%R~W{-Uo7WT>uBs$GT@6HR#%2-NNDl;O7lk%urEpHp_2A)uGLq+a5G*xBO;x6V9 z5MaJ(;rke`f7d$&E97#CNQ z<40WV+2U%}*)6+uP=lpuLCO(FR(^b4EuMHk9=Sg^ltEJfb(f(^CPMTCDejGZzl3rC(^ zdZx}6LF$u}KjevjT&d#XZ+o0Ed(h8y6(%V4a642A*GYxag%dK^rE$NTl8$+I4uUfu z8%1%vN^_8op|2q2Gr5glS;a9<`d-&UdY;9X{e*|Z?Ad_RIfoRFiAb62VhmqNO=jA8 z!!9TD>XvwNXPOv9jMd;mdT-XRauHuwr=duOHB+MN@}XXtvKDr2eIc*S-`P*c7E;pj ztEulrqii6y@gX*Crc_6RST31Wie$P(Ld5e_*vTs$GXhGSo{0z7%al@V`Sc``vz^>} zE3g_wq^22h$F8F$$i^g~Hjpn$P`cwS;P=gXX7K=nZ5Y4t=6K-3q3vBV21UH^l5R(9 zGVB?Bf2Fc@Mv)c`!CiJSO7Uyz)tQ`ZgP2Qh4=jGS zM|pB;6ivVyEaMZ2CuroieTgfwG?3CM0m=8cE|oUddQ(IdQ zo%(QO*pPwdv5B6fYd6A(vsf7xfqMUKj{~RXZ}PH$-dQsw6xpO&7DXh3-)#_2h@3Un zKNNgEkxd}YnJ+5MJXfe#AqNMz^{j9vy!bm^GVG{19-4xZh!Wu<-~JGOwYR)*U7bhN#3+&%8mlG^qiO{ELXF4X8}#E?i#(A~*rN(?f5=ff z(;-k!?HU#shEBTnqkz=_z0ID4rjX?q_}qG1XyB!#f$!2w<7mddLLi~KCF9n0!44x} z5+OE(Yh_acr+F&Ij#u^4%7Ix$X8OARROzAzL{X1Ul2VQ)rv@m;$bUcA)s=- zeZfFYJFm_yP z5~|?XZVSJ9AijxZBV;`%EE*NTT$A zMH170JPVGhJ>(|xjS^X?NN2P|f)I-5@hM5gZmulR`=@{3K|{?|&f%xit&Yzy!cYXV z27vLYrii1_k&%ncS<$0+WIYflpJ6DdHWI&1D*xX$B=`U_$)?+bn%Kvep=39Z%w;zk z4q2orrm1NWa(;VWKc*Gfn0UGv0B8zTn8nre-to`ZbPKi|PU#$`baT6%ED4icAHLCw zy&TGA@->A0Yln`HJo_PXtBUYnXYXI8lq1$^k zk9vgfy%6<(l@imk`rx+^l5-hyz_9LB6|O=g)B!^|x`-SZ?=$@nnqx;+xH>h;==vQm zL-M+(0=wbmBAz4u*I^A@wG^jh!07Q}z%()edTlsy_el1o=gqXD@`sG8LMC53@ewdU zX@j=;Ee7)?DWuP$W&HYIqjU!4c9s;;;hlH_F_dw!JhrO4N!JfB1(SMN@-(XS%*2?ILQ-3ETkUn`hqH1i*{ABMX z5chO5(YLkJJ+L(@snz=PFpiY~ar0QWuzvp&`?h|1HWjpcn{Finw+;W?6wn-}- z<65&24!71F%JuRxp_sDpzHBn{)e8;s7fo8yn3^NbV6Y zHUI)nkQt6dpU7It zMk!JG7ZM-pOBb1aa5MmTUkbR=acgaiXQ{eLjGMyKKY0N+*V!V%zpy>8;E8=bxqmQs z&`brUs{r2N1mdp?4{1dqgd}^NBRT~PI|VkwB|gw>3=OWWF86VBp(Cu69!$z}>SQ&lu zMkuM;@u;r7xbL^UF^P#$!R;Ps3?-a|=G)wayafPOI%@al2lTb-4)aUA9L03rGvMG# zOxU?b06f}OGTc*(NkR`zBTw993Cq1(U1NF1PFFA<)v^5*qElBN12P#wlkIP~rj{0( zR}kS3PclN7LiOt}VzCYf%9zBs>KsS!X(Angk)Su{0@xtx(b9OkWfgAs5)5p>6)ECo z0d*Vg|Ai~#;*5O)PI4o1d<;k;PtkBhfE|jYj z=K$!6U=Jmmb&`Tb^YL)wN=b&67!>5WxTYbaAK(bMjpK!D#)(H&frjp%T%*L}qDMFh zZ%$edRvN2Nn{1=uj4=Tlg>-YHY1cTd*g|ls=wJXITiUfv?07S%b#|bV6LkCZRHt9e z49QWrbvupwF-L~*{kwS?z3AXM2A^fHQk9WNE5YC2L7DVk zRt8GU?hI^np@+n6iz9zqJ(#hZOt^Y2mIaa>9hsB&`OP8O8P!8vqXgW)-4#12=A7Zy zUZe%Qg&d1VYq~#$8Xi$Nz)Djd{`>Lumb%_3XZU32p8y$NJ8NZ!D*&H*1l+Xiw?r2* z8P3IK(za~2mR_;~X(MA3873eqiI(B_sDj?!fj9kTM>2XAA&d58*O{5-bBx&f!1t5_ z4_51mOu`-Jb$DWTj>M&aet3^^dPFPj#>(+#Xu&?{5dw ze4X3GSy|>Cc9|$@i7XxK*N3?P<(UG2J8{M+WY^Ihg9wsEPdix21wsxoJYLX~?)L8* z3kcE4pok(=^tu{tslCDZqP_Y$P^nHW2|lx3-x@GQ?YAI&a}ED#x?S(^pV(y-B@~eht64&$D}-d>$16^6 zq&4tbi&+>;>-ws-8X!9;qBhFB<Dzm^MYC*}bcNu?J7DEv|CU3Z2Fz9z@pmwqK*+v`=d?Uc4G zzy&hO9KAf(9y&$9{>;V={aZHM8n#(Webr8xeb*b*`dEwZCpf>9aAqe`dx!__o$2oA zXcvLKKEGf4uwn`vesZ$i^n|FO9zsrl0Em{vMK&}E+WU8_>AaS0Y7{Eg9Tj!`@BTCEOv zyv5CdHSh=dMK9^E>~02qwFEdS^ahEDq*@HTFOxDfW^+3J^-b;fXW>qwEZ1}Aa<-kTwa>YfPKj+6mP)bF#Zab_3_I@m&6BzYz2Eb^aK-u z!auw%t#65J5`I2Oz?4hbvWTZ^i>_;+W5#kDjb2El?f#_MTsS(Z)(Ae5Ty zx!miyJ4{Liu>ARf)HGDTDiZ?|;G_2(kc~!_ip!A`__zy z$+(KknUU}j6uSy@9-RJIbKk?iUMIYS(6llAv|!Rx?I_|)9_eyDUlX})r2L3Sc4CtP z99H+u685A9fBrg^A@HvRes~4F{3;*2r^)GxsP5WDTJXo0i#|%+3>v1^*)*|kr0)_t z<+y8&jfC$BVWoUXS`JoOMq1dnRA^*?W5qvBU5;gFi(wpS9?TOy<@H0ppR8XOp3 z$lgk8L&*8?=PCS1Fetz-H0I*A{Utb^^aftbcB&9vIe5$%oXW5G%xxHKnXR1x=wk>B2f zr1{B;s9SlJec@diZFzqG#CZclW(D_n8K_<j;;0dZYRIF4F(NAt4<_4wV>m z{b3Vz;5Pcy9OftZmbllQiaZ{{LmRyxZ#Xs;4dK_i@Wjrtj%6?@mNS%6MN3Dpk?dup z;&>I)`USNk2j37#<=okUGCoj@KW0K-pST%p%!Za+F!A_a7Ql;P!lU6)q1LJ8o4Xv> z=F{G~RAa@yg)Te|mM!F_9Tm+{ct)q*W_oU$85g}nq-+VC@0mQb zL&s$AjgR>U>OWvd@`vw#9vBJ|w+UE!4aN(-?gy4Cst!y{U}IAyNaW~iGbZL0oaNP! zBx8mQtLIY!sHXR|f0dT!_Y`a7BZbwRnep&Yb-6K==r-4uznD&!X+$hHbTv#oAvC_i zgnaz(SoQy4WZ*YNSQYBLQ+dydGyPMCOXxx8xWl^YUE))T^%cBt360Evpl-N{_haec zJ{Mui`pP%wgc&`w`IiU=fcVtxKfe?(JBNTiuxX_0DPr%`5fTKwqRc9FVY;Ue= zJAa;E;{gbmq;QhE|5c_PN1k0-ShD&#N2w*5&61^M(j#J`*iiWB=MRIbZyhgvaeGCs zM|Tx&bCsE$3(L~JO&l^ryr1tcwppfNbHA~%YmzHK#VWuxGQ}sW!1BL8_ohqnT{6Z7 zE475|r8DR&NcfUww8EP=+lMc&uxtW^I{1%ijAu%*bYm9R%8g&sj{(jm(Hv4Gyw`_X zx!KWiLT*ak-1!aN{1{vH{2Ep755I9@kvv&kS@GDt4q?xq2dOx?nkeURl0TnnyLV^; zJ7WQES429`$Bm({LJdxiozg_*fd8bfM?=Gs*z~AzK9e&Xi$p8msaIHF9X$#dMULIf z<8{J32H4HWu!zyL>eHXCN(}m01z5t|aM6GmUFD?7m zT{$4tFeVfV?eG9_52mJll9?gG*lv=w^h-h~9Ym%=97bdv+%+qE|)T4abi0WOBwfV_eX-m7LIHO0LcjLg@g9DIv(%62qOfu1L z9z?xYt`Hv(;H-ZMV1A=4T;Cfow}eHQUPEBDei=*6cuy#Yh?lj1>$c!L>kAO>|HxOQLx$cQ(1r!tY{z z15*I@(vq>G6-)j7CTI@dPL(QI?%c7+KvMzCrS;2d#+m`~9p7SCB-pT&V35~yZRAm& zf6|87T6n8D9{q@RZ!hCdu@~$a)~#K7~01KIXW6ZMB}^Oxe@qfi;;)2QaHL zsTZPgkI=oPq~0lrR(@(T%PAdc#H-sxB-_x_nTTbTSb;#>IT7}DR+b{pj@<=*&*&ox zYk%XH0#n`_qlPD1W6taGpXcrS?t&6;0zfR}dZc(_ zE68?*d(4jq&X!14z^On?M)jkR2uEldw8A;^8op=m=R+MdXz-46v-ao;VjZD%|{Sg|M|2Kr-#d77Q6Y7&DjLyM47Kf8T;gK zp2A{{N__!Wgx~KmWnk}9M>(W=Jffpjd_72aM#(R4n=gs26%%-oGMJ`|?S&JDQ31T} zT3T8-zk7s~)k+-4Bo1d2ZrF5F^y!~4!l3SUiB~?%Qb>tZ7Di&dZeRM83SG*z<|eR1 zj7+xq#xjgbpq5SLIo}z@@&h|^IQZjJ5W$n2_4HREn02hOnb=O|hy}W^bH5M`S&;dY z*`A6;pL}*Qx#8ht554q%#?X$udUK1&QI3apMkvt8gJpFgS}8T$7}f>#~A-57Huyw!k`ohpPlHLF!rOm`g;9iHG`Im7L3lSQJTp0 z?Dm%t_WDmdtq{>7I=mjo8j+w4>t>qxovu;`!O(S`Md}YHUtay2>$#&d!~JI`I6Oqs z)r#{EP&yzO%Epc6P$!^pxPX;`D-Cnp<66b@75clOld}T3?QHcC@p&TP)))~G?}f5I zz@={Nf4wkGC93W@6cVZ<*V>cZZxw(RJYuRBr6u-TplNT3XBhRAjC??jFzga)|Kosp zbiK1wUwKWN56cp2SHljGTxjVwEZ3}f|7?p@KWoFZu|LldP^Vjfuf{cwLfW3KSSrL{ z?M0HA+To|p@3Q`ugD=zsXe;(w(>JhgRF^)Cx;QOYennH^IC5EOgT^Vw83FuRh{N7U z-5$QxwLjTNze+Ww7P<0b*9@~lMCx#A*i~wrwgR? z2pKA|fKGwpdZyZhvK7fh$U+Qwu=s;Dj2yR$#P9$Y%fA6qE~P(HvPj4ms!dSIIPc&Z z_)!6S8P8>NvC(XLspNU}2q~OrJ2!t1`HDrV7)U#=Wc%J39Jar%WY4y!27&SQ_ZTk5 zFL+L}6V7x1ERHv>uCCgI?gKS)KW1xyAe@ClCsJKfj^H;u)^dGtk;i7R-`eia=N8^n zQ4=`l!JpgJ_-84i77N~Gv-*{W%}zqPx5>rd4bpw6G12vh8k=BBZ-Y*vkyM=-=me%M zLU-nCC`5yTg?pI`E2M%7#K>V_6uQ+I(!N=Mf^0Dt{(Q)IwY@>D`ygHeZ|v&nhkoU^ z@tbTWEV+FozU>6%ezVBmF#tHXHcPdcQwp65vc+>FHLQ(cd*EF*% zymmCrFlsmqa@R&maGm4t;Rig@d4mc%&RNoThv~eHzW0=02gq#?CAb-#O1ZKc+D4d+ zuy!g^4i~gV5Yo&vBl1f&Z=ose<89no(3yr1$rOKf#!|@T`?u`TeZ2b0f}A^xyUhxW zChu(XL!rcAAlI#@ohjr0Xi44a*ZYY2yZ-B6-fiO+>P0yZNu0&MIGO5W+kce(7*xE5YBf)X4)eUd z|ItH+yB@t`*_mqZp1n-~jgK|1-%QiTHkq=rjQqLa+^U~7Z66rB&PU|T3bBIJw+DaJ z*c6qF`Ac1Lw$^+zA=RfGHx}W)ud(=MKWAU-exWtgiSNgyeWvzjp9a5%sXI>`qR*_F zhrm32)N#PG1Vh2>oA53b*83cA?aK{%NX2e^1?ccyKDMqQH;D_VgO;)R3*4tpskxDg4@M~8a#w_iWNp#cR=RNP&f;+J1pVuPYJLNUN zfOWYJF6mU!HLL35w5z?zpMCq}Lhrx8iV6{eFsVdGxfUBux0U}H7QqhCqbTp4MDZPTZJ3yc*tj~jM^DRUstgn@*KiRDcpk@COa_8bv!qZvxFT> z_0;`vA^AX=&tGpX=}ck1lr@Gen!l_S_bs``{NVr5JU=;D$*J%IE@-%@pcQkJe;;ls z!5I7+Wp9iRRueE9+F~^EPFX!DUEIqX5RFd2o6(FDNycG(_SLAJwEuB-_}voXFa_^L zm4W9_zES(__$}Ohrpv29>xO&#!CTNXElOdJ&+T$4U0C3xBU(QZ!8&#C*^5m}M57ze zlV}J)i=|vYeYTlhUZZIrzeRTQNA;?a|E1)hWXk#>5TQu0i*ejb>~!V1tF@IqKR1ic zkePeHxdGg{B12iYiC^fcS$=m8t7-$Mw>PWLl#Wc?!ht?ho^xtMG6BU6U4oFluKbh; zq3ArEGZJ$@`YLW3++bR+bcS#EaEfMYy-;H&tKTq=P2d^+ENPL}&1(r0rIJPZwO)d~jlN#3NjP()UYc0nLg< zVsE{fQ4Dx;2GIu!GDhyL-LAj+YIOZqDB*^<`8RiE zX1#9z*h_m}9v9AW%s{tD#{;cR96C7;x)ec=D~8+^J(!=7Smu|V z&$2>d5}luHPd9^RfMv5!yrX}=kUd~{hqg&(gS{g}X8YN3O1=zB6#SA;VqM6w{wc?1 zCDE|A`1|_MQ>#*tjx(%&AqVh|;yP}KvelCPJgc3mHofeSbdM`U?ne#);@wG2i0N`+ z6(j8v2l?U4o>YTNkI+{lU^lH|) zS(PJ5_x{7G*$wx9=e7Mm`n*#5KuCCuJNouWuj0nFAYY|db20D1RnjkHfh@o=a&a}h zQD3vFFL@1SxMZ!!OSRwjCy!^x(vHdZTQ0F{!8Q4iY61~-eQlKl82PE&nHk=1E?+_8Z-5aZ|u}|G{zL8=DJr~GvTvFaAgvQ@rETx&;}7n2gI#x*BbHR7P)u2vUFC>2mm* zB5E?pyts2LnJ*%qvAp$(GPkNbjw0%*8IPNUB=!*z@?)D`l{|cy5nDR%ZDVo$?}Nk2 z3bN5EXx=ME3AfNz5nBNPk}c~M{`uiF`)}94xt$2+AB)lD)jFFwAFpYdrF_i5wl#Xp zhtQ=*-GV+a^))I-1$9znH3>D^dpfy9EAb-ZZ(xgnSsD=fz18j{Wmo>wQ}(->XeNJN z8ncMqP~|0XcSt5|aqc$t_9=)#x~au8&u*gE%BEgm(Qps`3h@EKJAdKvJC#~OXoy@- z-6wA$p_U!)bSl=L#MX!l7l7Pga&cCY zgM1`huhumW$G<-nln-gzpmB0#+M^O^_wNn>!bM18J(_NONdZu^?tmU=qM{iQy!Dm+j);H^4sweoooR8F*!)J zm3&Eae$)dP z=iJtpiP(g{T+HbeU^&8nh?Y6%708Uw@}V!9B|xvm)nVk}sP44nnRM_6Fq%urH8>Rk z=Unx3DHdWbUc9Ac^cmd#!fISX3q6a?C<E!g**%g0)g6^ zdhzq3)UOZhPp|hk{Zw5>uJ(oAQb-SK==Eaarie)6*u$v@!Ut1zJIHWj-3?P<7+V1D1Kd z`M2#rnFUqQv=o(ao`6@qOs1+^J#Z1u&c9(I)Zq)Y2EqyJ-XVyDkQ%3;1p0Tb<<#PMNz0zX3y#Q}BM{oMA(Dja; zq2XR%^p|%ZWs%#%vrF&Tt7~HWtKE~3X~-#Mk(aAJ=Jm}Bo%`Ql7QeSo)^y)^!03u} z9vi|F*^$~)VG#NQ!Va3Z1t0c;z&bjwFk4ywA3p!4^82|<5e#FAp-P6d?6O7p?Q^=@1iM3Ak0Z2cSFZ!j19{(Y63 z)yki-p-jQnOWnTc6NlzzbcFx!&I5MkwrdN~(RX*=K`KdyYPBUYb4i_`5BW#M@CW{a zx%S2RH4}zpGjGP)?85)_k%g*~O#>-1o&$T0s7uLp_PGelHrRJSazdfHN^iDUt>@Pp zkyJ@#A!Y3W!RuyyBZJ^?yM!Gb{Pt|CDvbLsu?-d66Y6VUsdbes!GZQTtbwN z-#zGyNST7H{p6Q9j1Sl6(UB-NT@XDg_A!MB%KS+>vV)4A_l6H24`H8}^`{tsvYBi1 z6!4lU294aQUUFn#{(o+5;EqWXs}LlH;Zm4OrK-A4f0FaCtDlpk*I|NJKse!o2CZ=+ z;B*>m`nq#)avbXrh5zMXWT4t^rHZlBr?V&hKQ1gLE9a%)e*NTG$ix&aNdC*nUjf`e$%8evjLj>w_l3MR5Mh|`M zg@ydzQ#R{aO?+8?mg}i+R_>5-{}MO{sS1)A>dKzI#MAO3AWm7OmtK6NU2Eh+t0fCT*fN-P%cYGT*_s<2AbN!WJ)RGEa r<%tqtC5tZwN#Y(xQD>U*ukcJN@+ngw4aK+HKmb`OCCN&0WB>mHQ2>AP literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..16320ed --- /dev/null +++ b/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFD8D9 + \ No newline at end of file diff --git a/logo.png b/logo.png index e433182b647def68e27d9edb7fed1445632c8ca4..6901ef51516d33796942ff82522900489677a065 100644 GIT binary patch literal 31989 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

l7>ty&k2Iw^qr5wNbK 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 literal 36945 zcmeFZc|4Tu-#31aJ&C4lUA7uZvX;ueT$i0JkzKYHB>PU7>XHc&iR>y%*@f&zAxVZP zB!f`XWY50M{65oleee5ze$T(ppLefUjnjE7pY{D&j$^uOVx+T=^$%7ALH6nCYMLSl z1N_K9}mhj6%{#sW4W?onQgPeS?AVEPvQf{8^ zewUoQuSj|Mx@62N|A8Qf5k1X6F9c`K65StVxr7L9ZHElSiST`S`~9%Q$@JS2xL40_ z-y<@K&S`!AyMkUbStI85zP~?;5cQe{7-aGlW-}$a`u-MCVix7R-zswQv*2IpPxt8Q zcN3)I_i-JwdXb;@L6?O^@J3Sp2b*4sV;b)z+rl%;B|$3q@qi`N#liREsV-xyCDgF- z1^tY(9yA^u>(1oU!zW^3jG}#Tnb7`KXXK=Pn4lPG9~adB_tpPO+SRr$LINm8D}375M<@^j~}isLuD7GXIDcl3zF>x(1ik1<^1tDJPzlP zW#kfi{rYtuvKbxHtq0bqaXBz>Z6|Y?FSL1#&s4uxzDs)f6K+G7uvvRdRMczEMHR{A z2ji_C71r4io_uj>XG-*441%!jq5ZN?FK#2}gg712=L^)jCaT{1_wg?p@!kf?laWOw zEQq?nac~fXi+4%Q+=2mdY!!n?EZbWg_4x}7g3#*%AyNA_{`2@3JTg{$w^J`zqY>T_20P$=U{I5<#xO@Y}Ie$?6C+>weegiM4kyaRlbF$K6cbX z5W(AY2=?cpC82AyX~*G}`Kd_<0ho0G{9fHWZsQ=lc$N&K9=o*Xh{7D~HCUWiUwcR4 zPk6-}3Zl6agO1#41u<%X4%BB3ExGIgRvleopzBd#ii9kzSDg)OSe%^fMJh0ex;T)_ z8?3!^$Pw0X-3R;9cj43|FTwIR3qhK>yh|=DReImz*<3WJ!4F#>qTZO|vQ#USch@J8bu zPR*MRwxyw{%w>30_%;Sc3haE9t&K#0y?*1VdHAx1B=QBNh8`jH;-J=0xJdfS>e@%cGwF6 zsY%GftZzUDCs>{pllBfu@Bz%ak_S&1c#6-UJ>??E4;Y9P(xx4N%~o!rBe6%Fw2<5c zAW_sUG_)aPY&m`;s07{IUF%@0rWB+=k4%U``W0!0~IapPB5; zWu1(I&w(?gwGlT43Jf=wD6c+${v6v#oPQ{mKcv&H(ESLVk_7DPfLuQP;*7j=K^mjV zh5o|L!{aqv=Q9;9`YV-(o7+NCLZV4o@I;&aALy*3Z&|u~3R#f9>5yml(UEt~>$^!| zJmr0-->&kVymd-dKprj&DOOa!H&XE8a3`IWQf45S5 z$N1Ci>}*G~{X!8g_@ZWJ{e^Mnlr%0>?g>`#C2%Sn@c?>ANI7`1jg%8fY3|;<$H6b} zJ@V={vjaEUQmZ`{gOMbyM;`?feRhiu;Z+3xGF=wS=O{>y2-@9RZPbsxiyN+SAF?VO zs8`PSH`hG(kU$>}!+C9Bi{s#Pyx%f~&WVMW49$2%u2tpiipIvq68qBxyH{5H{k}%= zv>eX&*V42TM7tyt7=F(L;&N+17ww*RadR;Gi=5}^#;1NKqjt*fcCX@%jm3h@WiBTz z>{qZBURD?#K-1jXw@kJEnbnA(wmbW%#r}^XhMU9It4#G%J2f6CJjh>G&jBIX7@&~q zTOiesk8vAM?aOO-GyMpg1D}d5g~SA0#gwmUO>7HK>gCJ+`Fpe$3SpBFrm$7oVw}SY z2R8eLhlefoqpgkn{QQjPS3}3$wXjFPCR`aA5gG5_RFE>gltT*_W%JwEZq?Veef$8fvp1ja}@YtI&Vf{Y0#qJ9$IIkWGI>K%G} z-;{}t{!bJlp#(&TUBZX2E!JR2J8y7SW{MmucikCH;^+`7?)jf5^BT}gcX4%N7n}2C z6%|K5gHHDP5kQ6O+U+s@X}QMd_M*D=VWmSfcE0!#zW5RrGSbtxOvy55>X!*hz4QKx z<$7YxM@cu%la>2KEf}y@9wW#W4Jof3!B7s9n!4G(<10 z^oQgcgS#7OqmY#-5bXsyjB29kNXxZPMSMdg)_xWKhg&`qvXm_S6|+)L!!*t7F}M#j znqXEqSglby%o-;75rnKNojaHZOKsOX`kmw>l!E4!UHtu5KB1S|&`Tcws&EUUU#1Lj z@w{BCeSvRDNHD<)9qgy6T;nhJx<}{Dn>T{T1#pxv zm6tl-4H&EKHpZ8+G@Zg|>$}`i1zgPB&xkD6(TuKTKN`=2UdVa$XxL1CZ?~(b=lrN= z?e++6<0fvyBJEPiLx)obGvP>(#tE1)1)qk3nNJvPO z*jQNwhiKYyp`~MR7vvAD#B!mYftB5PL{rjOa({Gs!Dd!vWu=lq^kYFt%!Xvm^v82d zw}Q}>kN?qt38X%3M?gbQGna3RTqxI*j7at0G!`Y%mEj#RTtaq@fpcmp?DV@YBdL@sb|KX!G13h!E3{*s6&jmz z9)g|hWbghjIesmb1LP(e8sS0Dz5 zkHdKsTb8##dU7W0!mI5foP09`DllD{RuIeK-(rFEmG97@kcEE$=jNZXa&qg_V29yf zw|W=Bn&`pX7-^;veg>m@0F75TdD6$0EYrsg$TSWxIOa+hM?)qi2qUaAU=+Tsw^a`b z2+Yln)XYS&I^Vg^g*pytWp_I`%IsR^^2^NS?Sg`WmJ5n(Y<%THY$wI(D&BJ<6@Syn znUBZug*A_PLGHa9PL?r=O-oB7X|_L9AjxUBr_*>mcmLHXkjVksRzJ1dMKP0G9UUDB zo}+b3-eh%?;%G|-Um6@0;CLnf!8(Z}jL6DewBbLV|0A$*L2aRFnLU}E{>D=!_-WRt za5){f@fa6u4|t?w!I0a_iFmWp$l=CJa`+Oyh>D7;Su3)6-w0e7+Z`=%D|@RzRo7H5 z{l~`oL|GB}Jv1K$e=APzUn_7^J$3f%nmSp%wd-@eA1MYlNP<}`;&g00;&k4uuzV&g zU*b!k-Z$OaP43@*)7j~wPeN_E{}&1bn`zov0rnR^J`NVQlhJA*{?f2RW7!jsScaZ>D59)j(pMd?qmIAg8$m-glBkDot(zHPuv_imU5 zPO=2~DXyiy3txhC+I7F`_DNeXOzb%hnKTWzl`xZlgp|8?@2W&qA@o<_j|XA%j99)L zDHBh_KVfmY#pA3<(N)+X(3r6K6w1~E57O!mRSs6+Hpu2_;dOHBHZw=W#?EptzSf^N*N7QlU~b~oZRuECF=kQ=oye+lE20w9YGQ`S zoTk~p8bD&Q=@xNyW@zDr0MkU`f1?3xVg|elS)(0)97kNw&}jb$iB?0K=XxX7s;HNJ zd@5}f54Ijm%g*+cYFd2Flb2kE!-1mW{s~Mnr#X@8r2pW7kB`sxn|pkC8%4I(u3>y6 z)jFC(Xe`;U1yjNzV^_k`ca0UXX#RrD2`%FFqftK!iH$*O;`#m|$}3wc z*8fNl0gX z3FYU+N>702Oq=MF!@w@p>=jw~yLHKkx3VvR^tT+9EgF)P?YD2=MnkY`IeH+bDY;&gxC^AyUD4EOmbaWWh%oN$w-7a0a?#Gs($Cg*6NI!5PB#sKEB0| zR>r?qaNt6Z^P$CAb?9Be_FC`OtB{%`NjojzSke#K=}lq*ism;qHhR!L%UMBVA%TSh zA%?UN$HNoP)CV0n?4?E}jOTj=ubj-xoy%kyq~=S7QybC8U&|44?Ou=c?=hLn8JJ0O z)Ke7OY1rb@3}Bq8{uj$qn}DhGGw$pu>5#*d?&zg$D17d;(QNRK@g~gTcU^gtS1JmmgtLZKbAz^CyBh_D8NOt7Bw6D1<(#s%n3h3!%RP@v>I4T~aA< zHu%dSm&~OYT-_;5i&Ex;n@6T!GqGiShD-wrDO$*xlM-OU1_Eu~mo!J~Ao&bHFKs3F zX9zoA`g|GLojQVTm67K~%Rw*a#utxTL+JT9O!cTCqVB%Fz7g=ZyS=@=D!m{iLV4vb z-Fgav(Yxpzf_SX1qN!jRd}lpJgB>9DBU>{+Vp?svxw*^iX-SZBHD<9N_aoVm$$Jv= z@-MT7V&Tu+(#H?+@ikWY^CCYhLRWt>TbA3016{#G7lTw}^H+Ao@*{cBeEKf*^7aNAA*;F}6c*^6uluk7G~8=}0P&61DW#Bk>&!h|F6kc4mZbEWYA^LTqzg z8|rY!3gsq@_eASW>hk{t!gt5$H?Bf))%U(IS@n@$!~!r!02NLImsnSQcjVvYym_%P z@LqsoR=1fxMBEFY3kMfQw$*W9*SE=c+ZX0P-)h>0%dMSD0-<2w=oUX*m&s1;#WfjlKATw!~_SW zi08H+K@QMiz03hmsmgCdT7Bi$NBtJ={{K-$vt9Fpqq=zsf^>g1fiR)j6uA2H(+q_4 z^0n_mSR1gGa3^QyNf)oixtIII@_9&^wL0ze`F^OjUIwHhnbzO?9|;l)`=_tJ*2H&Q zT?m9~9Wb1At@ej#AM4MTTPvUe68_MS;;gv?O~mkn2M^Xlk&1Z8Kr&Dh{KM(yP;XC9 zxIyig-CFcg0nW>-(RK-jLge0=;yLR?%4phD9~MkFGy00>F-22}Wk7N=u2AkmEg zG2SO=#B?j*y{=vRX+YyyCS*FM6`GI{5*T|v$m7kRbz$_8i1xWuKD0dtsDzgmU_!3R zoIF{%U&oRGqImW}wB`5AabC203=_Q#l%4zuo|-o>m@)@DyPY54_8gE>AT@so3E@>R zWst{(lgchO+CTDZIe|H=)$aP$wG|6xkMT4ulY=yo0u|kYIsjR#nzfzXY5od<`j`0q-O88hhyFh;M5 zLNqm3Fq7r~1O1fUcoCaxP#yZAeR`nMi)?_5IL|GeW)}Ndk!Lo9O(9c#e2!`8IC#N1 zvNEDht zR%FWw^Cbv*q+k6~T03^FT?mmc01ORZ>Jg_aPr&&>4BCRUy6rI!IwuC_@n88B3-r2L z?}i0yIXXFgo!h&2uXF-VTzHa}Wo59*o3kRWmH$_Ig|seOL4)cxtynmT@f`g>a;?`N zun#^avm==mx52LT$sM(0p)(-e-ynk+xcv|4dsE<+4FOZ9y&2p`^bG@2-6@Io*@Z5T z+6~GkX`Igq*szKKOB{PqQQ^J%f$Qc!ITt`pJlLY-eLqSYgnP?W0t#8I&?#lPA(FpR z)SreGy~>E#9M1nJo`pgtmgI}om7q6!{f(pxtNb4H8YyIDnc8!q6a6v|ap1pytCKt9 zBZ7G{WDq20sLGqz(%-X`Al9k2=DgIsx%hQ=fmX2BM~WMLlAa%}$CO(6cpiLe9Gjf; z2in-pR5^dhpzw^LsuBjX?kr-O8M0E&uO~Kt5BF9<<&jy7(rQ0Ztiv+QaAE#KCh2Og zvfp@^MY*c!&+$Eo(L>s4%|?D&+LDof_Jj15(YNFs{!OS^lrh;pBI!o&(9JkpvhX(? zj$c9T4UhiPs+uwRYveJt(+5&9iYE_L`sOu;1V*T8&EDm2e0sOhR60`X%;w8w&-!m= zmYyRkRt{-b0tZ(7M*@~Q%<5BHB<0BU=n#$R(`fXA%3mu1=ntAZ1Cd3ULYw2tn0~p4 z=E$uOg)P}+-)Wp~Gp7!wVT!Ly!3k=Bk^`7j-+n@Bmb{)^P`p?Oy=KA~4)4ljvh zD$>rCNJF&Z^d@sc(_yU}VMa^6!jt{F!o~@>a=ep+a~5Z%DrQh8Ci0L1rjS#iux{#! z!94Ml5*3f>AJ>^S{(fT`e^FMo#p^jey7J2U&43RQ5iWV(U*K+h5a7A^t2A-yy{^xS z4n|-~JoAN-W=SmP45qMKa4SU&gkXD>gijWxl-*qkYQ`CtD$lG?m!^s>)#^UpL?$!= zVR>0>udZEuWY#326|qE*e;2*`pSu9)akQAlz8@ZIvci*$=uJlSlCapl_LR??O2VC@ zelZ!#x?2N5B^S37@-^6ROG1D9o_(mBX6X664Z@H13p)diyMHdPa4!Ag-~1+qVITLS zzLIokq&`r{&k*jfAyViAy^qhosP@B7U-YqH|l)IR2s{U;Ot- z4aKBJV1lX>ztU-VS}5$xmdlM6|GKmFo>!@U4T%ofrcDx0HrI4Nh-HyQvbe?UGckC1 zjMwK=jb4`en;d>}ltt^>-Cko`VN@;yD5Lw@^85EAxDVp9-Mqwwn71Cy#bKwi4<<$) zyVq{)kw)B>OPmVtY2F*TIJj3z{(_>F-q74|<%^*23gf95yjakrLjiwJfB7OuTxI6e zoZ-N3mt@s)B-)U&>Jq*+5P9tcg3T|0W6Cb&ons5}vC<*7E0gv4%bbInc|6)NJZl8S z?Tfag@8dyvLDO>XVWB(HJv~`py0U6l;0>5np*bbK_8?jsltu>)Mn?rAsZ*RVT`6N5ruc`Tgc7*fHXbaiXC}X^m zGHRE(7yoxl^u-l+Ta%_3|96yb`#OGGG}`8B8dnwfIjUcMQw` zhT5hYpq1^Joq^vP8y!6)hF8L5+ba%W`MMPF4R^;1Yu^*7T{U6f9ZVEW@E&80>n~_> z=+|5rP#{@GXK)xxbfn`}a)jjlrwOHg%W7+}NUS!eKfQI6-dn#cD`R``m>m89n%dx>^7X#`u)!wYE9=X8w4v&+_#8WY zge6&1bTV~qc6|7Bv%6WI<+o75pS6Gg3VE(K0EVnK=0Ekb)~IaTj;x7Pr|yA7|DCk7 zM9GM9<2q0J=;(p5opsxHz&l@7uSZrE^`V2Z_e5s@&G>I4;oI3Su6Qn#2d0maOxug~ zNr(QD{uwYiSSq`$7DS8}5I2ZMbg7UK;e3uE2Tjmiy&<@jr9 zkpd*S{rPQ=gHC&GGQljdun;##^UJFM&9jIR(&3y`V`+3;wa(Z5=^9rL(?JOX#6a8x9O~*tdD5 zXM3LQoec|ks4US|^|c zTC9WOo%i#p+I6BrJ|E`Sq5S1VU2;^j=Z&ih;~O4XpSK%?>o?EEY*==$swfC<#^E*= zQ_?nrE;d(89Lz?7?Et|92Lfbejcvnv!z0lOyV3pD!PgZgXK@?Nl2zLgb80<3lAqhw zBYa2%E?bxHkyDQ`$1S8kt$$6<(_K2~zEHmaX4<1t104dU2N3kUe2Jr@ckE?UWC z_gl*gZt4(b&*Tg%%T~P{cL<^37vbFiRk3j6Yeb|+%3q;Q)87})E)ch8`}GiBWuT|! z)%WHw>6vfe7ciYw`YvA?^6Dh=6OA1jT_}vZTS>OxzqbhIC)%2}*RIdFzmO;}l@5QA zqqY}eV+P=Is0|3DjOW=mC}6Tp759pM8!fn-QA;3DGt74X%5Yh0QS@C-MK8svPCIX^ z)VNJf*B?#7XQ*%Y1OjjLv}j#5c^ToiQ0gx;|bq!4cXBtZOF;St=8 zR+4U+9!VbHc*vrOHiVWRP0mk1rYSkMh19Q#O3M~uD&uHrS_q1@e zWWeFem>6C?vE8wNs%@$k@FpQ0t%i-UYb3=UH2k?cq`Q>YZ+%?&+eR-eO3-Qln%rNW zO3*l2xcX$hGN^|Tv26^^mtwHKl;}Nh(AN~^Ip1aIH*JjRNQa35RO)HOL9;QJPR`J{5IjU0P2TCZ=4C04rzHH$Urw0*ejDB>9i+R^+98-r z7i8y8?$vC^i)GRC>Pk0GJt0vqkoO}JD$wP;{{>_jhI!GZvdGYHtma>eI6i`A?w#T9 zX=ycZgDZMQWwAZ|ZOC@xcT%T5Gs=-Hzn_lnIRIEjvbO4ew6SCsBkv9HIAP-Od=x&{%+Y8An>D{lem%tz-W|z z8}a_h&xyLz%9Fjmld2Qbtq*feV!8t_`ge8fcS4sOIIx*7Ad}&^!#Lj$X)ESgicF(J zT-D&hPB#E#K6Fl!fcnR4O-fQND`5uFFbQ%&8)?u9gF2%xh1`!u)O^*M|EN=PLj7evO*!^>s^5CY7^bu183ySoJs1fXaY9Tu# z%r|DE3>XW|$EEI!W;rM{`m-ZOa2TC?h1+lW7tRXgZ&Jf0uFbK@d4P5%i&USB*(vHj zgqZ&Aj#lrc$zU2T*jRkieM7xD>Dz7)5#r=z4mQJ2lU=Mt#2jTo7hMQ_jr$lQwVj%6 zY4I$2>=azNa($5OV5dme+GcvNOb?NSt4ywm{9R6byu8iO8gxAf(+zfhWvdhmPrmL~ zKm=1TEptC=_F%c;rcZTyBH^7uTL2%gM9<{gw@33e5bqoOA}E_DJk62k73o`_uKN0V z(7D1fxw`F2znZiFYT|<_q0A7Gge1o`HW^>)4~PFL*_MhZq*DikL8l}1qUNPPJGQf8 zjWoaW?lW!4>ok4JpFZ_#6c`rlbtUy}f)M}twQloDChfPz13vfYTy?Jj*aQ$&H z*mT}QA`6ARL=(Jve07UI6Snh#Ssc7;tprOO0sLkw%T79wyAQNBH!=T*Oa(N{tKnK- zuD~EPoM44^S$!8|Vi?}jdoHKqZ(P+Z0j*B#DcR`AQtCYp&LdiYc^BnU`bGN;WNNFG3gUFXnPWCI?(y9q0dioiW;ZUSsCCRS% z=b)HCZk~PlkYpArKAH||p(|#75y?y5DYKA}Bfkg!;>9|w^My?=d~$g>(pyxm^9lc~ zI@+RU-l92BjPwws!EZ*$HaD#t@v@lCbXP0xKVVLM(l2N@@NukY>tdlN|M@Yimob;vzI1{QZR>#8JQe@okd$wh+V z=fuR26Db&?0~lT93Z}(EkzT9x1PHajO%ROWw@~3`neHb>^$TM~mgT7nVql9_>7MJw z`LZTPg!-RVF;yo#9)mK|3$~c|rXkO)WcwRy!DcR5Z%&JfBPT4jtDpQkh$#-GbA)>ws!R_oOprd-oUMMy4tKC{|gNNu_-Z5$sbryJKFTQN6>LP&1xaSN`vyyq~e|~g;IB~tFss{vz!wx%%?dcNK(ez*K3I?o^|sDC-O<{Svp)7?K@`9 zgPG*wYIK<1jdi|*g>PC+@Cc@snH*sWU3EmZ%C&B5cRQz4h{w|suvaEP*k^> zdR~!^{%co0ee%bd)oW@``yrUxv}qtS5k5zsgl$lIwc8*6M%l2QP6HRm!xzFIygu~s z?C(tzEWc$I3ziE{X7R}h#$FeI6{n?rR`XndjOK_mUOe!6A@W*N>uyTGgSb#&Xc_RaG27|$L_T&r8 z$Xvtgo!>t6@He|P4t89KX3YG!wx(1T{b3!76`74KuBi8Tjq&q-DbV%h$H25N!5m-r z>wax~LZpJ}s67O%<}gd;%{b#^_E)XXLg@~Zc53<$O$3XdtAv&9uYWH&J_99UxehaI>`H?kL76*vnW27eYN^%ylt0n{_w_>D+?7e^Vm zKQ&Q}3pOS5AH5eB_wir-zDaY*uHXM~K{Y4jdz!IW*3DlQ*{gZ@c-%HExF-t>;sz{^ zWA5T`ZP6T-;p=LcU*y6ZPe$w@IL{w&0-<_9)df(^8Z-H0xRhv{8^=E|q&(-go)Z7c z(aO%QBwTB0?5WEI+D%9gvu&LDob(I+hkh;3{h4x&#C|b@*1YqQui+KWZ+}jPNZohV zTk+T@joj+<02ldrT~!K3}%=F3@@wRA&zw0uqho;u}vpd#(%Z%u0 zqk=b+MtYCc!oj(U1|Tgu(~uIpB1>C!)1Y7kKnR=?V`%h9Ap^rbqSpPeB+{{TZ+undX4mQT*FP z>JyNURo?jK-O9?({bIa!&GzL#W%cy+Q0g;4&eJ04mkOlH{zJT%vud?9YyDYsR|Vrd zUHrg-UXFO_uY@)i_2yMS00)2G>`}Vgks=z{v*o9jA^Z}u`)a#*>h|0N_o9gAZ^M~- zKU>7Kl)xqbS#-qVy27200-MkIzdqJ%?dn?kBwVZ=@!X${DMwb1=wdnoB=DKN?o)(RLbIK` zy*3x7Pa{*9Lv?W;2Vp}2J6K=r*ZbNlh5gk;<8+e2U|zDtL&AAeLj9Vom}DN@d4?N_ zcDo&Gi(lIW8QvZYCBZEcGb1%lbiF@!u8L{9?Re-b#%O(#X##Cit2jcD-Qk&e-e#$bgdW> zL5=tw4K>*_0g=E+Y?Ut2<@^Z59NV7XtGfAyhK?*qcg|(a42GZlw(}G!D)1@hGHd*N zuYPClMQunA(C4@5?-r}Z_S=uC_vyp((hcI^__qS`HTtBy_^8y+jmz?lKes4T3k&sr zRqBTizLe?C3Uf)i`&fI=N1Hhg&WhZ_lZITc7;8^(adMqZLvhwfJ-nusccP|l%BJY) zB$L#{omK?Oz!)AH~)U0<=28&JB2a8O2{rNbkA(M2qnCp`S5epZ+ty- zflRrTNxc=oj2*5E?`)r4E)~A7EG#U{s8>~@B;g|&ljn@6V?q|(2loyB+PpEyG5*Tl z^?{ns=t~y$q-p!Gt|uCAO2qFgD^sQK_L_=t(jy1RxwqMi4Bo92#{?fl*4{8iz2>g} zA))s;U@xL%v^A=3OtLIhx_=I4;2mGxIzPkW=p}<3P8|92W#Pe!&J6pd-9eOY!Og$E ziYA4n1~4PSMtH9t&#BeiVIFHCgd!gz$tuE5k0g~`6>#iQSeKt+5*aF>Uk^)dinvBZ zIlj^QGcVPy$@}ZY!6UlWB@VYgme6CHI}ohM7gqsCi5a1mVdm7@T4M$$?}9v~Qd{J` z$okmBjxxSd@%zC#R?Jqv#=I&#ku`4ELSiQJ29I1u&)FFkk)d}j@#A6jvK=9a`Z0O3 zMq|y(r(??frf~;6?9iAD=)s?Prc3h(jTFA9jDE^ftV*+0T$kj}3qM#4i4r!@l7PPn67R z(@->1EOE#x=&(ShUmDycphxuHAlUX3oUFDYyIl=!N$c4t#LPL@WW#L#1}W4nBVaF9 zEWkj%#Unp}!Sv|NkYG@Xettm!Lq#pnx6dZd2;5m^jT}9A~jZ~_w7tygN4FA3XMfRf^Z|1E55uZNv{li9E^9A(Z_kql^n$|&PPmXVu z2GCbX(`W=uu6raM`%Sf@P03G%8{reTWZNSg&9Ll>PmGXqu2McYnKrfcwt zmaE)s2XFi1@|H!(@fganoL*9i(tUgSC_*tP6lAXaBqeBmC01V`O^t_nppa&Gl9lr^ zDP(t}JbHSh|L{O$T$Z2TiHG|50OtNVA9qiMaXp9Hd1TRhtZ|5A&7acRKuMt)X zojX2rhj-&%08&v7+y#$qzvn>4!c>z_&M|SQ_`Cmj^5E#F5?e&qe(Md$vbn2){&Q>1 z9gztCzgWS=m$)UYD(p>NiB54GSKi}dS);!Au^K1)M+fY^?=jEA+<-esJ^3L1CA$oF zPnOa;IGv*dSjiF%84lugukLCblKs)6qQb|yLDFp)YG8c(Y~1KQA8{(+=xykFTB6Lo*P8BwtzToF7Kw5+=gzz2SvKiC;N!uRetkqdOKSz?@QGFj+ji2 z<&kRYhS@$VA9SRXPLDUV@zzp>xqv@b;7{n>o2rmUZpExw#`u;xQAw8m7npEy@~ z3f#KBr)|-zl&>UYA-a?g`@9vwUSPR}g>SMUOiZj{Nnu(N9Wwa<+&u)>qJzZ)pS#27l33!sm6Unpupjh=K17J zcSD+nO}|>=x6HNriGu=fvabtZXKh|QTVc|3sF_Fl--fKeG4GhC*37G)H55c1t)d*^ z3uI$9HStIR9ZY>}Cl#hQ112o+=1*+JizlC0*E5J~&LO)W8yIzY*5l1P2;zX`7rRrX z9VEz(U>^AFra^`S2`I!ZY16iItktIpm)v3H|B^JSptuU5yX2PG2R`i6kyJI8i@)xY&)2sX7tqyggpc6eLQ)j0XWp zf6cI5()kCM9dn24Eu<8!`z>a;4_l8)KiR#S6*%@f>Px8sHZd{LIw`(-UWPk#A@Y&{ z>KqpnlBez9Fy5TxSv4>7avbh`9V`(>^lZ$J@4RNFT-IB+sYSXbB2`W*1-+Yi9DOSD z2=~ayNQyza2hnLZ=)uq<^%G#o9uaN=j*=|5-j5eWZ}85}Q=aeLVbxPAvBk>!^}p35 zs4P!L?Ok}`iK5(cXVtT_#asbvIx)6wTSBvy9A_e;+*dR|KXY{bFFoa6w%J>$+M+w{ zcX@&Wc0V*Q1|MeUNoiUKPHE)oOQlXFRQtyTAd4pSDp?K>*UOVRt!t5!%h87mr=)+Q zYO55#yMW_8q15|lVb()>4rOmE)9!}0;V0TpKR5}Xls~FhZdds#_BPPt5|!wMGOLS< zi=74NlrQ9)l2blj0*|SoQnslhigb_kX)CO)t!;~3q2vt$4CMd_iql7xB?NCSmnva- zhY!^KuojOMz}K*&0*|uXa@CKi{Lfv0LTkD9)`qC2M0&9{FoSnHr8Z+>Oi25nqwzX( z^G;)_5+ZIta*QXd;f0Bn2a!&hwd`nJfhH?>`8|1NtRJ%9@3sojYpH)5M$&)zcFT;J zH7ds{8cDe6zNbtq@h>1wfZaV&L{jL`p)?oZEWNX|<;ugn1nVF~_Sv^grSOWrC5@T= z6CY0hac?t8(2Izsw==^8fczCbJUnJZuIz@CzO=5odWG^y1y{@U?S;dOtrWlM9Uf5L zq5b-b?&gn|GX{^eUb_3_hmgoOa2Jo>Z@y`2maJsp=%W}XtE3+O#eBv0=H8v+u>FzZ z@4mSf?{sIb1k7+d{-O1Y!bPug(cuM%hIwdzQl5jMy&2u}*9f+HD=k2sjo(WEnT-$P zVl5qv_b3b_^9@S2o?bMfjNWu!cPZ7ts(9ZDz@8zE8Uvh=0ZytLx)cvHW%s+DUaN{n z0y{f)cc;F_d-S?6sJ{zdSQ#-_AyTgh(9M>?w-tmAlU--n-N(YpjwaHSn14K`j$S?e z%qE-AeU>;x_mFfU#M1`VYcT#Ud`(4AT+EB;hyOU*9`am))&okQAF2cm9w5DZFXv10c(-I++E zhNTwb)${*M>j|R@&oH@>G(NjSPHJ%>-nzbIl*-24Fy=-?oy&*sWX$O$v4bbPS*E_F zV?r*YBHthV=Bwa2r%{wy>-}|YV!qNWi{=)Wqau|YD2dv@McUv#A24ePFt(o_#D-O# zq?fiqR?B04bsVNH-(Fl%vQc`OB}En=l+>;5a-obn!B)%*D)iXu@Gmbte27Kv+Jj=y%@O-C}so)D?Jft?<7EXPPA;_ zeCOjAzbC!E#ke;@itITP&nsX5`T9$1;Npr_{cLJU%Qt1wi=M<=ntQWW-hsX7l)$E^ zLkwGwyy_pclj;P?(sunTENuI4zj)imyxZ^V!n<6((hN zH?s-lHqnS|zD4n>5-9~Nx^-c1)a!*3VQd}TyFd`Yd~v)`T>z|Gz2LFgvbHM zlLg018@N{Um)>~IJnk;ZmKhne;A)KE6qEn6Kc~c2My2WWA6pZ{d-q1!LQxIKI8e&x zJgM|x=x_A`$eA8w`i=fN+7%Y*`}D&jFCxmSv7&Iw@+L>Nl-q-Vy#$|rUH5{bZ_LF2khBIdBU`A(>i zA%9g-aV#~5u7SFU{|v0}4_PRuDTcN?Yt-u;5u!5@&HU&7rq%`&F7{Om;aWy)e9!?r zw`gXnMfYamKJM7jPpBQPoXw=Bb-8s2hJZg-fK@3zGpQmAyRtgk+JJb-- z_{BFJK=NMoInx*YU$+t}d9Zo+_~fL#30aP?(Sx8{bZLOc?^$n6*nqh{de}=c26`r^ z4Fv=;f~vpsi{3r>8oEu&0!@|J&jAcn?wit(JhjfvME15fq9jhhXRri@l~=?|y(xYURi3XdZS`A_ zEHlT)B60#)_RFn??waUzS_ieao7CH_4WhA-lU^3!SylRGTgtt_$Q0;AgY9GUjq8kr zdiN6BMO@jK{{%%k#PV?;WI>b1W1h&0)WH0kex7d|P!%ALbKT#3<#hk3n#a*E>>8Bt zVe1;|@R3dU^5B98+kXe_6?`8O?oWf&z!1Q_fW7-I2@0xHK_jPBRVl(VEUn-^r%Ef9 zhcHIBh-4vfhG9qq+dsuvh|fBNFBfO7{5iutJDn+Y(R@}hNUNS7l4YMWii!e%^KQZ1?)OW`9BC7o&?;RICS{QhB zM(7ljLuqm+PcBI=s6=b){TjfzjeDhRy;l71$y+S|8SN}!@-u9c1 z8r*lX@)C4n$06e=0q9uX+TLF9A?)@w2p`)@Q2zB64>pnH2u1euAVtdqwK=_+ePQcA zUuAm=wjqHUr54-Fdb_as(ynm4{4LABG0VINvc%h};cc?NB7cHQkoy3aMR~9td#0bu*+1?z1u);|g!W9%@)+La0JDK% zj=(L|mPl|N9 zNr1*@>_f{^Us~7Z^)(Y_KE866!;hiD9LJhM3iT9+VMB1Em4Do*9Yv2UT2e0w?B@Xo zeBFT3O@EbLwoun9Bu(xeloaca!(>$#4X>)q>_2>SLxL(^wuIGVLs}hn%Y)-Blct;1 z>H&ytf)G7fDB=C~|0E}!wXPM(9=aM5G#Zs(mSbIr=$SziNhIqs5q)r!!l4YwlFV}} zi7_#9Cy4I@x7G*iLA3gT(%HGKdpX{nx+AW{B*&UQ=1z7_r6Is+z3I%b`n=2l9e#O| z=k!|S1oSwt%-#f_*kKXUsCe|9JDDIk&D-HwpZc^q^&37l91Ypoa>U55Ju&UX1?;)6 z`5=cV4RIG;Hiu<)gzJ8@e}JAGB&=I*Y^qu5AbJ7kAA4`d56%`EY}E%C+}bfEsCis* z=v;tYBTwbuC-8(Y=3-+Q1Mln|R8^t;ry#pcC6`H`Qr220$%Yf;=WM{U)RK@g6U zo4m+EW;Up=6I6bitJGo`zxCa+3mSv9?Qf&EEysWLLpc;z*2=j!mILukcu3N|DYziGrA7?|8`$a;j1`#VfD^HqCRe$SK=_(2XO#`r2gsokGz`kY_f zEiFJN&Rdds7CIgkd(U(3(`)E#5SF@ic!LK((~v1PD^;Hoko02X+faAoUJI^Z zH(Bd0Y}}0sEa*qhQ&Usr-h`e?n$>*8>a^1S$14cWS4R+UoPb>b=&P z%X)4RjAP9=_hwfW4fho9zbST>*6{M#`2X7b^1qnZH||eF4%(cKkQS9gl(MEhlr}`0 zl$5OyEvA&F%~Fk}Qd+g4lJ-bir*euoY099arj3kDdok_vyg$zO`755s4_?&FXSwcc zd0+4Ay6>ygo)ur;n+IsobCZwo<_}8BFynU*yRYUA z9XNXAdkF))Pikto_Edc26ddE%`UM?|^E73lbno1+_Rr_v<(BL@|BjXTFOQjj6}TR1 zvmIrp7td}sb8G+i1bct;8eJRxL$yw0^LMgKF3p!(0JU2m91`Lh`3!DiZ?bvzM`MW1 zCYK~jSL|Q?B~6qQg04+ySlFhRaYcZr))L2tdnC+oe+3ELyja?w zL`iuLeN0TFAg$R}{@6OFxcA!0-fibuPlf%nZ#+NQ+5W!p1sqo4`kTkr<*|p@be;tn zq9k<_M+D}3FNG1Afol|%%g?gdFpW!}{q-m;tU=?IQ;JM}icN8UP|DDm25ratUft5b z-P^G1Gk#rPFV=BcQBjfKE2x47WU(0zZ1xya7!o?QON3wfX&AvAjMNXgy}-6Ec}-t- zvl6vy+J7+TE*X&HJQv-$H0e8cI`W&XSM6&quIaiW<>hFi2a%ZchZ7x8VrM z+}hMXSh>c`?P{8aQ@{NW&%-2e*Rt!3e-f}Ra9aP6M{?Q`(zdk`^UvZzjL6FzR9rq3 zh1@o5r#plG+$^&nfcDh8AT7zN#Ye|2j3k`8?28o^Km1~~T*LL=l>qU;kjKzL4fe4M zEYYod{zsw6{{g9lBvPacU1;&wE|#{NK+|(Gw?W<%^3C ze5pcz-|OCsJd&Fw?>k!z>)ZzYkg_RsY~Zd91vtFHooi@tENp;ivPgRUH^}UBdOsY_ zJKeP|`O>ZjD(Zr~^F;Xr)DG0VxyLs+H|I=V@#O#SLL@*`+R%EX;JiOe6!I5L=z_@p5%9>S+h zfTeWJ{#g6G{NO`MN zaCZihLHQE|@oQcP-yri(5+OOkdXIPkr%ptEEUqxT7&|baQ}Z84Ob+m;PWzd+E_7&= zglU{Ms?X6l5nRIyq}LKe|5_aSvXk8o-jy)i`0r_*ruUP753#zE=Z4fXOb-85&aiut zTcoSFlRfd1w`S*z@FyzddF-C%QnzbRof*GeD-8ykH4l(HQ17^nQTf>Ej{oAuFYj%H ziq?kcfB%R~K8Hn>_&fgv(Z2vzrW{>=dWg<@>}k-xvzT4Ab6%V_$(|YxPWp^fOkVZQ z-dcDwNjffb6A|8^<`v<&r`>x<$81w99pJ(Ox7UvIm8hmSOS<>a103nc0wPfht6KHF zZzd~NL!X%^G+utVBUa!h%iP^fCQ!jF*D9qyks6H0ZRaFTr(r2ikr!DXZM>h|{t+_u zxZw#HBhlYCb46Bb4>M(MRENT}7VAp`=U6QGp6I_y8N2{e;|ra4KGWhH39;aV`%~B7 z%)3*Ydq%j69&i94RD&Z#2=6%fqwJ*ucbk!*QL(||u=0WrKev8SM3~3n62*}R;II>5 zZK<)<+T;Qra&;YYm7jfGCKtTvIT}3OvVDZ?rKfJ3Y&$w0^&&aU-j+*vm#n|pvE~i5 z=&hiZmex$eykDZgZ3_}9yt6EkJ&nDJgiJD7I}{gNoJv;BTt-`X<~bTY!Olt!=MZSk z9p+{x_xvUvR6D4H*ct2~Jj~&3x`3>U0|j11e&#-%?zfvsYFMouftUN+e>Ol*dJ}ju zShOH4S^-o~0Owt2VUm7WIX>}8>yQ}TZf1&iP~+kHvVRdmmtbjcl3=zwaT*wLsaCN~ zu6Ce5w2fR13Xb&Ad5aW_)9fz%l zAn(}*ob~7+zM*c^f^ZQ^89Y*CGq4kaCVCzp%hv&6c$L&5c4d7wFEH~ZLG0T+G%JuJ zapH$vGao_JMsVloSUE9$(H4tpF#z>P))2YZ+9y^z?K}x=<_GzM+nVLKnBEP7j)V(XJ;M6jwpEw?XFI`hhqR%rSBSzD4L8u1j()~cmvu>`nAE*`HP>1;A3NiY zuSizP?1c6_cV=%F3p`s50o*A#y^yB}V$={TYwy&7vpEWy7d?>s{?6#NfhRy@qb5$3Y(2ZxhwJO!3#pWSeX z&P=x(XAwa-n&HHqsPVn1d_GqV|kWnfO$wgBJ?V1I3t)Qb@ zPvHcPP7el)l$}A??b{Vh@*(?hN=z zD*>*|y}n*7T^qFf_$^P|#2ma{k;$qE51OaR>dQlo-vFG1ttqwYra#_3ENdG+b6cV`qA z*9@yhI@%W3ez;|l&SWEEDw0kMA9AZMpHg7js7P598VFvjL)0BDPU!No4S0*7- z4a8hvmHn4GyW=EF^yEf#o$;F@^GWpr21lup3i&3-H{xkd)6yePFzUl07ZQNl|s};N;4| zkw^dzHbhD}u|yAdOnVih@dQQWBM43_&N@3!=cHu;r`y4cqx%7${xjM*-FBI4(dAP= zaTr%4`P4A`6~D_)i3^5be^X<3fbAfvlNVj>+F~>fxACbQghCw&9pH19Vu?*nklBi! zRL-%=u7h?F1sXqoPHmOff+f8=mutn@N``glXYk^n-Sui*A)pBg!wwagQPM&+?~zs0 z4yw=`RjgyWc$A~#fNG4&bMKL!MiX>I7~IyFxUov_?F7c$NRLvm;>!HTR8edv$pWuZ`HWZ-#AMV!7$PlE2N|<_cB-E z5^c(ht_uHt-i;m8JTU>D);;@toIJA;_JvPcuP527fEx&ONl^WNNvqRD*NBE4GZU-s zb*S`c7(@u2e)6uZjhdU503#Wc3*CFNk~F7CkLiJ8>GgeEV9e#0y}c)Fae+&a*oj&- zt`*oh&Z3&(3*x*#b^G1VD;E!X%QKIT-- zXm5SvNQbmDOO(RBetg0O4_J=1uC;h#U181?z_K#bxI;Kdc0JUaV4^8%+;B>j6IMcD z&|OD*UMAq#`%!xlISCEaso(}6J1Cvs_W5%j>BG`&R|Fq6RIkPx4Ssrlq3tvlLJF={ zx^8E zfRO|k9klzwX%_a+z)=2ZYH8sL8nqnplCRE$Ya*X6&;w2|Kg#1K0<;?2zll^i$gd7E zk-ttE^fmgEyq}sYHcIwqpDX$d&r;=SFz@=^mi5FkG>90|u;jKzDbEHC11C|LPFVpE z+`NVeJVl~mhMLQ4rte6e zcZw6n|LI;MyVFsU&w)!mGP9+{D}*u#9Qnt{oK3FP?@!l%b*h`r(TJ>8<0j|j<>>(H zee#2v{6n5*uFFKAS8rPQ-!~cDy#GDc9-T&5TE%g!5` zbyinbZzgZOwVjWUZ~9#1T-BdA4dQE=_fY4dT&r*-5=5;ns0*8AjfF!fyoTdAwrL$K z@vp>Kt8dlBXjOUM*Ls~hM zeJ+H&D_)EGYclefD;`c8toygd6#GIUz5-W7RKqKPO?SC-=Qv?$!yQ%Ohv(1Jy#&~h znndBjSY%QL;I@9&=q`r)RCw3iyhDa8S6+`(>KltTJ{^E}seZc({D?UJ3-M=Tg+%zk z;L%O0z(cJ7RSHDr;MhAh$%}ecTPC+_Q+&lM;?6us_2xL2 zYu}w{dw~@p#wZQQ`*=>7Tz8fC+V5H{}l(EVe`cRlx!^Hbc|C)(5CpNg}jD!@TJ zlA2H4F++b1g)E*&$ahSWk1vIa5)rrR<2lb8+~m5RUvEPJt?UcJkV`@(JTzLU0V$q( zSKoq7tw-q6Athg#`I|ea+>kuo`R5l@(YN`^wW+D8rV+IXcE9$0r3YA2sT$#e^ArGK zPwASPHa4!cgHKf{ye3of2!yO7{KzLQgazvr`tNv#Xrqc$kscTrn7u(h6Zxgu{?=&M{a%BkEvjL$@}9QE@^Ak(azzD2Wh>-#8y(~&ZB!m$1HXD@ z>-ow$fJyT6->OV}%HU>`Y&S&T!y-5?#3HQ0BG^V&o@Yhqy5?DBD?{2uzYYDEjyZF( zS<>iB;vzCyw$6*Na z8r~ot;Ox}fo|m^&sY8b$)+Rm_!6eXeKzi~dk{Wi~6g!=jHk)f3`HIT>h87i9*uP34 zUSg>Y?0?-_)Y&6+({J4PLudhi;EFTbR!!pAFK2lrDExg6>Gu>6#I~a9^!h$nQ4r5} zY9HuOU#oF%qjjEFFo>%8lA7U*WQ|U~i3RPj{GWDQhIZ`ziF{!fa|0(#{vv~3X_Za? z3^4XI%OEbbhw5a6m)lYXIF4Lp9~s47H;AE%mDn=^!tv!pdzO-ie4frh=>taH8`G<2wk!cBQ zCC?>B>Ups*maZG-=-jyguYaojYfv>HLF8*SFK;YyF=Xb;Sxy+1|JTUm+*8l%=xGih zmJ)=wn1i&I_R<>VuVa&mScx=CWHMxb=vZVjDmZ%WQ^H-!-u&qA&a}zBq{ePGI)}ET z$7I@&08^F;g{B7>`vAG_cIW5>PP+>bgb}yuFNbtbgR4pQ`7LS@tB^PYTUEeQ0p$hDFN6?8Ri2PfwGlsR6szP|S<%5x&pcrmH8{QMyy_UdAr zLHc~;7e2@~p9%2=rh%_!F-nIFdz3a((cpgXf1#Qtz7Q1^bH(Mn!%U|fjb%CC={%QQ zt1r6x#HT&Qo&M8Tc8MI_nAujg_Jy|A2h-Msc5@;DEo=K}nK!*LG}4{$a*5uhQ~b`QR0j~QI@MCT`-af_P(5y)yLv0GZK z$>=KuBd;@?V$1z8dSC%ULEKq1n{B=Mkn=K@=hsW;^4`V<5Y(%9PN_cl)I52Y?d{+I zc9Ryhm+Vz=;R}pM^WZn?P}SPZQ>;i2Mrl2SetDa4wG_f@LET^}J9(GU>K)I9Vi2#L z(ctjyNC;8wVO!-t%ZHN-J0m>OJWUqow3c~p3>lmE=_K^_*C$|*O917vMr}E^W?h+} zpQk>5Ye-2awS-e^bLA2nokB?8Yi8}I8 z!3yp=^vlow&N-Wv2$hdGq+gYaUN8Fyj|xu{qF zHut!04Xl+|wQ4cMq%GIy!HJ3bqyjFy5YbOwLOh=MWfXw62ykP%%uD#C_ZtB1d=i>t z1q+IUgM-`g1Dy?h=uSEdf~JwmyBZc2R*udWc?qPue$UUmduW?P5x4eAd%ZD6+1`Jx z96Z#$nbCkCdH>vGSw^WUxSYHvgTx(Q$n=rk6YH7BX^ltl@z&c&SHJPu&)GY(B4zE9 zH7NqbFXT3X3TVGMR&$v!zbQ)So>(dw$li$+xm=Sg?4S;m7iX3zfPErd-c#Sn(fSqm&^vpVX?8s?iYnJQ zJ3sE+|LoZ?9=*W!I}#dR{`R)ArfM@7>e1;|BiJ(HC82v%v+H?4<&0@=Bi@FDNxD;{ z3ZLEVHP~L5M9I$8F#8sI*J<8xu|%Mn%XG?)Dn{=`HfrI9>wx=Il%O@L@6PW)-)2nO zY!21ztE;fi%<#*|N^K`b;%oJVx;vnj?cf=-Hy!(_`tcQeN^B$YU;vkvk&N3ef|!7gp4VpzUCT z$asvCNJW|Sv-eOVlK+jI=G+AIB+F<(CmfM`E1US-fbP@5()qo|o0UNY<1Rr-E+?e9 z+IpomWsZGonEvrU#W$?loBG6FJB1gV_80mYJp7SyjbD|31+Qu;uUytzHEm&(Zak4XGzfg&>o*2Au-bD03Np zf8>zZtS<8b#JPQ0aQDj9Qv%hf>l1&16z~GkWxn>p6Bnb*$&P6b2!VL=UKqWiW6CU+ zmqdIrv!!!4E?2VIMqVxf5hD&XTGie0EhL~dZur#^06>(BXebhZ{7$fAT3Lhr&AK?v z0>tqxDwT>I1M_6cFPg+|Dsmz297hZ*zR>zqKQavPLSbEBE%4Vhmx_^BoS02^KXR`T zwe?L+cm4}-9hpf1TUE3=K7$q@^SATJJc)13IY-98MDT39(&8zDKe5rG%IDOnQ!&_k zH37dwft#3HYt*i=jXviDhDr-!?fSR(spov+@w+qq;=$dak;!o4j*L=icwf_?-B$|5 z18=us-Va&^RON5X-;>dz1O!;J`}ckr0#Q|0QEYM01^jFq`)Ezs+6MSrus82XLcoR3 z!3jr%`{9=va3LOTU+MNQ5Kr7+AcNllTNywLpFHa%EAnD^tcMBG@n+;$Z?juCrVVJ| zGE)DiY;EtLJ0pqN);28wyP80Wgm_}MAv$<%(wZAwIn(?-S7k~_&`BoWZ!1yb;WxL5%}q>tE)7EL_Iz709<(K4x^3t8XlE*2TQno9U~0$ zv29EhE{>1g9vwN_thLh3ADA7T;e;l(90ppSb9JrCY(2jzYTOIj!j_k8dH3##1+$3q z?QML4&^(nQGOm;#T<`mjn%5QYhR%H@09kfqK2!dW9Oxj>3iMq}ZjQ#&YHGmV!qy5h z=?`ZuTKBA|h;=m6 zA`A(6!4QCFXV7u)LJ|m_x8n7&1AaS!6qco+N zHp6X_2(n)gihSb(_8mpk_a2k!%V<_w z>ESEFU$qJ)wVP=1&_`EfCP=%g$Z;Tt9Ms~yAvERlMKYG`9MDiy}ev0U3N=T2&;=se2K=7f{TM47bt9jMfY=4@Ff=YTQC6MqN*vi|MZ$?UnvrA~g)szqQ;Fg{?jJJ ze?)kIs6}eePndsEE}k)&x{-E_lYINLY+tLNpPwZOMi*;hhJYp9^kzmWN4}xRsYL@8{1WVXQqNF=Mklk!#hYO1j*w?lp&*3ILbI3R3=fquM1%-o-C(4;Lhpf zXt-6qr3bgG(i7XXiff72Vhr3|4N?1} zplbVYQqU4{sjrFCRNTY$N?IW{P%Ou6DLYlS9oRws?#$aNPG0$(7An<->a}G80lkUS z`Jh246Qja1w@6j}dw<6t!wZMB@_lb&R)7Wq#mFN<-U{@Q+D#JS=Zm-4Jn6x=wmUZu z!95C}cAAny|Kaxu?jmHEAbUBFTHbN>At51+U+Q%N6;DPlymJ<0jqnFe$st|FM)nsOKW(`VEs2y^Y#B$71tB61dsR8x$4n=~vj6$>{o3qy9UE>}cOvCN zWLN?uwG#S1c>y5nW7!|A<_MV49=Yh1zRQc(TdKz1q_q6jHS$91aG_z5CCe2j&K9<| z|J^73l3M=dhl7z5;CYA6Y@eyBq(>9ab*ST-qB2J#JRpVQ^I23tvqlVKUK)qS_bu79 zett)fr=^JaUl;U-pUSQZy_3tjV_lS9p0LGnV{~Xh&W*AJz1vj2n8&FP=uu@iR~=f~ zao_#WL#_9IJ~k^3JCyATaeq|aSQwz<@?p`ICYC98670gE4;I{M|Enr!as@+uFJ zSy#*rxQ?-WRr?g^8)f}dJ%qU%4Qg$(vZlT;*AULwJJEIcOp%R!QbNM?apOMy#a5~ z3lVrGCQ43n;iY>lsEr)qWz9MDi3AqCJxmb(p@>R!y!DMJ=4En9n{ZY0my3)l zEghZCo!-M;su-~Fm0v*kGv?ME!aN3^wybuXna{L_cf8XCVkvPm`51AA_%wZNF5&u2neJkQz{>LEHRMRug#8) ziTN9XoyIhdu#J*>EAQUDTgQ0&cIGT&vYA$*;@cQNpL9%p=Y61@m8<|^ba?+EgXVth zMwc$Zv<)4Uj8j&Nwi$EX^zMm{q|v3N+NRq2KSFO=u5o!W=X7C2~a0biyEn^W^3HLaxee6pBmM$}+8O>0ZKM{`e4 z&&#o~vFUJ)!IB%t@?%X5p3Gnrl!Sz;i?2T8vS#`?#tm7Q-H?kln`$%AnR>?-78GRJ z;=*+D!b@@CBkF@CU-C-fOm}2NC0mt+gnW&o?eyxb^kWaT6}w(Ss@$n8Sv!j18K&fA zTSw}odGBZwheh9QVAbxqYv$9kUzIi9hPge~>sj*(l1mp54)Gr4ta{lVyYATy999dJ z-XV>tDJABqJMQm`a+8CJO1DuElLbN|N)MgnbPcSpRKlN!MV{+@!f_ zdiqh%rM{c+#-jbe;Enk7lRLM(fB(Mm$E9-nw`u{KG-vXi)z~TD679cqOFN)lorpPv zp`(vlI9fWg{uX6HAp?DCY-g$+;@pFpUewef6Rv?MyAr^Iqvuj2|BA zerf^#I=fONUqYfA^`Xt+9NqtYe=*UaVPswyC=HyLmcf>@OR_Jx18aw|{RN|-a z!kxA@Ha_PpEn8xR_`a(yBm)0Z(bTMP#!!#5Av`qEbtlqFD%%G9Pve{I%*~!&6OVc8 z5Iiul=qgi7F+6b$!)%ENGV<<#Vt55XPhuq}tn_@hq>m@0 zCsVW*tMM=1#{L;mXqr$66HQ2EiTA?kk2((*2x=nnv} zg1zlhHd7Z+ugEjf+hyUy$u)4r1c<7PD26g?w`k{0T75#pH_O?Jno}{hE|+UD{RuOQ zF?6)hm|HMqW}Je^C@u&mV~2cb2z`TFrFau{yoqm6p|0U1Hl3-JQ?^dOb~+{|#$^aI z9^nxtozkyKWkJ&CQ}CbnIBaoNMpk>Z)EsAhMpVb;_xn{tFHZTrH)Td?)4c?eO{+YJ(xrgw}{o4{6 z4kP`;(6M>dItaklHQ(55RYpSt9n-zaA>yr-e~BL6q^NjQ4V%^S^{PAQ)NnO~QOwMN zmA_pkn1fkq8wD0F+%ypDWlfCBp=hGsG;j$6sH+yanzE%?5~3~WddWr+`&VgDP*8gG z%xRQf&kSNTXMf_DGbSn0yuTXHX*WmDsX-#-Lyy~%7%3QYF(uC=jTePZhS`r?9qUog6Se&$WlXP-oqUI$i@me+ZE!m#Q?ktDF z&KERqXG_Z=Qlt?u!W@hYG zgIq6*zEiY$N&4orl4TFEE%n4Yhsq?9z+Eqz}H{%fkXsi`R$P^toUUoxc8NeElQ%O&IX{m`fV z(P4ZJm&wl=W`DHF$@(FwkiJ#!glV6YgWYGu&0~mG=g*uu^T1;%QICpxQwYFJtkek2 zKokB$nKdtGqXta<(zCV!4*Xrg48oJ&kL!OPD9OmmGLh|hDf*@+jt?*;%8>B7v*0 zWFOw*8sjAUA=eX0n{e-5?cm8up!m1pNAUxfsE_bg*&F`@b@%VM6x+V^Q(aJT-)(Wh zXrA-7RjvSj9hNZ4EwJjxPqMPgEG?5HxpWB!d&oz>T~ai5-@bjCEj2p2^zEkFlV6#F zgjn;rqRQzn(!7a(6UPjHN0ox}+Gyc8_My+C^7~e4;sAk(%A%-sQnRysF1LHF>S8dp zs%y50bLri@m*DMn)=SQ>{tR}#OMG>uLRS>61X0(m_M+a=2s8CJ5_5bLr$Hgj-9Rg) zw56rzA!Ce;ad+;M>e|(c`Nvqp9tg+)0%}H=2*J%}xdec{OpYO=+-gPE{2AjV3h7?Y zZF1K^n5E3kM2;P6ix8yuJ#+b~y za^(sIY8&epHowboqG@5ZC`_j9DAY?)HaXF3>SCYN;~N}!!oH*fY)?oh?+1Su4VLfy zIxFkmnc}v_zMnqIp){>@>U~pIvRT>0ushE+7TP;I`WK%5IUq$q01)Ajse+PT?R&Ws z_dWg`zY>%<7Qh0BJsIxTf3j+Ds{|n&i*7u{TM*tXa9nB&Cn<&kbT4Ji){drV7rpO0 zdg-4(*0r0fFASW+8aN!maiqTa@B0#A4ZHN(kCq8E$J%yky7ceXMMFRgS2J;w%7qi#Fd`o@fv*vpJi!z!X7q1qT zHc|*JY8wcb@*96AU?RZR#Pgk)=kO7^MH|#K?cEtoC0T%T0pp!Bk#D!+M+GdG#;8HQ z``R$joHCFQu27vzdYXtKy-ckF<4UN9f5v+?nC%U`(g&Dm;0b)MlI5aP7s@wYI<&Vo z2sK;NAvkSC$@#i|Sex~OPO1y_YJ)_dlzRv(-qjLye?z`)cGhRL9Xn$1SO;BQ5bpP5 zuIFm}sd(1HnT3Upq*J@rlxVSMQs6t4r6nb`EYueg{>X8v?|IZK6>FZr_Hl88TIs#D zH}KJ26Nea+c4WPgN`l1uP{f%nkht^buV24*1q(`$KqH)1C&sv9|MHp+!9mSB(DQ{z z^{THgqys(EFOR-i7wbX<+B+i$HUUDk6&(==WUG*qO%klKp*SgW%%VBoME~xx5Tt6?jH7A%QIs$0>6NQJL?;$6*w4?JERhMl8QT-U} z?>^R`nu0;rfE)H3S$duK3>EA&@jElbkzd2Y)jqwrpx;R#t|JQR#d~W_jEkGZ^M-!< z49)y1u9|&=s?Sk~LTVFU&(8^H{47v@uIR{9x6h$+?@bg!fyulusWKmmAK1I?pgIzY zHu$&}*`8hmAE}iqR(MkwlaaJD(Ss-UPaEkSWu4!_g9HCAZCpoG8@r(`zOoom>LgA~ zod~8)%+k)p4j$j%Dj^!Htf*Ll!Sx>Y@Eq1gVfyo$xCeH2U#Dhe`EcPcUw4ZyJZ4{Z zqo*?3tgPhYIl;r0KZO7XKU{%5ePEJWG>Vxndgw34iPP<{=cg?kdNJ^y72e<2eI7x`p78apaG&bS(9vQ0 z9?`4VDQnjEw^Yn((UfpnJ<6EC`p!=<03ynfz}h}_YD^x$WbfX@PBBqiGM~lxZ{hT) z4wg%Cl`XE>jGg^pHprCL2ZLoVGF)%doI=d`oGrs>95Z9-Pw)~3|LKUa zhRxK|y!YrW6=!s7Q!$$~Eo#mO4)8E3B@Py!5Z(=B3RiOS#EFN$eMJ9lS`gE2J2(-{ zheQ#e5RcILty`LqTD=ZVeNEZ_5WlybUd1Na0}8D7Y|K&J2wTYi1kle@lAKR)BKWYh zF95?8paBmP$2hV**O^*=CtMkqo%H%i{9(7=(F97R zI@`Aa>NLmPMKp!OQxq)5lydrI2Zyfq#IXgUBmdAo9W2W%NT-#ok-hZGhhDXE<;uxJ zeKN#%F9^)~G)X@Q2?(;GxxNEFI?E=i3m73*l zzY;{7D5rgDMUj5xs#Rr$ZoQH}VW=JVY@)I+% zq!8Re`GmeV)tNmD+e#c$6CJ5#?ho-pR-XyQd?MjmF~R|HO2;j#XSc#Hsc!{llR!bo z{%fNBGErq3t$D-jk6Gm1w24|U92vzRL&}Y-#0l$#q$KLFiL{BFeHjLv>Y`U6FUz3O zp53m(7Mz(kds9bl>w-zaVoZO6Pv3@Pv z+!z|~jNmy?&ss!89f!JWKgW#I2*<+9R(gqlaRukq%`v4Xjr7{@P%59Jx0L!NRJ8-m z(=ms�YD5JkaACf)YEnVNh+Op+eG1%+;Hlfu{~dCTo)3Mg&HylCH#BlKj7=rJtN^ ztK$n+|JETR{R4V=yB)6n9|-?{+yDRo diff --git a/logo.svg b/logo.svg index 7f03e01..c666498 100644 --- a/logo.svg +++ b/logo.svg @@ -27,12 +27,12 @@ inkscape:deskcolor="#505050" inkscape:document-units="px" showgrid="false" - inkscape:zoom="6.5551718" - inkscape:cx="-55.833777" - inkscape:cy="15.865336" + inkscape:zoom="13.110344" + inkscape:cx="11.40321" + inkscape:cy="21.967388" inkscape:window-width="1920" - inkscape:window-height="1051" - inkscape:window-x="1920" + inkscape:window-height="1007" + inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="layer1" /> @@ -55,6 +55,6 @@ diff --git a/pubspec.yaml b/pubspec.yaml index 269c3e0..936cdf8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,7 +58,6 @@ flutter_intl: enabled: true flutter_launcher_icons: - android: "ic_launcher" ios: true image_path: "logo.png" min_sdk_android: 23 From 911852dff5eb6fe10ce2c1cee404542f4613b6a4 Mon Sep 17 00:00:00 2001 From: theskyblockman Date: Sun, 23 Jul 2023 16:10:50 +0200 Subject: [PATCH 13/13] :bookmark: Updated changelogs and versions --- fastlane/metadata/android/en-US/changelogs/10300.txt | 1 + fastlane/metadata/android/fr-FR/changelogs/10300.txt | 1 + pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/10300.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/10300.txt diff --git a/fastlane/metadata/android/en-US/changelogs/10300.txt b/fastlane/metadata/android/en-US/changelogs/10300.txt new file mode 100644 index 0000000..e8e4ca8 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/10300.txt @@ -0,0 +1 @@ +- Fixed bugs and improved stability. The video viewer is now stable although less secure but secure enough to be used. \ No newline at end of file diff --git a/fastlane/metadata/android/fr-FR/changelogs/10300.txt b/fastlane/metadata/android/fr-FR/changelogs/10300.txt new file mode 100644 index 0000000..df79433 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/10300.txt @@ -0,0 +1 @@ +- Bugs reglés et amelioration générale de la stabilité. Le lecteur vidéo est maintenant stable même si il est moins sécurisé mais assez pour être utilisé. \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 936cdf8..dd479f2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A safe container for your data publish_to: 'none' homepage: https://github.com/theskyblockman/life-chest -version: 1.2.2+10202 +version: 1.3.0+10300 environment: sdk: '>=3.0.0 <4.0.0'