Compare commits
10 Commits
v0.10.5-be
...
v0.10.6-be
Author | SHA1 | Date | |
---|---|---|---|
eef4d33431 | |||
d56342e907 | |||
c72c0fdb57 | |||
ffe29009ed | |||
60e3b68ebd | |||
ee4d0f259f | |||
0ecfbef0a0 | |||
1b60e75ca7 | |||
abcfa389e8 | |||
a64bd67ef1 |
@ -31,4 +31,4 @@ Currently supported App sources:
|
||||
|
||||
| <img src="./assets/screenshots/1.apps.png" alt="Apps Page" /> | <img src="./assets/screenshots/2.dark_theme.png" alt="Dark Theme" /> | <img src="./assets/screenshots/3.material_you.png" alt="Material You" /> |
|
||||
| ------------------------------------------------------ | ----------------------------------------------------------------------- | -------------------------------------------------------------------- |
|
||||
| <img src="./assets/screenshots/4.app.png" alt="App Page" /> | <img src="./assets/screenshots/5.apk_picker.png" alt="Multiple APK Support" /> | <img src="./assets/screenshots/6.apk_install.png" alt="App Installation" /> |
|
||||
| <img src="./assets/screenshots/4.app.png" alt="App Page" /> | <img src="./assets/screenshots/5.app_opts.png" alt="App Options" /> | <img src="./assets/screenshots/6.app_webview.png" alt="App Web View" /> |
|
||||
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 238 KiB |
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 188 KiB |
BIN
assets/screenshots/5.app_opts.png
Normal file
After Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 192 KiB |
BIN
assets/screenshots/6.app_webview.png
Normal file
After Width: | Height: | Size: 262 KiB |
@ -7,7 +7,7 @@
|
||||
"appIdMismatch": "ダウンロードしたパッケージのIDが既存のApp IDと一致しません",
|
||||
"functionNotImplemented": "このクラスはこの機能を実装していません",
|
||||
"placeholder": "プレースホルダー",
|
||||
"someErrors": "いくつかのエラーが発生しました",
|
||||
"someErrors": "何らかのエラーが発生しました",
|
||||
"unexpectedError": "予期せぬエラーが発生しました",
|
||||
"ok": "OK",
|
||||
"and": "と",
|
||||
@ -82,7 +82,7 @@
|
||||
"pinToTop": "トップに固定",
|
||||
"unpinFromTop": "トップから固定解除",
|
||||
"resetInstallStatusForSelectedAppsQuestion": "選択したアプリのインストール状態をリセットしますか?",
|
||||
"installStatusOfXWillBeResetExplanation": "選択したアプリのインストール状態がリセットされます。\n\nアップデートに失敗するなどして、Obtainiumに表示されるアプリのバージョンが正しくない場合に役立ちます。",
|
||||
"installStatusOfXWillBeResetExplanation": "選択したアプリのインストール状態がリセットされます。\n\nアップデートに失敗した場合など、Obtainiumに表示されるアプリのバージョンが正しくない場合に有効です。",
|
||||
"shareSelectedAppURLs": "選択したアプリのURLを共有する",
|
||||
"resetInstallStatus": "インストール状態をリセットする",
|
||||
"more": "もっと見る",
|
||||
@ -109,7 +109,7 @@
|
||||
"searchX": "{}で検索",
|
||||
"noResults": "結果は見つかりませんでした",
|
||||
"importX": "{}をインポートする",
|
||||
"importedAppsIdDisclaimer": "インポートしたアプリが「未インストール」と表示されることがあります。\nこれを解決するには、Obtainiumから再インストールしてください。\nアプリのデータには影響しません。\n\nURLとサードパーティーのインポートメソッドにのみ影響します。",
|
||||
"importedAppsIdDisclaimer": "インポートしたアプリが「未インストール」と表示されることがあります。\nこれを解決するには、Obtainiumから再インストールしてください。\nアプリのデータには影響しません。\n\nURLとサードパーティのインポートメソッドにのみ影響します。",
|
||||
"importErrors": "インポートエラー",
|
||||
"importedXOfYApps": "{} / {} アプリをインポートしました",
|
||||
"followingURLsHadErrors": "以下のURLでエラーが発生しました:",
|
||||
@ -133,7 +133,7 @@
|
||||
"bgUpdateCheckInterval": "バックグラウンドでのアップデート確認の間隔",
|
||||
"neverManualOnly": "手動",
|
||||
"appearance": "外観",
|
||||
"showWebInAppView": "アプリビューにソースウェブページを表示する",
|
||||
"showWebInAppView": "アプリページにソースのWebページを表示する",
|
||||
"pinUpdates": "アップデートがあるアプリをトップに固定する",
|
||||
"updates": "アップデート",
|
||||
"sourceSpecific": "Github アクセストークン",
|
||||
@ -184,7 +184,7 @@
|
||||
"appIdOrName": "アプリのIDまたは名前",
|
||||
"appWithIdOrNameNotFound": "そのIDや名前を持つアプリは見つかりませんでした",
|
||||
"reposHaveMultipleApps": "リポジトリには複数のアプリが含まれることがあります",
|
||||
"fdroidThirdPartyRepo": "F-Droid Third-Party Repo",
|
||||
"fdroidThirdPartyRepo": "F-Droid サードパーティリポジトリ",
|
||||
"steam": "Steam",
|
||||
"steamMobile": "Steam Mobile",
|
||||
"steamChat": "Steam Chat",
|
||||
@ -211,7 +211,7 @@
|
||||
"language": "言語",
|
||||
"storagePermissionDenied": "ストレージ権限が拒否されました",
|
||||
"selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。",
|
||||
"filterAPKsByRegEx": "Filter APKs by Regular Expression",
|
||||
"filterAPKsByRegEx": "正規表現でAPKを絞り込む",
|
||||
"tooManyRequestsTryAgainInMinutes": {
|
||||
"one": "リクエストが多すぎます(レート制限)- {}分後に再試行してください",
|
||||
"other": "リクエストが多すぎます(レート制限)- {}分後に再試行してください"
|
||||
|
@ -150,6 +150,7 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
||||
Map<String, dynamic> values = {};
|
||||
late List<List<Widget>> formInputs;
|
||||
List<List<Widget>> rows = [];
|
||||
String? initKey;
|
||||
|
||||
// If any value changes, call this to update the parent with value and validity
|
||||
void someValueChanged({bool isBuilding = false}) {
|
||||
@ -169,13 +170,10 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
||||
widget.onValueChanges(returnValues, valid, isBuilding);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
initForm() {
|
||||
initKey = widget.key.toString();
|
||||
// Initialize form values as all empty
|
||||
values.clear();
|
||||
int j = 0;
|
||||
for (var row in widget.items) {
|
||||
for (var e in row) {
|
||||
values[e.key] = e.defaultValue;
|
||||
@ -245,8 +243,17 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
||||
someValueChanged(isBuilding: true);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initForm();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.key.toString() != initKey) {
|
||||
initForm();
|
||||
}
|
||||
for (var r = 0; r < formInputs.length; r++) {
|
||||
for (var e = 0; e < formInputs[r].length; e++) {
|
||||
if (widget.items[r][e] is GeneratedFormSwitch) {
|
||||
|
@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart';
|
||||
// ignore: implementation_imports
|
||||
import 'package:easy_localization/src/localization.dart';
|
||||
|
||||
const String currentVersion = '0.10.5';
|
||||
const String currentVersion = '0.10.6';
|
||||
const String currentReleaseTag =
|
||||
'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
|
||||
|
||||
|
@ -32,6 +32,7 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
Map<String, dynamic> additionalSettings = {};
|
||||
bool additionalSettingsValid = true;
|
||||
List<String> pickedCategories = [];
|
||||
int searchnum = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -40,10 +41,14 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
|
||||
bool doingSomething = gettingAppInfo || searching;
|
||||
|
||||
changeUserInput(String input, bool valid, bool isBuilding) {
|
||||
changeUserInput(String input, bool valid, bool isBuilding,
|
||||
{bool isSearch = false}) {
|
||||
userInput = input;
|
||||
if (!isBuilding) {
|
||||
setState(() {
|
||||
if (isSearch) {
|
||||
searchnum++;
|
||||
}
|
||||
var source = valid ? sourceProvider.getSource(userInput) : null;
|
||||
if (pickedSource.runtimeType != source.runtimeType) {
|
||||
pickedSource = source;
|
||||
@ -169,30 +174,32 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: GeneratedForm(
|
||||
key: Key(searchnum.toString()),
|
||||
items: [
|
||||
[
|
||||
GeneratedFormTextField('appSourceURL',
|
||||
label: tr('appSourceURL'),
|
||||
additionalValidators: [
|
||||
(value) {
|
||||
try {
|
||||
sourceProvider
|
||||
.getSource(value ?? '')
|
||||
.standardizeURL(
|
||||
preStandardizeUrl(
|
||||
value ?? ''));
|
||||
} catch (e) {
|
||||
return e is String
|
||||
? e
|
||||
: e is ObtainiumError
|
||||
? e.toString()
|
||||
: tr('error');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
])
|
||||
]
|
||||
],
|
||||
[
|
||||
GeneratedFormTextField('appSourceURL',
|
||||
label: tr('appSourceURL'),
|
||||
defaultValue: userInput,
|
||||
additionalValidators: [
|
||||
(value) {
|
||||
try {
|
||||
sourceProvider
|
||||
.getSource(value ?? '')
|
||||
.standardizeURL(
|
||||
preStandardizeUrl(
|
||||
value ?? ''));
|
||||
} catch (e) {
|
||||
return e is String
|
||||
? e
|
||||
: e is ObtainiumError
|
||||
? e.toString()
|
||||
: tr('error');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
])
|
||||
]
|
||||
],
|
||||
onValueChanges: (values, valid, isBuilding) {
|
||||
changeUserInput(values['appSourceURL']!,
|
||||
valid, isBuilding);
|
||||
@ -296,8 +303,8 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
if (selectedUrls != null &&
|
||||
selectedUrls.isNotEmpty) {
|
||||
changeUserInput(
|
||||
selectedUrls[0], true, false);
|
||||
addApp(resetUserInputAfter: true);
|
||||
selectedUrls[0], true, false,
|
||||
isSearch: true);
|
||||
}
|
||||
}).catchError((e) {
|
||||
showError(e, context);
|
||||
@ -327,6 +334,7 @@ class _AddAppPageState extends State<AddAppPage> {
|
||||
height: 16,
|
||||
),
|
||||
GeneratedForm(
|
||||
key: Key(pickedSource.runtimeType.toString()),
|
||||
items: pickedSource!
|
||||
.combinedAppSpecificSettingFormItems,
|
||||
onValueChanges: (values, valid, isBuilding) {
|
||||
|
@ -564,18 +564,22 @@ class _UrlSelectionModalState extends State<UrlSelectionModal> {
|
||||
widget.onlyOneSelectionAllowed ? tr('selectURL') : tr('selectURLs')),
|
||||
content: Column(children: [
|
||||
...urlWithDescriptionSelections.keys.map((urlWithD) {
|
||||
select(bool? value) {
|
||||
setState(() {
|
||||
value ??= false;
|
||||
if (value! && widget.onlyOneSelectionAllowed) {
|
||||
selectOnlyOne(urlWithD.key);
|
||||
} else {
|
||||
urlWithDescriptionSelections[urlWithD] = value!;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Row(children: [
|
||||
Checkbox(
|
||||
value: urlWithDescriptionSelections[urlWithD],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
value ??= false;
|
||||
if (value! && widget.onlyOneSelectionAllowed) {
|
||||
selectOnlyOne(urlWithD.key);
|
||||
} else {
|
||||
urlWithDescriptionSelections[urlWithD] = value!;
|
||||
}
|
||||
});
|
||||
select(value);
|
||||
}),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
@ -599,12 +603,17 @@ class _UrlSelectionModalState extends State<UrlSelectionModal> {
|
||||
const TextStyle(decoration: TextDecoration.underline),
|
||||
textAlign: TextAlign.start,
|
||||
)),
|
||||
Text(
|
||||
urlWithD.value.length > 128
|
||||
? '${urlWithD.value.substring(0, 128)}...'
|
||||
: urlWithD.value,
|
||||
style: const TextStyle(
|
||||
fontStyle: FontStyle.italic, fontSize: 12),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
select(!(urlWithDescriptionSelections[urlWithD] ?? false));
|
||||
},
|
||||
child: Text(
|
||||
urlWithD.value.length > 128
|
||||
? '${urlWithD.value.substring(0, 128)}...'
|
||||
: urlWithD.value,
|
||||
style: const TextStyle(
|
||||
fontStyle: FontStyle.italic, fontSize: 12),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
|
@ -247,7 +247,11 @@ class AppsProvider with ChangeNotifier {
|
||||
!(await canDowngradeApps())) {
|
||||
throw DowngradeError();
|
||||
}
|
||||
await InstallPlugin.installApk(file.file.path, 'dev.imranr.obtainium');
|
||||
await InstallPlugin.installApk(file.file.path, obtainiumId);
|
||||
if (file.appId == obtainiumId) {
|
||||
// Obtainium prompt should be lowest
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
apps[file.appId]!.app.installedVersion =
|
||||
apps[file.appId]!.app.latestVersion;
|
||||
// Don't correct install status as installation may not be done yet
|
||||
|
@ -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
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 0.10.5+111 # When changing this, update the tag in main() accordingly
|
||||
version: 0.10.6+112 # When changing this, update the tag in main() accordingly
|
||||
|
||||
environment:
|
||||
sdk: '>=2.18.2 <3.0.0'
|
||||
|