Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 11c3dd97c3 | |||
| 92f15150cd | |||
| f8e809da8b | |||
| 12b9349e62 | |||
| a580494bde |
@@ -25,8 +25,8 @@ jobs:
|
|||||||
uses: android-actions/setup-android@v3.2.0
|
uses: android-actions/setup-android@v3.2.0
|
||||||
with:
|
with:
|
||||||
log-accepted-android-sdk-licenses: false
|
log-accepted-android-sdk-licenses: false
|
||||||
cmdline-tools-version: '12266719'
|
cmdline-tools-version: '13114758'
|
||||||
packages: 'platforms;android-35 build-tools;35.0.0 platform-tools'
|
packages: 'platforms;android-36.1 build-tools;36.1.0 platform-tools'
|
||||||
|
|
||||||
- name: Install NDK
|
- name: Install NDK
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
+1
-1
Submodule AndroidLibXrayLite updated: 16222c3387...df33063839
@@ -12,8 +12,8 @@ android {
|
|||||||
applicationId = "com.v2ray.ang"
|
applicationId = "com.v2ray.ang"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 702
|
versionCode = 703
|
||||||
versionName = "2.0.2"
|
versionName = "2.0.3"
|
||||||
multiDexEnabled = true
|
multiDexEnabled = true
|
||||||
|
|
||||||
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
|
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
|
||||||
|
|||||||
@@ -42,6 +42,13 @@
|
|||||||
"name": "xray0",
|
"name": "xray0",
|
||||||
"MTU": 1500,
|
"MTU": 1500,
|
||||||
"userLevel": 8
|
"userLevel": 8
|
||||||
|
},
|
||||||
|
"sniffing": {
|
||||||
|
"enabled": true,
|
||||||
|
"destOverride": [
|
||||||
|
"http",
|
||||||
|
"tls"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ data class V2rayConfig(
|
|||||||
var protocol: String,
|
var protocol: String,
|
||||||
var listen: String? = null,
|
var listen: String? = null,
|
||||||
var settings: InSettingsBean? = null,
|
var settings: InSettingsBean? = null,
|
||||||
val sniffing: SniffingBean? = null,
|
var sniffing: SniffingBean? = null,
|
||||||
val streamSettings: Any? = null,
|
val streamSettings: Any? = null,
|
||||||
val allocate: Any? = null
|
val allocate: Any? = null
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -398,6 +398,7 @@ object V2rayConfigManager {
|
|||||||
if (!SettingsManager.isUsingHevTun()) {
|
if (!SettingsManager.isUsingHevTun()) {
|
||||||
val inboundTun = v2rayConfig.inbounds.firstOrNull { e -> e.tag == "tun" }
|
val inboundTun = v2rayConfig.inbounds.firstOrNull { e -> e.tag == "tun" }
|
||||||
inboundTun?.settings?.mtu = SettingsManager.getVpnMtu()
|
inboundTun?.settings?.mtu = SettingsManager.getVpnMtu()
|
||||||
|
inboundTun?.sniffing = inbound1.sniffing
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(AppConfig.TAG, "Failed to configure inbounds", e)
|
Log.e(AppConfig.TAG, "Failed to configure inbounds", e)
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.v2ray.ang.ui
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common Adapter -> host callback interface that includes common actions: edit, remove and refresh.
|
||||||
|
* Extend this interface or define more specific interfaces for different adapters as needed.
|
||||||
|
*/
|
||||||
|
interface BaseAdapterListener {
|
||||||
|
/**
|
||||||
|
* Request the host to edit the specified item.
|
||||||
|
* @param guid Unique identifier (GUID) of the item
|
||||||
|
*/
|
||||||
|
fun onEdit(guid: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the host to remove the specified item. Position is provided for optional animation or validation.
|
||||||
|
* @param guid Unique identifier (GUID) of the item
|
||||||
|
* @param position Current position in the adapter (optional; host should validate it)
|
||||||
|
*/
|
||||||
|
fun onRemove(guid: String, position: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the host to share the specified URL.
|
||||||
|
* @param url The URL to be shared
|
||||||
|
*/
|
||||||
|
fun onShare(url: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the host to refresh data (for example, reload from the ViewModel or call notifyDataSetChanged).
|
||||||
|
*/
|
||||||
|
fun onRefreshData()
|
||||||
|
}
|
||||||
@@ -3,18 +3,27 @@ package com.v2ray.ang.ui
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.v2ray.ang.AppConfig
|
||||||
import com.v2ray.ang.R
|
import com.v2ray.ang.R
|
||||||
import com.v2ray.ang.databinding.ActivitySubSettingBinding
|
import com.v2ray.ang.databinding.ActivitySubSettingBinding
|
||||||
|
import com.v2ray.ang.databinding.ItemQrcodeBinding
|
||||||
|
import com.v2ray.ang.extension.toast
|
||||||
import com.v2ray.ang.extension.toastError
|
import com.v2ray.ang.extension.toastError
|
||||||
import com.v2ray.ang.extension.toastSuccess
|
import com.v2ray.ang.extension.toastSuccess
|
||||||
import com.v2ray.ang.handler.AngConfigManager
|
import com.v2ray.ang.handler.AngConfigManager
|
||||||
|
import com.v2ray.ang.handler.MmkvManager
|
||||||
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
|
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
|
||||||
|
import com.v2ray.ang.util.QRCodeDecoder
|
||||||
|
import com.v2ray.ang.util.Utils
|
||||||
import com.v2ray.ang.viewmodel.SubscriptionsViewModel
|
import com.v2ray.ang.viewmodel.SubscriptionsViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -22,17 +31,21 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
class SubSettingActivity : BaseActivity() {
|
class SubSettingActivity : BaseActivity() {
|
||||||
private val binding by lazy { ActivitySubSettingBinding.inflate(layoutInflater) }
|
private val binding by lazy { ActivitySubSettingBinding.inflate(layoutInflater) }
|
||||||
|
private val ownerActivity: SubSettingActivity
|
||||||
|
get() = this
|
||||||
private val viewModel: SubscriptionsViewModel by viewModels()
|
private val viewModel: SubscriptionsViewModel by viewModels()
|
||||||
private lateinit var adapter: SubSettingRecyclerAdapter
|
private lateinit var adapter: SubSettingRecyclerAdapter
|
||||||
private var mItemTouchHelper: ItemTouchHelper? = null
|
private var mItemTouchHelper: ItemTouchHelper? = null
|
||||||
|
private val share_method: Array<out String> by lazy {
|
||||||
|
resources.getStringArray(R.array.share_sub_method)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
//setContentView(binding.root)
|
//setContentView(binding.root)
|
||||||
setContentViewWithToolbar(binding.root, showHomeAsUp = true, title = getString(R.string.title_sub_setting))
|
setContentViewWithToolbar(binding.root, showHomeAsUp = true, title = getString(R.string.title_sub_setting))
|
||||||
|
|
||||||
adapter = SubSettingRecyclerAdapter(this, viewModel)
|
adapter = SubSettingRecyclerAdapter(viewModel, ActivityAdapterListener())
|
||||||
|
|
||||||
binding.recyclerView.setHasFixedSize(true)
|
binding.recyclerView.setHasFixedSize(true)
|
||||||
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
binding.recyclerView.layoutManager = LinearLayoutManager(this)
|
||||||
@@ -88,4 +101,62 @@ class SubSettingActivity : BaseActivity() {
|
|||||||
viewModel.reload()
|
viewModel.reload()
|
||||||
adapter.notifyDataSetChanged()
|
adapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inner class ActivityAdapterListener : BaseAdapterListener {
|
||||||
|
override fun onEdit(guid: String) {
|
||||||
|
startActivity(
|
||||||
|
Intent(ownerActivity, SubEditActivity::class.java)
|
||||||
|
.putExtra("subId", guid)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRemove(guid: String, position: Int) {
|
||||||
|
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_CONFIRM_REMOVE)) {
|
||||||
|
AlertDialog.Builder(ownerActivity)
|
||||||
|
.setMessage(R.string.del_config_comfirm)
|
||||||
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
viewModel.remove(guid)
|
||||||
|
refreshData()
|
||||||
|
}
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.show()
|
||||||
|
} else {
|
||||||
|
viewModel.remove(guid)
|
||||||
|
refreshData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onShare(url: String) {
|
||||||
|
AlertDialog.Builder(ownerActivity)
|
||||||
|
.setItems(share_method.asList().toTypedArray()) { _, i ->
|
||||||
|
try {
|
||||||
|
when (i) {
|
||||||
|
0 -> {
|
||||||
|
val ivBinding =
|
||||||
|
ItemQrcodeBinding.inflate(LayoutInflater.from(ownerActivity))
|
||||||
|
ivBinding.ivQcode.setImageBitmap(
|
||||||
|
QRCodeDecoder.createQRCode(
|
||||||
|
url
|
||||||
|
|
||||||
|
)
|
||||||
|
)
|
||||||
|
AlertDialog.Builder(ownerActivity).setView(ivBinding.root).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
Utils.setClipboard(ownerActivity, url)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> ownerActivity.toast("else")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(AppConfig.TAG, "Share subscription failed", e)
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRefreshData() {
|
||||||
|
refreshData()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,22 @@
|
|||||||
package com.v2ray.ang.ui
|
package com.v2ray.ang.ui
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.v2ray.ang.AppConfig
|
|
||||||
import com.v2ray.ang.R
|
|
||||||
import com.v2ray.ang.databinding.ItemQrcodeBinding
|
|
||||||
import com.v2ray.ang.databinding.ItemRecyclerSubSettingBinding
|
import com.v2ray.ang.databinding.ItemRecyclerSubSettingBinding
|
||||||
import com.v2ray.ang.extension.toast
|
|
||||||
import com.v2ray.ang.handler.MmkvManager
|
|
||||||
import com.v2ray.ang.helper.ItemTouchHelperAdapter
|
import com.v2ray.ang.helper.ItemTouchHelperAdapter
|
||||||
import com.v2ray.ang.helper.ItemTouchHelperViewHolder
|
import com.v2ray.ang.helper.ItemTouchHelperViewHolder
|
||||||
import com.v2ray.ang.util.QRCodeDecoder
|
|
||||||
import com.v2ray.ang.util.Utils
|
import com.v2ray.ang.util.Utils
|
||||||
import com.v2ray.ang.viewmodel.SubscriptionsViewModel
|
import com.v2ray.ang.viewmodel.SubscriptionsViewModel
|
||||||
|
|
||||||
class SubSettingRecyclerAdapter(
|
class SubSettingRecyclerAdapter(
|
||||||
val activity: SubSettingActivity,
|
private val viewModel: SubscriptionsViewModel,
|
||||||
private val viewModel: SubscriptionsViewModel
|
private val adapterListener: BaseAdapterListener?
|
||||||
) : RecyclerView.Adapter<SubSettingRecyclerAdapter.MainViewHolder>(), ItemTouchHelperAdapter {
|
) : RecyclerView.Adapter<SubSettingRecyclerAdapter.MainViewHolder>(), ItemTouchHelperAdapter {
|
||||||
|
|
||||||
private var mActivity: SubSettingActivity = activity
|
|
||||||
|
|
||||||
private val share_method: Array<out String> by lazy {
|
|
||||||
mActivity.resources.getStringArray(R.array.share_sub_method)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount() = viewModel.getAll().size
|
override fun getItemCount() = viewModel.getAll().size
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: MainViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: MainViewHolder, position: Int) {
|
||||||
@@ -45,14 +30,11 @@ class SubSettingRecyclerAdapter(
|
|||||||
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
|
holder.itemView.setBackgroundColor(Color.TRANSPARENT)
|
||||||
|
|
||||||
holder.itemSubSettingBinding.layoutEdit.setOnClickListener {
|
holder.itemSubSettingBinding.layoutEdit.setOnClickListener {
|
||||||
mActivity.startActivity(
|
adapterListener?.onEdit(subId)
|
||||||
Intent(mActivity, SubEditActivity::class.java)
|
|
||||||
.putExtra("subId", subId)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.itemSubSettingBinding.layoutRemove.setOnClickListener {
|
holder.itemSubSettingBinding.layoutRemove.setOnClickListener {
|
||||||
removeSubscription(subId, position)
|
adapterListener?.onRemove(subId, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.itemSubSettingBinding.chkEnable.setOnCheckedChangeListener { it, isChecked ->
|
holder.itemSubSettingBinding.chkEnable.setOnCheckedChangeListener { it, isChecked ->
|
||||||
@@ -72,58 +54,11 @@ class SubSettingRecyclerAdapter(
|
|||||||
holder.itemSubSettingBinding.chkEnable.visibility = View.VISIBLE
|
holder.itemSubSettingBinding.chkEnable.visibility = View.VISIBLE
|
||||||
holder.itemSubSettingBinding.layoutLastUpdated.visibility = View.VISIBLE
|
holder.itemSubSettingBinding.layoutLastUpdated.visibility = View.VISIBLE
|
||||||
holder.itemSubSettingBinding.layoutShare.setOnClickListener {
|
holder.itemSubSettingBinding.layoutShare.setOnClickListener {
|
||||||
AlertDialog.Builder(mActivity)
|
adapterListener?.onShare(subItem.url)
|
||||||
.setItems(share_method.asList().toTypedArray()) { _, i ->
|
|
||||||
try {
|
|
||||||
when (i) {
|
|
||||||
0 -> {
|
|
||||||
val ivBinding =
|
|
||||||
ItemQrcodeBinding.inflate(LayoutInflater.from(mActivity))
|
|
||||||
ivBinding.ivQcode.setImageBitmap(
|
|
||||||
QRCodeDecoder.createQRCode(
|
|
||||||
subItem.url
|
|
||||||
|
|
||||||
)
|
|
||||||
)
|
|
||||||
AlertDialog.Builder(mActivity).setView(ivBinding.root).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
1 -> {
|
|
||||||
Utils.setClipboard(mActivity, subItem.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> mActivity.toast("else")
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(AppConfig.TAG, "Share subscription failed", e)
|
|
||||||
}
|
|
||||||
}.show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSubscription(subId: String, position: Int) {
|
|
||||||
if (MmkvManager.decodeSettingsBool(AppConfig.PREF_CONFIRM_REMOVE)) {
|
|
||||||
AlertDialog.Builder(mActivity).setMessage(R.string.del_config_comfirm)
|
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
|
||||||
removeSubscriptionSub(subId, position)
|
|
||||||
}
|
|
||||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
|
||||||
//do noting
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
} else {
|
|
||||||
removeSubscriptionSub(subId, position)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun removeSubscriptionSub(subId: String, position: Int) {
|
|
||||||
viewModel.remove(subId)
|
|
||||||
notifyItemRemoved(position)
|
|
||||||
notifyItemRangeChanged(position, viewModel.getAll().size)
|
|
||||||
mActivity.refreshData()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder {
|
||||||
return MainViewHolder(
|
return MainViewHolder(
|
||||||
ItemRecyclerSubSettingBinding.inflate(
|
ItemRecyclerSubSettingBinding.inflate(
|
||||||
@@ -154,7 +89,7 @@ class SubSettingRecyclerAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemMoveCompleted() {
|
override fun onItemMoveCompleted() {
|
||||||
mActivity.refreshData()
|
adapterListener?.onRefreshData()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemDismiss(position: Int) {
|
override fun onItemDismiss(position: Int) {
|
||||||
|
|||||||
Reference in New Issue
Block a user