Compare commits

..

9 Commits

Author SHA1 Message Date
Imran
71bf23a110 Merge pull request #2427 from ImranR98/dev
Stop accidentally sharing GitHub/GitLab PATs with Codeberg, Mullvad (#2423)
2025-07-25 09:51:56 -04:00
Imran
544a1d6711 Merge pull request #2397 from Nassau123/patch-1
Patch 1
2025-07-25 09:51:17 -04:00
Imran
d43370e7f5 Delete .devcontainer/devcontainer.json 2025-07-25 09:51:02 -04:00
Imran Remtulla
c3c0525ab6 Upgrade Flutter + packages, increment version 2025-07-25 09:45:19 -04:00
Imran Remtulla
4680401808 Stop accidentally sharing GitHub/GitLab PATs with Codeberg, Mullvad (#2423) 2025-07-25 09:37:43 -04:00
Imran Remtulla
48a8ebabbb Merge remote-tracking branch 'origin/main' into dev 2025-07-20 14:32:48 -04:00
Imran
a3f0805b8e Merge pull request #2413 from LilligantMatsuri/dev
feat(i18n): Update Simplified Chinese translation
2025-07-20 14:05:21 -04:00
Matsuri
dcdf7046a6 feat(i18n): Update Simplified Chinese translation
- Translate new strings
- Correct inaccurate translations
- Other trivial improvements

Signed-off-by: Matsuri <matsuri@vmoe.info>
2025-07-19 12:00:00 +08:00
Nassau123
58c24ec6de Create devcontainer.json 2025-07-09 04:59:29 +03:00
10 changed files with 70 additions and 62 deletions

2
.gitignore vendored
View File

@@ -46,6 +46,8 @@ app.*.map.json
/android/app/profile /android/app/profile
/android/app/release /android/app/release
/android/app/.cxx /android/app/.cxx
/android/build/reports
/android/.kotlin
# Custom # Custom
TODO.txt TODO.txt

View File

@@ -23,7 +23,7 @@
"dropdownNoOptsError": "错误:下拉菜单必须包含至少一个选项", "dropdownNoOptsError": "错误:下拉菜单必须包含至少一个选项",
"colour": "配色", "colour": "配色",
"standard": "标准", "standard": "标准",
"custom": "定制", "custom": "自定义",
"useMaterialYou": "使用 Material You", "useMaterialYou": "使用 Material You",
"githubStarredRepos": "已星标的 GitHub 仓库", "githubStarredRepos": "已星标的 GitHub 仓库",
"uname": "用户名", "uname": "用户名",
@@ -50,7 +50,7 @@
"appsString": "应用列表", "appsString": "应用列表",
"noApps": "无应用", "noApps": "无应用",
"noAppsForFilter": "没有符合条件的应用", "noAppsForFilter": "没有符合条件的应用",
"byX": "者:{}", "byX": "开发者:{}",
"percentProgress": "进度:{}%", "percentProgress": "进度:{}%",
"pleaseWait": "请稍候", "pleaseWait": "请稍候",
"updateAvailable": "更新可用", "updateAvailable": "更新可用",
@@ -157,8 +157,8 @@
"appsRemovedNotifDescription": "当应用因加载出错而被删除时发送通知", "appsRemovedNotifDescription": "当应用因加载出错而被删除时发送通知",
"xWasRemovedDueToErrorY": "“{}”由于以下错误被删除:{}", "xWasRemovedDueToErrorY": "“{}”由于以下错误被删除:{}",
"completeAppInstallation": "完成应用安装", "completeAppInstallation": "完成应用安装",
"obtainiumMustBeOpenToInstallApps": "必须启 Obtainium 才能安装应用", "obtainiumMustBeOpenToInstallApps": "必须启 Obtainium 才能安装应用",
"completeAppInstallationNotifDescription": "提示返回 Obtainium 以完成应用安装", "completeAppInstallationNotifDescription": "提示返回 Obtainium 以完成应用安装",
"checkingForUpdates": "正在检查更新", "checkingForUpdates": "正在检查更新",
"checkingForUpdatesNotifDescription": "检查更新时短暂显示的通知", "checkingForUpdatesNotifDescription": "检查更新时短暂显示的通知",
"pleaseAllowInstallPerm": "请授予 Obtainium 安装应用的权限", "pleaseAllowInstallPerm": "请授予 Obtainium 安装应用的权限",
@@ -199,7 +199,7 @@
"noCategory": "无类别", "noCategory": "无类别",
"noCategories": "无类别", "noCategories": "无类别",
"deleteCategoriesQuestion": "是否删除选中的类别?", "deleteCategoriesQuestion": "是否删除选中的类别?",
"categoryDeleteWarning": "被删除类别的应用将恢复为未分类状态。", "categoryDeleteWarning": "被删除类别的应用将恢复为未分类状态。",
"addCategory": "添加类别", "addCategory": "添加类别",
"label": "标签", "label": "标签",
"language": "语言", "language": "语言",
@@ -211,7 +211,7 @@
"uninstallFromDevice": "从设备中卸载", "uninstallFromDevice": "从设备中卸载",
"onlyWorksWithNonVersionDetectApps": "仅适用于禁用版本检测的应用。", "onlyWorksWithNonVersionDetectApps": "仅适用于禁用版本检测的应用。",
"releaseDateAsVersion": "将发行日期作为版本号", "releaseDateAsVersion": "将发行日期作为版本号",
"releaseTitleAsVersion": "使用版本标题作为版本字符串", "releaseTitleAsVersion": "将发行标题作为版本字符串",
"releaseDateAsVersionExplanation": "此选项应该仅用于无法进行版本检测但能够获取发行日期的应用。", "releaseDateAsVersionExplanation": "此选项应该仅用于无法进行版本检测但能够获取发行日期的应用。",
"changes": "更新日志", "changes": "更新日志",
"releaseDate": "发行日期", "releaseDate": "发行日期",
@@ -220,8 +220,8 @@
"versionDetection": "版本检测", "versionDetection": "版本检测",
"standardVersionDetection": "常规版本检测", "standardVersionDetection": "常规版本检测",
"groupByCategory": "按类别分组显示", "groupByCategory": "按类别分组显示",
"autoApkFilterByArch": "如果可能,尝试按设备支持的 CPU 架构筛选 APK 文件", "autoApkFilterByArch": "尽可能按设备支持的 CPU 架构筛选 APK 文件",
"autoLinkFilterByArch": "尽可能按 CPU 架构过滤链接", "autoLinkFilterByArch": "尽可能按设备支持的 CPU 架构筛选链接",
"overrideSource": "覆盖来源", "overrideSource": "覆盖来源",
"dontShowAgain": "不再显示", "dontShowAgain": "不再显示",
"dontShowTrackOnlyWarnings": "忽略“仅追踪”模式警告", "dontShowTrackOnlyWarnings": "忽略“仅追踪”模式警告",
@@ -249,7 +249,7 @@
"xWasPossiblyUpdatedToY": "已尝试将“{}”更新至 {}。", "xWasPossiblyUpdatedToY": "已尝试将“{}”更新至 {}。",
"enableBackgroundUpdates": "启用全局后台更新", "enableBackgroundUpdates": "启用全局后台更新",
"backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。", "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。",
"backgroundUpdateLimitsExplanation": "只有在启 Obtainium 时才能确认安装是否成功。", "backgroundUpdateLimitsExplanation": "只有在启 Obtainium 时才能确认是否安装成功。",
"verifyLatestTag": "验证“Latest”标签", "verifyLatestTag": "验证“Latest”标签",
"intermediateLinkRegex": "筛选中转链接的正则表达式", "intermediateLinkRegex": "筛选中转链接的正则表达式",
"filterByLinkText": "根据链接文本进行筛选", "filterByLinkText": "根据链接文本进行筛选",
@@ -257,12 +257,12 @@
"intermediateLink": "中转链接", "intermediateLink": "中转链接",
"exemptFromBackgroundUpdates": "禁用后台更新(仅此应用生效,即使已启用全局后台更新)", "exemptFromBackgroundUpdates": "禁用后台更新(仅此应用生效,即使已启用全局后台更新)",
"bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新", "bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新",
"bgUpdatesWhileChargingOnly": "充电时禁用后台更新", "bgUpdatesWhileChargingOnly": "充电时禁用后台更新",
"autoSelectHighestVersionCode": "自动选择内部版本号最高的 APK 文件", "autoSelectHighestVersionCode": "自动选择内部版本号最高的 APK 文件",
"versionExtractionRegEx": "提取版本号的正则表达式", "versionExtractionRegEx": "提取版本号的正则表达式",
"trimVersionString": "使用 RegEx 修剪版本字符串", "trimVersionString": "修剪版本字符串的正则表达式",
"matchGroupToUseForX": "用于\"{}\"的匹配组", "matchGroupToUseForX": "“{}”中引用的捕获组",
"matchGroupToUse": "从上述匹配结果中引用的捕获组", "matchGroupToUse": "“提取版本字符串的正则表达式”中引用的捕获组",
"highlightTouchTargets": "突出展示不明显的可交互区域", "highlightTouchTargets": "突出展示不明显的可交互区域",
"pickExportDir": "选择导出文件夹", "pickExportDir": "选择导出文件夹",
"autoExportOnChanges": "数据变更时自动导出", "autoExportOnChanges": "数据变更时自动导出",
@@ -314,32 +314,32 @@
"beforeNewInstallsShareToAppVerifier": "通过 AppVerifier 校验新应用(如果可用)", "beforeNewInstallsShareToAppVerifier": "通过 AppVerifier 校验新应用(如果可用)",
"appVerifierInstructionToast": "分享至 AppVerifier完成后返回此处。", "appVerifierInstructionToast": "分享至 AppVerifier完成后返回此处。",
"wiki": "帮助/Wiki", "wiki": "帮助/Wiki",
"crowdsourcedConfigsLabel": "众包应用程序配置(使用风险自负", "crowdsourcedConfigsLabel": "来自社区的应用配置(谨慎使用",
"crowdsourcedConfigsShort": "众包应用程序配置", "crowdsourcedConfigsShort": "来自社区的应用配置",
"allowInsecure": "允许不安全的 HTTP 请求", "allowInsecure": "允许不安全的 HTTP 请求",
"stayOneVersionBehind": "比最新版本晚一个版本", "stayOneVersionBehind": "始终延后一个版本进行更新",
"useFirstApkOfVersion": "多个 APK 自动选择第一个", "useFirstApkOfVersion": "存在多个 APK 文件时自动选择第一个",
"refreshBeforeDownload": "下载前刷新应用程序详细信息", "refreshBeforeDownload": "下载前刷新应用详情",
"tencentAppStore": "腾讯应用宝", "tencentAppStore": "腾讯应用宝",
"coolApk": "酷安", "coolApk": "酷安",
"vivoAppStore": "vivo 应用商店(中国)", "vivoAppStore": "(中国)vivo应用商店",
"name": "名称", "name": "发行名称",
"smartname": "姓名(智能)", "smartname": "发行名称(智能)",
"sortMethod": "排序方法", "sortMethod": "排序方法",
"welcome": "欢迎光临", "welcome": "欢迎",
"documentationLinksNote": "下链接的 Obtainium GitHub 页面包含视频、文章、讨论其他资源的链接,可帮助您了解如何使用该应用程序。", "documentationLinksNote": "下链接的 GitHub 页面包含关于 Obtainium 的视频、文章、讨论其他资源,可帮助您了解本应用的使用方法。",
"batteryOptimizationNote": "请注意,如果为 Obtainium 禁用操作系统电池优化功能,后台下载可能会更稳定。", "batteryOptimizationNote": "请注意,在设置中切换为“前台服务”,并/或关闭操作系统对 Obtainium 的电池优化,可能会让后台下载更稳定。",
"fileDeletionError": "删除文件失败(尝试手动删除,然后再试一次\"{}\"", "fileDeletionError": "删除文件失败(手动删除后再次尝试\"{}\"",
"foregroundService": "获取前台服务", "foregroundService": "Obtainium 前台服务",
"foregroundServiceExplanation": "使用前台服务进行更新检查(更可靠,耗电量更大", "foregroundServiceExplanation": "使用前台服务检查更新(更稳定,但也更耗电",
"fgServiceNotice": "后台更新检查需要此通知(可在操作系统设置中隐藏)", "fgServiceNotice": "后台检查更新时需要此通知(可在操作系统设置中隐藏)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "是否删除应用?", "one": "是否删除应用?",
"other": "是否删除应用?" "other": "是否删除应用?"
}, },
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "API 请求过于频繁(速率限制)- 请在 {} 分钟后重试", "one": "请求过于频繁(API 速率限制)- 请在 {} 分钟后重试",
"other": "API 请求过于频繁(速率限制)- 请在 {} 分钟后重试" "other": "请求过于频繁(API 速率限制)- 请在 {} 分钟后重试"
}, },
"bgUpdateGotErrorRetryInMinutes": { "bgUpdateGotErrorRetryInMinutes": {
"one": "后台更新检查遇到了“{}”问题,将于 {} 分钟后重试", "one": "后台更新检查遇到了“{}”问题,将于 {} 分钟后重试",
@@ -370,27 +370,27 @@
"other": "{} 天" "other": "{} 天"
}, },
"clearedNLogsBeforeXAfterY": { "clearedNLogsBeforeXAfterY": {
"one": "清除了 {n} 日志({before} 之前{after} 之后", "one": "清除了 {n} 日志(早于 {before}晚于 {after}",
"other": "清除了 {n} 日志({before} 之前{after} 之后" "other": "清除了 {n} 日志(早于 {before}晚于 {after}"
}, },
"xAndNMoreUpdatesAvailable": { "xAndNMoreUpdatesAvailable": {
"one": "“{}”和另外 1 个应用可以更新了。", "one": "“{}”和另外 1 个应用可以更新了。",
"other": "“{}”和另外 {} 个应用可以更新了。" "other": "“{}”和另外 {} 个应用可以更新了。"
}, },
"xAndNMoreUpdatesInstalled": { "xAndNMoreUpdatesInstalled": {
"one": "{} 和另外 1 个应用已更新。", "one": "{}和另外 1 个应用已更新。",
"other": "“{}”和另外 {} 个应用已更新。" "other": "“{}”和另外 {} 个应用已更新。"
}, },
"xAndNMoreUpdatesFailed": { "xAndNMoreUpdatesFailed": {
"one": "{} 和另外 1 个应用更新失败。", "one": "{}和另外 1 个应用更新失败。",
"other": "{} 和另外 {} 个应用更新失败。" "other": "{}和另外 {} 个应用更新失败。"
}, },
"xAndNMoreUpdatesPossiblyInstalled": { "xAndNMoreUpdatesPossiblyInstalled": {
"one": "{} 和另外 1 个应用已尝试更新。", "one": "已尝试更新“{}和另外 1 个应用。",
"other": "“{}”和另外 {} 个应用已尝试更新。" "other": "已尝试更新“{}”和另外 {} 个应用。"
}, },
"apk": { "apk": {
"one": "{}APK", "one": "{} 个 APK 文件",
"other": "{}APK" "other": "{} 个 APK 文件"
} }
} }

View File

@@ -3,7 +3,7 @@ import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
class Codeberg extends AppSource { class Codeberg extends AppSource {
GitHub gh = GitHub(); GitHub gh = GitHub(hostChanged: true);
Codeberg() { Codeberg() {
name = 'Forgejo (Codeberg)'; name = 'Forgejo (Codeberg)';
hosts = ['codeberg.org']; hosts = ['codeberg.org'];

View File

@@ -112,13 +112,17 @@ class FDroid extends AppSource {
bool isGitHub = false; bool isGitHub = false;
bool isGitLab = false; bool isGitLab = false;
try { try {
GitHub().sourceSpecificStandardizeURL(details.changeLog!); GitHub(
hostChanged: true,
).sourceSpecificStandardizeURL(details.changeLog!);
isGitHub = true; isGitHub = true;
} catch (e) { } catch (e) {
// //
} }
try { try {
GitLab().sourceSpecificStandardizeURL(details.changeLog!); GitLab(
hostChanged: true,
).sourceSpecificStandardizeURL(details.changeLog!);
isGitLab = true; isGitLab = true;
} catch (e) { } catch (e) {
// //

View File

@@ -13,10 +13,11 @@ import 'package:obtainium/providers/source_provider.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
class GitHub extends AppSource { class GitHub extends AppSource {
GitHub() { GitHub({hostChanged = false}) {
hosts = ['github.com']; hosts = ['github.com'];
appIdInferIsOptional = true; appIdInferIsOptional = true;
showReleaseDateAsVersionToggle = true; showReleaseDateAsVersionToggle = true;
this.hostChanged = hostChanged;
sourceConfigSettingFormItems = [ sourceConfigSettingFormItems = [
GeneratedFormTextField( GeneratedFormTextField(

View File

@@ -12,10 +12,11 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
class GitLab extends AppSource { class GitLab extends AppSource {
GitLab() { GitLab({bool hostChanged = false}) {
hosts = ['gitlab.com']; hosts = ['gitlab.com'];
canSearch = true; canSearch = true;
showReleaseDateAsVersionToggle = true; showReleaseDateAsVersionToggle = true;
this.hostChanged = hostChanged;
sourceConfigSettingFormItems = [ sourceConfigSettingFormItems = [
GeneratedFormTextField( GeneratedFormTextField(
@@ -144,7 +145,7 @@ class GitLab extends AppSource {
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
// Prepare request params // Prepare request params
var names = GitHub().getAppNames(standardUrl); var names = GitHub(hostChanged: true).getAppNames(standardUrl);
String projectUriComponent = String projectUriComponent =
'${Uri.encodeComponent(names.author)}%2F${Uri.encodeComponent(names.name)}'; '${Uri.encodeComponent(names.author)}%2F${Uri.encodeComponent(names.name)}';
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {}); String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});

View File

@@ -55,7 +55,7 @@ class Mullvad extends AppSource {
} }
String? changeLog; String? changeLog;
try { try {
changeLog = (await GitHub().getLatestAPKDetails( changeLog = (await GitHub(hostChanged: true).getLatestAPKDetails(
'https://github.com/mullvad/mullvadvpn-app', 'https://github.com/mullvad/mullvadvpn-app',
{'fallbackToOlderReleases': true}, {'fallbackToOlderReleases': true},
)).changeLog; )).changeLog;

View File

@@ -240,10 +240,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: easy_localization name: easy_localization
sha256: "0f5239c7b8ab06c66440cfb0e9aa4b4640429c6668d5a42fe389c5de42220b12" sha256: "2ccdf9db8fe4d9c5a75c122e6275674508fd0f0d49c827354967b8afcc56bbed"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.7+1" version: "3.0.8"
easy_logger: easy_logger:
dependency: transitive dependency: transitive
description: description:
@@ -341,18 +341,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: flutter_charset_detector_android name: flutter_charset_detector_android
sha256: "443145e8fc8515b3b32aee375691e40dd59197a86a2ae153166bc88c8200d83b" sha256: "617345b0f78ad56c2633ea6132e57c2e374f6970792afbe9743237f683eeae8e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.0" version: "3.1.1"
flutter_charset_detector_darwin: flutter_charset_detector_darwin:
dependency: transitive dependency: transitive
description: description:
name: flutter_charset_detector_darwin name: flutter_charset_detector_darwin
sha256: daac20390275efb92fbb14350fe11286c5e29c7b80d6b0867f52d760f0d69763 sha256: "65d91133ea8ef06a440941b1126702b4735a8bd487430b41760e706a0b6b26d4"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.2.0"
flutter_charset_detector_platform_interface: flutter_charset_detector_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -716,10 +716,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: permission_handler name: permission_handler
sha256: "2d070d8684b68efb580a5997eb62f675e8a885ef0be6e754fb9ef489c177470f" sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "12.0.0+1" version: "12.0.1"
permission_handler_android: permission_handler_android:
dependency: transitive dependency: transitive
description: description:
@@ -1051,10 +1051,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: url_launcher name: url_launcher
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.1" version: "6.3.2"
url_launcher_android: url_launcher_android:
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: f6e6afef6e234801da77170f7a1847ded8450778caf2fe13979d140484be3678 sha256: "9573ad97890d199ac3ab32399aa33a5412163b37feb573eb5b0a76b35e9ffe41"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.7.0" version: "4.8.2"
webview_flutter_platform_interface: webview_flutter_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -1171,10 +1171,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: a3d461fe3467014e05f3ac4962e5fdde2a4bf44c561cb53e9ae5c586600fdbc3 sha256: "71523b9048cf510cfa1fd4e0a3fa5e476a66e0884d5df51d59d5023dba237107"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.22.0" version: "3.22.1"
win32: win32:
dependency: transitive dependency: transitive
description: description:

View File

@@ -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.2.0+2316 version: 1.2.1+2317
environment: environment:
sdk: ^3.8.1 sdk: ^3.8.1