Skip to content

Commit

Permalink
Merge branch 'main' into l10n
Browse files Browse the repository at this point in the history
  • Loading branch information
ibrahim-zehhaf-mawaqit authored Nov 27, 2024
2 parents e08dfa6 + 76dfbce commit dc89e2f
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 60 deletions.
62 changes: 29 additions & 33 deletions android/app/src/main/kotlin/com/flyweb/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,39 +63,35 @@ class MainActivity : FlutterActivity() {
val isSuccess = clearDataRestart()
result.success(isSuccess)
}
"installApk" -> {
val filePath = call.argument<String>("filePath")
if (filePath != null) {
AsyncTask.execute {
try {
// Check if file exists
val file = java.io.File(filePath)
if (!file.exists()) {
Log.e("APK_INSTALL", "APK file not found at path: $filePath")
result.error("FILE_NOT_FOUND", "APK file not found", null)
return@execute
}
// Check if device is rooted
if (!checkRoot()) {
Log.e("APK_INSTALL", "Device is not rooted")
result.error("NOT_ROOTED", "Device is not rooted", null)
return@execute
}



executeCommand(listOf("pm install -r -d $filePath"), result)

result.success("Installation initiated")
} catch (e: Exception) {
Log.e("APK_INSTALL", "Failed to install APK", e)
result.error("INSTALL_FAILED", e.message, null)
}
}
} else {
result.error("INVALID_PATH", "File path is null", null)
}
}
"installApk" -> {
val filePath = call.argument<String>("filePath")
if (filePath != null) {
AsyncTask.execute {
try {
// Check if file exists
val file = java.io.File(filePath)
if (!file.exists()) {
Log.e("APK_INSTALL", "APK file not found at path: $filePath")
result.error("FILE_NOT_FOUND", "APK file not found", null)
return@execute
}
// Check if device is rooted
if (!checkRoot()) {
Log.e("APK_INSTALL", "Device is not rooted")
result.error("NOT_ROOTED", "Device is not rooted", null)
return@execute
}
val commands = listOf("pm install -r -d $filePath")
executeCommand(commands, result)
} catch (e: Exception) {
Log.e("APK_INSTALL", "Failed to install APK", e)
result.error("INSTALL_FAILED", e.message, null)
}
}
} else {
result.error("INVALID_PATH", "File path is null", null)
}
}
else -> result.notImplemented()
}
}
Expand Down
17 changes: 16 additions & 1 deletion lib/l10n/intl_ar.arb
Original file line number Diff line number Diff line change
Expand Up @@ -364,5 +364,20 @@
"downloadingUpdate": "جارٍ تنزيل التحديث...",
"installingUpdate": "جارٍ تنزيل التحديث...",
"updateCompletedSuccessfully": "تم التحديث بنجاح",
"updateFailed": "فشل التحديث"
"updateFailed": "فشل التحديث",
"checkInternetUpdate": "يجب عليك الاتصال بالإنترنت للتحقق من وجود تحديثات جديدة",
"appUpdateAvailable": "تطبيقك يعمل بالإصدار {currentVersion}. تحديث جديد (الإصدار {updatedVersion}) متوفر مع أحدث الميزات والتحسينات.",
"@appUpdateAvailable": {
"description": "نص بديل لعرض رسالة التحديث المتاح",
"placeholders": {
"currentVersion": {
"type": "String",
"example": "1"
},
"updatedVersion": {
"type": "String",
"example": "604"
}
}
}
}
20 changes: 18 additions & 2 deletions lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -364,5 +364,21 @@
"downloadingUpdate": "Downloading update...",
"installingUpdate": "Installing update...",
"updateCompletedSuccessfully": "Update completed successfully",
"updateFailed": "Update failed"
}
"updateFailed": "Update failed",
"checkInternetUpdate": "You must connect to internet to check for new updates",
"appUpdateAvailable": "Your app is running version {currentVersion}. A new update (version {updatedVersion}) is available with the latest features and improvements.",
"@appUpdateAvailable": {
"description": "Placeholder text for displaying update available message",
"placeholders": {
"currentVersion": {
"type": "String",
"example": "1"
},
"updatedVersion": {
"type": "String",
"example": "604"
}
}
}

}
17 changes: 16 additions & 1 deletion lib/l10n/intl_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -364,5 +364,20 @@
"downloadingUpdate": "Téléchargement de la mise à jour...",
"installingUpdate": "Installation de la mise à jour...",
"updateCompletedSuccessfully": "Mise à jour terminée avec succès",
"updateFailed": "Échec de la mise à jour"
"updateFailed": "Échec de la mise à jour",
"checkInternetUpdate": "Vous devez être connecté à Internet pour vérifier les nouvelles mises à jour",
"appUpdateAvailable": "Votre application utilise la version {currentVersion}. Une nouvelle mise à jour (version {updatedVersion}) est disponible avec les dernières fonctionnalités et améliorations.",
"@appUpdateAvailable": {
"description": "Texte de remplacement pour afficher le message de mise à jour disponible",
"placeholders": {
"currentVersion": {
"type": "String",
"example": "1"
},
"updatedVersion": {
"type": "String",
"example": "604"
}
}
}
}
54 changes: 46 additions & 8 deletions lib/src/pages/SettingScreen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,52 @@ class _SettingScreenState extends ConsumerState<SettingScreen> {
_SettingItem(
title: S.of(context).checkForUpdates,
subtitle: S.of(context).checkForNewVersion,
icon: const Icon(Icons.system_update, size: 35),
onTap: () async {
var softwareFuture = await PackageInfo.fromPlatform();

ref
.read(manualUpdateNotifierProvider.notifier)
.checkForUpdates(softwareFuture.version, context.read<AppLanguage>().appLocal.languageCode);
},
icon: ref.watch(manualUpdateNotifierProvider).isLoading
? const SizedBox(
width: 35,
height: 35,
child: CircularProgressIndicator(),
)
: const Icon(Icons.system_update, size: 35),
onTap: ref.watch(manualUpdateNotifierProvider).isLoading
? null
: () async {
await ref.read(connectivityProvider.notifier).checkInternetConnection();
ref.watch(connectivityProvider).maybeWhen(
orElse: () {
showCheckInternetDialog(
context: context,
onRetry: () {
AppRouter.pop();
},
title: checkInternet,
content: S.of(context).checkInternetUpdate,
);
},
data: (isConnectedToInternet) async {
if (isConnectedToInternet == ConnectivityStatus.disconnected) {
showCheckInternetDialog(
context: context,
onRetry: () {
AppRouter.pop();
},
title: checkInternet,
content: S.of(context).checkInternetUpdate,
);
} else {
var softwareFuture = await PackageInfo.fromPlatform();
final isDeviceRooted = ref.watch(onBoardingProvider).maybeWhen(
orElse: () => false,
data: (value) => value.isRootedDevice,
);
ref.read(manualUpdateNotifierProvider.notifier).checkForUpdates(
softwareFuture.version,
context.read<AppLanguage>().appLocal.languageCode,
isDeviceRooted);
}
},
);
},
),
],
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,31 +51,35 @@ class ManualUpdateNotifier extends AsyncNotifier<UpdateState> {

Future<void> checkForUpdates(
String currentVersion,
String languageCode, {
bool? isDeviceRooted,
}) async {
String languageCode,
bool isDeviceRooted,
) async {
state = const AsyncLoading();
try {
state = const AsyncValue.data(UpdateState(status: UpdateStatus.checking, message: 'Checking updates...'));

final hasUpdate = isDeviceRooted ?? false
final hasUpdate = isDeviceRooted
? await _isUpdateAvailableForRootedDevice(currentVersion)
: await _isUpdateAvailableStandard(languageCode);

if (hasUpdate) {
final downloadUrl = await _getLatestReleaseUrl();
state = AsyncValue.data(state.value!.copyWith(
final latestVersion = await _getLatestVersion();

state = AsyncData(state.value!.copyWith(
status: UpdateStatus.available,
message: 'Update available',
downloadUrl: downloadUrl,
currentVersion: currentVersion,
availableVersion: latestVersion,
));
} else {
state = const AsyncValue.data(UpdateState(
state = AsyncData(UpdateState(
status: UpdateStatus.notAvailable,
message: 'You are using the latest version',
currentVersion: currentVersion,
));
}
} catch (e, st) {
state = AsyncValue.error('Failed to check updates', st);
state = AsyncError(e, st);
}
}

Expand All @@ -93,7 +97,6 @@ class ManualUpdateNotifier extends AsyncNotifier<UpdateState> {
(release) => release['prerelease'] == false,
orElse: () => throw Exception('No stable release found'),
);

final latestVersion = latestRelease['tag_name'].toString();
return _compareVersions(latestVersion, currentVersion) > 0;
}
Expand All @@ -113,6 +116,15 @@ class ManualUpdateNotifier extends AsyncNotifier<UpdateState> {
return response.data as List;
}

Future<String> _getLatestVersion() async {
final releases = await _fetchReleases();
final latestRelease = releases.firstWhere(
(release) => release['prerelease'] == false,
orElse: () => throw Exception('No stable release found'),
);
return latestRelease['tag_name'].toString();
}

Future<void> downloadAndInstallUpdate() async {
final downloadUrl = state.value?.downloadUrl;
if (downloadUrl == null) return;
Expand Down Expand Up @@ -243,7 +255,6 @@ class ManualUpdateNotifier extends AsyncNotifier<UpdateState> {
int _compareVersions(String v1, String v2) {
final version1 = v1.replaceAll('v', '').split('.');
final version2 = v2.replaceAll('v', '').split('.');

for (var i = 0; i < version1.length && i < version2.length; i++) {
final num1 = int.parse(version1[i]);
final num2 = int.parse(version2[i]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class UpdateState extends Equatable {
final String? error;
final String? downloadUrl;
final String? filePath;
final String? currentVersion;
final String? availableVersion;

const UpdateState({
this.status = UpdateStatus.initial,
Expand All @@ -27,6 +29,8 @@ class UpdateState extends Equatable {
this.error,
this.downloadUrl,
this.filePath,
this.currentVersion,
this.availableVersion,
});

UpdateState copyWith({
Expand All @@ -36,6 +40,8 @@ class UpdateState extends Equatable {
String? error,
String? downloadUrl,
String? filePath,
String? currentVersion,
String? availableVersion,
}) {
return UpdateState(
status: status ?? this.status,
Expand All @@ -44,6 +50,8 @@ class UpdateState extends Equatable {
error: error ?? this.error,
downloadUrl: downloadUrl ?? this.downloadUrl,
filePath: filePath ?? this.filePath,
currentVersion: currentVersion ?? this.currentVersion,
availableVersion: availableVersion ?? this.availableVersion,
);
}

Expand Down
25 changes: 22 additions & 3 deletions lib/src/widgets/manual_update_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class UpdateDialogMessages {
static Map<UpdateStatus, String> getLocalizedMessage(BuildContext context) {
return {
UpdateStatus.checking: S.of(context).checkingForUpdates,
UpdateStatus.available: S.of(context).updateAvailable,
/* UpdateStatus.available: S.of(context).updateAvailable,
*/
UpdateStatus.notAvailable: S.of(context).usingLatestVersion,
UpdateStatus.downloading: S.of(context).downloadingUpdate,
UpdateStatus.installing: S.of(context).installingUpdate,
Expand Down Expand Up @@ -46,7 +47,21 @@ class UpdateDialog {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(localizedMessages[updateState.value?.status] ?? S.of(context).wouldYouLikeToUpdate),
if (updateState.value?.currentVersion != null && updateState.value?.availableVersion != null) ...[
Text(S.of(context).appUpdateAvailable(
updateState.value?.currentVersion as String, updateState.value?.availableVersion as String)),
const SizedBox(height: 8),
],
if (updateState.value?.status == UpdateStatus.error)
Text(
updateState.value?.message ?? S.of(context).updateFailed,
style: TextStyle(color: Theme.of(context).colorScheme.error),
textAlign: TextAlign.center,
)
else
Text(
localizedMessages[updateState.value?.status] ?? S.of(context).wouldYouLikeToUpdate,
),
if (updateState.value?.progress != null) ...[
const SizedBox(height: 16),
LinearProgressIndicator(
Expand All @@ -67,6 +82,10 @@ class UpdateDialog {
}

static List<Widget> _buildDialogActions(BuildContext context, WidgetRef ref) {
final updateState = ref.watch(manualUpdateNotifierProvider);
final isUpdating =
updateState.value?.status == UpdateStatus.downloading || updateState.value?.status == UpdateStatus.installing;

return [
TextButton(
onPressed: () {
Expand All @@ -76,7 +95,7 @@ class UpdateDialog {
child: Text(S.of(context).cancel),
),
TextButton(
onPressed: () => _handleUpdateAction(context, ref),
onPressed: isUpdating ? null : () => _handleUpdateAction(context, ref),
child: Text(S.of(context).update),
),
];
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html


version: 1.17.1+1
version: 1.17.3+1


environment:
Expand Down

0 comments on commit dc89e2f

Please sign in to comment.