mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-19 14:40:06 +08:00
optimize
This commit is contained in:
parent
912de10cc3
commit
cddcd84ca6
@ -113,7 +113,7 @@ object DataStore : OnPreferenceDataStoreChangeListener {
|
|||||||
var remoteDns by configurationStore.string(Key.REMOTE_DNS) { "https://dns.google/dns-query" }
|
var remoteDns by configurationStore.string(Key.REMOTE_DNS) { "https://dns.google/dns-query" }
|
||||||
var directDns by configurationStore.string(Key.DIRECT_DNS) { "https://223.5.5.5/dns-query" }
|
var directDns by configurationStore.string(Key.DIRECT_DNS) { "https://223.5.5.5/dns-query" }
|
||||||
var enableDnsRouting by configurationStore.boolean(Key.ENABLE_DNS_ROUTING) { true }
|
var enableDnsRouting by configurationStore.boolean(Key.ENABLE_DNS_ROUTING) { true }
|
||||||
var enableFakeDns by configurationStore.boolean(Key.ENABLE_FAKEDNS)
|
var enableFakeDns by configurationStore.boolean(Key.ENABLE_FAKEDNS) { true }
|
||||||
|
|
||||||
var rulesProvider by configurationStore.stringToInt(Key.RULES_PROVIDER)
|
var rulesProvider by configurationStore.stringToInt(Key.RULES_PROVIDER)
|
||||||
var logLevel by configurationStore.stringToInt(Key.LOG_LEVEL)
|
var logLevel by configurationStore.stringToInt(Key.LOG_LEVEL)
|
||||||
@ -156,7 +156,7 @@ object DataStore : OnPreferenceDataStoreChangeListener {
|
|||||||
var connectionTestConcurrent by configurationStore.int("connectionTestConcurrent") { 5 }
|
var connectionTestConcurrent by configurationStore.int("connectionTestConcurrent") { 5 }
|
||||||
var alwaysShowAddress by configurationStore.boolean(Key.ALWAYS_SHOW_ADDRESS)
|
var alwaysShowAddress by configurationStore.boolean(Key.ALWAYS_SHOW_ADDRESS)
|
||||||
|
|
||||||
var tunImplementation by configurationStore.stringToInt(Key.TUN_IMPLEMENTATION) { TunImplementation.MIXED }
|
var tunImplementation by configurationStore.stringToInt(Key.TUN_IMPLEMENTATION) { TunImplementation.GVISOR }
|
||||||
var profileTrafficStatistics by configurationStore.boolean(Key.PROFILE_TRAFFIC_STATISTICS) { true }
|
var profileTrafficStatistics by configurationStore.boolean(Key.PROFILE_TRAFFIC_STATISTICS) { true }
|
||||||
|
|
||||||
var yacdURL by configurationStore.string("yacdURL") { "http://127.0.0.1:9090/ui" }
|
var yacdURL by configurationStore.string("yacdURL") { "http://127.0.0.1:9090/ui" }
|
||||||
|
|||||||
@ -34,6 +34,7 @@ abstract class SagerDatabase : RoomDatabase() {
|
|||||||
SagerNet.application.getDatabasePath(Key.DB_PROFILE).parentFile?.mkdirs()
|
SagerNet.application.getDatabasePath(Key.DB_PROFILE).parentFile?.mkdirs()
|
||||||
Room.databaseBuilder(SagerNet.application, SagerDatabase::class.java, Key.DB_PROFILE)
|
Room.databaseBuilder(SagerNet.application, SagerDatabase::class.java, Key.DB_PROFILE)
|
||||||
// .addMigrations(*SagerDatabase_Migrations.build())
|
// .addMigrations(*SagerDatabase_Migrations.build())
|
||||||
|
.setJournalMode(JournalMode.TRUNCATE)
|
||||||
.allowMainThreadQueries()
|
.allowMainThreadQueries()
|
||||||
.enableMultiInstanceInvalidation()
|
.enableMultiInstanceInvalidation()
|
||||||
.fallbackToDestructiveMigration()
|
.fallbackToDestructiveMigration()
|
||||||
|
|||||||
@ -16,6 +16,7 @@ abstract class PublicDatabase : RoomDatabase() {
|
|||||||
val instance by lazy {
|
val instance by lazy {
|
||||||
SagerNet.application.getDatabasePath(Key.DB_PROFILE).parentFile?.mkdirs()
|
SagerNet.application.getDatabasePath(Key.DB_PROFILE).parentFile?.mkdirs()
|
||||||
Room.databaseBuilder(SagerNet.application, PublicDatabase::class.java, Key.DB_PUBLIC)
|
Room.databaseBuilder(SagerNet.application, PublicDatabase::class.java, Key.DB_PUBLIC)
|
||||||
|
.setJournalMode(JournalMode.TRUNCATE)
|
||||||
.allowMainThreadQueries()
|
.allowMainThreadQueries()
|
||||||
.enableMultiInstanceInvalidation()
|
.enableMultiInstanceInvalidation()
|
||||||
.fallbackToDestructiveMigration()
|
.fallbackToDestructiveMigration()
|
||||||
|
|||||||
@ -248,16 +248,19 @@ fun Fragment.needReload() {
|
|||||||
|
|
||||||
fun Fragment.needRestart() {
|
fun Fragment.needRestart() {
|
||||||
snackbar(R.string.need_restart).setAction(R.string.apply) {
|
snackbar(R.string.need_restart).setAction(R.string.apply) {
|
||||||
|
triggerFullRestart(requireContext())
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun triggerFullRestart(ctx: Context) {
|
||||||
|
runOnDefaultDispatcher {
|
||||||
SagerNet.stopService()
|
SagerNet.stopService()
|
||||||
val ctx = requireContext()
|
delay(500)
|
||||||
runOnDefaultDispatcher {
|
Executable.killAll(true)
|
||||||
delay(500)
|
runOnMainDispatcher {
|
||||||
SagerDatabase.instance.close()
|
|
||||||
PublicDatabase.instance.close()
|
|
||||||
Executable.killAll(true)
|
|
||||||
ProcessPhoenix.triggerRebirth(ctx, Intent(ctx, MainActivity::class.java))
|
ProcessPhoenix.triggerRebirth(ctx, Intent(ctx, MainActivity::class.java))
|
||||||
}
|
}
|
||||||
}.show()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.getColour(@ColorRes colorRes: Int): Int {
|
fun Context.getColour(@ColorRes colorRes: Int): Int {
|
||||||
|
|||||||
@ -266,6 +266,7 @@ class AboutFragment : ToolbarFragment(R.layout.layout_about) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
Logs.w(e)
|
||||||
runOnMainDispatcher {
|
runOnMainDispatcher {
|
||||||
Toast.makeText(app, e.readableMessage, Toast.LENGTH_SHORT).show()
|
Toast.makeText(app, e.readableMessage, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import com.jakewharton.processphoenix.ProcessPhoenix
|
|||||||
import io.nekohasekai.sagernet.BuildConfig
|
import io.nekohasekai.sagernet.BuildConfig
|
||||||
import io.nekohasekai.sagernet.R
|
import io.nekohasekai.sagernet.R
|
||||||
import io.nekohasekai.sagernet.SagerNet
|
import io.nekohasekai.sagernet.SagerNet
|
||||||
|
import io.nekohasekai.sagernet.bg.Executable
|
||||||
import io.nekohasekai.sagernet.database.*
|
import io.nekohasekai.sagernet.database.*
|
||||||
import io.nekohasekai.sagernet.database.preference.KeyValuePair
|
import io.nekohasekai.sagernet.database.preference.KeyValuePair
|
||||||
import io.nekohasekai.sagernet.database.preference.PublicDatabase
|
import io.nekohasekai.sagernet.database.preference.PublicDatabase
|
||||||
@ -65,19 +66,11 @@ class BackupFragment : NamedFragment(R.layout.layout_backup) {
|
|||||||
|
|
||||||
binding.resetSettings.setOnClickListener {
|
binding.resetSettings.setOnClickListener {
|
||||||
MaterialAlertDialogBuilder(requireContext()).setTitle(R.string.confirm)
|
MaterialAlertDialogBuilder(requireContext()).setTitle(R.string.confirm)
|
||||||
.setMessage(R.string.reset_settings)
|
.setMessage(R.string.reset_settings_message)
|
||||||
.setNegativeButton(R.string.no, null)
|
.setNegativeButton(R.string.no, null)
|
||||||
.setPositiveButton(R.string.yes) { _, _ ->
|
.setPositiveButton(R.string.yes) { _, _ ->
|
||||||
runOnDefaultDispatcher {
|
DataStore.configurationStore.reset()
|
||||||
DataStore.configurationStore.reset()
|
triggerFullRestart(requireContext())
|
||||||
delay(500)
|
|
||||||
runOnMainDispatcher {
|
|
||||||
ProcessPhoenix.triggerRebirth(
|
|
||||||
requireContext(),
|
|
||||||
Intent(requireContext(), MainActivity::class.java)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
@ -251,9 +244,7 @@ class BackupFragment : NamedFragment(R.layout.layout_backup) {
|
|||||||
import.backupRules.isChecked,
|
import.backupRules.isChecked,
|
||||||
import.backupSettings.isChecked
|
import.backupSettings.isChecked
|
||||||
)
|
)
|
||||||
ProcessPhoenix.triggerRebirth(
|
triggerFullRestart(requireContext())
|
||||||
requireContext(), Intent(requireContext(), MainActivity::class.java)
|
|
||||||
)
|
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
Logs.w(it)
|
Logs.w(it)
|
||||||
onMainDispatcher {
|
onMainDispatcher {
|
||||||
|
|||||||
@ -9,9 +9,10 @@ import android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
|||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ScrollView
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.doOnLayout
|
||||||
import io.nekohasekai.sagernet.R
|
import io.nekohasekai.sagernet.R
|
||||||
import io.nekohasekai.sagernet.databinding.LayoutLogcatBinding
|
import io.nekohasekai.sagernet.databinding.LayoutLogcatBinding
|
||||||
import io.nekohasekai.sagernet.ktx.*
|
import io.nekohasekai.sagernet.ktx.*
|
||||||
@ -41,7 +42,6 @@ class LogcatFragment : ToolbarFragment(R.layout.layout_logcat),
|
|||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root, ListListener)
|
ViewCompat.setOnApplyWindowInsetsListener(binding.root, ListListener)
|
||||||
|
|
||||||
reloadSession()
|
reloadSession()
|
||||||
// TODO new logcat
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getColorForLine(line: String): ForegroundColorSpan {
|
private fun getColorForLine(line: String): ForegroundColorSpan {
|
||||||
@ -76,8 +76,15 @@ class LogcatFragment : ToolbarFragment(R.layout.layout_logcat),
|
|||||||
}
|
}
|
||||||
binding.textview.text = span
|
binding.textview.text = span
|
||||||
|
|
||||||
binding.scroolview.post {
|
// 阻止自动滚动/焦点干扰
|
||||||
binding.scroolview.fullScroll(ScrollView.FOCUS_DOWN)
|
binding.scroolview.descendantFocusability = ViewGroup.FOCUS_BLOCK_DESCENDANTS
|
||||||
|
binding.textview.isFocusable = false
|
||||||
|
binding.textview.isFocusableInTouchMode = false
|
||||||
|
binding.textview.clearFocus()
|
||||||
|
|
||||||
|
// 等 textview 完成最终 layout 再滚动到底部
|
||||||
|
binding.textview.doOnLayout {
|
||||||
|
binding.scroolview.scrollTo(0, binding.textview.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -493,4 +493,5 @@
|
|||||||
<string name="update_dialog_message">当前版本:%1$s\n可升级版本:%2$s\n是否前往下载?</string>
|
<string name="update_dialog_message">当前版本:%1$s\n可升级版本:%2$s\n是否前往下载?</string>
|
||||||
<string name="check_update_no">检查成功,但没有更新。</string>
|
<string name="check_update_no">检查成功,但没有更新。</string>
|
||||||
<string name="reset_settings">恢复默认设置</string>
|
<string name="reset_settings">恢复默认设置</string>
|
||||||
|
<string name="reset_settings_message">恢复默认设置,但节点、分组等数据将保留。如需完全清除数据,请在系统设置中直接清除应用数据。</string>
|
||||||
</resources>
|
</resources>
|
||||||
@ -573,4 +573,5 @@
|
|||||||
<string name="update_dialog_message">Current version: %1$s\nAvailable version: %2$s\nDo you want to download it?</string>
|
<string name="update_dialog_message">Current version: %1$s\nAvailable version: %2$s\nDo you want to download it?</string>
|
||||||
<string name="check_update_no">Check successful, but no updates.</string>
|
<string name="check_update_no">Check successful, but no updates.</string>
|
||||||
<string name="reset_settings">Restore default settings</string>
|
<string name="reset_settings">Restore default settings</string>
|
||||||
|
<string name="reset_settings_message">Restore default settings, but data such as nodes and groups will be retained. To completely clear data, clear application data directly in the system settings.</string>
|
||||||
</resources>
|
</resources>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
app:title="@string/service_mode"
|
app:title="@string/service_mode"
|
||||||
app:useSimpleSummaryProvider="true" />
|
app:useSimpleSummaryProvider="true" />
|
||||||
<moe.matsuri.nb4a.ui.SimpleMenuPreference
|
<moe.matsuri.nb4a.ui.SimpleMenuPreference
|
||||||
app:defaultValue="2"
|
app:defaultValue="0"
|
||||||
app:entries="@array/tun_implementation"
|
app:entries="@array/tun_implementation"
|
||||||
app:entryValues="@array/int_array_3"
|
app:entryValues="@array/int_array_3"
|
||||||
app:icon="@drawable/ic_baseline_flip_camera_android_24"
|
app:icon="@drawable/ic_baseline_flip_camera_android_24"
|
||||||
@ -181,6 +181,7 @@
|
|||||||
app:summary="@string/dns_routing_message"
|
app:summary="@string/dns_routing_message"
|
||||||
app:title="@string/enable_dns_routing" />
|
app:title="@string/enable_dns_routing" />
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
|
app:defaultValue="true"
|
||||||
app:icon="@drawable/ic_action_lock"
|
app:icon="@drawable/ic_action_lock"
|
||||||
app:key="enableFakeDns"
|
app:key="enableFakeDns"
|
||||||
app:summary="@string/fakedns_message"
|
app:summary="@string/fakedns_message"
|
||||||
|
|||||||
@ -13,9 +13,11 @@ func GoDebug(any interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeferPanicToError(name string, err func(error)) {
|
func DeferPanicToError(name string, onError func(error)) {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
s := fmt.Errorf("%s panic: %s\n%s", name, r, string(debug.Stack()))
|
if onError != nil {
|
||||||
err(s)
|
s := fmt.Errorf("%s panic: %s\n%s", name, r, string(debug.Stack()))
|
||||||
|
onError(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -207,6 +207,7 @@ func (r *httpRequest) SetContentString(content string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *httpRequest) Execute() (HTTPResponse, error) {
|
func (r *httpRequest) Execute() (HTTPResponse, error) {
|
||||||
|
defer device.DeferPanicToError("http execute", func(err error) { log.Println(err) })
|
||||||
// full direct
|
// full direct
|
||||||
if r.tryH3Direct && !r.trySocks5 {
|
if r.tryH3Direct && !r.trySocks5 {
|
||||||
return r.doH3Direct()
|
return r.doH3Direct()
|
||||||
@ -272,7 +273,7 @@ func (r *httpRequest) doH3Direct() (HTTPResponse, error) {
|
|||||||
}
|
}
|
||||||
return echClient.Do(request)
|
return echClient.Do(request)
|
||||||
},
|
},
|
||||||
// H3
|
// H3 HTTPS
|
||||||
func() (response *http.Response, err error) {
|
func() (response *http.Response, err error) {
|
||||||
request := r.request.Clone(context.Background())
|
request := r.request.Clone(context.Background())
|
||||||
h3Client := &http.Client{
|
h3Client := &http.Client{
|
||||||
@ -287,11 +288,13 @@ func (r *httpRequest) doH3Direct() (HTTPResponse, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.request.URL.Scheme == "http" {
|
||||||
|
funcs = funcs[:1]
|
||||||
|
}
|
||||||
|
|
||||||
for i, f := range funcs {
|
for i, f := range funcs {
|
||||||
go func(f requestFunc) {
|
go func(f requestFunc) {
|
||||||
defer device.DeferPanicToError("http", func(err error) {
|
defer device.DeferPanicToError("http", func(err error) { log.Println(err) })
|
||||||
log.Println(err)
|
|
||||||
})
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if successCount.Load() == 0 {
|
if successCount.Load() == 0 {
|
||||||
if failedCount.Add(1) >= uint32(len(funcs)) {
|
if failedCount.Add(1) >= uint32(len(funcs)) {
|
||||||
@ -317,17 +320,19 @@ func (r *httpRequest) doH3Direct() (HTTPResponse, error) {
|
|||||||
mu.Lock()
|
mu.Lock()
|
||||||
finalErr = errors.Join(finalErr, fmt.Errorf("%s: %w", t, err))
|
finalErr = errors.Join(finalErr, fmt.Errorf("%s: %w", t, err))
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
|
if rsp != nil && rsp.Body != nil {
|
||||||
|
rsp.Body.Close()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理 HTTP 状态码
|
// 处理 HTTP 状态码
|
||||||
if rsp.StatusCode != http.StatusOK {
|
if rsp.StatusCode != http.StatusOK {
|
||||||
hr := &httpResponse{Response: rsp}
|
hr := &httpResponse{Response: rsp}
|
||||||
err = errors.Join(finalErr, fmt.Errorf("%s: %s", t, hr.errorString()))
|
err = fmt.Errorf("%s: %s", t, hr.errorString())
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
finalErr = err
|
finalErr = errors.Join(finalErr, err)
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
rsp.Body.Close()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
PACKAGE_NAME=moe.nb4a
|
PACKAGE_NAME=moe.nb4a
|
||||||
VERSION_NAME=1.3.9
|
VERSION_NAME=1.3.9
|
||||||
PRE_VERSION_NAME=pre-1.4.0-20250903-1
|
PRE_VERSION_NAME=pre-1.4.0-20250904-1
|
||||||
VERSION_CODE=43
|
VERSION_CODE=43
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user