Merge branch 'ImranR98:main' into rustore
2
.flutter
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 418 KiB |
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 418 KiB |
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 265 KiB |
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 220 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 362 KiB |
@ -31,7 +31,7 @@
|
|||||||
"xIsTrackOnly": "{} ist nur zur Nachverfolgung",
|
"xIsTrackOnly": "{} ist nur zur Nachverfolgung",
|
||||||
"source": "Quelle",
|
"source": "Quelle",
|
||||||
"app": "App",
|
"app": "App",
|
||||||
"appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind nur zur Versionsüberwachung.",
|
"appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind nur zur Nachverfolgung.",
|
||||||
"youPickedTrackOnly": "Du hast die Option „Nur nachverfolgen“ gewählt.",
|
"youPickedTrackOnly": "Du hast die Option „Nur nachverfolgen“ gewählt.",
|
||||||
"trackOnlyAppDescription": "Die App wird auf neue verfügbare Versionen überwacht, aber Obtainium wird sie nicht herunterladen oder installieren.",
|
"trackOnlyAppDescription": "Die App wird auf neue verfügbare Versionen überwacht, aber Obtainium wird sie nicht herunterladen oder installieren.",
|
||||||
"cancelled": "Abgebrochen",
|
"cancelled": "Abgebrochen",
|
||||||
@ -85,7 +85,7 @@
|
|||||||
"filter": "Filter",
|
"filter": "Filter",
|
||||||
"filterApps": "Apps filtern",
|
"filterApps": "Apps filtern",
|
||||||
"appName": "App-Name",
|
"appName": "App-Name",
|
||||||
"author": "Autor:in",
|
"author": "Herausgebende",
|
||||||
"upToDateApps": "Apps mit aktuellster Version",
|
"upToDateApps": "Apps mit aktuellster Version",
|
||||||
"nonInstalledApps": "Nicht installierte Apps",
|
"nonInstalledApps": "Nicht installierte Apps",
|
||||||
"importExport": "Import/Export",
|
"importExport": "Import/Export",
|
||||||
@ -109,15 +109,15 @@
|
|||||||
"selectURL": "URL auswählen",
|
"selectURL": "URL auswählen",
|
||||||
"selectURLs": "URLs auswählen",
|
"selectURLs": "URLs auswählen",
|
||||||
"pick": "Auswählen",
|
"pick": "Auswählen",
|
||||||
"theme": "Theme",
|
"theme": "Design",
|
||||||
"dark": "Dunkel",
|
"dark": "Dunkel",
|
||||||
"light": "Hell",
|
"light": "Hell",
|
||||||
"followSystem": "Systemstandard",
|
"followSystem": "Systemstandard",
|
||||||
"followSystemThemeExplanation": "Das Abrufen des Systemdesigns ist unter Android < 10 nur mit Hilfe von Drittanbieterapps möglich",
|
"followSystemThemeExplanation": "Das Abrufen des Systemdesigns ist unter Android < 10 nur mit Hilfe von Drittanbieterapps möglich",
|
||||||
"useBlackTheme": "Rein schwarzen Hintergrund verwenden",
|
"useBlackTheme": "Rein schwarzen Hintergrund verwenden",
|
||||||
"appSortBy": "App sortieren nach",
|
"appSortBy": "App sortieren nach",
|
||||||
"authorName": "Autor:in/Name",
|
"authorName": "Hrsg./Name",
|
||||||
"nameAuthor": "Name/Autor:in",
|
"nameAuthor": "Name/Hrsg.",
|
||||||
"asAdded": "Wie hinzugefügt",
|
"asAdded": "Wie hinzugefügt",
|
||||||
"appSortOrder": "App sortieren nach",
|
"appSortOrder": "App sortieren nach",
|
||||||
"ascending": "Aufsteigend",
|
"ascending": "Aufsteigend",
|
||||||
@ -152,9 +152,9 @@
|
|||||||
"xWasUpdatedToY": "{} wurde auf {} aktualisiert.",
|
"xWasUpdatedToY": "{} wurde auf {} aktualisiert.",
|
||||||
"xWasNotUpdatedToY": "Die Aktualisierung von {} auf {} ist fehlgeschlagen.",
|
"xWasNotUpdatedToY": "Die Aktualisierung von {} auf {} ist fehlgeschlagen.",
|
||||||
"errorCheckingUpdates": "Fehler beim Prüfen auf Aktualisierungen",
|
"errorCheckingUpdates": "Fehler beim Prüfen auf Aktualisierungen",
|
||||||
"errorCheckingUpdatesNotifDescription": "Weist darauf hin, dass die Prüfung der Hintergrundaktualisierung fehlgeschlagen ist",
|
"errorCheckingUpdatesNotifDescription": "Benachrichtigt, wenn die Prüfung der Hintergrundaktualisierung fehlgeschlagen ist",
|
||||||
"appsRemoved": "Apps entfernt",
|
"appsRemoved": "Apps entfernt",
|
||||||
"appsRemovedNotifDescription": "Weist darauf hin, dass eine oder mehrere Apps aufgrund von Fehlern beim Laden entfernt wurden",
|
"appsRemovedNotifDescription": "Benachrichtigt, wenn eine oder mehrere Apps aufgrund von Fehlern beim Laden entfernt wurden",
|
||||||
"xWasRemovedDueToErrorY": "{} wurde aufgrund des folgenden Fehlers entfernt: {}",
|
"xWasRemovedDueToErrorY": "{} wurde aufgrund des folgenden Fehlers entfernt: {}",
|
||||||
"completeAppInstallation": "App-Installation abschließen",
|
"completeAppInstallation": "App-Installation abschließen",
|
||||||
"obtainiumMustBeOpenToInstallApps": "Obtainium muss geöffnet sein, um Apps zu installieren",
|
"obtainiumMustBeOpenToInstallApps": "Obtainium muss geöffnet sein, um Apps zu installieren",
|
||||||
@ -244,10 +244,10 @@
|
|||||||
"filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck\nfiltern",
|
"filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck\nfiltern",
|
||||||
"customLinkFilterRegex": "Benutzerdefinierter APK-Linkfilter durch regulären Ausdruck (Standard '.apk$')",
|
"customLinkFilterRegex": "Benutzerdefinierter APK-Linkfilter durch regulären Ausdruck (Standard '.apk$')",
|
||||||
"appsPossiblyUpdated": "App-Aktualisierungen wurden versucht",
|
"appsPossiblyUpdated": "App-Aktualisierungen wurden versucht",
|
||||||
"appsPossiblyUpdatedNotifDescription": "Benachrichtigt, dass Aktualisierungen für eine oder mehrere Apps möglicherweise im Hintergrund durchgeführt wurden",
|
"appsPossiblyUpdatedNotifDescription": "Benachrichtigt, dass möglicherweise eine oder mehrere Apps im Hintergrund aktualisiert wurden",
|
||||||
"xWasPossiblyUpdatedToY": "{} wurde möglicherweise aktualisiert auf {}.",
|
"xWasPossiblyUpdatedToY": "{} wurde eventuell auf Version {} aktualisiert.",
|
||||||
"enableBackgroundUpdates": "Hintergrundaktualisierungen aktivieren",
|
"enableBackgroundUpdates": "Hintergrundaktualisierungen aktivieren",
|
||||||
"backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.",
|
"backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist unter Umständen nicht für alle Apps möglich.",
|
||||||
"backgroundUpdateLimitsExplanation": "Der Erfolg einer Hintergrundinstallation kann nur festgestellt werden, wenn Obtainium geöffnet wird.",
|
"backgroundUpdateLimitsExplanation": "Der Erfolg einer Hintergrundinstallation kann nur festgestellt werden, wenn Obtainium geöffnet wird.",
|
||||||
"verifyLatestTag": "„Latest“-Tag überprüfen",
|
"verifyLatestTag": "„Latest“-Tag überprüfen",
|
||||||
"intermediateLinkRegex": "Filter für einen „Zwischen“-Link, der zuerst besucht werden soll",
|
"intermediateLinkRegex": "Filter für einen „Zwischen“-Link, der zuerst besucht werden soll",
|
||||||
@ -292,8 +292,8 @@
|
|||||||
"parallelDownloads": "Parallele Downloads erlauben",
|
"parallelDownloads": "Parallele Downloads erlauben",
|
||||||
"useShizuku": "Shizuku oder Sui zur Installation verwenden",
|
"useShizuku": "Shizuku oder Sui zur Installation verwenden",
|
||||||
"shizukuBinderNotFound": "Kompatibler Shizuku-Dienst wurde nicht gefunden",
|
"shizukuBinderNotFound": "Kompatibler Shizuku-Dienst wurde nicht gefunden",
|
||||||
"shizukuOld": "Alte Shizuku-Version (< 11) - aktualisieren Sie sie",
|
"shizukuOld": "Veraltete Shizuku-Version (< 11) - bitte aktualisiere sie",
|
||||||
"shizukuOldAndroidWithADB": "Shizuku läuft auf Android < 8.1 mit ADB - aktualisieren Sie Android oder verwenden Sie stattdessen Sui",
|
"shizukuOldAndroidWithADB": "Shizuku läuft auf Android < 8.1 mit ADB - aktualisiere die Android-Version oder verwende stattdessen Sui",
|
||||||
"shizukuPretendToBeGooglePlay": "(Mittels Shizuku) Google Play als Installationsquelle registrieren",
|
"shizukuPretendToBeGooglePlay": "(Mittels Shizuku) Google Play als Installationsquelle registrieren",
|
||||||
"useSystemFont": "Systemschriftart verwenden",
|
"useSystemFont": "Systemschriftart verwenden",
|
||||||
"useVersionCodeAsOSVersion": "Versionscode (versionCode) als erkannte Version vom Betriebssystem verwenden",
|
"useVersionCodeAsOSVersion": "Versionscode (versionCode) als erkannte Version vom Betriebssystem verwenden",
|
||||||
|
382
assets/translations/ko.json
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
{
|
||||||
|
"invalidURLForSource": "유효한 {} 앱 URL이 아닙니다",
|
||||||
|
"noReleaseFound": "적절한 릴리스를 찾을 수 없습니다",
|
||||||
|
"noVersionFound": "릴리스 버전을 결정할 수 없습니다",
|
||||||
|
"urlMatchesNoSource": "URL이 알려진 소스와 일치하지 않습니다",
|
||||||
|
"cantInstallOlderVersion": "앱의 이전 버전을 설치할 수 없습니다",
|
||||||
|
"appIdMismatch": "다운로드된 패키지 ID가 기존 앱 ID와 일치하지 않습니다",
|
||||||
|
"functionNotImplemented": "이 클래스는 이 기능을 구현하지 않았습니다",
|
||||||
|
"placeholder": "플레이스홀더",
|
||||||
|
"someErrors": "일부 오류가 발생했습니다",
|
||||||
|
"unexpectedError": "예기치 않은 오류",
|
||||||
|
"ok": "확인",
|
||||||
|
"and": "그리고",
|
||||||
|
"githubPATLabel": "GitHub 개인 액세스 토큰 (속도 제한 증가)",
|
||||||
|
"includePrereleases": "사전 릴리스 포함",
|
||||||
|
"fallbackToOlderReleases": "이전 릴리스로 대체",
|
||||||
|
"filterReleaseTitlesByRegEx": "정규 표현식으로 릴리스 제목 필터링",
|
||||||
|
"invalidRegEx": "잘못된 정규 표현식",
|
||||||
|
"noDescription": "설명 없음",
|
||||||
|
"cancel": "취소",
|
||||||
|
"continue": "계속",
|
||||||
|
"requiredInBrackets": "(필수)",
|
||||||
|
"dropdownNoOptsError": "오류: 드롭다운에는 최소 하나의 옵션이 있어야 합니다",
|
||||||
|
"colour": "색상",
|
||||||
|
"standard": "표준",
|
||||||
|
"custom": "사용자 정의",
|
||||||
|
"useMaterialYou": "Material You 사용",
|
||||||
|
"githubStarredRepos": "GitHub 즐겨찾기 저장소",
|
||||||
|
"uname": "사용자 이름",
|
||||||
|
"wrongArgNum": "잘못된 인수 수 제공",
|
||||||
|
"xIsTrackOnly": "{}는 추적 전용입니다",
|
||||||
|
"source": "소스",
|
||||||
|
"app": "앱",
|
||||||
|
"appsFromSourceAreTrackOnly": "이 소스의 앱은 '추적 전용'입니다.",
|
||||||
|
"youPickedTrackOnly": "당신은 '추적 전용' 옵션을 선택했습니다.",
|
||||||
|
"trackOnlyAppDescription": "앱은 업데이트를 위해 추적되지만 Obtainium은 다운로드하거나 설치할 수 없습니다.",
|
||||||
|
"cancelled": "취소됨",
|
||||||
|
"appAlreadyAdded": "앱이 이미 추가되었습니다",
|
||||||
|
"alreadyUpToDateQuestion": "앱이 이미 최신 상태입니까?",
|
||||||
|
"addApp": "앱 추가",
|
||||||
|
"appSourceURL": "앱 소스 URL",
|
||||||
|
"error": "오류",
|
||||||
|
"add": "추가",
|
||||||
|
"searchSomeSourcesLabel": "검색 (일부 소스만)",
|
||||||
|
"search": "검색",
|
||||||
|
"additionalOptsFor": "{}에 대한 추가 옵션",
|
||||||
|
"supportedSources": "지원되는 소스",
|
||||||
|
"trackOnlyInBrackets": "(추적 전용)",
|
||||||
|
"searchableInBrackets": "(검색 가능)",
|
||||||
|
"appsString": "앱",
|
||||||
|
"noApps": "앱 없음",
|
||||||
|
"noAppsForFilter": "필터에 대한 앱 없음",
|
||||||
|
"byX": "{}에 의해",
|
||||||
|
"percentProgress": "진행률: {}%",
|
||||||
|
"pleaseWait": "기다려 주세요",
|
||||||
|
"updateAvailable": "업데이트 가능",
|
||||||
|
"notInstalled": "설치되지 않음",
|
||||||
|
"pseudoVersion": "의사 버전",
|
||||||
|
"selectAll": "모두 선택",
|
||||||
|
"deselectX": "{} 선택 해제",
|
||||||
|
"xWillBeRemovedButRemainInstalled": "{}는 Obtainium에서 제거되지만 장치에 설치된 상태로 남아 있습니다.",
|
||||||
|
"removeSelectedAppsQuestion": "선택한 앱을 제거하시겠습니까?",
|
||||||
|
"removeSelectedApps": "선택한 앱 제거",
|
||||||
|
"updateX": "{} 업데이트",
|
||||||
|
"installX": "{} 설치",
|
||||||
|
"markXTrackOnlyAsUpdated": "{}\n(추적 전용)\n업데이트됨으로 표시",
|
||||||
|
"changeX": "{} 변경",
|
||||||
|
"installUpdateApps": "앱 설치/업데이트",
|
||||||
|
"installUpdateSelectedApps": "선택한 앱 설치/업데이트",
|
||||||
|
"markXSelectedAppsAsUpdated": "{} 선택한 앱을 업데이트됨으로 표시하시겠습니까?",
|
||||||
|
"no": "아니요",
|
||||||
|
"yes": "예",
|
||||||
|
"markSelectedAppsUpdated": "선택한 앱을 업데이트됨으로 표시",
|
||||||
|
"pinToTop": "상단에 고정",
|
||||||
|
"unpinFromTop": "상단에서 고정 해제",
|
||||||
|
"resetInstallStatusForSelectedAppsQuestion": "선택한 앱의 설치 상태를 재설정하시겠습니까?",
|
||||||
|
"installStatusOfXWillBeResetExplanation": "선택한 앱의 설치 상태가 재설정됩니다.\n\n이것은 실패한 업데이트나 기타 문제로 인해 Obtainium에 표시된 앱 버전이 잘못된 경우에 도움이 될 수 있습니다.",
|
||||||
|
"customLinkMessage": "이 링크는 Obtainium이 설치된 장치에서 작동합니다",
|
||||||
|
"shareAppConfigLinks": "앱 구성 HTML 링크로 공유",
|
||||||
|
"shareSelectedAppURLs": "선택한 앱 URL 공유",
|
||||||
|
"resetInstallStatus": "설치 상태 재설정",
|
||||||
|
"more": "더보기",
|
||||||
|
"removeOutdatedFilter": "구식 앱 필터 제거",
|
||||||
|
"showOutdatedOnly": "구식 앱만 표시",
|
||||||
|
"filter": "필터",
|
||||||
|
"filterApps": "앱 필터",
|
||||||
|
"appName": "앱 이름",
|
||||||
|
"author": "저자",
|
||||||
|
"upToDateApps": "최신 상태의 앱",
|
||||||
|
"nonInstalledApps": "설치되지 않은 앱",
|
||||||
|
"importExport": "가져오기/내보내기",
|
||||||
|
"settings": "설정",
|
||||||
|
"exportedTo": "{}로 내보내기 완료",
|
||||||
|
"obtainiumExport": "Obtainium 내보내기",
|
||||||
|
"invalidInput": "잘못된 입력",
|
||||||
|
"importedX": "{} 가져오기 완료",
|
||||||
|
"obtainiumImport": "Obtainium 가져오기",
|
||||||
|
"importFromURLList": "URL 목록에서 가져오기",
|
||||||
|
"searchQuery": "검색 쿼리",
|
||||||
|
"appURLList": "앱 URL 목록",
|
||||||
|
"line": "줄",
|
||||||
|
"searchX": "{} 검색",
|
||||||
|
"noResults": "결과가 없습니다",
|
||||||
|
"importX": "{} 가져오기",
|
||||||
|
"importedAppsIdDisclaimer": "가져온 앱은 \"설치되지 않음\"으로 잘못 표시될 수 있습니다.\n이를 수정하려면 Obtainium을 통해 다시 설치하십시오.\n앱 데이터에는 영향을 미치지 않습니다.\n\nURL 및 타사 가져오기 방법에만 영향을 미칩니다.",
|
||||||
|
"importErrors": "가져오기 오류",
|
||||||
|
"importedXOfYApps": "{}개의 앱 중 {}개 가져오기 완료.",
|
||||||
|
"followingURLsHadErrors": "다음 URL에 오류가 있었습니다:",
|
||||||
|
"selectURL": "URL 선택",
|
||||||
|
"selectURLs": "URL 선택",
|
||||||
|
"pick": "선택",
|
||||||
|
"theme": "테마",
|
||||||
|
"dark": "다크",
|
||||||
|
"light": "라이트",
|
||||||
|
"followSystem": "시스템 따르기",
|
||||||
|
"followSystemThemeExplanation": "시스템 테마를 따르려면 타사 애플리케이션을 사용해야 합니다",
|
||||||
|
"useBlackTheme": "순수한 검은색 다크 테마 사용",
|
||||||
|
"appSortBy": "앱 정렬 기준",
|
||||||
|
"authorName": "저자/이름",
|
||||||
|
"nameAuthor": "이름/저자",
|
||||||
|
"asAdded": "추가된 순서대로",
|
||||||
|
"appSortOrder": "앱 정렬 순서",
|
||||||
|
"ascending": "오름차순",
|
||||||
|
"descending": "내림차순",
|
||||||
|
"bgUpdateCheckInterval": "백그라운드 업데이트 확인 간격",
|
||||||
|
"neverManualOnly": "절대 - 수동만",
|
||||||
|
"appearance": "외관",
|
||||||
|
"showWebInAppView": "앱 보기에서 소스 웹페이지 표시",
|
||||||
|
"pinUpdates": "앱 보기 상단에 업데이트 고정",
|
||||||
|
"updates": "업데이트",
|
||||||
|
"sourceSpecific": "소스별",
|
||||||
|
"appSource": "앱 소스",
|
||||||
|
"noLogs": "로그 없음",
|
||||||
|
"appLogs": "앱 로그",
|
||||||
|
"close": "닫기",
|
||||||
|
"share": "공유",
|
||||||
|
"appNotFound": "앱을 찾을 수 없습니다",
|
||||||
|
"obtainiumExportHyphenatedLowercase": "obtainium-export",
|
||||||
|
"pickAnAPK": "APK 선택",
|
||||||
|
"appHasMoreThanOnePackage": "{}에는 둘 이상의 패키지가 있습니다:",
|
||||||
|
"deviceSupportsXArch": "장치는 {} CPU 아키텍처를 지원합니다.",
|
||||||
|
"deviceSupportsFollowingArchs": "장치는 다음 CPU 아키텍처를 지원합니다:",
|
||||||
|
"warning": "경고",
|
||||||
|
"sourceIsXButPackageFromYPrompt": "앱 소스는 '{}'이지만 릴리스 패키지는 '{}'에서 제공됩니다. 계속하시겠습니까?",
|
||||||
|
"updatesAvailable": "업데이트 가능",
|
||||||
|
"updatesAvailableNotifDescription": "Obtainium이 추적하는 하나 이상의 앱에 대한 업데이트가 있음을 사용자에게 알립니다",
|
||||||
|
"noNewUpdates": "새로운 업데이트가 없습니다.",
|
||||||
|
"xHasAnUpdate": "{}에 업데이트가 있습니다.",
|
||||||
|
"appsUpdated": "앱 업데이트됨",
|
||||||
|
"appsNotUpdated": "앱 업데이트 실패",
|
||||||
|
"appsUpdatedNotifDescription": "백그라운드에서 하나 이상의 앱에 대한 업데이트가 적용되었음을 사용자에게 알립니다",
|
||||||
|
"xWasUpdatedToY": "{}가 {}로 업데이트되었습니다.",
|
||||||
|
"xWasNotUpdatedToY": "{}를 {}로 업데이트하지 못했습니다.",
|
||||||
|
"errorCheckingUpdates": "업데이트 확인 오류",
|
||||||
|
"errorCheckingUpdatesNotifDescription": "백그라운드 업데이트 확인이 실패할 때 표시되는 알림",
|
||||||
|
"appsRemoved": "앱 제거됨",
|
||||||
|
"appsRemovedNotifDescription": "로드 중 오류로 인해 하나 이상의 앱이 제거되었음을 사용자에게 알립니다",
|
||||||
|
"xWasRemovedDueToErrorY": "{}가 다음 오류로 인해 제거되었습니다: {}",
|
||||||
|
"completeAppInstallation": "앱 설치 완료",
|
||||||
|
"obtainiumMustBeOpenToInstallApps": "앱을 설치하려면 Obtainium이 열려 있어야 합니다",
|
||||||
|
"completeAppInstallationNotifDescription": "앱 설치를 완료하려면 Obtainium으로 돌아가도록 사용자에게 요청합니다",
|
||||||
|
"checkingForUpdates": "업데이트 확인 중",
|
||||||
|
"checkingForUpdatesNotifDescription": "업데이트 확인 시 나타나는 일시적인 알림",
|
||||||
|
"pleaseAllowInstallPerm": "Obtainium이 앱을 설치할 수 있도록 허용해 주세요",
|
||||||
|
"trackOnly": "추적 전용",
|
||||||
|
"errorWithHttpStatusCode": "오류 {}",
|
||||||
|
"versionCorrectionDisabled": "버전 수정 비활성화됨 (플러그인이 작동하지 않는 것 같습니다)",
|
||||||
|
"unknown": "알 수 없음",
|
||||||
|
"none": "없음",
|
||||||
|
"never": "절대",
|
||||||
|
"latestVersionX": "최신: {}",
|
||||||
|
"installedVersionX": "설치됨: {}",
|
||||||
|
"lastUpdateCheckX": "마지막 업데이트 확인: {}",
|
||||||
|
"remove": "제거",
|
||||||
|
"yesMarkUpdated": "예, 업데이트됨으로 표시",
|
||||||
|
"fdroid": "F-Droid 공식",
|
||||||
|
"appIdOrName": "앱 ID 또는 이름",
|
||||||
|
"appId": "앱 ID",
|
||||||
|
"appWithIdOrNameNotFound": "해당 ID 또는 이름의 앱을 찾을 수 없습니다",
|
||||||
|
"reposHaveMultipleApps": "저장소에는 여러 앱이 포함될 수 있습니다",
|
||||||
|
"fdroidThirdPartyRepo": "F-Droid 타사 저장소",
|
||||||
|
"install": "설치",
|
||||||
|
"markInstalled": "설치됨으로 표시",
|
||||||
|
"update": "업데이트",
|
||||||
|
"markUpdated": "업데이트됨으로 표시",
|
||||||
|
"additionalOptions": "추가 옵션",
|
||||||
|
"disableVersionDetection": "버전 감지 비활성화",
|
||||||
|
"noVersionDetectionExplanation": "이 옵션은 버전 감지가 올바르게 작동하지 않는 앱에만 사용해야 합니다.",
|
||||||
|
"downloadingX": "{} 다운로드 중",
|
||||||
|
"downloadX": "{} 다운로드",
|
||||||
|
"downloadedX": "{} 다운로드 완료",
|
||||||
|
"releaseAsset": "릴리스 자산",
|
||||||
|
"downloadNotifDescription": "앱 다운로드 진행 상황을 사용자에게 알립니다",
|
||||||
|
"noAPKFound": "APK를 찾을 수 없습니다",
|
||||||
|
"noVersionDetection": "버전 감지 없음",
|
||||||
|
"categorize": "분류",
|
||||||
|
"categories": "카테고리",
|
||||||
|
"category": "카테고리",
|
||||||
|
"noCategory": "카테고리 없음",
|
||||||
|
"noCategories": "카테고리 없음",
|
||||||
|
"deleteCategoriesQuestion": "카테고리를 삭제하시겠습니까?",
|
||||||
|
"categoryDeleteWarning": "삭제된 카테고리의 모든 앱은 미분류로 설정됩니다.",
|
||||||
|
"addCategory": "카테고리 추가",
|
||||||
|
"label": "레이블",
|
||||||
|
"language": "언어",
|
||||||
|
"copiedToClipboard": "클립보드에 복사됨",
|
||||||
|
"storagePermissionDenied": "저장소 권한 거부됨",
|
||||||
|
"selectedCategorizeWarning": "이 작업은 선택한 앱의 기존 카테고리 설정을 대체합니다.",
|
||||||
|
"filterAPKsByRegEx": "정규 표현식으로 APK 필터링",
|
||||||
|
"removeFromObtainium": "Obtainium에서 제거",
|
||||||
|
"uninstallFromDevice": "장치에서 제거",
|
||||||
|
"onlyWorksWithNonVersionDetectApps": "버전 감지가 비활성화된 앱에만 작동합니다.",
|
||||||
|
"releaseDateAsVersion": "릴리스 날짜를 버전 문자열로 사용",
|
||||||
|
"releaseTitleAsVersion": "릴리스 제목을 버전 문자열로 사용",
|
||||||
|
"releaseDateAsVersionExplanation": "이 옵션은 버전 감지가 올바르게 작동하지 않지만 릴리스 날짜가 있는 앱에만 사용해야 합니다.",
|
||||||
|
"changes": "변경 사항",
|
||||||
|
"releaseDate": "릴리스 날짜",
|
||||||
|
"importFromURLsInFile": "파일의 URL에서 가져오기 (OPML과 같은)",
|
||||||
|
"versionDetectionExplanation": "OS에서 감지된 버전과 버전 문자열 조정",
|
||||||
|
"versionDetection": "버전 감지",
|
||||||
|
"standardVersionDetection": "표준 버전 감지",
|
||||||
|
"groupByCategory": "카테고리별 그룹화",
|
||||||
|
"autoApkFilterByArch": "가능한 경우 CPU 아키텍처별로 APK 필터링 시도",
|
||||||
|
"overrideSource": "소스 재정의",
|
||||||
|
"dontShowAgain": "다시 표시하지 않기",
|
||||||
|
"dontShowTrackOnlyWarnings": "'추적 전용' 경고 표시 안 함",
|
||||||
|
"dontShowAPKOriginWarnings": "APK 출처 경고 표시 안 함",
|
||||||
|
"moveNonInstalledAppsToBottom": "설치되지 않은 앱을 앱 보기 하단으로 이동",
|
||||||
|
"gitlabPATLabel": "GitLab 개인 액세스 토큰",
|
||||||
|
"about": "정보",
|
||||||
|
"requiresCredentialsInSettings": "{}는 추가 자격 증명이 필요합니다 (설정에서)",
|
||||||
|
"checkOnStart": "시작 시 업데이트 확인",
|
||||||
|
"tryInferAppIdFromCode": "소스 코드에서 앱 ID 추론 시도",
|
||||||
|
"removeOnExternalUninstall": "외부에서 제거된 앱 자동 제거",
|
||||||
|
"pickHighestVersionCode": "가장 높은 버전 코드 APK 자동 선택",
|
||||||
|
"checkUpdateOnDetailPage": "앱 세부 정보 페이지 열 때 업데이트 확인",
|
||||||
|
"disablePageTransitions": "페이지 전환 애니메이션 비활성화",
|
||||||
|
"reversePageTransitions": "페이지 전환 애니메이션 반전",
|
||||||
|
"minStarCount": "최소 별 개수",
|
||||||
|
"addInfoBelow": "아래에 이 정보를 추가하십시오.",
|
||||||
|
"addInfoInSettings": "설정에 이 정보를 추가하십시오.",
|
||||||
|
"githubSourceNote": "GitHub 속도 제한은 API 키를 사용하여 피할 수 있습니다.",
|
||||||
|
"sortByLastLinkSegment": "링크의 마지막 세그먼트로만 정렬",
|
||||||
|
"filterReleaseNotesByRegEx": "정규 표현식으로 릴리스 노트 필터링",
|
||||||
|
"customLinkFilterRegex": "정규 표현식으로 사용자 정의 APK 링크 필터링 (기본값 '.apk$')",
|
||||||
|
"appsPossiblyUpdated": "앱 업데이트 시도됨",
|
||||||
|
"appsPossiblyUpdatedNotifDescription": "백그라운드에서 하나 이상의 앱에 대한 업데이트가 잠재적으로 적용되었음을 사용자에게 알립니다",
|
||||||
|
"xWasPossiblyUpdatedToY": "{}가 {}로 업데이트되었을 수 있습니다.",
|
||||||
|
"enableBackgroundUpdates": "백그라운드 업데이트 활성화",
|
||||||
|
"backgroundUpdateReqsExplanation": "모든 앱에 대해 백그라운드 업데이트가 가능하지 않을 수 있습니다.",
|
||||||
|
"backgroundUpdateLimitsExplanation": "백그라운드 설치의 성공 여부는 Obtainium이 열릴 때만 확인할 수 있습니다.",
|
||||||
|
"verifyLatestTag": "'최신' 태그 확인",
|
||||||
|
"intermediateLinkRegex": "'중간' 링크 방문 필터",
|
||||||
|
"filterByLinkText": "링크 텍스트로 링크 필터링",
|
||||||
|
"intermediateLinkNotFound": "중간 링크를 찾을 수 없습니다",
|
||||||
|
"intermediateLink": "중간 링크",
|
||||||
|
"exemptFromBackgroundUpdates": "백그라운드 업데이트에서 제외 (활성화된 경우)",
|
||||||
|
"bgUpdatesOnWiFiOnly": "WiFi가 아닐 때 백그라운드 업데이트 비활성화",
|
||||||
|
"bgUpdatesWhileChargingOnly": "충전 중이 아닐 때 백그라운드 업데이트 비활성화",
|
||||||
|
"autoSelectHighestVersionCode": "가장 높은 versionCode APK 자동 선택",
|
||||||
|
"versionExtractionRegEx": "버전 문자열 추출 정규 표현식",
|
||||||
|
"trimVersionString": "정규 표현식으로 버전 문자열 자르기",
|
||||||
|
"matchGroupToUseForX": "\"{}\"에 사용할 일치 그룹",
|
||||||
|
"matchGroupToUse": "버전 문자열 추출 정규 표현식에 사용할 일치 그룹",
|
||||||
|
"highlightTouchTargets": "덜 명확한 터치 대상 강조",
|
||||||
|
"pickExportDir": "내보내기 디렉토리 선택",
|
||||||
|
"autoExportOnChanges": "변경 시 자동 내보내기",
|
||||||
|
"includeSettings": "설정 포함",
|
||||||
|
"filterVersionsByRegEx": "정규 표현식으로 버전 필터링",
|
||||||
|
"trySelectingSuggestedVersionCode": "제안된 versionCode APK 선택 시도",
|
||||||
|
"dontSortReleasesList": "API에서 릴리스 순서 유지",
|
||||||
|
"reverseSort": "정렬 반전",
|
||||||
|
"takeFirstLink": "첫 번째 링크 선택",
|
||||||
|
"skipSort": "정렬 건너뛰기",
|
||||||
|
"debugMenu": "디버그 메뉴",
|
||||||
|
"bgTaskStarted": "백그라운드 작업 시작됨 - 로그를 확인하세요.",
|
||||||
|
"runBgCheckNow": "지금 백그라운드 업데이트 확인 실행",
|
||||||
|
"versionExtractWholePage": "전체 페이지에 버전 문자열 추출 정규 표현식 적용",
|
||||||
|
"installing": "설치 중",
|
||||||
|
"skipUpdateNotifications": "업데이트 알림 건너뛰기",
|
||||||
|
"updatesAvailableNotifChannel": "업데이트 가능",
|
||||||
|
"appsUpdatedNotifChannel": "앱 업데이트됨",
|
||||||
|
"appsPossiblyUpdatedNotifChannel": "앱 업데이트 시도됨",
|
||||||
|
"errorCheckingUpdatesNotifChannel": "업데이트 확인 오류",
|
||||||
|
"appsRemovedNotifChannel": "앱 제거됨",
|
||||||
|
"downloadingXNotifChannel": "{} 다운로드 중",
|
||||||
|
"completeAppInstallationNotifChannel": "앱 설치 완료",
|
||||||
|
"checkingForUpdatesNotifChannel": "업데이트 확인 중",
|
||||||
|
"onlyCheckInstalledOrTrackOnlyApps": "설치된 앱과 추적 전용 앱만 업데이트 확인",
|
||||||
|
"supportFixedAPKURL": "고정 APK URL 지원",
|
||||||
|
"selectX": "{} 선택",
|
||||||
|
"parallelDownloads": "병렬 다운로드 허용",
|
||||||
|
"useShizuku": "Shizuku 또는 Sui를 사용하여 설치",
|
||||||
|
"shizukuBinderNotFound": "Shizuku 서비스가 실행 중이 아닙니다",
|
||||||
|
"shizukuOld": "오래된 Shizuku 버전 (<11) - 업데이트 필요",
|
||||||
|
"shizukuOldAndroidWithADB": "ADB로 Android < 8.1에서 실행 중인 Shizuku - Android를 업데이트하거나 대신 Sui를 사용하세요",
|
||||||
|
"shizukuPretendToBeGooglePlay": "설치 소스로 Google Play 설정 (Shizuku 사용 시)",
|
||||||
|
"useSystemFont": "시스템 글꼴 사용",
|
||||||
|
"useVersionCodeAsOSVersion": "앱 versionCode를 OS에서 감지된 버전으로 사용",
|
||||||
|
"requestHeader": "요청 헤더",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "최신 자산 업로드를 릴리스 날짜로 사용",
|
||||||
|
"defaultPseudoVersioningMethod": "기본 의사 버전 관리 방법",
|
||||||
|
"partialAPKHash": "부분 APK 해시",
|
||||||
|
"APKLinkHash": "APK 링크 해시",
|
||||||
|
"directAPKLink": "직접 APK 링크",
|
||||||
|
"pseudoVersionInUse": "의사 버전 사용 중",
|
||||||
|
"installed": "설치됨",
|
||||||
|
"latest": "최신",
|
||||||
|
"invertRegEx": "정규 표현식 반전",
|
||||||
|
"note": "노트",
|
||||||
|
"selfHostedNote": "\"{}\" 드롭다운을 사용하여 소스의 자체 호스팅/사용자 정의 인스턴스에 도달할 수 있습니다.",
|
||||||
|
"badDownload": "APK를 구문 분석할 수 없습니다 (호환되지 않거나 부분 다운로드)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "새 앱을 AppVerifier와 공유 (가능한 경우)",
|
||||||
|
"appVerifierInstructionToast": "AppVerifier에 공유한 후 준비가 되면 여기로 돌아오세요.",
|
||||||
|
"wiki": "도움말/위키",
|
||||||
|
"crowdsourcedConfigsLabel": "크라우드소싱 앱 구성 (자신의 책임 하에 사용)",
|
||||||
|
"crowdsourcedConfigsShort": "크라우드소싱 앱 구성",
|
||||||
|
"allowInsecure": "안전하지 않은 HTTP 요청 허용",
|
||||||
|
"stayOneVersionBehind": "최신 버전보다 한 버전 뒤에 머무르기",
|
||||||
|
"refreshBeforeDownload": "다운로드 전에 앱 세부 정보 새로 고침",
|
||||||
|
"tencentAppStore": "텐센트 앱 스토어",
|
||||||
|
"removeAppQuestion": {
|
||||||
|
"one": "앱을 제거하시겠습니까?",
|
||||||
|
"other": "앱을 제거하시겠습니까?"
|
||||||
|
},
|
||||||
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
|
"one": "요청이 너무 많습니다 (속도 제한) - {}분 후에 다시 시도하세요",
|
||||||
|
"other": "요청이 너무 많습니다 (속도 제한) - {}분 후에 다시 시도하세요"
|
||||||
|
},
|
||||||
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
|
"one": "BG 업데이트 확인 중 {} 오류가 발생했습니다. {}분 후에 다시 확인을 예약합니다",
|
||||||
|
"other": "BG 업데이트 확인 중 {} 오류가 발생했습니다. {}분 후에 다시 확인을 예약합니다"
|
||||||
|
},
|
||||||
|
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||||
|
"one": "BG 업데이트 확인에서 {}개의 업데이트를 발견했습니다 - 필요 시 사용자에게 알립니다",
|
||||||
|
"other": "BG 업데이트 확인에서 {}개의 업데이트를 발견했습니다 - 필요 시 사용자에게 알립니다"
|
||||||
|
},
|
||||||
|
"apps": {
|
||||||
|
"one": "{} 앱",
|
||||||
|
"other": "{} 앱"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"one": "{} URL",
|
||||||
|
"other": "{} URL"
|
||||||
|
},
|
||||||
|
"minute": {
|
||||||
|
"one": "{} 분",
|
||||||
|
"other": "{} 분"
|
||||||
|
},
|
||||||
|
"hour": {
|
||||||
|
"one": "{} 시간",
|
||||||
|
"other": "{} 시간"
|
||||||
|
},
|
||||||
|
"day": {
|
||||||
|
"one": "{} 일",
|
||||||
|
"other": "{} 일"
|
||||||
|
},
|
||||||
|
"clearedNLogsBeforeXAfterY": {
|
||||||
|
"one": "{n}개의 로그가 지워졌습니다 (이전 = {before}, 이후 = {after})",
|
||||||
|
"other": "{n}개의 로그가 지워졌습니다 (이전 = {before}, 이후 = {after})"
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesAvailable": {
|
||||||
|
"one": "{} 및 1개의 앱에 업데이트가 있습니다.",
|
||||||
|
"other": "{} 및 {}개의 앱에 업데이트가 있습니다."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesInstalled": {
|
||||||
|
"one": "{} 및 1개의 앱이 업데이트되었습니다.",
|
||||||
|
"other": "{} 및 {}개의 앱이 업데이트되었습니다."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesFailed": {
|
||||||
|
"one": "{} 및 1개의 앱 업데이트에 실패했습니다.",
|
||||||
|
"other": "{} 및 {}개의 앱 업데이트에 실패했습니다."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||||
|
"one": "{} 및 1개의 앱이 업데이트되었을 수 있습니다.",
|
||||||
|
"other": "{} 및 {}개의 앱이 업데이트되었을 수 있습니다."
|
||||||
|
},
|
||||||
|
"apk": {
|
||||||
|
"one": "{} APK",
|
||||||
|
"other": "{} APK"
|
||||||
|
}
|
||||||
|
}
|
@ -501,7 +501,7 @@ class GitHub extends AppSource {
|
|||||||
AppNames getAppNames(String standardUrl) {
|
AppNames getAppNames(String standardUrl) {
|
||||||
String temp = standardUrl.substring(standardUrl.indexOf('://') + 3);
|
String temp = standardUrl.substring(standardUrl.indexOf('://') + 3);
|
||||||
List<String> names = temp.substring(temp.indexOf('/') + 1).split('/');
|
List<String> names = temp.substring(temp.indexOf('/') + 1).split('/');
|
||||||
return AppNames(names[0], names[1]);
|
return AppNames(names[0], names.sublist(1).join('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, List<String>>> searchCommon(
|
Future<Map<String, List<String>>> searchCommon(
|
||||||
|
@ -54,7 +54,7 @@ class GitLab extends AppSource {
|
|||||||
@override
|
@override
|
||||||
String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) {
|
String sourceSpecificStandardizeURL(String url, {bool forSelection = false}) {
|
||||||
RegExp standardUrlRegEx = RegExp(
|
RegExp standardUrlRegEx = RegExp(
|
||||||
'^https?://(www\\.)?${getSourceRegex(hosts)}/[^/]+/[^/]+',
|
'^https?://(www\\.)?${getSourceRegex(hosts)}/[^/]+(/[^/]+){1,20}',
|
||||||
caseSensitive: false);
|
caseSensitive: false);
|
||||||
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
RegExpMatch? match = standardUrlRegEx.firstMatch(url);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
@ -126,6 +126,8 @@ class GitLab extends AppSource {
|
|||||||
) async {
|
) async {
|
||||||
// Prepare request params
|
// Prepare request params
|
||||||
var names = GitHub().getAppNames(standardUrl);
|
var names = GitHub().getAppNames(standardUrl);
|
||||||
|
String projectUriComponent =
|
||||||
|
'${Uri.encodeComponent(names.author)}%2F${Uri.encodeComponent(names.name)}';
|
||||||
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
|
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
|
||||||
String optionalAuth = (PAT != null) ? 'private_token=$PAT' : '';
|
String optionalAuth = (PAT != null) ? 'private_token=$PAT' : '';
|
||||||
|
|
||||||
@ -133,7 +135,7 @@ class GitLab extends AppSource {
|
|||||||
|
|
||||||
// Get project ID
|
// Get project ID
|
||||||
Response res0 = await sourceRequest(
|
Response res0 = await sourceRequest(
|
||||||
'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}?$optionalAuth',
|
'https://${hosts[0]}/api/v4/projects/$projectUriComponent?$optionalAuth',
|
||||||
additionalSettings);
|
additionalSettings);
|
||||||
if (res0.statusCode != 200) {
|
if (res0.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res0);
|
throw getObtainiumHttpError(res0);
|
||||||
@ -145,7 +147,7 @@ class GitLab extends AppSource {
|
|||||||
|
|
||||||
// Request data from REST API
|
// Request data from REST API
|
||||||
Response res = await sourceRequest(
|
Response res = await sourceRequest(
|
||||||
'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/${trackOnly ? 'repository/tags' : 'releases'}?$optionalAuth',
|
'https://${hosts[0]}/api/v4/projects/$projectUriComponent/${trackOnly ? 'repository/tags' : 'releases'}?$optionalAuth',
|
||||||
additionalSettings);
|
additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
@ -180,7 +182,7 @@ class GitLab extends AppSource {
|
|||||||
return APKDetails(
|
return APKDetails(
|
||||||
e['tag_name'] ?? e['name'],
|
e['tag_name'] ?? e['name'],
|
||||||
getApkUrlsFromUrls(apkUrlsSet.toList()),
|
getApkUrlsFromUrls(apkUrlsSet.toList()),
|
||||||
GitHub().getAppNames(standardUrl),
|
AppNames(names.author, names.name.split('/').last),
|
||||||
releaseDate: releaseDate);
|
releaseDate: releaseDate);
|
||||||
});
|
});
|
||||||
if (apkDetailsList.isEmpty) {
|
if (apkDetailsList.isEmpty) {
|
||||||
|
@ -44,7 +44,8 @@ List<MapEntry<Locale, String>> supportedLocales = const [
|
|||||||
MapEntry(Locale('da'), 'Dansk'),
|
MapEntry(Locale('da'), 'Dansk'),
|
||||||
MapEntry(Locale('en', 'EO'),
|
MapEntry(Locale('en', 'EO'),
|
||||||
'Esperanto'), // https://github.com/aissat/easy_localization/issues/220#issuecomment-846035493
|
'Esperanto'), // https://github.com/aissat/easy_localization/issues/220#issuecomment-846035493
|
||||||
MapEntry(Locale('in'), 'Bahasa Indonesia')
|
MapEntry(Locale('in'), 'Bahasa Indonesia'),
|
||||||
|
MapEntry(Locale('ko'), '한국어'),
|
||||||
];
|
];
|
||||||
const fallbackLocale = Locale('en');
|
const fallbackLocale = Locale('en');
|
||||||
const localeDir = 'assets/translations';
|
const localeDir = 'assets/translations';
|
||||||
@ -244,6 +245,7 @@ class _ObtainiumState extends State<Obtainium> {
|
|||||||
supportedLocales: context.supportedLocales,
|
supportedLocales: context.supportedLocales,
|
||||||
locale: context.locale,
|
locale: context.locale,
|
||||||
navigatorKey: globalNavigatorKey,
|
navigatorKey: globalNavigatorKey,
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
colorScheme: settingsProvider.theme == ThemeSettings.dark
|
colorScheme: settingsProvider.theme == ThemeSettings.dark
|
||||||
|
@ -151,13 +151,15 @@ Future<File> downloadFileWithRetry(String url, String fileName,
|
|||||||
{bool useExisting = true,
|
{bool useExisting = true,
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
int retries = 3,
|
int retries = 3,
|
||||||
bool allowInsecure = false}) async {
|
bool allowInsecure = false,
|
||||||
|
LogsProvider? logs}) async {
|
||||||
try {
|
try {
|
||||||
return await downloadFile(
|
return await downloadFile(
|
||||||
url, fileName, fileNameHasExt, onProgress, destDir,
|
url, fileName, fileNameHasExt, onProgress, destDir,
|
||||||
useExisting: useExisting,
|
useExisting: useExisting,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
allowInsecure: allowInsecure);
|
allowInsecure: allowInsecure,
|
||||||
|
logs: logs);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (retries > 0 && e is ClientException) {
|
if (retries > 0 && e is ClientException) {
|
||||||
await Future.delayed(const Duration(seconds: 5));
|
await Future.delayed(const Duration(seconds: 5));
|
||||||
@ -166,7 +168,8 @@ Future<File> downloadFileWithRetry(String url, String fileName,
|
|||||||
useExisting: useExisting,
|
useExisting: useExisting,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
retries: (retries - 1),
|
retries: (retries - 1),
|
||||||
allowInsecure: allowInsecure);
|
allowInsecure: allowInsecure,
|
||||||
|
logs: logs);
|
||||||
} else {
|
} else {
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
@ -219,7 +222,8 @@ Future<File> downloadFile(String url, String fileName, bool fileNameHasExt,
|
|||||||
Function? onProgress, String destDir,
|
Function? onProgress, String destDir,
|
||||||
{bool useExisting = true,
|
{bool useExisting = true,
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
bool allowInsecure = false}) async {
|
bool allowInsecure = false,
|
||||||
|
LogsProvider? logs}) async {
|
||||||
// Send the initial request but cancel it as soon as you have the headers
|
// Send the initial request but cancel it as soon as you have the headers
|
||||||
var reqHeaders = headers ?? {};
|
var reqHeaders = headers ?? {};
|
||||||
var req = Request('GET', Uri.parse(url));
|
var req = Request('GET', Uri.parse(url));
|
||||||
@ -280,6 +284,42 @@ Future<File> downloadFile(String url, String fileName, bool fileNameHasExt,
|
|||||||
// Download to a '.temp' file (to distinguish btn. complete/incomplete files)
|
// Download to a '.temp' file (to distinguish btn. complete/incomplete files)
|
||||||
File tempDownloadedFile = File('${downloadedFile.path}.part');
|
File tempDownloadedFile = File('${downloadedFile.path}.part');
|
||||||
|
|
||||||
|
// If there is already a temp file, a download may already be in progress - account for this (see #2073)
|
||||||
|
bool tempFileExists = tempDownloadedFile.existsSync();
|
||||||
|
if (tempFileExists && useExisting) {
|
||||||
|
logs?.add(
|
||||||
|
'Partial download exists - will wait: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
bool isDownloading = true;
|
||||||
|
int currentTempFileSize = await tempDownloadedFile.length();
|
||||||
|
bool shouldReturn = false;
|
||||||
|
while (isDownloading) {
|
||||||
|
await Future.delayed(Duration(seconds: 7));
|
||||||
|
if (tempDownloadedFile.existsSync()) {
|
||||||
|
int newTempFileSize = await tempDownloadedFile.length();
|
||||||
|
if (newTempFileSize > currentTempFileSize) {
|
||||||
|
currentTempFileSize = newTempFileSize;
|
||||||
|
logs?.add(
|
||||||
|
'Existing partial download still in progress: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
} else {
|
||||||
|
logs?.add(
|
||||||
|
'Ignoring existing partial download: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
shouldReturn = downloadedFile.existsSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldReturn) {
|
||||||
|
logs?.add(
|
||||||
|
'Existing partial download completed - not repeating: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
client.close();
|
||||||
|
return downloadedFile;
|
||||||
|
} else {
|
||||||
|
logs?.add(
|
||||||
|
'Existing partial download not in progress: ${tempDownloadedFile.uri.pathSegments.last}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the range feature is not available (or you need to start a ranged req from 0),
|
// If the range feature is not available (or you need to start a ranged req from 0),
|
||||||
// complete the already-started request, else cancel it and start a ranged request,
|
// complete the already-started request, else cancel it and start a ranged request,
|
||||||
// and open the file for writing in the appropriate mode
|
// and open the file for writing in the appropriate mode
|
||||||
@ -419,9 +459,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
// Delete any partial APKs (if safe to do so)
|
// Delete any partial APKs (if safe to do so)
|
||||||
var cutoff = DateTime.now().subtract(const Duration(days: 7));
|
var cutoff = DateTime.now().subtract(const Duration(days: 7));
|
||||||
APKDir.listSync()
|
APKDir.listSync()
|
||||||
.where((element) =>
|
.where((element) => element.statSync().modified.isBefore(cutoff))
|
||||||
element.path.endsWith('.part') ||
|
|
||||||
element.statSync().modified.isBefore(cutoff))
|
|
||||||
.forEach((partialApk) {
|
.forEach((partialApk) {
|
||||||
if (!areDownloadsRunning()) {
|
if (!areDownloadsRunning()) {
|
||||||
partialApk.delete(recursive: true);
|
partialApk.delete(recursive: true);
|
||||||
@ -495,7 +533,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
prevProg = prog;
|
prevProg = prog;
|
||||||
}, APKDir.path,
|
}, APKDir.path,
|
||||||
useExisting: useExisting,
|
useExisting: useExisting,
|
||||||
allowInsecure: app.additionalSettings['allowInsecure'] == true);
|
allowInsecure: app.additionalSettings['allowInsecure'] == true,
|
||||||
|
logs: logs);
|
||||||
// Set to 90 for remaining steps, will make null in 'finally'
|
// Set to 90 for remaining steps, will make null in 'finally'
|
||||||
if (apps[app.id] != null) {
|
if (apps[app.id] != null) {
|
||||||
apps[app.id]!.downloadProgress = -1;
|
apps[app.id]!.downloadProgress = -1;
|
||||||
@ -1124,7 +1163,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
forAPKDownload:
|
forAPKDownload:
|
||||||
fileUrl.key.endsWith('.apk') ? true : false),
|
fileUrl.key.endsWith('.apk') ? true : false),
|
||||||
useExisting: false,
|
useExisting: false,
|
||||||
allowInsecure: app.additionalSettings['allowInsecure'] == true);
|
allowInsecure: app.additionalSettings['allowInsecure'] == true,
|
||||||
|
logs: logs);
|
||||||
notificationsProvider
|
notificationsProvider
|
||||||
.notify(DownloadedNotification(fileUrl.key, fileUrl.value));
|
.notify(DownloadedNotification(fileUrl.key, fileUrl.value));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -1414,8 +1454,10 @@ class AppsProvider with ChangeNotifier {
|
|||||||
app = getCorrectedInstallStatusAppIfPossible(app, info) ?? app;
|
app = getCorrectedInstallStatusAppIfPossible(app, info) ?? app;
|
||||||
}
|
}
|
||||||
if (!onlyIfExists || this.apps.containsKey(app.id)) {
|
if (!onlyIfExists || this.apps.containsKey(app.id)) {
|
||||||
File('${(await getAppsDir()).path}/${app.id}.json')
|
String filePath = '${(await getAppsDir()).path}/${app.id}.json';
|
||||||
.writeAsStringSync(jsonEncode(app.toJson()));
|
File('$filePath.tmp')
|
||||||
|
.writeAsStringSync(jsonEncode(app.toJson())); // #2089
|
||||||
|
File('$filePath.tmp').renameSync(filePath);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.apps.update(app.id,
|
this.apps.update(app.id,
|
||||||
|
36
pubspec.lock
@ -224,10 +224,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: dbus
|
name: dbus
|
||||||
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
|
sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.10"
|
version: "0.7.11"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -256,10 +256,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: easy_localization
|
name: easy_localization
|
||||||
sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201
|
sha256: "0f5239c7b8ab06c66440cfb0e9aa4b4640429c6668d5a42fe389c5de42220b12"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.7"
|
version: "3.0.7+1"
|
||||||
easy_logger:
|
easy_logger:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -405,10 +405,10 @@ packages:
|
|||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_launcher_icons
|
name: flutter_launcher_icons
|
||||||
sha256: "31cd0885738e87c72d6f055564d37fabcdacee743b396b78c7636c169cac64f5"
|
sha256: bfa04787c85d80ecb3f8777bde5fc10c3de809240c48fa061a2c2bf15ea5211c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.14.2"
|
version: "0.14.3"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -524,10 +524,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
|
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.2"
|
version: "1.3.0"
|
||||||
http_parser:
|
http_parser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -844,18 +844,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
sha256: a752ce92ea7540fc35a0d19722816e04d0e72828a4200e83a98cf1a1eb524c9a
|
sha256: c59819dacc6669a1165d54d2735a9543f136f9b3cec94ca65cea6ab8dffc422e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.5"
|
version: "2.4.0"
|
||||||
shared_preferences_android:
|
shared_preferences_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: bf808be89fe9dc467475e982c1db6c2faf3d2acf54d526cd5ec37d86c99dbd84
|
sha256: "650584dcc0a39856f369782874e562efd002a9c94aec032412c9eb81419cce1f"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.4"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1155,10 +1155,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_android
|
name: webview_flutter_android
|
||||||
sha256: d1ee28f44894cbabb1d94cc42f9980297f689ff844d067ec50ff88d86e27d63f
|
sha256: "5568f17a9c25c0fdd0737900fa1c2d1fee2d780bc212d9aec10c2d1f48ef0f59"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.3.0"
|
version: "4.3.1"
|
||||||
webview_flutter_platform_interface:
|
webview_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1171,18 +1171,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_wkwebview
|
name: webview_flutter_wkwebview
|
||||||
sha256: "4adc14ea9a770cc9e2c8f1ac734536bd40e82615bd0fa6b94be10982de656cc7"
|
sha256: "8e0593559bfecd35eb1757d6907ed6b995a41ef82607d6113df897c2805ce6be"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.17.0"
|
version: "3.18.0"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: win32
|
name: win32
|
||||||
sha256: "154360849a56b7b67331c21f09a386562d88903f90a1099c5987afc1912e1f29"
|
sha256: daf97c9d80197ed7b619040e86c8ab9a9dad285e7671ee7390f9180cc828a51e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.10.0"
|
version: "5.10.1"
|
||||||
win32_registry:
|
win32_registry:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -16,7 +16,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
|
# 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
|
# 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.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.1.39+2296
|
version: 1.1.40+2297
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.6.0
|
sdk: ^3.6.0
|
||||||
|