Skip to content

Commit

Permalink
Merge pull request #48 from theskyblockman/master
Browse files Browse the repository at this point in the history
General update 1.2.2
  • Loading branch information
helomri authored Jul 14, 2023
2 parents 8bc5279 + 192580e commit 8ecb3aa
Show file tree
Hide file tree
Showing 20 changed files with 225 additions and 155 deletions.
1 change: 1 addition & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -0,0 +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.
1 change: 1 addition & 0 deletions fastlane/metadata/android/en-US/changelogs/10202.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fixed bugs and improved stability.
1 change: 1 addition & 0 deletions fastlane/metadata/android/fr-FR/changelogs/10202.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Bugs reglés et amelioration générale de la stabilité
126 changes: 41 additions & 85 deletions lib/file_explorer/file_explorer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:io';
import 'dart:isolate';

import 'package:cryptography/cryptography.dart';
import 'package:document_file_save_plus/document_file_save_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand All @@ -18,6 +19,8 @@ import 'package:life_chest/vault.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

typedef FileExportArgs = (String thumbnailFilePath, List<int> encryptionKey, Map<String, dynamic> data, List<int> fileContent, String unlockMechanismType, Map<String, dynamic> 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 {
final List<FileThumbnail> Function() thumbnails;
Expand Down Expand Up @@ -257,32 +260,11 @@ class FileExplorerState extends State<FileExplorer> {
bool isGridView = true;

static Future<void> exportEncryptedThumbnails(
List<
(
String thumbnailFilePath,
List<int> encryptionKey,
Map<String, dynamic> data,
List<int> fileContent,
String unlockMechanismType,
Map<String, dynamic> additionalUnlockData,
String saveLocationPath
)>
message) async {
for ((
String thumbnailFilePath,
List<int> encryptionKey,
Map<String, dynamic> data,
List<int> fileContent,
String unlockMechanismType,
Map<String, dynamic> additionalUnlockData,
String saveLocationPath
) data in message) {
(SendPort, List<FileExportArgs>) message) async {
for (FileExportArgs data in message.$2) {
List<int> exportedFile = await FileExporter.exportFile(basename(data.$1),
SecretKey(data.$2), data.$3, data.$4, data.$5, data.$6);
File fileToSaveTo =
File(join(data.$7, 'Life_Chest_${md5RandomFileName()}.lcef'));
fileToSaveTo.createSync();
fileToSaveTo.writeAsBytesSync(exportedFile);
message.$1.send(exportedFile);
}
}

Expand Down Expand Up @@ -446,83 +428,59 @@ class FileExplorerState extends State<FileExplorer> {
filesToExport.add(thumbnail);
}
}
String validDirectoryName =
S.of(context).lifeChestBulkSave;
Directory? downloadDirectory;
if (Platform.isIOS) {
downloadDirectory =
await getDownloadsDirectory();

if (downloadDirectory == null) return;
} else {
downloadDirectory = Directory(
'/storage/emulated/0/Download');
// Put file in global download folder, if for an unknown reason it didn't exist, we fallback
if (!await downloadDirectory.exists()) {
downloadDirectory =
await getExternalStorageDirectory();
}
}

Directory saveLocation = downloadDirectory!;

if (filesToExport.length > 1) {
String currentSuffix = '';
int currentDirID = 2;
List<FileSystemEntity> dirFiles =
downloadDirectory.listSync();
while (dirFiles.any((element) =>
basename(element.path) ==
validDirectoryName + currentSuffix)) {
currentSuffix = ' ($currentDirID)';
currentDirID++;
}
validDirectoryName =
validDirectoryName + currentSuffix;

saveLocation = Directory(join(
saveLocation.path, validDirectoryName));
saveLocation.createSync();
}
setState(() {
loaderTarget = filesToExport.length;
loaderCurrentLoad = 0;
});

List<int> encryptionKey = await widget
.vault.encryptionKey!
.extractBytes();

Isolate.spawn(
exportEncryptedThumbnails,
List<
(
String thumbnailFilePath,
List<int> encryptionKey,
Map<String, dynamic> data,
List<int> fileContent,
String unlockMechanismType,
Map<String,
dynamic> additionalUnlockData,
String saveLocationPath
)>.generate(filesToExport.length,
final receivePort = ReceivePort();

Isolate.spawn(exportEncryptedThumbnails,
(receivePort.sendPort, List<FileExportArgs>.generate(filesToExport.length,
(index) {
FileThumbnail fileToExport =
filesToExport[index];

return (
fileToExport.localPath,
encryptionKey,
fileToExport.data,
fileToExport.file.readAsBytesSync(),
widget.vault.unlockMechanismType,
widget.vault.additionalUnlockData,
saveLocation.path
widget.vault.additionalUnlockData
);
})).then((value) {
})));

List<Uint8List> decryptedFiles = [];

await for(List<int> decryptedFile in receivePort) {
decryptedFiles.add(Uint8List.fromList(decryptedFile));
setState(() {
loaderCurrentLoad = decryptedFiles.length;
});
if(loaderTarget == loaderCurrentLoad) break;
}

setState(() {
loaderTarget = null;
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) {
if (context.mounted) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content: Text(S
.of(context)
.savedToFolder(basename(
saveLocation.path)))));
content: Text(S
.of(context)
.savedToFolder)));
}
});
}
Expand Down Expand Up @@ -591,8 +549,7 @@ class FileExplorerState extends State<FileExplorer> {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(S.of(context).savedToFolder(
basename(saveLocation.path)))));
content: Text(S.of(context).savedToFolder)));
}
},
child: Text(S.of(context).exportAsCleartext)),
Expand Down Expand Up @@ -986,7 +943,6 @@ class FileExplorerState extends State<FileExplorer> {
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) {
Expand Down
32 changes: 23 additions & 9 deletions lib/file_recovery/single_threaded_recovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ 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';
Expand Down Expand Up @@ -33,16 +35,17 @@ class SingleThreadedRecovery {
}

/// Selects the portion to decrypt and decrypts it (maybe the file reading part could be worked on)
static Future<Stream<List<int>>> loadAndDecryptPartialFile(
static Stream<List<int>> loadAndDecryptPartialFile(
SecretKey encryptionKey,
File fileToRead,
int startByte,
int endByte) async {
return VaultsManager.cipher.decryptStream(
fileToRead.openRead(startByte, endByte),
mac: Mac.empty,
secretKey: encryptionKey,
nonce: Uint8List(VaultsManager.cipher.nonceLength));
int endByte) {
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);
});
}

/// Encrypts the file in a specific location with the [encryptionKey] in the ChaCha20 algorithm
Expand Down Expand Up @@ -99,8 +102,10 @@ class SingleThreadedRecovery {
? relative(createdFile.path, from: rootFolderPath)
: relative(importedFile!.$1['name'], from: rootFolderPath));
Map<String, dynamic> finalData = {'name': finalName, 'type': type};
if (FileThumbnailsPlaceholder.getPlaceholderFromFileName(
[finalData])[finalName] ==

FileThumbnailsPlaceholder? placeholder = FileThumbnailsPlaceholder.getPlaceholderFromFileName(
[finalData])[finalName];
if (placeholder ==
FileThumbnailsPlaceholder.audio) {
if (createdFile != null) {
Metadata foundData = await MetadataRetriever.fromFile(createdFile);
Expand All @@ -113,6 +118,15 @@ class SingleThreadedRecovery {
} else {
finalData['audioData'] = importedFile!.$1['audioData'];
}
} else if (placeholder == FileThumbnailsPlaceholder.videos) {
if (createdFile != null) {
MediaInformationSession result = await FFprobeKit.getMediaInformation(createdFile.absolute.path);

finalData['videoData'] = result.getMediaInformation()!.getAllProperties();

} else {
finalData['videoData'] = importedFile!.$1.containsKey('videoData') ? importedFile.$1['videoData'] : {};
}
}

try {
Expand Down
4 changes: 2 additions & 2 deletions lib/file_viewers/audio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,10 +348,10 @@ class EncryptedAudioSource extends StreamAudioSource {
return StreamAudioResponse(
sourceLength: fileByteLength,
contentLength: (end ?? fileByteLength) - (start ?? 0),
offset: start,
offset: start ?? 0,
stream: start == null && end == null ?
SingleThreadedRecovery.loadAndDecryptFile(encryptionKey, fileToRead) :
await SingleThreadedRecovery.loadAndDecryptPartialFile(encryptionKey, fileToRead, start ?? 0, end ?? fileByteLength),
SingleThreadedRecovery.loadAndDecryptPartialFile(encryptionKey, fileToRead, start ?? 0, end ?? fileByteLength),
contentType: mimeType,
rangeRequestsSupported: true);
}
Expand Down
11 changes: 5 additions & 6 deletions lib/file_viewers/video.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class VideoViewer extends FileViewer {
autoPlay: false,
looping: true,
autoDetectFullscreenDeviceOrientation: true,
controlsConfiguration: BetterPlayerControlsConfiguration.white(),
controlsConfiguration: const BetterPlayerControlsConfiguration(),
aspectRatio: fileData['videoData']['streams'][0]['width'] / fileData['videoData']['streams'][0]['height'],
fit: BoxFit.contain,
translations: [
BetterPlayerTranslations(),
BetterPlayerTranslations(
Expand All @@ -54,10 +56,10 @@ class VideoViewer extends FileViewer {
generalRetry: 'Réessayer',
playlistLoadingNextVideo: "Chargement de la prochaine vidéo",
controlsLive: "DIRECT",
controlsNextVideoIn: "Prochaine vidéo dans ",
controlsNextVideoIn: "Prochaine vidéo dans",
overflowMenuPlaybackSpeed: "Vitesse de lecture",
overflowMenuSubtitles: "Sous-titres",
overflowMenuQuality: "Qualitée",
overflowMenuQuality: "Qualité",
overflowMenuAudioTracks: "Audio",
qualityAuto: "Auto"
)
Expand All @@ -68,9 +70,6 @@ class VideoViewer extends FileViewer {
const BetterPlayerPlaylistConfiguration(
loopVideos: true, initialStartIndex: 0));

controller!.setOverriddenAspectRatio(
controller!.videoPlayerController!.value.aspectRatio);

return true;
}

Expand Down
13 changes: 6 additions & 7 deletions lib/generated/intl/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ class MessageLookup extends MessageLookupByLibrary {

static String m1(groupID) => "Group n.${groupID}";

static String m2(path) => "Saved the file(s) to ${path}";
static String m2(count) => "${count} selected";

static String m3(count) => "${count} selected";

static String m4(unlockName) =>
static String m3(unlockName) =>
"This group can be unlocked with: ${unlockName}.";

final messages = _notInlinedMessages(_notInlinedMessages);
Expand Down Expand Up @@ -141,12 +139,13 @@ class MessageLookup extends MessageLookupByLibrary {
"pleaseUseBiometrics": MessageLookupByLibrary.simpleMessage(
"Please use your biometrics to unlock the chest"),
"rename": MessageLookupByLibrary.simpleMessage("Rename"),
"savedToFolder": m2,
"savedToFolder": MessageLookupByLibrary.simpleMessage(
"We successfully saved the file(s)"),
"scheme": MessageLookupByLibrary.simpleMessage("Pattern"),
"selectAll": MessageLookupByLibrary.simpleMessage("Select all"),
"selected": m3,
"selected": m2,
"sortBy": MessageLookupByLibrary.simpleMessage("Sort by..."),
"unlockAbleBy": m4,
"unlockAbleBy": m3,
"unlockChest": MessageLookupByLibrary.simpleMessage("Unlock the chest"),
"unlockFile": MessageLookupByLibrary.simpleMessage("Unlock the file"),
"unlockWizard": MessageLookupByLibrary.simpleMessage("Unlock wizard"),
Expand Down
14 changes: 6 additions & 8 deletions lib/generated/intl/messages_fr.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ class MessageLookup extends MessageLookupByLibrary {

static String m1(groupID) => "Groupe n°${groupID}";

static String m2(path) =>
"Le(s) fichier(s) a/ont été sauvegardé(s) dans ${path}";

static String m3(count) =>
static String m2(count) =>
"${count} ${Intl.plural(count, one: 'fichier sélectionné', other: 'fichiers sélectionnés')}";

static String m4(unlockName) =>
static String m3(unlockName) =>
"Ce groupe peut être débloquer grâce à : ${unlockName}.";

final messages = _notInlinedMessages(_notInlinedMessages);
Expand Down Expand Up @@ -149,12 +146,13 @@ class MessageLookup extends MessageLookupByLibrary {
"pleaseUseBiometrics": MessageLookupByLibrary.simpleMessage(
"Veuillez utiliser votre empreinte digitale pour déverrouiller le coffre"),
"rename": MessageLookupByLibrary.simpleMessage("Renommer"),
"savedToFolder": m2,
"savedToFolder": MessageLookupByLibrary.simpleMessage(
"Le(s) fichier(s) a/ont été sauvegardé(s)."),
"scheme": MessageLookupByLibrary.simpleMessage("Modèle"),
"selectAll": MessageLookupByLibrary.simpleMessage("Tout sélectionner"),
"selected": m3,
"selected": m2,
"sortBy": MessageLookupByLibrary.simpleMessage("Trier par..."),
"unlockAbleBy": m4,
"unlockAbleBy": m3,
"unlockChest": MessageLookupByLibrary.simpleMessage(
"Veuillez déverrouiller le coffre"),
"unlockFile":
Expand Down
8 changes: 4 additions & 4 deletions lib/generated/l10n.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8ecb3aa

Please sign in to comment.