From 5e6e3f457ca749ba302a6a469680bcb975092cc6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 7 Mar 2025 18:05:45 -0500 Subject: [PATCH] Better sort options for GitHub releases (#2144) --- assets/translations/bs.json | 3 ++ assets/translations/cs.json | 3 ++ assets/translations/da.json | 3 ++ assets/translations/de.json | 3 ++ assets/translations/en-EO.json | 3 ++ assets/translations/en.json | 3 ++ assets/translations/es.json | 3 ++ assets/translations/fa.json | 3 ++ assets/translations/fr.json | 3 ++ assets/translations/hu.json | 3 ++ assets/translations/id.json | 3 ++ assets/translations/it.json | 3 ++ assets/translations/ja.json | 3 ++ assets/translations/ko.json | 3 ++ assets/translations/nl.json | 3 ++ assets/translations/pl.json | 3 ++ assets/translations/pt.json | 3 ++ assets/translations/ru.json | 3 ++ assets/translations/standardize.js | 70 +++++++++++++++++------------ assets/translations/sv.json | 3 ++ assets/translations/tr.json | 3 ++ assets/translations/uk.json | 3 ++ assets/translations/vi.json | 3 ++ assets/translations/zh-Hant-TW.json | 3 ++ assets/translations/zh.json | 3 ++ lib/app_sources/github.dart | 48 +++++++++++++------- lib/providers/source_provider.dart | 4 ++ 27 files changed, 150 insertions(+), 44 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 3537c57..fb958ac 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Stay one version behind latest", "refreshBeforeDownload": "Refresh app details before download", "tencentAppStore": "Tencent App Store", + "name": "Name", + "smartname": "Name (Smart)", + "sortMethod": "Sort Method", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index 8635c23..4f0c527 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Zůstaňte o jednu verzi pozadu za nejnovější", "refreshBeforeDownload": "Obnovení údajů o aplikaci před stažením", "tencentAppStore": "Tencent App Store", + "name": "Název", + "smartname": "Název (Smart)", + "sortMethod": "Metoda třídění", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/da.json b/assets/translations/da.json index f4d625c..ca82fa6 100644 --- a/assets/translations/da.json +++ b/assets/translations/da.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Forbliv én version bagud den seneste", "refreshBeforeDownload": "Opdater app-detaljer før download", "tencentAppStore": "Tencent App Store", + "name": "Navn", + "smartname": "Navn (Smart)", + "sortMethod": "Sorteringsmetode", "removeAppQuestion": { "one": "Fjern app?", "other": "Fjern apps?" diff --git a/assets/translations/de.json b/assets/translations/de.json index f478db1..62a8ac8 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Eine Version hinter der neuesten Version bleiben", "refreshBeforeDownload": "App-Details vor dem Download aktualisieren", "tencentAppStore": "Tencent App Store", + "name": "Name", + "smartname": "Name (Smart)", + "sortMethod": "Sortierverfahren", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en-EO.json b/assets/translations/en-EO.json index 26eeb10..26b3b67 100644 --- a/assets/translations/en-EO.json +++ b/assets/translations/en-EO.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Stay one version behind latest", "refreshBeforeDownload": "Refresh app details before download", "tencentAppStore": "Tencent App Store", + "name": "Name", + "smartname": "Name (Smart)", + "sortMethod": "Sort Method", "removeAppQuestion": { "one": "Forigi la aplikaĵon?", "other": "Forigi la aplikaĵojn?" diff --git a/assets/translations/en.json b/assets/translations/en.json index d4c8689..e745dfd 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Stay one version behind latest", "refreshBeforeDownload": "Refresh app details before download", "tencentAppStore": "Tencent App Store", + "name": "Name", + "smartname": "Name (Smart)", + "sortMethod": "Sort Method", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index b0b7873..4fec5d3 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Mantenerse una versión por detrás de la última", "refreshBeforeDownload": "Actualiza los datos de la aplicación antes de descargarla", "tencentAppStore": "Tencent App Store", + "name": "Nombre", + "smartname": "Nombre (Smart)", + "sortMethod": "Método de clasificación", "removeAppQuestion": { "one": "¿Eliminar aplicación?", "other": "¿Eliminar aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 4e72fca..50fa808 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "یک نسخه از آخرین نسخه پشت سر بگذارید", "refreshBeforeDownload": "قبل از دانلود، جزئیات برنامه را بازخوانی کنید", "tencentAppStore": "Tencent App Store", + "name": "Name", + "smartname": "Name (Smart)", + "sortMethod": "Sort Method", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index bb5e021..26ee458 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Rester une version en arrière de la dernière", "refreshBeforeDownload": "Actualiser les détails de l'application avant de la télécharger", "tencentAppStore": "Tencent App Store", + "name": "Nom", + "smartname": "Nom (Smart)", + "sortMethod": "Méthode de tri", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 2bc413b..b5b8355 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Maradjon egy verzióval a legújabb mögött", "refreshBeforeDownload": "Az alkalmazás adatainak frissítése a letöltés előtt", "tencentAppStore": "Tencent Appstore", + "name": "Név", + "smartname": "Név (Smart)", + "sortMethod": "Rendezési módszer", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazásokat?" diff --git a/assets/translations/id.json b/assets/translations/id.json index 0356fe0..0686b17 100644 --- a/assets/translations/id.json +++ b/assets/translations/id.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Tetap satu versi di belakang versi terbaru", "refreshBeforeDownload": "Segarkan detail aplikasi sebelum mengunduh", "tencentAppStore": "Tencent App Store", + "name": "Nama", + "smartname": "Nama (Cerdas)", + "sortMethod": "Metode Penyortiran", "removeAppQuestion": { "one": "Hapus aplikasi?", "other": "Hapus aplikasi?" diff --git a/assets/translations/it.json b/assets/translations/it.json index 5c7ddad..c41ac63 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Rimanere una versione indietro rispetto alla più recente", "refreshBeforeDownload": "Aggiornare i dettagli dell'app prima del download", "tencentAppStore": "Tencent App Store", + "name": "Nome", + "smartname": "Nome (intelligente)", + "sortMethod": "Metodo di ordinamento", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 9763ef1..3fef6a7 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "最新のバージョンから1つ前のものを使用する", "refreshBeforeDownload": "ダウンロード前にアプリの詳細を更新する", "tencentAppStore": "Tencent App Store", + "name": "Name", + "smartname": "名前(スマート)", + "sortMethod": "ソート方法", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/ko.json b/assets/translations/ko.json index de433fb..11dd4a8 100644 --- a/assets/translations/ko.json +++ b/assets/translations/ko.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "최신 버전보다 한 버전 뒤에 머무르기", "refreshBeforeDownload": "다운로드 전에 앱 세부 정보 새로 고침", "tencentAppStore": "텐센트 앱 스토어", + "name": "이름", + "smartname": "이름(스마트)", + "sortMethod": "정렬 방법", "removeAppQuestion": { "one": "앱을 제거하시겠습니까?", "other": "앱을 제거하시겠습니까?" diff --git a/assets/translations/nl.json b/assets/translations/nl.json index beef021..3393987 100644 --- a/assets/translations/nl.json +++ b/assets/translations/nl.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Blijf een versie achter op de nieuwste", "refreshBeforeDownload": "Vernieuw app details voor download", "tencentAppStore": "Tencent App Store", + "name": "Naam", + "smartname": "Naam (Slim)", + "sortMethod": "Sorteermethode", "removeAppQuestion": { "one": "App verwijderen?", "other": "Apps verwijderen?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 7123d1a..54be7b3 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Pozostań jedną wersję w tyle za najnowszą", "refreshBeforeDownload": "Odśwież szczegóły aplikacji przed pobraniem", "tencentAppStore": "Tencent App Store", + "name": "Nazwa", + "smartname": "Nazwa (Smart)", + "sortMethod": "Metoda sortowania", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 717a30a..d2e07bd 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Manter-se uma versão atrás da mais recente", "refreshBeforeDownload": "Atualizar os detalhes da aplicação antes da transferência", "tencentAppStore": "Tencent App Store", + "name": "Nome", + "smartname": "Nome (Smart)", + "sortMethod": "Método de ordenação", "removeAppQuestion": { "one": "Remover aplicativo?", "other": "Remover aplicativos?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 05b1246..4f3d70b 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Не отставайте от последней версии", "refreshBeforeDownload": "Обновляйте информацию о приложении перед загрузкой", "tencentAppStore": "Tencent App Store", + "name": "Имя", + "smartname": "Имя (умное)", + "sortMethod": "Метод сортировки", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/standardize.js b/assets/translations/standardize.js index b077689..53c7a6f 100644 --- a/assets/translations/standardize.js +++ b/assets/translations/standardize.js @@ -13,7 +13,10 @@ const neverAutoTranslate = { obtainiumExportHyphenatedLowercase: ['*'], theme: ['de'], appId: ['de'], - placeholder: ['pl'] + placeholder: ['pl'], + importExport: ['fr'], + url: ['fr'], + tencentAppStore: ['*'] } const translateText = async (text, targetLang, authKey) => { @@ -76,40 +79,49 @@ const main = async () => { const translationKeys = Object.keys(templateTranslation) for (let j in translationKeys) { const k = translationKeys[j] - if (JSON.stringify(thisTranslation[k]) == JSON.stringify(templateTranslation[k])) { - const lang = file.split('/').pop().split('.')[0] - if (!neverAutoTranslate[k] || (neverAutoTranslate[k].indexOf('*') < 0 && neverAutoTranslate[k].indexOf(lang) < 0)) { - const reportLine = `${file} :::: ${k} :::: ${JSON.stringify(thisTranslation[k])}` - if (deeplAPIKey) { - const translateFunc = async (str) => { - const response = await translateText(str, lang, deeplAPIKey) - if (response.translations) { - return response.translations[0].text - } else { - throw JSON.stringify(response) - } - } - try { - if (typeof templateTranslation[k] == 'string') { - thisTranslation[k] = await translateFunc(thisTranslation[k]) - } else { - const subKeys = Object.keys(templateTranslation[k]) - for (let n in subKeys) { - const kk = subKeys[n] - thisTranslation[k][kk] = await translateFunc(thisTranslation[k][kk]) + try { + if (JSON.stringify(thisTranslation[k]) == JSON.stringify(templateTranslation[k])) { + const lang = file.split('/').pop().split('.')[0] + if (!neverAutoTranslate[k] || (neverAutoTranslate[k].indexOf('*') < 0 && neverAutoTranslate[k].indexOf(lang) < 0)) { + const reportLine = `${file} :::: ${k} :::: ${JSON.stringify(thisTranslation[k])}` + if (deeplAPIKey) { + const translateFunc = async (str) => { + await new Promise((resolve, reject) => { + setTimeout(() => { + resolve() + }, Math.random() * 1000); // Try to avoid rate limit + }) + const response = await translateText(str, lang, deeplAPIKey) + if (response.translations) { + return response.translations[0].text + } else { + throw JSON.stringify(response) } } - } catch (e) { - if (typeof e == 'string') { - console.log(`${reportLine} :::: ${e}`) - } else { - throw e + try { + if (typeof templateTranslation[k] == 'string') { + thisTranslation[k] = await translateFunc(thisTranslation[k]) + } else { + const subKeys = Object.keys(templateTranslation[k]) + for (let n in subKeys) { + const kk = subKeys[n] + thisTranslation[k][kk] = await translateFunc(thisTranslation[k][kk]) + } + } + } catch (e) { + if (typeof e == 'string') { + console.log(`${reportLine} :::: ${e}`) + } else { + throw e + } } + } else { + console.log(reportLine) } - } else { - console.log(reportLine) } } + } catch (err) { + console.error(err) } } fs.writeFileSync(file, `${JSON.stringify(thisTranslation, null, ' ')}\n`) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index e56cbed..08a3ecd 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Håll dig en version bakom den senaste", "refreshBeforeDownload": "Uppdatera appdetaljerna före nedladdning", "tencentAppStore": "Tencent App Store", + "name": "Namn", + "smartname": "Namn (Smart)", + "sortMethod": "Sorteringsmetod", "removeAppQuestion": { "one": "Ta Bort App?", "other": "Ta Bort Appar?" diff --git a/assets/translations/tr.json b/assets/translations/tr.json index d62875c..9873950 100644 --- a/assets/translations/tr.json +++ b/assets/translations/tr.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "En son sürümün bir sürüm gerisinde kalın", "refreshBeforeDownload": "İndirmeden önce uygulama ayrıntılarını yenileyin", "tencentAppStore": "Tencent App Store", + "name": "İsim", + "smartname": "İsim (Akıllı)", + "sortMethod": "Sıralama Yöntemi", "removeAppQuestion": { "one": "Uygulamayı Kaldır?", "other": "Uygulamaları Kaldır?" diff --git a/assets/translations/uk.json b/assets/translations/uk.json index 0cb6d3a..de5843e 100644 --- a/assets/translations/uk.json +++ b/assets/translations/uk.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Залишайтеся на одну версію актуальнішою", "refreshBeforeDownload": "Оновіть інформацію про програму перед завантаженням", "tencentAppStore": "Tencent App Store", + "name": "Ім'я", + "smartname": "Ім'я (Smart)", + "sortMethod": "Метод сортування", "removeAppQuestion": { "one": "Видалити застосунок?", "other": "Видалити застосунки?" diff --git a/assets/translations/vi.json b/assets/translations/vi.json index 495a7b9..c871e17 100644 --- a/assets/translations/vi.json +++ b/assets/translations/vi.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Stay one version behind latest", "refreshBeforeDownload": "Refresh app details before download", "tencentAppStore": "Tencent App Store", + "name": "Name", + "smartname": "Name (Smart)", + "sortMethod": "Sort Method", "removeAppQuestion": { "one": "Gỡ ứng dụng?", "other": "Gỡ ứng dụng?" diff --git a/assets/translations/zh-Hant-TW.json b/assets/translations/zh-Hant-TW.json index b1f6983..1b635c5 100644 --- a/assets/translations/zh-Hant-TW.json +++ b/assets/translations/zh-Hant-TW.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "Stay one version behind latest", "refreshBeforeDownload": "Refresh app details before download", "tencentAppStore": "騰訊應用寶", + "name": "Name", + "smartname": "Name (Smart)", + "sortMethod": "Sort Method", "removeAppQuestion": { "one": "移除應用程式?", "other": "移除應用程式?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index f115f73..40884ff 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -319,6 +319,9 @@ "stayOneVersionBehind": "比最新版本晚一个版本", "refreshBeforeDownload": "下载前刷新应用程序详细信息", "tencentAppStore": "腾讯应用宝", + "name": "名称", + "smartname": "姓名(智能)", + "sortMethod": "排序方法", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index ab246e6..f2490cc 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -75,8 +75,18 @@ class GitHub extends AppSource { ], [GeneratedFormSwitch('verifyLatestTag', label: tr('verifyLatestTag'))], [ - GeneratedFormSwitch('dontSortReleasesList', - label: tr('dontSortReleasesList')) + GeneratedFormDropdown( + 'sortMethodChoice', + [ + MapEntry('date', tr('releaseDate')), + MapEntry('smartname', tr('smartname')), + MapEntry('none', tr('none')), + MapEntry('smartname-datefallback', + '${tr('smartname')} x ${tr('releaseDate')}'), + MapEntry('name', tr('name')), + ], + label: tr('sortMethod'), + defaultValue: 'date') ], [ GeneratedFormSwitch('useLatestAssetDateAsReleaseDate', @@ -244,10 +254,10 @@ class GitHub extends AppSource { ? additionalSettings['filterReleaseNotesByRegEx'] : null; bool verifyLatestTag = additionalSettings['verifyLatestTag'] == true; - bool dontSortReleasesList = - additionalSettings['dontSortReleasesList'] == true; bool useLatestAssetDateAsReleaseDate = additionalSettings['useLatestAssetDateAsReleaseDate'] == true; + String sortMethod = + additionalSettings['sortMethodChoice'] ?? 'smartname-datefallback'; dynamic latestRelease; if (verifyLatestTag) { var temp = requestUrl.split('?'); @@ -316,7 +326,7 @@ class GitHub extends AppSource { ? getPublishDateFromRelease(rel) : getNewestAssetDateFromRelease(rel); - if (dontSortReleasesList) { + if (sortMethod == 'none') { releases = releases.reversed.toList(); } else { releases.sort((a, b) { @@ -330,22 +340,30 @@ class GitHub extends AppSource { } else { var nameA = a['tag_name'] ?? a['name']; var nameB = b['tag_name'] ?? b['name']; - var stdFormats = findStandardFormatsForVersion(nameA, true) - .intersection(findStandardFormatsForVersion(nameB, true)); - if (stdFormats.isNotEmpty) { - var reg = RegExp(stdFormats.first); - var matchA = reg.firstMatch(nameA); - var matchB = reg.firstMatch(nameB); - return compareAlphaNumeric( - (nameA as String).substring(matchA!.start, matchA.end), - (nameB as String).substring(matchB!.start, matchB.end)); - } else { + var stdFormats = findStandardFormatsForVersion(nameA, false) + .intersection(findStandardFormatsForVersion(nameB, false)); + if (sortMethod == 'date' || + (sortMethod == 'smartname-datefallback' && + stdFormats.isEmpty)) { return (getReleaseDateFromRelease( a, useLatestAssetDateAsReleaseDate) ?? DateTime(1)) .compareTo(getReleaseDateFromRelease( b, useLatestAssetDateAsReleaseDate) ?? DateTime(0)); + } else { + if (sortMethod != 'name' && stdFormats.isNotEmpty) { + var reg = RegExp(stdFormats.last); + var matchA = reg.firstMatch(nameA); + var matchB = reg.firstMatch(nameB); + return compareAlphaNumeric( + (nameA as String).substring(matchA!.start, matchA.end), + (nameB as String).substring(matchB!.start, matchB.end)); + } else { + // 'name' + return compareAlphaNumeric( + (nameA as String), (nameB as String)); + } } } }); diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index e2e40e2..6084fb9 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -152,6 +152,10 @@ appJSONCompatibilityModifiers(Map json) { if (additionalSettings['autoApkFilterByArch'] == null) { additionalSettings['autoApkFilterByArch'] = false; } + // GitHub "don't sort" option to new dropdown format + if (additionalSettings['dontSortReleasesList'] == true) { + additionalSettings['sortMethodChoice'] = 'none'; + } if (source.runtimeType == HTML().runtimeType) { // HTML key rename if (originalAdditionalSettings['sortByFileNamesNotLinks'] != null) {