mirror of
https://github.com/revanced/revanced-manager
synced 2024-05-14 13:56:57 +02:00
feat: Add custom patches sources
This commit is contained in:
parent
10fbbe845e
commit
78317223cc
@ -57,13 +57,6 @@
|
|||||||
"widgetTitle": "Social Media",
|
"widgetTitle": "Social Media",
|
||||||
"widgetSubtitle": "We are online!"
|
"widgetSubtitle": "We are online!"
|
||||||
},
|
},
|
||||||
"sourcesCard": {
|
|
||||||
"widgetTitle": "Sources",
|
|
||||||
"widgetSubtitle": "Add your custom sources",
|
|
||||||
"organizationLabel": "Organization",
|
|
||||||
"patchesSourceLabel" : "Patches Source",
|
|
||||||
"integrationsSourceLabel": "Integrations Source"
|
|
||||||
},
|
|
||||||
"appSelectorView": {
|
"appSelectorView": {
|
||||||
"searchBarHint": "Search applications",
|
"searchBarHint": "Search applications",
|
||||||
"storageButton": "Storage",
|
"storageButton": "Storage",
|
||||||
@ -102,6 +95,12 @@
|
|||||||
"languageLabel": "Language",
|
"languageLabel": "Language",
|
||||||
"englishOption": "English",
|
"englishOption": "English",
|
||||||
"frenchOption": "French",
|
"frenchOption": "French",
|
||||||
|
"sourcesLabel": "Sources",
|
||||||
|
"sourcesLabelHint": "Add your custom sources",
|
||||||
|
"orgPatchesLabel" : "Patches Org",
|
||||||
|
"sourcesPatchesLabel" : "Patches Source",
|
||||||
|
"orgIntegrationsLabel": "Integrations Org",
|
||||||
|
"sourcesIntegrationsLabel": "Integrations Source",
|
||||||
"contributorsLabel": "Contributors",
|
"contributorsLabel": "Contributors",
|
||||||
"contributorsHint": "A list of contributors of ReVanced",
|
"contributorsHint": "A list of contributors of ReVanced",
|
||||||
"aboutLabel": "About",
|
"aboutLabel": "About",
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
String ghOrg = 'revanced';
|
|
||||||
String patchesRepo = 'revanced-patches';
|
|
||||||
String integrationsRepo = 'revanced-integrations';
|
|
||||||
const String patcherRepo = 'revanced-patcher';
|
|
||||||
const String cliRepo = 'revanced-cli';
|
|
||||||
const String managerRepo = 'revanced-manager';
|
|
@ -4,7 +4,6 @@ import 'package:device_apps/device_apps.dart';
|
|||||||
import 'package:github/github.dart';
|
import 'package:github/github.dart';
|
||||||
import 'package:injectable/injectable.dart';
|
import 'package:injectable/injectable.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:revanced_manager/constants.dart';
|
|
||||||
import 'package:revanced_manager/models/patched_application.dart';
|
import 'package:revanced_manager/models/patched_application.dart';
|
||||||
import 'package:revanced_manager/services/github_api.dart';
|
import 'package:revanced_manager/services/github_api.dart';
|
||||||
import 'package:revanced_manager/services/root_api.dart';
|
import 'package:revanced_manager/services/root_api.dart';
|
||||||
@ -14,34 +13,78 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
class ManagerAPI {
|
class ManagerAPI {
|
||||||
final GithubAPI _githubAPI = GithubAPI();
|
final GithubAPI _githubAPI = GithubAPI();
|
||||||
final RootAPI _rootAPI = RootAPI();
|
final RootAPI _rootAPI = RootAPI();
|
||||||
|
final String patcherRepo = 'revanced-patcher';
|
||||||
|
final String cliRepo = 'revanced-cli';
|
||||||
late SharedPreferences _prefs;
|
late SharedPreferences _prefs;
|
||||||
|
String defaultPatcherRepo = 'revanced/revanced-patcher';
|
||||||
|
String defaultPatchesRepo = 'revanced/revanced-patches';
|
||||||
|
String defaultIntegrationsRepo = 'revanced/revanced-integrations';
|
||||||
|
String defaultCliRepo = 'revanced/revanced-cli';
|
||||||
|
String defaultManagerRepo = 'revanced/revanced-manager';
|
||||||
|
|
||||||
Future<void> initialize() async {
|
Future<void> initialize() async {
|
||||||
_prefs = await SharedPreferences.getInstance();
|
_prefs = await SharedPreferences.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getPatcherRepo() {
|
||||||
|
return defaultPatcherRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPatchesRepo() {
|
||||||
|
return _prefs.getString('patchesRepo') ?? defaultPatchesRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setPatchesRepo(String value) async {
|
||||||
|
if (value.isEmpty) {
|
||||||
|
value = defaultPatchesRepo;
|
||||||
|
}
|
||||||
|
await _prefs.setString('patchesRepo', value);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getIntegrationsRepo() {
|
||||||
|
return _prefs.getString('integrationsRepo') ?? defaultIntegrationsRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setIntegrationsRepo(String value) async {
|
||||||
|
if (value.isEmpty) {
|
||||||
|
value = defaultIntegrationsRepo;
|
||||||
|
}
|
||||||
|
await _prefs.setString('integrationsRepo', value);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getCliRepo() {
|
||||||
|
return defaultCliRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getManagerRepo() {
|
||||||
|
return _prefs.getString('managerRepo') ?? defaultManagerRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setManagerRepo(String value) async {
|
||||||
|
if (value.isEmpty) {
|
||||||
|
value = defaultManagerRepo;
|
||||||
|
}
|
||||||
|
await _prefs.setString('managerRepo', value);
|
||||||
|
}
|
||||||
|
|
||||||
Future<File?> downloadPatches(String extension) async {
|
Future<File?> downloadPatches(String extension) async {
|
||||||
return await _githubAPI.latestReleaseFile(extension, ghOrg, patchesRepo);
|
return await _githubAPI.latestReleaseFile(extension, getPatchesRepo());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> downloadIntegrations(String extension) async {
|
Future<File?> downloadIntegrations(String extension) async {
|
||||||
return await _githubAPI.latestReleaseFile(
|
return await _githubAPI.latestReleaseFile(extension, getIntegrationsRepo());
|
||||||
extension,
|
|
||||||
ghOrg,
|
|
||||||
integrationsRepo,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<File?> downloadManager(String extension) async {
|
Future<File?> downloadManager(String extension) async {
|
||||||
return await _githubAPI.latestReleaseFile(extension, ghOrg, managerRepo);
|
return await _githubAPI.latestReleaseFile(extension, getManagerRepo());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> getLatestPatchesVersion() async {
|
Future<String?> getLatestPatchesVersion() async {
|
||||||
return await _githubAPI.latestReleaseVersion(ghOrg, patchesRepo);
|
return await _githubAPI.latestReleaseVersion(getPatchesRepo());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> getLatestManagerVersion() async {
|
Future<String?> getLatestManagerVersion() async {
|
||||||
return await _githubAPI.latestReleaseVersion(ghOrg, managerRepo);
|
return await _githubAPI.latestReleaseVersion(getManagerRepo());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getCurrentManagerVersion() async {
|
Future<String> getCurrentManagerVersion() async {
|
||||||
@ -140,8 +183,10 @@ class ManagerAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> hasAppUpdates(String packageName, DateTime patchDate) async {
|
Future<bool> hasAppUpdates(String packageName, DateTime patchDate) async {
|
||||||
List<RepositoryCommit> commits =
|
List<RepositoryCommit> commits = await _githubAPI.getCommits(
|
||||||
await _githubAPI.getCommits(packageName, ghOrg, patchesRepo);
|
packageName,
|
||||||
|
getPatchesRepo(),
|
||||||
|
);
|
||||||
return commits.any((c) =>
|
return commits.any((c) =>
|
||||||
c.commit != null &&
|
c.commit != null &&
|
||||||
c.commit!.author != null &&
|
c.commit!.author != null &&
|
||||||
@ -153,8 +198,10 @@ class ManagerAPI {
|
|||||||
String packageName,
|
String packageName,
|
||||||
DateTime patchDate,
|
DateTime patchDate,
|
||||||
) async {
|
) async {
|
||||||
List<RepositoryCommit> commits =
|
List<RepositoryCommit> commits = await _githubAPI.getCommits(
|
||||||
await _githubAPI.getCommits(packageName, ghOrg, patchesRepo);
|
packageName,
|
||||||
|
getPatchesRepo(),
|
||||||
|
);
|
||||||
List<String> newCommits = commits
|
List<String> newCommits = commits
|
||||||
.where((c) =>
|
.where((c) =>
|
||||||
c.commit != null &&
|
c.commit != null &&
|
||||||
|
@ -1,36 +1,33 @@
|
|||||||
import 'package:github/github.dart';
|
import 'package:github/github.dart';
|
||||||
import 'package:revanced_manager/constants.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/services/github_api.dart';
|
import 'package:revanced_manager/services/github_api.dart';
|
||||||
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
class ContributorsViewModel extends BaseViewModel {
|
class ContributorsViewModel extends BaseViewModel {
|
||||||
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
final GithubAPI _githubAPI = GithubAPI();
|
final GithubAPI _githubAPI = GithubAPI();
|
||||||
|
List<Contributor> patcherContributors = [];
|
||||||
List<Contributor> patchesContributors = [];
|
List<Contributor> patchesContributors = [];
|
||||||
List<Contributor> integrationsContributors = [];
|
List<Contributor> integrationsContributors = [];
|
||||||
List<Contributor> patcherContributors = [];
|
|
||||||
List<Contributor> cliContributors = [];
|
List<Contributor> cliContributors = [];
|
||||||
List<Contributor> managerContributors = [];
|
List<Contributor> managerContributors = [];
|
||||||
|
|
||||||
Future<void> getContributors() async {
|
Future<void> getContributors() async {
|
||||||
|
patcherContributors = await _githubAPI.getContributors(
|
||||||
|
_managerAPI.getPatcherRepo(),
|
||||||
|
);
|
||||||
patchesContributors = await _githubAPI.getContributors(
|
patchesContributors = await _githubAPI.getContributors(
|
||||||
ghOrg,
|
_managerAPI.getPatchesRepo(),
|
||||||
patchesRepo,
|
|
||||||
);
|
);
|
||||||
integrationsContributors = await _githubAPI.getContributors(
|
integrationsContributors = await _githubAPI.getContributors(
|
||||||
ghOrg,
|
_managerAPI.getIntegrationsRepo(),
|
||||||
integrationsRepo,
|
|
||||||
);
|
|
||||||
patcherContributors = await _githubAPI.getContributors(
|
|
||||||
ghOrg,
|
|
||||||
patcherRepo,
|
|
||||||
);
|
);
|
||||||
cliContributors = await _githubAPI.getContributors(
|
cliContributors = await _githubAPI.getContributors(
|
||||||
ghOrg,
|
_managerAPI.getCliRepo(),
|
||||||
cliRepo,
|
|
||||||
);
|
);
|
||||||
managerContributors = await _githubAPI.getContributors(
|
managerContributors = await _githubAPI.getContributors(
|
||||||
ghOrg,
|
_managerAPI.getManagerRepo(),
|
||||||
managerRepo,
|
|
||||||
);
|
);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ class NavigationViewModel extends IndexTrackingViewModel {
|
|||||||
case 1:
|
case 1:
|
||||||
return const PatcherView();
|
return const PatcherView();
|
||||||
case 2:
|
case 2:
|
||||||
return SettingsView();
|
return const SettingsView();
|
||||||
default:
|
default:
|
||||||
return const HomeView();
|
return const HomeView();
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,11 @@ import 'package:revanced_manager/ui/widgets/settingsView/custom_switch_tile.dart
|
|||||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_tile_dialog.dart';
|
import 'package:revanced_manager/ui/widgets/settingsView/settings_tile_dialog.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
|
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/social_media_widget.dart';
|
import 'package:revanced_manager/ui/widgets/settingsView/social_media_widget.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/sources_widget.dart';
|
|
||||||
import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart';
|
import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
|
|
||||||
class SettingsView extends StatelessWidget {
|
class SettingsView extends StatelessWidget {
|
||||||
final TextEditingController organizationController = TextEditingController();
|
const SettingsView({Key? key}) : super(key: key);
|
||||||
final TextEditingController patchesSourceController = TextEditingController();
|
|
||||||
final TextEditingController integrationsSourceController =
|
|
||||||
TextEditingController();
|
|
||||||
|
|
||||||
SettingsView({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -87,38 +81,18 @@ class SettingsView extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SettingsTileDialog(
|
SettingsTileDialog(
|
||||||
title: 'settingsView.languageLabel',
|
title: 'settingsView.languageLabel',
|
||||||
subtitle: 'English',
|
subtitle: 'English',
|
||||||
children: <Widget>[
|
onTap: () => model.showLanguagesDialog(context),
|
||||||
RadioListTile<String>(
|
),
|
||||||
title: I18nText('settingsView.englishOption'),
|
|
||||||
value: 'en',
|
|
||||||
groupValue: 'en',
|
|
||||||
onChanged: (value) {
|
|
||||||
model.updateLanguage(context, value);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RadioListTile<String>(
|
|
||||||
title: I18nText('settingsView.frenchOption'),
|
|
||||||
value: 'fr',
|
|
||||||
groupValue: 'en',
|
|
||||||
onChanged: (value) {
|
|
||||||
model.updateLanguage(context, value);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
const Divider(thickness: 1.0),
|
const Divider(thickness: 1.0),
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
title: 'settingsView.patcherSectionTitle',
|
title: 'settingsView.patcherSectionTitle',
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
SourcesWidget(
|
SettingsTileDialog(
|
||||||
title: 'settingsView.sourcesLabel',
|
title: 'settingsView.sourcesLabel',
|
||||||
organizationController: organizationController,
|
subtitle: 'settingsView.sourcesLabelHint',
|
||||||
patchesSourceController: patchesSourceController,
|
onTap: () => model.showSourcesDialog(context),
|
||||||
integrationsSourceController:
|
|
||||||
integrationsSourceController,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -3,9 +3,12 @@
|
|||||||
import 'package:dynamic_themes/dynamic_themes.dart';
|
import 'package:dynamic_themes/dynamic_themes.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:revanced_manager/app/app.locator.dart';
|
import 'package:revanced_manager/app/app.locator.dart';
|
||||||
import 'package:revanced_manager/app/app.router.dart';
|
import 'package:revanced_manager/app/app.router.dart';
|
||||||
import 'package:revanced_manager/services/manager_api.dart';
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
|
import 'package:revanced_manager/ui/widgets/installerView/custom_material_button.dart';
|
||||||
|
import 'package:revanced_manager/ui/widgets/settingsView/custom_text_field.dart';
|
||||||
import 'package:stacked/stacked.dart';
|
import 'package:stacked/stacked.dart';
|
||||||
import 'package:stacked_services/stacked_services.dart';
|
import 'package:stacked_services/stacked_services.dart';
|
||||||
import 'package:timeago/timeago.dart';
|
import 'package:timeago/timeago.dart';
|
||||||
@ -13,6 +16,10 @@ import 'package:timeago/timeago.dart';
|
|||||||
class SettingsViewModel extends BaseViewModel {
|
class SettingsViewModel extends BaseViewModel {
|
||||||
final NavigationService _navigationService = locator<NavigationService>();
|
final NavigationService _navigationService = locator<NavigationService>();
|
||||||
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
|
final TextEditingController _orgPatSourceController = TextEditingController();
|
||||||
|
final TextEditingController _patSourceController = TextEditingController();
|
||||||
|
final TextEditingController _orgIntSourceController = TextEditingController();
|
||||||
|
final TextEditingController _intSourceController = TextEditingController();
|
||||||
|
|
||||||
void setLanguage(String language) {
|
void setLanguage(String language) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -58,4 +65,115 @@ class SettingsViewModel extends BaseViewModel {
|
|||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> showLanguagesDialog(BuildContext context) {
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => SimpleDialog(
|
||||||
|
title: I18nText('settingsView.languageLabel'),
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
|
children: <Widget>[
|
||||||
|
RadioListTile<String>(
|
||||||
|
title: I18nText('settingsView.englishOption'),
|
||||||
|
value: 'en',
|
||||||
|
groupValue: 'en',
|
||||||
|
onChanged: (value) {
|
||||||
|
updateLanguage(context, value);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> showSourcesDialog(BuildContext context) async {
|
||||||
|
String patchesRepo = _managerAPI.getPatchesRepo();
|
||||||
|
String integrationsRepo = _managerAPI.getIntegrationsRepo();
|
||||||
|
_orgPatSourceController.text = patchesRepo.split('/')[0];
|
||||||
|
_patSourceController.text = patchesRepo.split('/')[1];
|
||||||
|
_orgIntSourceController.text = integrationsRepo.split('/')[0];
|
||||||
|
_intSourceController.text = integrationsRepo.split('/')[1];
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: I18nText('settingsView.sourcesLabel'),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
CustomTextField(
|
||||||
|
leadingIcon: Icon(
|
||||||
|
Icons.extension_outlined,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
inputController: _orgPatSourceController,
|
||||||
|
label: I18nText('settingsView.orgPatchesLabel'),
|
||||||
|
hint: patchesRepo.split('/')[0],
|
||||||
|
onChanged: (value) => notifyListeners(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
CustomTextField(
|
||||||
|
leadingIcon: const Icon(
|
||||||
|
Icons.extension_outlined,
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
inputController: _patSourceController,
|
||||||
|
label: I18nText('settingsView.sourcesPatchesLabel'),
|
||||||
|
hint: patchesRepo.split('/')[1],
|
||||||
|
onChanged: (value) => notifyListeners(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
CustomTextField(
|
||||||
|
leadingIcon: Icon(
|
||||||
|
Icons.merge_outlined,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
inputController: _orgIntSourceController,
|
||||||
|
label: I18nText('settingsView.orgIntegrationsLabel'),
|
||||||
|
hint: integrationsRepo.split('/')[0],
|
||||||
|
onChanged: (value) => notifyListeners(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
CustomTextField(
|
||||||
|
leadingIcon: const Icon(
|
||||||
|
Icons.merge_outlined,
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
inputController: _intSourceController,
|
||||||
|
label: I18nText('settingsView.sourcesIntegrationsLabel'),
|
||||||
|
hint: integrationsRepo.split('/')[1],
|
||||||
|
onChanged: (value) => notifyListeners(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
CustomMaterialButton(
|
||||||
|
isFilled: false,
|
||||||
|
label: I18nText('cancelButton'),
|
||||||
|
onPressed: () {
|
||||||
|
_orgPatSourceController.clear();
|
||||||
|
_patSourceController.clear();
|
||||||
|
_orgIntSourceController.clear();
|
||||||
|
_intSourceController.clear();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CustomMaterialButton(
|
||||||
|
label: I18nText('okButton'),
|
||||||
|
onPressed: () {
|
||||||
|
_managerAPI.setPatchesRepo(
|
||||||
|
'${_orgPatSourceController.text}/${_patSourceController.text}',
|
||||||
|
);
|
||||||
|
_managerAPI.setIntegrationsRepo(
|
||||||
|
'${_orgIntSourceController.text}/${_intSourceController.text}',
|
||||||
|
);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import 'package:flutter/material.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';
|
||||||
import 'package:revanced_manager/services/github_api.dart';
|
import 'package:revanced_manager/services/github_api.dart';
|
||||||
import 'package:revanced_manager/constants.dart';
|
import 'package:revanced_manager/services/manager_api.dart';
|
||||||
import 'package:revanced_manager/ui/views/home/home_viewmodel.dart';
|
import 'package:revanced_manager/ui/views/home/home_viewmodel.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/installerView/custom_material_button.dart';
|
import 'package:revanced_manager/ui/widgets/installerView/custom_material_button.dart';
|
||||||
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
|
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
|
||||||
@ -20,6 +20,7 @@ class LatestCommitCard extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _LatestCommitCardState extends State<LatestCommitCard> {
|
class _LatestCommitCardState extends State<LatestCommitCard> {
|
||||||
|
final ManagerAPI _managerAPI = locator<ManagerAPI>();
|
||||||
final GithubAPI _githubAPI = GithubAPI();
|
final GithubAPI _githubAPI = GithubAPI();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -41,7 +42,9 @@ class _LatestCommitCardState extends State<LatestCommitCard> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
FutureBuilder<String>(
|
FutureBuilder<String>(
|
||||||
future: _githubAPI.latestCommitTime(ghOrg, patcherRepo),
|
future: _githubAPI.latestCommitTime(
|
||||||
|
_managerAPI.getPatcherRepo(),
|
||||||
|
),
|
||||||
builder: (context, snapshot) => Text(
|
builder: (context, snapshot) => Text(
|
||||||
snapshot.hasData && snapshot.data!.isNotEmpty
|
snapshot.hasData && snapshot.data!.isNotEmpty
|
||||||
? FlutterI18n.translate(
|
? FlutterI18n.translate(
|
||||||
@ -68,7 +71,9 @@ class _LatestCommitCardState extends State<LatestCommitCard> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
FutureBuilder<String>(
|
FutureBuilder<String>(
|
||||||
future: _githubAPI.latestCommitTime(ghOrg, managerRepo),
|
future: _githubAPI.latestCommitTime(
|
||||||
|
_managerAPI.getManagerRepo(),
|
||||||
|
),
|
||||||
builder: (context, snapshot) =>
|
builder: (context, snapshot) =>
|
||||||
snapshot.hasData && snapshot.data!.isNotEmpty
|
snapshot.hasData && snapshot.data!.isNotEmpty
|
||||||
? I18nText(
|
? I18nText(
|
||||||
|
@ -4,6 +4,7 @@ class CustomTextField extends StatelessWidget {
|
|||||||
final TextEditingController inputController;
|
final TextEditingController inputController;
|
||||||
final Widget label;
|
final Widget label;
|
||||||
final String hint;
|
final String hint;
|
||||||
|
final Widget? leadingIcon;
|
||||||
final Function(String)? onChanged;
|
final Function(String)? onChanged;
|
||||||
|
|
||||||
const CustomTextField({
|
const CustomTextField({
|
||||||
@ -11,60 +12,59 @@ class CustomTextField extends StatelessWidget {
|
|||||||
required this.inputController,
|
required this.inputController,
|
||||||
required this.label,
|
required this.label,
|
||||||
required this.hint,
|
required this.hint,
|
||||||
|
this.leadingIcon,
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Padding(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
padding: const EdgeInsets.only(top: 4.0),
|
||||||
children: <Widget>[
|
child: TextField(
|
||||||
const SizedBox(height: 8),
|
controller: inputController,
|
||||||
TextField(
|
onChanged: onChanged,
|
||||||
controller: inputController,
|
keyboardType: TextInputType.text,
|
||||||
onChanged: onChanged,
|
decoration: InputDecoration(
|
||||||
keyboardType: TextInputType.text,
|
icon: leadingIcon,
|
||||||
decoration: InputDecoration(
|
label: label,
|
||||||
label: label,
|
filled: true,
|
||||||
filled: true,
|
fillColor: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
fillColor: Theme.of(context).colorScheme.secondaryContainer,
|
hintText: hint,
|
||||||
hintText: hint,
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
vertical: 8.0,
|
||||||
vertical: 0.0,
|
horizontal: 16.0,
|
||||||
horizontal: 20.0,
|
),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
width: 1.0,
|
||||||
),
|
),
|
||||||
border: OutlineInputBorder(
|
borderRadius: BorderRadius.circular(10),
|
||||||
borderSide: BorderSide(
|
gapPadding: 4.0,
|
||||||
color: Theme.of(context).colorScheme.primary,
|
),
|
||||||
width: 1.0,
|
focusedBorder: OutlineInputBorder(
|
||||||
),
|
borderSide: BorderSide(
|
||||||
borderRadius: BorderRadius.circular(10),
|
color: Theme.of(context).colorScheme.primary,
|
||||||
gapPadding: 4.0,
|
width: 2.0,
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
borderRadius: BorderRadius.circular(10),
|
||||||
borderSide: BorderSide(
|
),
|
||||||
color: Theme.of(context).colorScheme.primary,
|
errorBorder: OutlineInputBorder(
|
||||||
width: 2.0,
|
borderSide: BorderSide(
|
||||||
),
|
color: Theme.of(context).colorScheme.error,
|
||||||
borderRadius: BorderRadius.circular(10),
|
width: 1.0,
|
||||||
),
|
),
|
||||||
errorBorder: OutlineInputBorder(
|
borderRadius: BorderRadius.circular(10),
|
||||||
borderSide: const BorderSide(
|
),
|
||||||
color: Colors.red,
|
enabledBorder: OutlineInputBorder(
|
||||||
width: 1.0,
|
borderSide: BorderSide(
|
||||||
),
|
color: Theme.of(context).colorScheme.primary,
|
||||||
borderRadius: BorderRadius.circular(10),
|
width: 1.0,
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderSide: BorderSide(
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
width: 1.0,
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ import 'package:flutter_i18n/flutter_i18n.dart';
|
|||||||
class SettingsTileDialog extends StatelessWidget {
|
class SettingsTileDialog extends StatelessWidget {
|
||||||
final String title;
|
final String title;
|
||||||
final String subtitle;
|
final String subtitle;
|
||||||
final List<Widget> children;
|
final Function()? onTap;
|
||||||
|
|
||||||
const SettingsTileDialog({
|
const SettingsTileDialog({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.subtitle,
|
required this.subtitle,
|
||||||
required this.children,
|
required this.onTap,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -28,14 +28,7 @@ class SettingsTileDialog extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
subtitle: I18nText(subtitle),
|
subtitle: I18nText(subtitle),
|
||||||
onTap: () => showDialog(
|
onTap: onTap,
|
||||||
context: context,
|
|
||||||
builder: (context) => SimpleDialog(
|
|
||||||
title: I18nText(title),
|
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
|
||||||
children: children,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
import 'package:expandable/expandable.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
|
||||||
import 'package:revanced_manager/constants.dart';
|
|
||||||
import 'package:revanced_manager/ui/widgets/settingsView/custom_text_field.dart';
|
|
||||||
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
|
|
||||||
|
|
||||||
class SourcesWidget extends StatelessWidget {
|
|
||||||
final String title;
|
|
||||||
final TextEditingController organizationController;
|
|
||||||
final TextEditingController patchesSourceController;
|
|
||||||
final TextEditingController integrationsSourceController;
|
|
||||||
|
|
||||||
const SourcesWidget({
|
|
||||||
Key? key,
|
|
||||||
required this.title,
|
|
||||||
required this.organizationController,
|
|
||||||
required this.patchesSourceController,
|
|
||||||
required this.integrationsSourceController,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ExpandablePanel(
|
|
||||||
theme: ExpandableThemeData(
|
|
||||||
hasIcon: true,
|
|
||||||
iconColor: Theme.of(context).iconTheme.color,
|
|
||||||
iconPadding: const EdgeInsets.symmetric(vertical: 16.0),
|
|
||||||
animationDuration: const Duration(milliseconds: 400),
|
|
||||||
),
|
|
||||||
header: ListTile(
|
|
||||||
contentPadding: EdgeInsets.zero,
|
|
||||||
title: I18nText(
|
|
||||||
'sourcesCard.widgetTitle',
|
|
||||||
child: const Text(
|
|
||||||
'',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
subtitle: I18nText('sourcesCard.widgetSubtitle'),
|
|
||||||
),
|
|
||||||
expanded: CustomCard(
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
CustomTextField(
|
|
||||||
inputController: organizationController,
|
|
||||||
label: I18nText('sourcesCard.organizationLabel'),
|
|
||||||
hint: ghOrg,
|
|
||||||
onChanged: (value) => ghOrg = value,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
CustomTextField(
|
|
||||||
inputController: patchesSourceController,
|
|
||||||
label: I18nText('sourcesCard.patchesSourceLabel'),
|
|
||||||
hint: patchesRepo,
|
|
||||||
onChanged: (value) => patchesRepo = value,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
CustomTextField(
|
|
||||||
inputController: integrationsSourceController,
|
|
||||||
label: I18nText('sourcesCard.integrationsSourceLabel'),
|
|
||||||
hint: integrationsRepo,
|
|
||||||
onChanged: (value) => integrationsRepo = value,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
collapsed: Container(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user