diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/LogcatRecyclerAdapter.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/LogcatRecyclerAdapter.kt index 4a9c35fa..c7f92412 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/LogcatRecyclerAdapter.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/LogcatRecyclerAdapter.kt @@ -11,9 +11,15 @@ class LogcatRecyclerAdapter(val activity: LogcatActivity) : RecyclerView.Adapter override fun getItemCount() = mActivity.logsets.size override fun onBindViewHolder(holder: MainViewHolder, position: Int) { - val content = mActivity.logsets[position] - holder.itemSubSettingBinding.logContent.text = content - + val log = mActivity.logsets[position] + if (log.isEmpty()) { + holder.itemSubSettingBinding.logTag.text = "" + holder.itemSubSettingBinding.logContent.text = "" + } else { + val content = log.split("):", limit = 2) + holder.itemSubSettingBinding.logTag.text = content.first().trim() + holder.itemSubSettingBinding.logContent.text = if (content.count() > 1) content.last().trim() else "" + } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainViewHolder { diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt index a6ca521d..b8ba755b 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/MainActivity.kt @@ -391,24 +391,8 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList // true // } - R.id.sub_update -> { - importConfigViaSub() - true - } - R.id.export_all -> { - binding.pbWaiting.show() - lifecycleScope.launch(Dispatchers.IO) { - val ret = mainViewModel.exportAllServer() - launch(Dispatchers.Main) { - if (ret > 0) - toast(getString(R.string.title_export_config_count, ret)) - else - toast(R.string.toast_failure) - binding.pbWaiting.hide() - } - } - + exportAll() true } @@ -430,77 +414,31 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList } R.id.del_all_config -> { - AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm) - .setPositiveButton(android.R.string.ok) { _, _ -> - binding.pbWaiting.show() - lifecycleScope.launch(Dispatchers.IO) { - val ret = mainViewModel.removeAllServer() - launch(Dispatchers.Main) { - mainViewModel.reloadServerList() - toast(getString(R.string.title_del_config_count, ret)) - binding.pbWaiting.hide() - } - } - } - .setNegativeButton(android.R.string.cancel) { _, _ -> - //do noting - } - .show() + delAllConfig() true } R.id.del_duplicate_config -> { - AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm) - .setPositiveButton(android.R.string.ok) { _, _ -> - binding.pbWaiting.show() - lifecycleScope.launch(Dispatchers.IO) { - val ret = mainViewModel.removeDuplicateServer() - launch(Dispatchers.Main) { - mainViewModel.reloadServerList() - toast(getString(R.string.title_del_duplicate_config_count, ret)) - binding.pbWaiting.hide() - } - } - } - .setNegativeButton(android.R.string.cancel) { _, _ -> - //do noting - } - .show() + delDuplicateConfig() true } R.id.del_invalid_config -> { - AlertDialog.Builder(this).setMessage(R.string.del_invalid_config_comfirm) - .setPositiveButton(android.R.string.ok) { _, _ -> - binding.pbWaiting.show() - lifecycleScope.launch(Dispatchers.IO) { - val ret = mainViewModel.removeInvalidServer() - launch(Dispatchers.Main) { - mainViewModel.reloadServerList() - toast(getString(R.string.title_del_config_count, ret)) - binding.pbWaiting.hide() - } - } - } - .setNegativeButton(android.R.string.cancel) { _, _ -> - //do noting - } - .show() + delInvalidConfig() true } R.id.sort_by_test_results -> { - binding.pbWaiting.show() - lifecycleScope.launch(Dispatchers.IO) { - mainViewModel.sortByTestResults() - launch(Dispatchers.Main) { - mainViewModel.reloadServerList() - binding.pbWaiting.hide() - } - } + sortByTestResults() true } + R.id.sub_update -> { + importConfigViaSub() + true + } + + else -> super.onOptionsItemSelected(item) } @@ -679,6 +617,88 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList return true } + private fun exportAll() { + binding.pbWaiting.show() + lifecycleScope.launch(Dispatchers.IO) { + val ret = mainViewModel.exportAllServer() + launch(Dispatchers.Main) { + if (ret > 0) + toast(getString(R.string.title_export_config_count, ret)) + else + toast(R.string.toast_failure) + binding.pbWaiting.hide() + } + } + } + + private fun delAllConfig() { + AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm) + .setPositiveButton(android.R.string.ok) { _, _ -> + binding.pbWaiting.show() + lifecycleScope.launch(Dispatchers.IO) { + val ret = mainViewModel.removeAllServer() + launch(Dispatchers.Main) { + mainViewModel.reloadServerList() + toast(getString(R.string.title_del_config_count, ret)) + binding.pbWaiting.hide() + } + } + } + .setNegativeButton(android.R.string.cancel) { _, _ -> + //do noting + } + .show() + } + + private fun delDuplicateConfig() { + AlertDialog.Builder(this).setMessage(R.string.del_config_comfirm) + .setPositiveButton(android.R.string.ok) { _, _ -> + binding.pbWaiting.show() + lifecycleScope.launch(Dispatchers.IO) { + val ret = mainViewModel.removeDuplicateServer() + launch(Dispatchers.Main) { + mainViewModel.reloadServerList() + toast(getString(R.string.title_del_duplicate_config_count, ret)) + binding.pbWaiting.hide() + } + } + } + .setNegativeButton(android.R.string.cancel) { _, _ -> + //do noting + } + .show() + } + + private fun delInvalidConfig() { + AlertDialog.Builder(this).setMessage(R.string.del_invalid_config_comfirm) + .setPositiveButton(android.R.string.ok) { _, _ -> + binding.pbWaiting.show() + lifecycleScope.launch(Dispatchers.IO) { + val ret = mainViewModel.removeInvalidServer() + launch(Dispatchers.Main) { + mainViewModel.reloadServerList() + toast(getString(R.string.title_del_config_count, ret)) + binding.pbWaiting.hide() + } + } + } + .setNegativeButton(android.R.string.cancel) { _, _ -> + //do noting + } + .show() + } + + private fun sortByTestResults() { + binding.pbWaiting.show() + lifecycleScope.launch(Dispatchers.IO) { + mainViewModel.sortByTestResults() + launch(Dispatchers.Main) { + mainViewModel.reloadServerList() + binding.pbWaiting.hide() + } + } + } + /** * show file chooser */ @@ -772,37 +792,19 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList override fun onNavigationItemSelected(item: MenuItem): Boolean { // Handle navigation view item clicks here. when (item.itemId) { - R.id.sub_setting -> { - requestSubSettingActivity.launch(Intent(this, SubSettingActivity::class.java)) - } + R.id.sub_setting -> requestSubSettingActivity.launch(Intent(this, SubSettingActivity::class.java)) + R.id.settings -> startActivity( + Intent(this, SettingsActivity::class.java) + .putExtra("isRunning", mainViewModel.isRunning.value == true) + ) - R.id.settings -> { - startActivity( - Intent(this, SettingsActivity::class.java) - .putExtra("isRunning", mainViewModel.isRunning.value == true) - ) - } - - R.id.per_app_proxy_settings -> { - startActivity(Intent(this, PerAppProxyActivity::class.java)) - } - - R.id.routing_setting -> { - requestSubSettingActivity.launch(Intent(this, RoutingSettingActivity::class.java)) - } - - R.id.promotion -> { - Utils.openUri(this, "${Utils.decode(AppConfig.PromotionUrl)}?t=${System.currentTimeMillis()}") - } - - R.id.logcat -> { - startActivity(Intent(this, LogcatActivity::class.java)) - } - - R.id.about -> { - startActivity(Intent(this, AboutActivity::class.java)) - } + R.id.per_app_proxy_settings -> startActivity(Intent(this, PerAppProxyActivity::class.java)) + R.id.routing_setting -> requestSubSettingActivity.launch(Intent(this, RoutingSettingActivity::class.java)) + R.id.promotion -> Utils.openUri(this, "${Utils.decode(AppConfig.PromotionUrl)}?t=${System.currentTimeMillis()}") + R.id.logcat -> startActivity(Intent(this, LogcatActivity::class.java)) + R.id.about -> startActivity(Intent(this, AboutActivity::class.java)) } + binding.drawerLayout.closeDrawer(GravityCompat.START) return true } diff --git a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/RoutingSettingActivity.kt b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/RoutingSettingActivity.kt index e4fcb0c5..609f0e6c 100644 --- a/V2rayNG/app/src/main/java/com/v2ray/ang/ui/RoutingSettingActivity.kt +++ b/V2rayNG/app/src/main/java/com/v2ray/ang/ui/RoutingSettingActivity.kt @@ -38,7 +38,7 @@ class RoutingSettingActivity : BaseActivity() { private val preset_rulesets: Array by lazy { resources.getStringArray(R.array.preset_rulesets) } - + private val requestCameraPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted: Boolean -> @@ -85,87 +85,75 @@ class RoutingSettingActivity : BaseActivity() { return super.onCreateOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) { - R.id.add_rule -> { - startActivity(Intent(this, RoutingEditActivity::class.java)) - true - } + override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { + R.id.add_rule -> startActivity(Intent(this, RoutingEditActivity::class.java)).let { true } + R.id.user_asset_setting -> startActivity(Intent(this, UserAssetActivity::class.java)).let { true } + R.id.import_predefined_rulesets -> importPredefined().let { true } + R.id.import_rulesets_from_clipboard -> importFromClipboard().let { true } + R.id.import_rulesets_from_qrcode -> requestCameraPermissionLauncher.launch(Manifest.permission.CAMERA).let { true } + R.id.export_rulesets_to_clipboard -> export2Clipboard().let { true } + else -> super.onOptionsItemSelected(item) + } - R.id.user_asset_setting -> { - startActivity(Intent(this, UserAssetActivity::class.java)) - true - } - - R.id.import_predefined_rulesets -> { + private fun importPredefined() { + AlertDialog.Builder(this).setItems(preset_rulesets.asList().toTypedArray()) { _, i -> AlertDialog.Builder(this).setMessage(R.string.routing_settings_import_rulesets_tip) .setPositiveButton(android.R.string.ok) { _, _ -> - AlertDialog.Builder(this).setItems(preset_rulesets.asList().toTypedArray()) { _, i -> - try { - lifecycleScope.launch(Dispatchers.IO) { - SettingsManager.resetRoutingRulesetsFromPresets(this@RoutingSettingActivity, i) - launch(Dispatchers.Main) { - refreshData() - toast(R.string.toast_success) - } - } - } catch (e: Exception) { - e.printStackTrace() - } - }.show() - } - .setNegativeButton(android.R.string.cancel) { _, _ -> - //do nothing - } - .show() - true - } - - R.id.import_rulesets_from_clipboard -> { - AlertDialog.Builder(this).setMessage(R.string.routing_settings_import_rulesets_tip) - .setPositiveButton(android.R.string.ok) { _, _ -> - val clipboard = try { - Utils.getClipboard(this) - } catch (e: Exception) { - e.printStackTrace() - toast(R.string.toast_failure) - return@setPositiveButton - } - lifecycleScope.launch(Dispatchers.IO) { - val result = SettingsManager.resetRoutingRulesets(clipboard) - withContext(Dispatchers.Main) { - if (result) { + try { + lifecycleScope.launch(Dispatchers.IO) { + SettingsManager.resetRoutingRulesetsFromPresets(this@RoutingSettingActivity, i) + launch(Dispatchers.Main) { refreshData() toast(R.string.toast_success) - } else { - toast(R.string.toast_failure) } } + } catch (e: Exception) { + e.printStackTrace() } } .setNegativeButton(android.R.string.cancel) { _, _ -> //do nothing } .show() - true - } + }.show() + } - R.id.import_rulesets_from_qrcode -> { - requestCameraPermissionLauncher.launch(Manifest.permission.CAMERA) - true - } - - R.id.export_rulesets_to_clipboard -> { - val rulesetList = MmkvManager.decodeRoutingRulesets() - if (rulesetList.isNullOrEmpty()) { - toast(R.string.toast_failure) - } else { - Utils.setClipboard(this, JsonUtil.toJson(rulesetList)) - toast(R.string.toast_success) + private fun importFromClipboard() { + AlertDialog.Builder(this).setMessage(R.string.routing_settings_import_rulesets_tip) + .setPositiveButton(android.R.string.ok) { _, _ -> + val clipboard = try { + Utils.getClipboard(this) + } catch (e: Exception) { + e.printStackTrace() + toast(R.string.toast_failure) + return@setPositiveButton + } + lifecycleScope.launch(Dispatchers.IO) { + val result = SettingsManager.resetRoutingRulesets(clipboard) + withContext(Dispatchers.Main) { + if (result) { + refreshData() + toast(R.string.toast_success) + } else { + toast(R.string.toast_failure) + } + } + } } - true - } + .setNegativeButton(android.R.string.cancel) { _, _ -> + //do nothing + } + .show() + } - else -> super.onOptionsItemSelected(item) + private fun export2Clipboard() { + val rulesetList = MmkvManager.decodeRoutingRulesets() + if (rulesetList.isNullOrEmpty()) { + toast(R.string.toast_failure) + } else { + Utils.setClipboard(this, JsonUtil.toJson(rulesetList)) + toast(R.string.toast_success) + } } private val scanQRcodeForRulesets = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { diff --git a/V2rayNG/app/src/main/res/layout/activity_routing_setting.xml b/V2rayNG/app/src/main/res/layout/activity_routing_setting.xml index 17038020..ec98e78b 100644 --- a/V2rayNG/app/src/main/res/layout/activity_routing_setting.xml +++ b/V2rayNG/app/src/main/res/layout/activity_routing_setting.xml @@ -7,7 +7,7 @@ android:fitsSystemWindows="true" tools:context=".ui.RoutingSettingActivity"> - @@ -55,7 +55,8 @@ android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" + android:nestedScrollingEnabled="false" tools:listitem="@layout/item_recycler_routing_setting" /> - + \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/layout/activity_sub_setting.xml b/V2rayNG/app/src/main/res/layout/activity_sub_setting.xml index 769cf513..1654701d 100644 --- a/V2rayNG/app/src/main/res/layout/activity_sub_setting.xml +++ b/V2rayNG/app/src/main/res/layout/activity_sub_setting.xml @@ -1,31 +1,25 @@ - - + android:layout_height="wrap_content" + android:indeterminate="true" + android:visibility="invisible" + app:indicatorColor="@color/color_fab_active" /> - + - - \ No newline at end of file diff --git a/V2rayNG/app/src/main/res/layout/item_recycler_logcat.xml b/V2rayNG/app/src/main/res/layout/item_recycler_logcat.xml index a6cfadec..f71e28b9 100644 --- a/V2rayNG/app/src/main/res/layout/item_recycler_logcat.xml +++ b/V2rayNG/app/src/main/res/layout/item_recycler_logcat.xml @@ -13,11 +13,19 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/margin_spacing_dp8" android:paddingTop="@dimen/margin_spacing_dp8" + android:orientation="vertical" android:paddingBottom="@dimen/margin_spacing_dp8"> + +