Skip to content

Commit

Permalink
Release 1.0.9
Browse files Browse the repository at this point in the history
  • Loading branch information
desistefanova committed Sep 2, 2024
1 parent e7b25fa commit 5e528fb
Show file tree
Hide file tree
Showing 18 changed files with 153 additions and 108 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
# Mobi Sync Client
An App for wireless syncing of photos and videos from devices to home server. (https://mobisync.eu)


## 1.0.9 Release notes (2024-09-02)

### Enhancements
* Files synced from the newest to the oldest
* Requesting permissions for managing external storage
* Fixed not responding buttons in release

## 1.0.8 Release notes (2024-08-23)

### Enhancements
Expand Down
9 changes: 7 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ if (localPropertiesFile.exists()) {

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '108'
flutterVersionCode = '109'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0.8'
flutterVersionName = '1.0.9'
}

def keystoreProperties = new Properties()
Expand Down Expand Up @@ -72,6 +72,11 @@ android {
// Signing with the debug keys for now,
// so `flutter run --release` works.
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}
Expand Down
23 changes: 11 additions & 12 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,16 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<application
android:label="sync_client"
android:name="${applicationName}"
Expand Down Expand Up @@ -38,4 +26,15 @@
android:name="flutterEmbedding"
android:value="2" />
</application>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>
4 changes: 2 additions & 2 deletions lib/config/router/app_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ limitations under the License.
import 'package:go_router/go_router.dart';
import 'package:sync_client/screens/screens.dart';

GoRouter getAppRouter(bool isAuthenticated) {
return GoRouter(initialLocation: isAuthenticated ? '/' : "/login", routes: [
GoRouter getAppRouter() {
return GoRouter(initialLocation: '/', routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
Expand Down
21 changes: 16 additions & 5 deletions lib/core/impl/background.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ class BackgroundAction implements IAction {

Future<void> _uploadFiles(StreamController<SyncedFile> syncFileController,
List<FileSystemEntity> files, String userName) async {
for (var file in files) {
final reversedFiles = files.reversed;
for (FileSystemEntity file in reversedFiles) {
if (!FileSystemEntity.isDirectorySync(file.path)) {
DateTime lastFileDate = await File(file.path).lastModified();
String dateClassifier = "${lastFileDate.year}-${lastFileDate.month}";
Expand All @@ -69,10 +70,20 @@ class BackgroundAction implements IAction {
f.filename.toLowerCase() == file.path.toLowerCase() &&
(f.errorMessage ?? "").trim() == "" ||
f.failedAttempts > 3);
if (!fileHadBeenSynced) {
if (p.extension(file.path).isNotEmpty) {
var syncedFile = await _transfers.sendFile(
syncFileController, file.path, userName, dateClassifier);
if (fileHadBeenSynced) {
if (!syncFileController.isClosed) {
syncFileController.add(SyncedFile(file.path));
}
if (currentDeviceSettings.deleteLocalFilesEnabled ?? false) {
await File(file.path).delete();
currentDeviceSettings.syncedFiles.removeWhere(
(f) => f.filename.toLowerCase() == file.path.toLowerCase());
}
} else {
if (file is File && p.extension(file.path).isNotEmpty) {
final fileLength = file.lengthSync();
var syncedFile = await _transfers.sendFile(syncFileController,
file.path, userName, dateClassifier, fileLength);

if (syncedFile != null) {
if ((currentDeviceSettings.deleteLocalFilesEnabled ?? false) &&
Expand Down
6 changes: 4 additions & 2 deletions lib/core/impl/server_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ Future<List<NetFolder>?> apiGetFolders(String userName, String deviceId) async {

if (response.statusCode == 200) {
final List<dynamic> result = json.decode(response.body);
final List<NetFolder> folders = result
final List<NetFolder> folders = result.reversed
.map((item) => NetFolder(item["Year"],
subFolders: (List<String>.from(item["Months"])
.reversed
.map((m) => NetFolder(m))
.toList())))
.toList();
Expand Down Expand Up @@ -70,7 +71,8 @@ Future<List<String>> apiGetFiles(

if (response.statusCode == 200) {
final List<dynamic> result = json.decode(response.body);
final List<String> files = result.map((item) => item.toString()).toList();
final List<String> files =
result.reversed.map((item) => item.toString()).toList();
return files;
}
} catch (err) {
Expand Down
11 changes: 8 additions & 3 deletions lib/core/impl/transfers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,18 @@ import 'request_utils.dart';
class Transfers {
Transfers();

Future<SyncedFile?> sendFile(StreamController<SyncedFile> syncFileController,
String filename, String userName, String dateClassifier) async {
Future<SyncedFile?> sendFile(
StreamController<SyncedFile> syncFileController,
String filename,
String userName,
String dateClassifier,
int fileLength) async {
SyncedFile? result;
var request = MultipartRequest('POST', getUrl("upload"));
final hdr = <String, String>{
"user": utf8.encode(userName).toString(),
"date": dateClassifier
"date": dateClassifier,
"fileLength": fileLength.toString()
};
request.headers.addEntries(hdr.entries);

Expand Down
7 changes: 4 additions & 3 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:permission_handler/permission_handler.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await loadDeviceSettings();
if (Platform.isAndroid) {
final mediaStorePlugin = MediaStore();
await mediaStorePlugin.getPlatformSDKInt();
Expand All @@ -33,14 +34,15 @@ void main() async {
await requestPermissions();
}

await loadDeviceSettings();
runApp(const BlocProviders());
}

Future<void> requestPermissions() async {
List<Permission> permissions = [
Permission.storage,
];
permissions.add(Permission.manageExternalStorage);
permissions.add(Permission.accessMediaLocation);
permissions.add(Permission.storage);
permissions.add(Permission.photos);
permissions.add(Permission.audio);
Expand Down Expand Up @@ -75,11 +77,10 @@ class MyApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
final deviceService = context.read<DeviceServicesCubit>();
return MaterialApp.router(
title: 'Mobi Sync Client',
debugShowCheckedModeBanner: false,
routerConfig: getAppRouter(deviceService.isAuthenticated()),
routerConfig: getAppRouter(),
theme: AppTheme.getTheme(context));
}
}
4 changes: 3 additions & 1 deletion lib/screens/components/edit_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ class EditServerFormState extends State<EditServerForm> {
String newServer) async {
if (_formKey.currentState!.validate()) {
await deviceService.edit((state) {
if (state.serverUrl != newServer) {
state.syncedFiles.clear();
}
state.serverUrl = newServer;
state.syncedFiles.clear();
state.lastErrorMessage = null;
state.lastSyncDateTime = null;
state.deleteLocalFilesEnabled = false;
Expand Down
1 change: 0 additions & 1 deletion lib/screens/components/folder_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ class FolderItem extends StatelessWidget {
if (menuItem == FolderMenuOption.delete) {
await deviceService.edit((state) {
state.mediaDirectories.remove(folder);
state.syncedFiles.clear();
state.lastSyncDateTime = null;
state.lastErrorMessage = null;
});
Expand Down
24 changes: 19 additions & 5 deletions lib/screens/components/status_widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ List<Widget> getStateWidgets(
List<Widget> children;

if (snapshot.hasError) {
children = _errorState(context, syncService, snapshot.error as CustomError);
children = _errorState(
context, syncService, deviceService, snapshot.error as CustomError);
} else {
switch (snapshot.connectionState) {
case ConnectionState.none:
Expand All @@ -45,15 +46,28 @@ List<Widget> getStateWidgets(
return children;
}

List<Widget> _errorState(
BuildContext context, SyncServicesCubit syncService, CustomError error) {
List<Widget> _errorState(BuildContext context, SyncServicesCubit syncService,
DeviceServicesCubit deviceService, CustomError error) {
return <Widget>[
const Icon(Icons.error_outline, color: Colors.red, size: 30),
Padding(
Center(
child: Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
'${error is SyncCanceledError ? "" : "Error: "}${error.message}'),
),
)),
okButton(context, "Stop", onPressed: () {
if (syncService.state != null) {
if (!syncService.state!.isClosed) {
syncService.state!.addError(SyncCanceledError());
syncService.state!.close();
syncService.reset();
}
}
deviceService.edit((state) {
state.isSyncing = false;
});
}),
];
}

Expand Down
2 changes: 0 additions & 2 deletions lib/screens/deleting_enabled_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ class _DeletingEnabledScreenView extends StatelessWidget {
await deviceService.edit((state) {
state.deleteLocalFilesEnabled =
!(state.deleteLocalFilesEnabled ?? false);
state.syncedFiles.clear();
state.lastErrorMessage = null;
});
} else {
Expand Down Expand Up @@ -117,7 +116,6 @@ class _DeletingEnabledScreenView extends StatelessWidget {
await deviceService.edit((state) {
state.deleteLocalFilesEnabled =
!(state.deleteLocalFilesEnabled ?? false);
state.syncedFiles.clear();
state.lastErrorMessage = null;
});
if (!context.mounted) return;
Expand Down
8 changes: 3 additions & 5 deletions lib/screens/folders_list_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,10 @@ class FoldersListScreen extends StatelessWidget {
BuildContext context, DeviceServicesCubit deviceService) async {
String? selectedDirectory = await FilePicker.platform.getDirectoryPath();

if (selectedDirectory == null) {
return;
}
await deviceService.edit((state) {
state.mediaDirectories.add(selectedDirectory);
state.syncedFiles.clear();
if (selectedDirectory != null) {
state.mediaDirectories.add(selectedDirectory);
}
state.lastErrorMessage = null;
});
}
Expand Down
Loading

0 comments on commit 5e528fb

Please sign in to comment.