Skip to content

Commit 1135f68

Browse files
committed
Merge remote-tracking branch 'upstream/main' into main
2 parents 5637c46 + 2c2b6dc commit 1135f68

16 files changed

Lines changed: 114 additions & 54 deletions

File tree

app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222

2323
<uses-permission
2424
android:name="android.permission.QUERY_ALL_PACKAGES"
25-
tools:ignore="QueryAllPackagesPermission" />
25+
tools:ignore="PackageVisibilityPolicy" />
26+
<uses-permission android:name="com.android.permission.GET_INSTALLED_APPS" />
27+
2628
<uses-permission android:name="android.permission.CAMERA" />
2729
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
2830

app/src/main/java/io/nekohasekai/sagernet/ui/AppListActivity.kt

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package io.nekohasekai.sagernet.ui
22

33
import android.content.Intent
44
import android.content.pm.ApplicationInfo
5-
import android.content.pm.PackageInfo
65
import android.content.pm.PackageManager
76
import android.graphics.drawable.Drawable
87
import android.os.Bundle
@@ -45,6 +44,11 @@ import kotlin.coroutines.coroutineContext
4544
class AppListActivity : ThemedActivity() {
4645
companion object {
4746
private const val SWITCH = "switch"
47+
48+
private val cachedApps
49+
get() = PackageCache.installedPackages.toMutableMap().apply {
50+
remove(BuildConfig.APPLICATION_ID)
51+
}
4852
}
4953

5054
private class ProxiedApp(
@@ -96,7 +100,8 @@ class AppListActivity : ThemedActivity() {
96100
var filteredApps = apps
97101

98102
suspend fun reload() {
99-
apps = getCachedApps().mapNotNull { (packageName, packageInfo) ->
103+
PackageCache.reload()
104+
apps = cachedApps.mapNotNull { (packageName, packageInfo) ->
100105
coroutineContext[Job]!!.ensureActive()
101106
packageInfo.applicationInfo?.let { ProxiedApp(packageManager, it, packageName) }
102107
}.sortedWith(compareBy({ !isProxiedApp(it) }, { it.name.toString() }))
@@ -156,7 +161,7 @@ class AppListActivity : ThemedActivity() {
156161

157162
private fun initProxiedUids(str: String = DataStore.routePackages) {
158163
proxiedUids.clear()
159-
val apps = getCachedApps()
164+
val apps = cachedApps
160165
for (line in str.lineSequence()) {
161166
val app = (apps[line] ?: continue)
162167
val uid = app.applicationInfo?.uid ?: continue
@@ -174,14 +179,12 @@ class AppListActivity : ThemedActivity() {
174179
val adapter = binding.list.adapter as AppsAdapter
175180
withContext(Dispatchers.IO) { adapter.reload() }
176181
adapter.filter.filter(binding.search.text?.toString() ?: "")
177-
binding.list.crossFadeFrom(loading)
178-
}
179-
}
180-
181-
fun getCachedApps(): MutableMap<String, PackageInfo> {
182-
val packages = PackageCache.installedPackages
183-
return packages.toMutableMap().apply {
184-
remove(BuildConfig.APPLICATION_ID)
182+
if (apps.isEmpty()) {
183+
binding.list.visibility = View.GONE
184+
binding.appPlaceholder.root.crossFadeFrom(loading)
185+
} else {
186+
binding.list.crossFadeFrom(loading)
187+
}
185188
}
186189
}
187190

@@ -191,6 +194,14 @@ class AppListActivity : ThemedActivity() {
191194
binding = LayoutAppListBinding.inflate(layoutInflater)
192195
setContentView(binding.root)
193196

197+
binding.appPlaceholder.openSettings.setOnClickListener {
198+
val intent =
199+
Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
200+
data = android.net.Uri.fromParts("package", packageName, null)
201+
}
202+
startActivity(intent)
203+
}
204+
194205
setSupportActionBar(binding.toolbar)
195206
supportActionBar?.apply {
196207
setTitle(R.string.select_apps)

app/src/main/java/io/nekohasekai/sagernet/ui/AppManagerActivity.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class AppManagerActivity : ThemedActivity() {
106106
var filteredApps = apps
107107

108108
suspend fun reload() {
109+
PackageCache.reload()
109110
apps = cachedApps.mapNotNull { (packageName, packageInfo) ->
110111
coroutineContext[Job]!!.ensureActive()
111112
packageInfo.applicationInfo?.let { ProxiedApp(packageManager, it, packageName) }
@@ -184,7 +185,12 @@ class AppManagerActivity : ThemedActivity() {
184185
val adapter = binding.list.adapter as AppsAdapter
185186
withContext(Dispatchers.IO) { adapter.reload() }
186187
adapter.filter.filter(binding.search.text?.toString() ?: "")
187-
binding.list.crossFadeFrom(loading)
188+
if (apps.isEmpty()) {
189+
binding.list.visibility = View.GONE
190+
binding.appPlaceholder.root.crossFadeFrom(loading)
191+
} else {
192+
binding.list.crossFadeFrom(loading)
193+
}
188194
}
189195
}
190196

@@ -194,6 +200,14 @@ class AppManagerActivity : ThemedActivity() {
194200
binding = LayoutAppsBinding.inflate(layoutInflater)
195201
setContentView(binding.root)
196202

203+
binding.appPlaceholder.openSettings.setOnClickListener {
204+
val intent =
205+
Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
206+
data = android.net.Uri.fromParts("package", packageName, null)
207+
}
208+
startActivity(intent)
209+
}
210+
197211
setSupportActionBar(binding.toolbar)
198212
supportActionBar?.apply {
199213
setTitle(R.string.proxied_apps)

app/src/main/java/io/nekohasekai/sagernet/utils/PackageCache.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,6 @@ object PackageCache {
6767
operator fun get(uid: Int) = uidMap[uid]
6868
operator fun get(packageName: String) = packageMap[packageName]
6969

70-
suspend fun awaitLoad() {
71-
if (::packageMap.isInitialized) {
72-
return
73-
}
74-
loaded.withLock {
75-
// just await
76-
}
77-
}
78-
7970
fun awaitLoadSync() {
8071
if (::packageMap.isInitialized) {
8172
return

app/src/main/java/moe/matsuri/nb4a/net/LocalResolverImpl.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,11 @@ object LocalResolverImpl : LocalDNSTransport {
128128
// 老版本系统,继续用阻塞的 InetAddress
129129
try {
130130
val u = SagerNet.underlyingNetwork
131-
val answer = if (u != null) {
132-
u.getAllByName(domain)
133-
} else {
134-
InetAddress.getAllByName(domain)
135-
}
131+
val answer = try {
132+
u?.getAllByName(domain)
133+
} catch (e: UnknownHostException) {
134+
null
135+
} ?: InetAddress.getAllByName(domain)
136136
if (answer != null) {
137137
ctx.success(answer.mapNotNull { it.hostAddress }.joinToString("\n"))
138138
} else {

app/src/main/res/layout/layout_app_list.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,8 @@
116116
app:layout_behavior="@string/appbar_scrolling_view_behavior"
117117
tools:listitem="@layout/layout_apps_item" />
118118

119+
<include
120+
android:id="@+id/app_placeholder"
121+
layout="@layout/layout_app_placeholder" />
122+
119123
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:layout_width="match_parent"
4+
android:layout_height="match_parent"
5+
android:gravity="center"
6+
android:orientation="vertical"
7+
android:padding="32dp"
8+
android:visibility="gone">
9+
10+
<TextView
11+
android:id="@+id/empty_message"
12+
android:layout_width="wrap_content"
13+
android:layout_height="wrap_content"
14+
android:gravity="center"
15+
android:paddingBottom="16dp"
16+
android:text="@string/app_list_permission_denied"
17+
android:textColor="?attr/colorOnBackground"
18+
android:textSize="16sp" />
19+
20+
<com.google.android.material.button.MaterialButton
21+
android:id="@+id/open_settings"
22+
android:layout_width="wrap_content"
23+
android:layout_height="wrap_content"
24+
android:text="@string/open_app_settings" />
25+
</LinearLayout>

app/src/main/res/layout/layout_apps.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,8 @@
153153
app:layout_behavior="@string/appbar_scrolling_view_behavior"
154154
tools:listitem="@layout/layout_apps_item" />
155155

156+
<include
157+
android:id="@+id/app_placeholder"
158+
layout="@layout/layout_app_placeholder" />
159+
156160
</androidx.coordinatorlayout.widget.CoordinatorLayout>

app/src/main/res/values-fa/strings.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@
208208
<string name="action_trojan_go" translatable="false">Trojan Go</string>
209209
<string name="action_mieru" translatable="false">Mieru</string>
210210
<string name="action_naive" translatable="false">Naïve</string>
211-
<string name="action_ping_tunnel" translatable="false">Ping Tunnel</string>
212211
<string name="action_hysteria" translatable="false">Hysteria</string>
213212
<string name="action_ssh" translatable="false">SSH</string>
214213
<string name="action_wireguard" translatable="false">WireGuard</string>
@@ -521,10 +520,7 @@
521520
<string name="enable_ech">فعال کردن ECH</string>
522521
<string name="enable_ech_sum">فعال کردن ECH</string>
523522
<string name="ech_settings">تنظیمات ECH</string>
524-
<string name="pq_signature_schemes_enabled">فعال کردن پشتیبانی از امضای مجوز post-quantum همتا</string>
525-
<string name="dynamic_record_sizing_disabled">اندازه تطبیقی ​​رکوردهای TLS را غیرفعال می‌کند</string>
526523
<string name="ech_config">پیکربندی ECH</string>
527-
<string name="dynamic_record_sizing_sum">اگر فعال باشد، همیشه از بزرگترین اندازه رکورد TLS ممکن استفاده می‌شود. در صورت غیرفعال کردن، اندازه رکوردهای TLS ممکن است در تلاش برای بهبود تاخیر تنظیم شود.</string>
528524
<string name="http_upgrade_host">میزبان HTTPUpgrade</string>
529525
<string name="http_upgrade_path">مسیر HTTPUpgrade</string>
530526
<string name="update_current_subscription">به‌روزرسانی اشتراک این گروه</string>

app/src/main/res/values-ru/strings.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@
7575
<string name="chain_settings">Настройки цепочки</string>
7676
<string name="character_counter_content_description">Введено символов: %1$d из %2$d</string>
7777
<string name="character_counter_overflowed_content_description">Превышено ограничение на количество символов (%1$d из %2$d)</string>
78+
<string name="check_update_no">Обновления не найдены.</string>
79+
<string name="check_update_preview">Проверить наличие обновлений предварительной версии</string>
80+
<string name="check_update_release">Проверить наличие обновлений релизнойной версии</string>
7881
<string name="circular_reference">Циклическая ссылка</string>
7982
<string name="circular_reference_sum">Маршрут не может содержать сам себя.</string>
8083
<string name="clear_logcat">Очистить журнал</string>
@@ -250,6 +253,7 @@
250253
<string name="menu_traffic">Трафик</string>
251254
<string name="metered">Подсказка о соединении с лимитным тарифным планом</string>
252255
<string name="metered_summary">Подсказывать системе, что VPN следует рассматривать как сеть с лимитным тарифным планом</string>
256+
<string name="minimize">Свернуть</string>
253257
<string name="missing_plugin">Отсутствующий плагин</string>
254258
<string name="move">Переместить</string>
255259
<string name="mtrl_badge_numberless_content_description">Новое уведомление</string>
@@ -319,6 +323,7 @@
319323
<string name="port_transproxy">Транспрокси-порт</string>
320324
<string name="prefer">Предпочитать</string>
321325
<string name="preference_copied">Текст "%1$s" скопирован в буфер обмена</string>
326+
<string name="preview_version_hint">Это приложение является предварительной версией и может содержать множество проблем. Если вы не хотите тестировать его, скачайте релизную версию с GitHub!</string>
322327
<string name="profile_config">Конфигурация профиля</string>
323328
<string name="profile_empty">Пожалуйста, выберите профиль</string>
324329
<string name="profile_import">Импортировать профиль</string>
@@ -342,6 +347,8 @@
342347
<string name="remote_dns">Удаленный DNS</string>
343348
<string name="remove_duplicate">Удалить дубликаты серверов</string>
344349
<string name="reset_connections">Сбросить соединения</string>
350+
<string name="reset_settings">Восстановить настройки по умолчанию</string>
351+
<string name="reset_settings_message">Восстановить настройки по умолчанию, такие данные, как узлы и группы, будут сохранены. Для полной очистки данных, очистите данные приложения непосредственно в системных настройках.</string>
345352
<string name="resolve_destination">Определить адрес назначения</string>
346353
<string name="resolve_destination_summary">Если адрес назначения является доменом, то он передается в соответствии с правилом IPv6.</string>
347354
<string name="route_add">Создать маршрут</string>
@@ -404,7 +411,7 @@
404411
<string name="sniff_routing">Перехватывать результат для Маршрутизации</string>
405412
<string name="speed">%s/с</string>
406413
<string name="speed_detail">Прокси :%1$s↑ %2$s↓
407-
Прямой :%3$s↑%4$s↓</string>
414+
\nПрямой :%3$s↑%4$s↓</string>
408415
<string name="speed_interval">Интервал обновления уведомлений о скорости</string>
409416
<string name="ss_cat">Настройки Shadowsocks</string>
410417
<string name="ssh_auth_type_none">Без аутентификации</string>
@@ -453,6 +460,8 @@
453460
<string name="unsaved_changes_prompt">Есть несохраненные изменения. Сохранить?</string>
454461
<string name="update_all_subscription">Обновить все подписки</string>
455462
<string name="update_current_subscription">Обновить подписку текущей группы</string>
463+
<string name="update_dialog_message">Текущая версия: %1$s\nДоступная версия: %2$s\nХотите загрузить её?</string>
464+
<string name="update_dialog_title">Доступна новая версия</string>
456465
<string name="update_settings">Обновить настройки</string>
457466
<string name="update_subscription_warning">Прокси-сервер не подключен, вы уверены, что хотите продолжить обновление?</string>
458467
<string name="update_when_connected_only">Обновлять только при подключении</string>

0 commit comments

Comments
 (0)