Skip to content
This repository has been archived by the owner on Sep 22, 2024. It is now read-only.

Commit

Permalink
Support working on background #7
Browse files Browse the repository at this point in the history
  • Loading branch information
iamalper committed Dec 15, 2023
1 parent fe04914 commit 1a27821
Show file tree
Hide file tree
Showing 29 changed files with 1,016 additions and 177 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:
- run: flutter config --enable-linux-desktop

- name: Running flutter tests
run: xvfb-run flutter test integration_test
run: xvfb-run flutter test integration_test/app_test.dart

- name: Start linux build
run: flutter build linux
Expand Down Expand Up @@ -166,7 +166,7 @@ jobs:
- run: flutter config --enable-windows-desktop

- name: Running flutter tests
run: flutter test integration_test
run: flutter test integration_test\app_test.dart

- name: Build for windows
run: flutter build windows
Expand Down
7 changes: 7 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ android {
ndkVersion flutter.ndkVersion

compileOptions {
//flutter_local_notifications
coreLibraryDesugaringEnabled true
//------
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
Expand Down Expand Up @@ -93,4 +96,8 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:multidex:2.0.1'
//for flutter_local_notifications
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
implementation 'androidx.window:window:1.0.0'
implementation 'androidx.window:window-java:1.0.0'
}
30 changes: 29 additions & 1 deletion android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
-keep class androidx.lifecycle.DefaultLifecycleObserver
-keep class androidx.lifecycle.DefaultLifecycleObserver

## flutter_local_notification
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature

# For using GSON @Expose annotation
-keepattributes *Annotation*

# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }

# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * extends com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
4 changes: 4 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
android:requestLegacyExternalStorage="true">
<!-- Need for API level 29. Scoped Storage has some issue in Android 10. So, google recommanded to add this. -->
<!-- Read more from here: https://developer.android.com/training/data-storage/shared/media#access-other-apps-files-->

<!--for flutter_local_notifications-->
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />

<activity
android:name=".MainActivity"
android:exported="true"
Expand Down
6 changes: 3 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
buildscript {
ext.kotlin_version = '1.7.10'
ext.kotlin_version = '1.9.21'
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:7.2.0'
classpath 'com.android.tools.build:gradle:7.3.1'
// START: FlutterFire Configuration
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.google.gms:google-services:4.3.14'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
// END: FlutterFire Configuration
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
Expand Down
85 changes: 59 additions & 26 deletions integration_test/app_test.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:io';
import 'dart:math';
import 'package:file_picker/file_picker.dart';
import 'package:weepy/classes/database.dart';
import 'package:weepy/classes/discover.dart';
import 'package:weepy/classes/exceptions.dart';
import 'package:weepy/classes/sender.dart';
Expand All @@ -17,6 +18,7 @@ void main() {
var sendingFiles = <File>[];
var platformFiles = <PlatformFile>[];
late Directory subdir;
//TODO: Refactor
setUpAll(() async {
final tempDir = await getTemporaryDirectory();
subdir = tempDir.createTempSync("sending");
Expand All @@ -43,30 +45,60 @@ void main() {
name: path.basename(sendingFiles[index].path),
path: sendingFiles[index].path));
});
group('IO tests', () {
var downloadedFiles = <DbFile>[];
final recieve = Receiver(
saveToTemp: true,
useDb: false,
onAllFilesDownloaded: (files) => downloadedFiles = files);

testWidgets('Discover, send and receive files', (_) async {
final code = await recieve.listen();
var allDevices = <Device>[];
while (allDevices.isEmpty) {
allDevices = await Discover.discover();
}
final devices = allDevices.where((device) => device.code == code);
expect(devices, isNotEmpty, reason: "Expected to discover itself");
await Sender.send(devices.first, platformFiles, useDb: false);
for (var i = 0; i < sendingFiles.length; i++) {
final gidenDosya = sendingFiles[i];
final gelenDosya = File(downloadedFiles[i].path);
expect(
gidenDosya.readAsBytesSync(), equals(gelenDosya.readAsBytesSync()),
reason: "All sent files expected to has same content as originals");
}
group("Database tests", () {
final db = DatabaseManager();
setUp(() => db.clear());
testWidgets("Downloaded file insert", (_) async {
final file = DbFile(
name: "test1",
path: "/.../../",
time: DateTime.now(),
fileStatus: DbFileStatus.download);
await db.insert(file);
final savedFiles = await db.files;
expect(savedFiles, equals([file]));
});
testWidgets("Uploaded file insert", (_) async {
final file = DbFile(
name: "test1",
path: "/.../../",
time: DateTime.now(),
fileStatus: DbFileStatus.upload);
await db.insert(file);
final savedFiles = await db.files;
expect(savedFiles, equals([file]));
});
tearDown(() => db.close());
});
group('IO tests', () {
var downloadedFiles = <DbFile>[];
Receiver? receiver;
testWidgets(
'Discover, send and receive files',
(_) async {
receiver = Receiver(
saveToTemp: true,
useDb: false,
onAllFilesDownloaded: (files) => downloadedFiles = files);
final code = await receiver!.listen();
var allDevices = <Device>[];
while (allDevices.isEmpty) {
allDevices = await Discover.discover();
}
final devices = allDevices.where((device) => device.code == code);
expect(devices, isNotEmpty, reason: "Expected to discover itself");
await Sender().send(devices.first, platformFiles, useDb: false);
for (var i = 0; i < sendingFiles.length; i++) {
final gidenDosya = sendingFiles[i];
final gelenDosya = File(downloadedFiles[i].path);
expect(gidenDosya.readAsBytesSync(),
equals(gelenDosya.readAsBytesSync()),
reason:
"All sent files expected to has same content as originals");
}
},
);

tearDown(() {
for (var file in downloadedFiles) {
Expand All @@ -75,22 +107,23 @@ void main() {
downloadedFiles = [];
});
tearDownAll(() async {
await recieve.stopListening();
await receiver?.stopListening();
});
});

group('Error handling', () {
testWidgets("Handle no_receiver error", (_) async {
final rand1 = Random().nextInt(30);
final rand2 = Random().nextInt(30);
final sendFuture = Sender.send(
final sendFuture = Sender().send(
Device(adress: "192.168.$rand1.$rand2", code: 1000, port: 2326),
platformFiles,
useDb: false);
await expectLater(sendFuture, throwsA(isA<FileDropException>()));
}, retry: 2);
testWidgets("Handle connection lost while reciving", (_) async {
FileDropException? throwedError;
final sender = Sender();
final code = await Receiver(
onDownloadError: (error) => throwedError = error,
useDb: false,
Expand All @@ -101,8 +134,8 @@ void main() {
devices = await Discover.discover();
}
expect(devices.where((device) => device.code == code), isNotEmpty);
Future.delayed(const Duration(milliseconds: 500), Sender.cancel);
await Sender.send(
Future.delayed(const Duration(milliseconds: 500), sender.cancel);
await sender.send(
devices.first,
[
PlatformFile(
Expand Down
1 change: 0 additions & 1 deletion integration_test/fake_path_provider.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
Expand Down
81 changes: 81 additions & 0 deletions integration_test/mobile_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:path/path.dart' as path;
import 'package:file_picker/file_picker.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:path_provider/path_provider.dart';
import 'package:weepy/classes/discover.dart';
import 'package:weepy/classes/workers/worker_interface.dart';
import 'package:weepy/models.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
var sendingFiles = <File>[];
var platformFiles = <PlatformFile>[];
var downloadedFiles = <DbFile>[];
IsolatedReceiver? receiver;
late Directory subdir;
setUpAll(() async {
final tempDir = await getTemporaryDirectory();
subdir = tempDir.createTempSync("sending");
final testImageData = await rootBundle.load("assets/test_image.png");
final testImageFile = File(path.join(subdir.path, "test_image.png"));
testImageFile.writeAsBytesSync(testImageData.buffer.asInt8List(),
mode: FileMode.writeOnly);
sendingFiles = [
File(path.join(subdir.path, "deneme 1.txt")),
File(path.join(subdir.path, "deneme 2.txt")),
testImageFile
];
for (var gidenDosya in sendingFiles) {
if (path.extension(gidenDosya.path) == ".txt") {
gidenDosya.writeAsStringSync("deneme gövdesi",
mode: FileMode.writeOnly);
}
}
platformFiles = List.generate(
sendingFiles.length,
(index) => PlatformFile(
//readStream: sendingFiles[index].openRead(),
size: sendingFiles[index].lengthSync(),
name: path.basename(sendingFiles[index].path),
path: sendingFiles[index].path));
});

final dbStatusVariant = ValueVariant({true, false});

testWidgets("Test IsolatedReceiver & IsolatedSender", (_) async {
receiver = IsolatedReceiver(
saveToTemp: true,
useDb: dbStatusVariant.currentValue!,
onAllFilesDownloaded: (files) => downloadedFiles = files,
onDownloadError: (error) => throw error,
progressNotification: true);
final code = await receiver!.listen();
var allDevices = <Device>[];
while (allDevices.isEmpty) {
allDevices = await Discover.discover();
}
final devices = allDevices.where((device) => device.code == code);
expect(devices, isNotEmpty, reason: "Expected to discover itself");
await IsolatedSender(progressNotification: false).send(
devices.first, platformFiles,
useDb: dbStatusVariant.currentValue!);
for (var i = 0; i < sendingFiles.length; i++) {
final gidenDosya = sendingFiles[i];
final gelenDosya = File(downloadedFiles[i].path);
expect(gidenDosya.readAsBytesSync(), equals(gelenDosya.readAsBytesSync()),
reason: "All sent files expected to has same content as originals");
}
}, variant: dbStatusVariant);
tearDown(() {
for (var file in downloadedFiles) {
File(file.path).deleteSync();
}
downloadedFiles = [];
});
tearDownAll(() async {
await receiver?.stopListening();
});
}
2 changes: 1 addition & 1 deletion ios/Flutter/Generated.xcconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=C:\flutter
FLUTTER_APPLICATION_PATH=C:\Flutter projects\filedrop
FLUTTER_APPLICATION_PATH=C:\Flutter_projects\filedrop
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib\main.dart
FLUTTER_BUILD_DIR=build
Expand Down
2 changes: 1 addition & 1 deletion ios/Flutter/flutter_export_environment.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=C:\flutter"
export "FLUTTER_APPLICATION_PATH=C:\Flutter projects\filedrop"
export "FLUTTER_APPLICATION_PATH=C:\Flutter_projects\filedrop"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
Expand Down
14 changes: 14 additions & 0 deletions ios/Runner/GeneratedPluginRegistrant.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
@import firebase_remote_config;
#endif

#if __has_include(<flutter_local_notifications/FlutterLocalNotificationsPlugin.h>)
#import <flutter_local_notifications/FlutterLocalNotificationsPlugin.h>
#else
@import flutter_local_notifications;
#endif

#if __has_include(<flutter_store_listing/FlutterStoreListingPlugin.h>)
#import <flutter_store_listing/FlutterStoreListingPlugin.h>
#else
Expand Down Expand Up @@ -90,13 +96,20 @@
@import url_launcher_ios;
#endif

#if __has_include(<workmanager/WorkmanagerPlugin.h>)
#import <workmanager/WorkmanagerPlugin.h>
#else
@import workmanager;
#endif

@implementation GeneratedPluginRegistrant

+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
[FilePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FilePickerPlugin"]];
[FLTFirebaseCorePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseCorePlugin"]];
[FLTFirebaseCrashlyticsPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseCrashlyticsPlugin"]];
[FLTFirebaseRemoteConfigPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseRemoteConfigPlugin"]];
[FlutterLocalNotificationsPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterLocalNotificationsPlugin"]];
[FlutterStoreListingPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterStoreListingPlugin"]];
[IntegrationTestPlugin registerWithRegistrar:[registry registrarForPlugin:@"IntegrationTestPlugin"]];
[OpenFilePlugin registerWithRegistrar:[registry registrarForPlugin:@"OpenFilePlugin"]];
Expand All @@ -107,6 +120,7 @@ + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
[SqflitePlugin registerWithRegistrar:[registry registrarForPlugin:@"SqflitePlugin"]];
[Sqlite3FlutterLibsPlugin registerWithRegistrar:[registry registrarForPlugin:@"Sqlite3FlutterLibsPlugin"]];
[URLLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"URLLauncherPlugin"]];
[WorkmanagerPlugin registerWithRegistrar:[registry registrarForPlugin:@"WorkmanagerPlugin"]];
}

@end
Loading

0 comments on commit 1a27821

Please sign in to comment.