You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
if (subscriptions.isNotEmpty()) for (profile in subscriptions) {
if (legacySubscriptions.isNotEmpty()) for (profile in legacySubscriptions) {
val subscription = profile.subscription!!
if (((System.currentTimeMillis() / 1000).toInt() - subscription.lastUpdated) < subscription.autoUpdateDelay * 60) {
}
\ No newline at end of file
diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt b/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt
index b975695..966131f 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt
@@ -46,6 +46,7 @@ import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSSettingsActivity
data class ProxyEntity( @PrimaryKey(autoGenerate = true) var id: Long = 0L,
var groupId: Long = 0L,
@ColumnInfo(defaultValue = "0") var subscriptionId: Long = 0L,
var type: Int = 0,
var userOrder: Long = 0L,
var tx: Long = 0L,
@@ -119,10 +120,11 @@ data class ProxyEntity(
}
override fun serializeToBuffer(output: ByteBufferOutput) {
if (version >= 1) subscriptionId = input.readLong()
type = input.readInt()
userOrder = input.readLong()
tx = input.readLong()
@@ -491,6 +494,15 @@ data class ProxyEntity( @query("SELECT * FROM proxy_entities WHERE groupId = :groupId ORDER BY userOrder")
fun getByGroup(groupId: Long): List
@Query("SELECT * FROM proxy_entities WHERE groupId = :groupId AND subscriptionId = :subscriptionId ORDER BY userOrder")
fun getByGroupAndSubscription(groupId: Long, subscriptionId: Long): List<ProxyEntity>
@Query("DELETE FROM proxy_entities WHERE subscriptionId = :subscriptionId")
fun deleteBySubscription(subscriptionId: Long)
@Query("DELETE FROM proxy_entities WHERE groupId = :groupId AND subscriptionId = :subscriptionId")
fun deleteByGroupAndSubscription(groupId: Long, subscriptionId: Long)
@Query("SELECT * FROM proxy_entities WHERE id in (:proxyIds)")
fun getEntities(proxyIds: List<Long>): List<ProxyEntity>
if (proxyGroup.name?.startsWith("Subscription #") == true) {
val currentName = groupRef?.name ?: entityRef?.name
if (currentName?.startsWith("Subscription #") == true) {
var remoteName = Util.getStringBox(response.getHeader("content-disposition"))
if (remoteName.isNotBlank()) {
remoteName = Util.decodeFilename(remoteName)
if (remoteName.isNotBlank()) {
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_add_subscription.xml b/app/src/main/res/layout/dialog_add_subscription.xml
new file mode 100644
index 0000000..b35f56b
--- /dev/null
+++ b/app/src/main/res/layout/dialog_add_subscription.xml
@@ -0,0 +1,34 @@
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1995ff0..6664c72 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -579,4 +579,21 @@
Minimize
Unable to read installed apps.\nThis is usually because the system has restricted app read permissions.\nPlease grant permissions in the system settings.
Open System Settings
+ Add subscription to this group
+ Manage subscriptions
+ Merge into another group
+ Subscription name (optional)
+ Subscription link
+ Auto update
+ Please enter a subscription link
+ No subscriptions in this group
+ Update
+ Edit subscription
+ Delete subscription
+ Delete this subscription and all its proxies?
+ No other groups to merge into
+ Merge \"%1$s\" into \"%2$s\"?\nIts subscriptions and proxies will be moved into the target group, and this group will be deleted.
+ %1$d nodes · %2$d subscriptions
+ Updated %1$s
+ Never updated
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 7d843ab..e76e3a6 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,7 +6,9 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -Dfile.encoding=UTF-8
+org.gradle.jvmargs=-Xmx1536m -XX:+UseParallelGC -Dfile.encoding=UTF-8
+org.gradle.workers.max=2
+kotlin.daemon.jvmargs=-Xmx1024m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
diff --git a/release.keystore b/release.keystore
index 91dcf36..bdfc3a7 100644
Binary files a/release.keystore and b/release.keystore differ
Activity
fuoins commentedon Sep 11, 2026
diff --git a/app/src/main/java/io/nekohasekai/sagernet/bg/SubscriptionUpdater.kt b/app/src/main/java/io/nekohasekai/sagernet/bg/SubscriptionUpdater.kt
index a000672..ce56d7e 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/bg/SubscriptionUpdater.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/bg/SubscriptionUpdater.kt
@@ -23,17 +23,26 @@ object SubscriptionUpdater {
suspend fun reconfigureUpdater() {
RemoteWorkManager.getInstance(app).cancelUniqueWork(WORK_NAME)
@@ -62,14 +71,17 @@ object SubscriptionUpdater {
.setCategory(NotificationCompat.CATEGORY_SERVICE)
@@ -88,6 +100,25 @@ object SubscriptionUpdater {
GroupUpdater.executeUpdate(profile, false)
}
diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/GroupManager.kt b/app/src/main/java/io/nekohasekai/sagernet/database/GroupManager.kt
index b2688f4..e73f1e7 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/database/GroupManager.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/database/GroupManager.kt
@@ -12,6 +12,10 @@ object GroupManager {
}
interface Interface {
@@ -98,6 +102,7 @@ object GroupManager {
}
suspend fun deleteGroup(groupId: Long) {
@@ -105,10 +110,77 @@ object GroupManager {
}
}
suspend fun createSubscription(entity: SubscriptionEntity): SubscriptionEntity {
}
suspend fun updateSubscription(entity: SubscriptionEntity) {
}
suspend fun deleteSubscription(entity: SubscriptionEntity) {
}
/**
suspend fun mergeGroup(sourceId: Long, targetId: Long) {
}
}
\ No newline at end of file
diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt b/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt
index b975695..966131f 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt
@@ -46,6 +46,7 @@ import moe.matsuri.nb4a.proxy.shadowtls.ShadowTLSSettingsActivity
data class ProxyEntity(
@PrimaryKey(autoGenerate = true) var id: Long = 0L,
var groupId: Long = 0L,
@ColumnInfo(defaultValue = "0") var subscriptionId: Long = 0L,
var type: Int = 0,
var userOrder: Long = 0L,
var tx: Long = 0L,
@@ -119,10 +120,11 @@ data class ProxyEntity(
}
override fun serializeToBuffer(output: ByteBufferOutput) {
@@ -144,6 +146,7 @@ data class ProxyEntity(
@@ -491,6 +494,15 @@ data class ProxyEntity(
@query("SELECT * FROM proxy_entities WHERE groupId = :groupId ORDER BY userOrder")
fun getByGroup(groupId: Long): List
diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/SagerDatabase.kt b/app/src/main/java/io/nekohasekai/sagernet/database/SagerDatabase.kt
index ececc10..42c3412 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/database/SagerDatabase.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/database/SagerDatabase.kt
@@ -15,12 +15,13 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@database(
autoMigrations = [
AutoMigration(from = 3, to = 4),
AutoMigration(from = 4, to = 5),
]
)
@TypeConverters(value = [KryoConverters::class, GsonConverters::class])
@@ -44,12 +45,14 @@ abstract class SagerDatabase : RoomDatabase() {
}
abstract fun groupDao(): ProxyGroup.Dao
abstract fun proxyDao(): ProxyEntity.Dao
abstract fun subscriptionDao(): SubscriptionEntity.Dao
abstract fun rulesDao(): RuleEntity.Dao
}
diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/SubscriptionEntity.kt b/app/src/main/java/io/nekohasekai/sagernet/database/SubscriptionEntity.kt
new file mode 100644
index 0000000..8001d6b
--- /dev/null
+++ b/app/src/main/java/io/nekohasekai/sagernet/database/SubscriptionEntity.kt
@@ -0,0 +1,58 @@
+package io.nekohasekai.sagernet.database
+
+import androidx.room.*
+
+/**
*/
+@entity(tableName = "subscriptions")
+data class SubscriptionEntity(
@PrimaryKey(autoGenerate = true) var id: Long = 0L,
var userOrder: Long = 0L,
var name: String? = null,
@ColumnInfo(defaultValue = "0") var groupId: Long = 0L,
var bean: SubscriptionBean? = null
+) {
fun displayName(): String {
}
@androidx.room.Dao
interface Dao {
}
+}
diff --git a/app/src/main/java/io/nekohasekai/sagernet/group/GroupUpdater.kt b/app/src/main/java/io/nekohasekai/sagernet/group/GroupUpdater.kt
index 426e3d7..41a3db5 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/group/GroupUpdater.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/group/GroupUpdater.kt
@@ -4,7 +4,9 @@ import io.nekohasekai.sagernet.*
import io.nekohasekai.sagernet.database.DataStore
import io.nekohasekai.sagernet.database.GroupManager
import io.nekohasekai.sagernet.database.ProxyGroup
+import io.nekohasekai.sagernet.database.SagerDatabase
import io.nekohasekai.sagernet.database.SubscriptionBean
+import io.nekohasekai.sagernet.database.SubscriptionEntity
import io.nekohasekai.sagernet.fmt.AbstractBean
import io.nekohasekai.sagernet.fmt.http.HttpBean
import io.nekohasekai.sagernet.fmt.hysteria.HysteriaBean
@@ -130,6 +132,45 @@ abstract class GroupUpdater {
}
}
@@ -161,9 +202,13 @@ abstract class GroupUpdater {
}
diff --git a/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt b/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt
index a759799..d2cd221 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt
@@ -1,6 +1,7 @@
package io.nekohasekai.sagernet.group
import android.annotation.SuppressLint
+import io.nekohasekai.sagernet.GroupType
import io.nekohasekai.sagernet.R
import io.nekohasekai.sagernet.database.*
import io.nekohasekai.sagernet.fmt.AbstractBean
@@ -44,6 +45,43 @@ object RawUpdater : GroupUpdater() {
userInterface: GroupManager.Interface?,
byUser: Boolean
) {
}
suspend fun doUpdate(
) {
}
private suspend fun doUpdateCore(
) {
@@ -76,12 +114,13 @@ object RawUpdater : GroupUpdater() {
Util.getStringBox(response.getHeader("Subscription-Userinfo"))
@@ -102,9 +141,13 @@ object RawUpdater : GroupUpdater() {
}
proxies = proxiesMap.values.toList()
@@ -190,7 +233,7 @@ object RawUpdater : GroupUpdater() {
changed++
SagerDatabase.proxyDao.addProxy(
ProxyEntity(
@@ -208,18 +251,30 @@ object RawUpdater : GroupUpdater() {
Logs.d("Deleted profiles: $it")
}
diff --git a/app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt b/app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt
index 0540910..5f063d8 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/ui/ConfigurationFragment.kt
@@ -447,12 +447,20 @@ class ConfigurationFragment @jvmoverloads constructor(
diff --git a/app/src/main/java/io/nekohasekai/sagernet/ui/GroupFragment.kt b/app/src/main/java/io/nekohasekai/sagernet/ui/GroupFragment.kt
index 840234b..46c39df 100644
--- a/app/src/main/java/io/nekohasekai/sagernet/ui/GroupFragment.kt
+++ b/app/src/main/java/io/nekohasekai/sagernet/ui/GroupFragment.kt
@@ -2,11 +2,17 @@ package io.nekohasekai.sagernet.ui
import android.content.Intent
import android.os.Bundle
+import android.text.TextUtils
import android.text.format.Formatter
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
+import android.widget.Button
+import android.widget.EditText
import android.widget.LinearLayout
+import android.widget.ScrollView
+import android.widget.TextView
+import com.google.android.material.switchmaterial.SwitchMaterial
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.Toolbar
@@ -122,6 +128,10 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group),
.forEach {
GroupUpdater.startUpdate(it, true)
}
@@ -300,6 +310,18 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group),
}
}
}
override fun onDestroy() {
@@ -372,6 +394,18 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group),
.setNegativeButton(android.R.string.cancel, null)
.show()
}
@@ -394,7 +428,7 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group),
}
@@ -406,8 +440,16 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group),
if (proxyGroup.type != GroupType.SUBSCRIPTION) {
popup.menu.removeItem(R.id.action_share_subscription)
}
@@ -513,9 +555,20 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group),
@@ -523,7 +576,7 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group),
}
}
@@ -542,6 +595,221 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group),
}
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_add_subscription.xml b/app/src/main/res/layout/dialog_add_subscription.xml
new file mode 100644
index 0000000..b35f56b
--- /dev/null
+++ b/app/src/main/res/layout/dialog_add_subscription.xml
@@ -0,0 +1,34 @@
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+
diff --git a/app/src/main/res/menu/group_action_menu.xml b/app/src/main/res/menu/group_action_menu.xml
index f749f3d..a18e253 100644
--- a/app/src/main/res/menu/group_action_menu.xml
+++ b/app/src/main/res/menu/group_action_menu.xml
@@ -24,6 +24,15 @@
android:title="@string/action_export_file" />
- <item
-
-
- <item
-
-
- <item
-
-
- 添加订阅到本组
- 管理订阅
- 并入其他分组
- 订阅名称(可选)
- 订阅链接
- 自动更新
- 请输入订阅链接
- 本组暂无订阅
- 更新
- 编辑订阅
- 删除订阅
- 确定删除该订阅及其全部节点吗?
- 没有其他分组可合并
- 将“%1$s”并入“%2$s”?\n其订阅与节点会移入目标分组,原分组将被删除。
- %1$d 个节点 · %2$d 个订阅
- 更新于 %1$s
- 尚未更新
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1995ff0..6664c72 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -579,4 +579,21 @@ Minimize Unable to read installed apps.\nThis is usually because the system has restricted app read permissions.\nPlease grant permissions in the system settings. Open System Settings + Add subscription to this group + Manage subscriptions + Merge into another group + Subscription name (optional) + Subscription link + Auto update + Please enter a subscription link + No subscriptions in this group + Update + Edit subscription + Delete subscription + Delete this subscription and all its proxies? + No other groups to merge into + Merge \"%1$s\" into \"%2$s\"?\nIts subscriptions and proxies will be moved into the target group, and this group will be deleted. + %1$d nodes · %2$d subscriptions + Updated %1$s + Never updated \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 7d843ab..e76e3a6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,9 @@ # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx1536m -XX:+UseParallelGC -Dfile.encoding=UTF-8 +org.gradle.workers.max=2 +kotlin.daemon.jvmargs=-Xmx1024m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects diff --git a/release.keystore b/release.keystore index 91dcf36..bdfc3a7 100644 Binary files a/release.keystore and b/release.keystore differdiff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index a9f0c1c..c9f7c96 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -499,4 +499,21 @@
最小化
无法读取已安装的应用。\n这通常是由于系统限制了应用的读取权限(例如某些中国厂商系统)。\n请在系统设置中授予权限。
打开系统设置