feat: ability to search query for suggested version (#1151)

Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
Co-authored-by: Ushie <ushiekane@gmail.com>
This commit is contained in:
Aditya Arora 2023-11-21 20:03:21 +05:30 committed by GitHub
parent c0516c3665
commit 9bd48c19ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 240 additions and 25 deletions

View File

@ -1,5 +1,7 @@
package app.revanced.manager.flutter package app.revanced.manager.flutter
import android.app.SearchManager
import android.content.Intent
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import app.revanced.manager.flutter.utils.Aapt import app.revanced.manager.flutter.utils.Aapt
@ -41,6 +43,17 @@ class MainActivity : FlutterActivity() {
val patcherChannel = "app.revanced.manager.flutter/patcher" val patcherChannel = "app.revanced.manager.flutter/patcher"
val installerChannel = "app.revanced.manager.flutter/installer" val installerChannel = "app.revanced.manager.flutter/installer"
val openBrowserChannel = "app.revanced.manager.flutter/browser"
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, openBrowserChannel).setMethodCallHandler { call, result ->
if (call.method == "openBrowser") {
val searchQuery = call.argument<String>("query")
openBrowser(searchQuery)
result.success(null)
} else {
result.notImplemented()
}
}
val mainChannel = val mainChannel =
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, patcherChannel) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, patcherChannel)
@ -176,6 +189,15 @@ class MainActivity : FlutterActivity() {
} }
} }
fun openBrowser(query: String?) {
val intent = Intent(Intent.ACTION_WEB_SEARCH).apply {
putExtra(SearchManager.QUERY, query)
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
}
@OptIn(InternalCoroutinesApi::class) @OptIn(InternalCoroutinesApi::class)
private fun runPatcher( private fun runPatcher(
result: MethodChannel.Result, result: MethodChannel.Result,

View File

@ -112,6 +112,10 @@ class _AppSelectorViewState extends State<AppSelectorView> {
context, context,
app.packageName, app.packageName,
), ),
onLinkTap: () =>
model.searchSuggestedVersionOnWeb(
packageName: app.packageName,
),
), ),
) )
, ,
@ -126,6 +130,10 @@ class _AppSelectorViewState extends State<AppSelectorView> {
onTap: () { onTap: () {
model.showDownloadToast(); model.showDownloadToast();
}, },
onLinkTap: () =>
model.searchSuggestedVersionOnWeb(
packageName: app,
),
), ),
) )
, ,

View File

@ -3,6 +3,7 @@ import 'dart:io';
import 'package:device_apps/device_apps.dart'; import 'package:device_apps/device_apps.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_file_dialog/flutter_file_dialog.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart';
import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.locator.dart';
@ -70,6 +71,33 @@ class AppSelectorViewModel extends BaseViewModel {
return true; return true;
} }
Future<void> searchSuggestedVersionOnWeb({
required String packageName,
}) async {
final String suggestedVersion = getSuggestedVersion(packageName);
if (suggestedVersion.isNotEmpty) {
await openDefaultBrowser('$packageName apk version v$suggestedVersion');
} else {
await openDefaultBrowser('$packageName apk');
}
}
Future<void> openDefaultBrowser(String query) async {
if (Platform.isAndroid) {
try {
const platform = MethodChannel('app.revanced.manager.flutter/browser');
await platform.invokeMethod('openBrowser', {'query': query});
} catch (e) {
if (kDebugMode) {
print(e);
}
}
} else {
throw 'Platform not supported';
}
}
Future<void> selectApp( Future<void> selectApp(
BuildContext context, BuildContext context,
ApplicationWithIcon application, [ ApplicationWithIcon application, [

View File

@ -1,6 +1,10 @@
// ignore_for_file: use_build_context_synchronously // ignore_for_file: use_build_context_synchronously
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:injectable/injectable.dart'; import 'package:injectable/injectable.dart';
import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.locator.dart';
@ -157,6 +161,29 @@ class PatcherViewModel extends BaseViewModel {
return text; return text;
} }
String getCurrentVersionString(BuildContext context) {
return '${FlutterI18n.translate(
context,
'appSelectorCard.currentVersion',
)}: v${selectedApp!.version}';
}
Future<void> searchSuggestedVersionOnWeb() async {
final String suggestedVersion =
_patcherAPI.getSuggestedVersion(selectedApp!.packageName);
if (suggestedVersion.isNotEmpty) {
await openDefaultBrowser(
'${selectedApp!.packageName} apk version v$suggestedVersion');
} else {
await openDefaultBrowser('${selectedApp!.packageName} apk');
}
}
String getSuggestedVersion() {
return _patcherAPI.getSuggestedVersion(selectedApp!.packageName);
}
String getSuggestedVersionString(BuildContext context) { String getSuggestedVersionString(BuildContext context) {
String suggestedVersion = String suggestedVersion =
_patcherAPI.getSuggestedVersion(selectedApp!.packageName); _patcherAPI.getSuggestedVersion(selectedApp!.packageName);
@ -169,14 +196,26 @@ class PatcherViewModel extends BaseViewModel {
suggestedVersion = 'v$suggestedVersion'; suggestedVersion = 'v$suggestedVersion';
} }
return '${FlutterI18n.translate( return '${FlutterI18n.translate(
context,
'appSelectorCard.currentVersion',
)}: v${selectedApp!.version}\n${FlutterI18n.translate(
context, context,
'appSelectorCard.suggestedVersion', 'appSelectorCard.suggestedVersion',
)}: $suggestedVersion'; )}: $suggestedVersion';
} }
Future<void> openDefaultBrowser(String query) async {
if (Platform.isAndroid) {
try {
const platform = MethodChannel('app.revanced.manager.flutter/browser');
await platform.invokeMethod('openBrowser', {'query': query});
} catch (e) {
if (kDebugMode) {
print(e);
}
}
} else {
throw 'Platform not supported';
}
}
Future<void> loadLastSelectedPatches() async { Future<void> loadLastSelectedPatches() async {
this.selectedPatches.clear(); this.selectedPatches.clear();
removedPatches.clear(); removedPatches.clear();

View File

@ -13,7 +13,9 @@ class InstalledAppItem extends StatefulWidget {
required this.suggestedVersion, required this.suggestedVersion,
required this.installedVersion, required this.installedVersion,
this.onTap, this.onTap,
this.onLinkTap,
}); });
final String name; final String name;
final String pkgName; final String pkgName;
final Uint8List icon; final Uint8List icon;
@ -21,6 +23,7 @@ class InstalledAppItem extends StatefulWidget {
final String suggestedVersion; final String suggestedVersion;
final String installedVersion; final String installedVersion;
final Function()? onTap; final Function()? onTap;
final Function()? onLinkTap;
@override @override
State<InstalledAppItem> createState() => _InstalledAppItemState(); State<InstalledAppItem> createState() => _InstalledAppItemState();
@ -71,17 +74,52 @@ class _InstalledAppItemState extends State<InstalledAppItem> {
), ),
), ),
Wrap( Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: [ children: [
I18nText( Material(
'suggested', color: Theme.of(context).colorScheme.secondaryContainer,
translationParams: { borderRadius:
'version': widget.suggestedVersion.isEmpty const BorderRadius.all(Radius.circular(8)),
? FlutterI18n.translate( child: InkWell(
context, onTap: widget.onLinkTap,
'appSelectorCard.allVersions', borderRadius:
) const BorderRadius.all(Radius.circular(8)),
: 'v${widget.suggestedVersion}', child: Container(
}, padding: const EdgeInsets.all(4),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
I18nText(
'suggested',
translationParams: {
'version': widget.suggestedVersion.isEmpty
? FlutterI18n.translate(
context,
'appSelectorCard.allVersions',
)
: 'v${widget.suggestedVersion}',
},
child: Text(
'',
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onSecondaryContainer,
),
),
),
const SizedBox(width: 4),
Icon(
Icons.search,
size: 16,
color: Theme.of(context)
.colorScheme
.onSecondaryContainer,
),
],
),
),
),
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(

View File

@ -9,11 +9,14 @@ class NotInstalledAppItem extends StatefulWidget {
required this.patchesCount, required this.patchesCount,
required this.suggestedVersion, required this.suggestedVersion,
this.onTap, this.onTap,
this.onLinkTap,
}); });
final String name; final String name;
final int patchesCount; final int patchesCount;
final String suggestedVersion; final String suggestedVersion;
final Function()? onTap; final Function()? onTap;
final Function()? onLinkTap;
@override @override
State<NotInstalledAppItem> createState() => _NotInstalledAppItem(); State<NotInstalledAppItem> createState() => _NotInstalledAppItem();
@ -65,17 +68,52 @@ class _NotInstalledAppItem extends State<NotInstalledAppItem> {
), ),
), ),
Wrap( Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: [ children: [
I18nText( Material(
'suggested', color: Theme.of(context).colorScheme.secondaryContainer,
translationParams: { borderRadius:
'version': widget.suggestedVersion.isEmpty const BorderRadius.all(Radius.circular(8)),
? FlutterI18n.translate( child: InkWell(
context, onTap: widget.onLinkTap,
'appSelectorCard.allVersions', borderRadius:
) const BorderRadius.all(Radius.circular(8)),
: 'v${widget.suggestedVersion}', child: Container(
}, padding: const EdgeInsets.all(4),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
I18nText(
'suggested',
translationParams: {
'version': widget.suggestedVersion.isEmpty
? FlutterI18n.translate(
context,
'appSelectorCard.allVersions',
)
: 'v${widget.suggestedVersion}',
},
child: Text(
'',
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onSecondaryContainer,
),
),
),
const SizedBox(width: 4),
Icon(
Icons.search,
size: 16,
color: Theme.of(context)
.colorScheme
.onSecondaryContainer,
),
],
),
),
),
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(

View File

@ -10,6 +10,7 @@ class AppSelectorCard extends StatelessWidget {
super.key, super.key,
required this.onPressed, required this.onPressed,
}); });
final Function() onPressed; final Function() onPressed;
@override @override
@ -61,11 +62,52 @@ class AppSelectorCard extends StatelessWidget {
Container() Container()
else else
Column( Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
locator<PatcherViewModel>() locator<PatcherViewModel>().getCurrentVersionString(context),
.getSuggestedVersionString(context), ),
Row(
children: [
Material(
color: Theme.of(context).colorScheme.secondaryContainer,
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: InkWell(
onTap: () {
locator<PatcherViewModel>()
.searchSuggestedVersionOnWeb();
},
borderRadius:
const BorderRadius.all(Radius.circular(8)),
child: Container(
padding: const EdgeInsets.all(4),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
locator<PatcherViewModel>()
.getSuggestedVersionString(context),
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onSecondaryContainer,
),
),
const SizedBox(width: 4),
Icon(
Icons.search,
size: 16,
color: Theme.of(context)
.colorScheme
.onSecondaryContainer,
),
],
),
),
),
),
],
), ),
], ],
), ),