mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-08-28 00:49:28 +02:00
Added "URLs in file (like OPML)" import
This commit is contained in:
@@ -217,6 +217,7 @@
|
|||||||
"releaseDateAsVersionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert, aber ein Veröffentlichungsdatum verfügbar ist.",
|
"releaseDateAsVersionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert, aber ein Veröffentlichungsdatum verfügbar ist.",
|
||||||
"changes": "Änderungen",
|
"changes": "Änderungen",
|
||||||
"releaseDate": "Veröffentlichungsdatum",
|
"releaseDate": "Veröffentlichungsdatum",
|
||||||
|
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "App entfernen?",
|
"one": "App entfernen?",
|
||||||
"other": "App entfernen?"
|
"other": "App entfernen?"
|
||||||
|
@@ -217,6 +217,7 @@
|
|||||||
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
||||||
"changes": "Changes",
|
"changes": "Changes",
|
||||||
"releaseDate": "Release Date",
|
"releaseDate": "Release Date",
|
||||||
|
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Remove App?",
|
"one": "Remove App?",
|
||||||
"other": "Remove Apps?"
|
"other": "Remove Apps?"
|
||||||
|
@@ -217,6 +217,7 @@
|
|||||||
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
||||||
"changes": "Changes",
|
"changes": "Changes",
|
||||||
"releaseDate": "Release Date",
|
"releaseDate": "Release Date",
|
||||||
|
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "برنامه حذف شود؟",
|
"one": "برنامه حذف شود؟",
|
||||||
"other": "برنامه ها حذف شوند؟"
|
"other": "برنامه ها حذف شوند؟"
|
||||||
|
@@ -216,6 +216,7 @@
|
|||||||
"releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió érzékelése nem működik megfelelően, de elérhető a kiadás dátuma.",
|
"releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió érzékelése nem működik megfelelően, de elérhető a kiadás dátuma.",
|
||||||
"changes": "Változtatások",
|
"changes": "Változtatások",
|
||||||
"releaseDate": "Kiadás dátuma",
|
"releaseDate": "Kiadás dátuma",
|
||||||
|
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Eltávolítja az alkalmazást?",
|
"one": "Eltávolítja az alkalmazást?",
|
||||||
"other": "Eltávolítja az alkalmazást?"
|
"other": "Eltávolítja az alkalmazást?"
|
||||||
|
@@ -217,6 +217,7 @@
|
|||||||
"releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.",
|
"releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.",
|
||||||
"changes": "Novità",
|
"changes": "Novità",
|
||||||
"releaseDate": "Data di rilascio",
|
"releaseDate": "Data di rilascio",
|
||||||
|
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Rimuovere l'App?",
|
"one": "Rimuovere l'App?",
|
||||||
"other": "Rimuovere le App?"
|
"other": "Rimuovere le App?"
|
||||||
|
@@ -217,6 +217,7 @@
|
|||||||
"releaseDateAsVersionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリで、リリース日が利用可能な場合にのみ使用する必要があります。",
|
"releaseDateAsVersionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリで、リリース日が利用可能な場合にのみ使用する必要があります。",
|
||||||
"changes": "変更点",
|
"changes": "変更点",
|
||||||
"releaseDate": "リリース日",
|
"releaseDate": "リリース日",
|
||||||
|
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "アプリを削除しますか?",
|
"one": "アプリを削除しますか?",
|
||||||
"other": "アプリを削除しますか?"
|
"other": "アプリを削除しますか?"
|
||||||
|
@@ -217,6 +217,7 @@
|
|||||||
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
"releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.",
|
||||||
"changes": "Changes",
|
"changes": "Changes",
|
||||||
"releaseDate": "Release Date",
|
"releaseDate": "Release Date",
|
||||||
|
"importFromURLsInFile": "Import from URLs in File (like OPML)",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "删除应用?",
|
"one": "删除应用?",
|
||||||
"other": "删除应用?"
|
"other": "删除应用?"
|
||||||
|
@@ -41,6 +41,66 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
urlListImport({String? initValue, bool overrideInitValid = false}) {
|
||||||
|
showDialog<Map<String, dynamic>?>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext ctx) {
|
||||||
|
return GeneratedFormModal(
|
||||||
|
initValid: overrideInitValid,
|
||||||
|
title: tr('importFromURLList'),
|
||||||
|
items: [
|
||||||
|
[
|
||||||
|
GeneratedFormTextField('appURLList',
|
||||||
|
defaultValue: initValue ?? '',
|
||||||
|
label: tr('appURLList'),
|
||||||
|
max: 7,
|
||||||
|
additionalValidators: [
|
||||||
|
(dynamic value) {
|
||||||
|
if (value != null && value.isNotEmpty) {
|
||||||
|
var lines = value.trim().split('\n');
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
try {
|
||||||
|
sourceProvider.getSource(lines[i]);
|
||||||
|
} catch (e) {
|
||||||
|
return '${tr('line')} ${i + 1}: $e';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
])
|
||||||
|
]
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).then((values) {
|
||||||
|
if (values != null) {
|
||||||
|
var urls = (values['appURLList'] as String).split('\n');
|
||||||
|
setState(() {
|
||||||
|
importInProgress = true;
|
||||||
|
});
|
||||||
|
appsProvider.addAppsByURL(urls).then((errors) {
|
||||||
|
if (errors.isEmpty) {
|
||||||
|
showError(tr('importedX', args: [plural('apps', urls.length)]),
|
||||||
|
context);
|
||||||
|
} else {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext ctx) {
|
||||||
|
return ImportErrorDialog(
|
||||||
|
urlsLength: urls.length, errors: errors);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catchError((e) {
|
||||||
|
showError(e, context);
|
||||||
|
}).whenComplete(() {
|
||||||
|
setState(() {
|
||||||
|
importInProgress = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
body: CustomScrollView(slivers: <Widget>[
|
body: CustomScrollView(slivers: <Widget>[
|
||||||
@@ -150,6 +210,8 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
const Divider(
|
const Divider(
|
||||||
height: 32,
|
height: 32,
|
||||||
),
|
),
|
||||||
@@ -157,81 +219,51 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
onPressed: importInProgress
|
onPressed: importInProgress
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
showDialog<Map<String, dynamic>?>(
|
urlListImport();
|
||||||
context: context,
|
|
||||||
builder: (BuildContext ctx) {
|
|
||||||
return GeneratedFormModal(
|
|
||||||
title: tr('importFromURLList'),
|
|
||||||
items: [
|
|
||||||
[
|
|
||||||
GeneratedFormTextField(
|
|
||||||
'appURLList',
|
|
||||||
label: tr('appURLList'),
|
|
||||||
max: 7,
|
|
||||||
additionalValidators: [
|
|
||||||
(dynamic value) {
|
|
||||||
if (value != null &&
|
|
||||||
value.isNotEmpty) {
|
|
||||||
var lines = value
|
|
||||||
.trim()
|
|
||||||
.split('\n');
|
|
||||||
for (int i = 0;
|
|
||||||
i < lines.length;
|
|
||||||
i++) {
|
|
||||||
try {
|
|
||||||
sourceProvider
|
|
||||||
.getSource(
|
|
||||||
lines[i]);
|
|
||||||
} catch (e) {
|
|
||||||
return '${tr('line')} ${i + 1}: $e';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
])
|
|
||||||
]
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}).then((values) {
|
|
||||||
if (values != null) {
|
|
||||||
var urls =
|
|
||||||
(values['appURLList'] as String)
|
|
||||||
.split('\n');
|
|
||||||
setState(() {
|
|
||||||
importInProgress = true;
|
|
||||||
});
|
|
||||||
appsProvider
|
|
||||||
.addAppsByURL(urls)
|
|
||||||
.then((errors) {
|
|
||||||
if (errors.isEmpty) {
|
|
||||||
showError(
|
|
||||||
tr('importedX', args: [
|
|
||||||
plural('apps', urls.length)
|
|
||||||
]),
|
|
||||||
context);
|
|
||||||
} else {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext ctx) {
|
|
||||||
return ImportErrorDialog(
|
|
||||||
urlsLength: urls.length,
|
|
||||||
errors: errors);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}).catchError((e) {
|
|
||||||
showError(e, context);
|
|
||||||
}).whenComplete(() {
|
|
||||||
setState(() {
|
|
||||||
importInProgress = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
tr('importFromURLList'),
|
tr('importFromURLList'),
|
||||||
)),
|
)),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
TextButton(
|
||||||
|
onPressed: importInProgress
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
FilePicker.platform
|
||||||
|
.pickFiles()
|
||||||
|
.then((result) {
|
||||||
|
if (result != null) {
|
||||||
|
urlListImport(
|
||||||
|
overrideInitValid: true,
|
||||||
|
initValue:
|
||||||
|
RegExp('https?://[^"]+')
|
||||||
|
.allMatches(File(result
|
||||||
|
.files
|
||||||
|
.single
|
||||||
|
.path!)
|
||||||
|
.readAsStringSync())
|
||||||
|
.map((e) =>
|
||||||
|
e.input.substring(
|
||||||
|
e.start, e.end))
|
||||||
|
.toSet()
|
||||||
|
.toList()
|
||||||
|
.where((url) {
|
||||||
|
try {
|
||||||
|
sourceProvider
|
||||||
|
.getSource(url);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}).join('\n'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
tr('importFromURLsInFile'),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
...sourceProvider.sources
|
...sourceProvider.sources
|
||||||
.where((element) => element.canSearch)
|
.where((element) => element.canSearch)
|
||||||
.map((source) => Column(
|
.map((source) => Column(
|
||||||
@@ -280,6 +312,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
if (urlsWithDescriptions
|
if (urlsWithDescriptions
|
||||||
.isNotEmpty) {
|
.isNotEmpty) {
|
||||||
var selectedUrls =
|
var selectedUrls =
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
await showDialog<
|
await showDialog<
|
||||||
List<
|
List<
|
||||||
String>?>(
|
String>?>(
|
||||||
@@ -314,6 +347,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
]),
|
]),
|
||||||
context);
|
context);
|
||||||
} else {
|
} else {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
@@ -391,6 +425,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
e.toString())
|
e.toString())
|
||||||
.toList());
|
.toList());
|
||||||
var selectedUrls =
|
var selectedUrls =
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
await showDialog<
|
await showDialog<
|
||||||
List<String>?>(
|
List<String>?>(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -418,6 +453,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
|||||||
]),
|
]),
|
||||||
context);
|
context);
|
||||||
} else {
|
} else {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
|
Reference in New Issue
Block a user