Unverified Commit f053a62f authored by Mygod's avatar Mygod Committed by GitHub

Migrate to Android X (#1881)

* Initial draft for porting to Android X

* Use Android KTX

* Fix wrong constants

* Fix code style

* Migrate to NavigationView

* Fix deprecation

* Update dependencies
parent ff0cd960
...@@ -9,13 +9,12 @@ buildscript { ...@@ -9,13 +9,12 @@ buildscript {
sdkVersion = 28 sdkVersion = 28
compileSdkVersion = 28 compileSdkVersion = 28
buildToolsVersion = '28.0.1' buildToolsVersion = '28.0.1'
supportLibraryVersion = '28.0.0-alpha3' androidxVersion = '1.0.0-beta01'
takisoftFixVersion = '27.1.1.2'
roomVersion = '1.1.1' roomVersion = '1.1.1'
workVersion = '1.0.0-alpha04' workVersion = '1.0.0-alpha04'
junitVersion = '4.12' junitVersion = '4.12'
androidTestVersion = '1.0.2' androidTestVersion = '1.1.0-alpha3'
androidEspressoVersion = '3.0.2' androidEspressoVersion = '3.1.0-alpha3'
} }
repositories { repositories {
...@@ -29,7 +28,7 @@ buildscript { ...@@ -29,7 +28,7 @@ buildscript {
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.2.0-beta03' classpath 'com.android.tools.build:gradle:3.2.0-beta03'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
classpath 'com.google.gms:google-services:4.0.1' classpath 'com.google.gms:google-services:4.0.2'
classpath 'io.fabric.tools:gradle:1.25.4' classpath 'io.fabric.tools:gradle:1.25.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
} }
......
...@@ -12,7 +12,7 @@ android { ...@@ -12,7 +12,7 @@ android {
versionCode 1 versionCode 1
versionName "1.0.0" versionName "1.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild { externalNativeBuild {
ndkBuild { ndkBuild {
...@@ -65,6 +65,6 @@ tasks.whenTaskAdded { task -> ...@@ -65,6 +65,6 @@ tasks.whenTaskAdded { task ->
dependencies { dependencies {
api project(':plugin') api project(':plugin')
testImplementation "junit:junit:$junitVersion" testImplementation "junit:junit:$junitVersion"
androidTestImplementation "com.android.support.test:runner:$androidTestVersion" androidTestImplementation "androidx.test:runner:$androidTestVersion"
androidTestImplementation "com.android.support.test.espresso:espresso-core:$androidEspressoVersion" androidTestImplementation "androidx.test.espresso:espresso-core:$androidEspressoVersion"
} }
package com.github.shadowsocks; package com.github.shadowsocks;
import android.content.Context; import android.content.Context;
import android.support.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
......
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,8 @@
package com.github.shadowsocks; package com.github.shadowsocks;
import android.os.Build; import android.os.Build;
import android.support.annotation.NonNull; import androidx.annotation.NonNull;
import android.support.annotation.Nullable; import androidx.annotation.Nullable;
import android.system.ErrnoException; import android.system.ErrnoException;
public class JniHelper { public class JniHelper {
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
# Specifies the JVM arguments used for the daemon process. # Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings. # The setting is particularly useful for tweaking memory settings.
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536m org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode. # When configured, Gradle will run in incubating parallel mode.
......
...@@ -26,7 +26,7 @@ android { ...@@ -26,7 +26,7 @@ android {
versionCode 4060100 versionCode 4060100
versionName "4.6.1" versionName "4.6.1"
testApplicationId "com.github.shadowsocks.test" testApplicationId "com.github.shadowsocks.test"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW" resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW"
javaCompileOptions { javaCompileOptions {
annotationProcessorOptions { annotationProcessorOptions {
...@@ -61,32 +61,28 @@ android { ...@@ -61,32 +61,28 @@ android {
dependencies { dependencies {
implementation project(':core') implementation project(':core')
implementation "android.arch.persistence.room:runtime:$roomVersion"
implementation "android.arch.work:work-runtime-ktx:$workVersion" implementation "android.arch.work:work-runtime-ktx:$workVersion"
implementation "com.android.support:customtabs:$supportLibraryVersion" implementation "androidx.browser:browser:$androidxVersion"
implementation "com.android.support:design:$supportLibraryVersion" implementation "androidx.gridlayout:gridlayout:$androidxVersion"
implementation "com.android.support:gridlayout-v7:$supportLibraryVersion" implementation 'androidx.room:room-runtime:2.0.0-beta01'
implementation "com.android.support:support-v4:$supportLibraryVersion" implementation "com.google.android.material:material:$androidxVersion"
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.4' implementation 'com.crashlytics.sdk.android:crashlytics:2.9.4'
implementation 'com.futuremind.recyclerfastscroll:fastscroll:0.2.5'
implementation 'com.google.android.gms:play-services-vision:15.0.2' implementation 'com.google.android.gms:play-services-vision:15.0.2'
implementation 'com.google.firebase:firebase-ads:15.0.1' implementation 'com.google.firebase:firebase-ads:15.0.1'
implementation 'com.google.firebase:firebase-config:16.0.0' implementation 'com.google.firebase:firebase-config:16.0.0'
implementation 'com.google.firebase:firebase-core:16.0.0' implementation 'com.google.firebase:firebase-core:16.0.0'
implementation 'com.mikepenz:materialdrawer:6.0.8' implementation 'com.squareup.okhttp3:okhttp:3.11.0'
implementation 'com.squareup.okhttp3:okhttp:3.10.0' implementation 'com.takisoft.preferencex:preferencex-simplemenu:1.0.0-alpha1'
implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion"
implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2' implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2'
implementation 'eu.chainfire:libsuperuser:1.0.0.201704021214' implementation 'eu.chainfire:libsuperuser:1.0.0.201704021214'
implementation 'net.glxn.qrgen:android:2.0' implementation 'net.glxn.qrgen:android:2.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation 'xyz.belvi.mobilevision:barcodescanner:2.0.3' implementation 'xyz.belvi.mobilevision:barcodescanner:2.0.3'
kapt "android.arch.persistence.room:compiler:$roomVersion" kapt 'androidx.room:room-compiler:2.0.0-beta01'
testImplementation "android.arch.persistence.room:testing:$roomVersion" testImplementation 'androidx.room:room-testing:2.0.0-beta01'
testImplementation "junit:junit:$junitVersion" testImplementation "junit:junit:$junitVersion"
androidTestImplementation "android.arch.work:work-testing:$workVersion" androidTestImplementation "android.arch.work:work-testing:$workVersion"
androidTestImplementation "com.android.support.test:runner:$androidTestVersion" androidTestImplementation "androidx.test:runner:$androidTestVersion"
androidTestImplementation "com.android.support.test.espresso:espresso-core:$androidEspressoVersion" androidTestImplementation "androidx.test.espresso:espresso-core:$androidEspressoVersion"
} }
repositories { repositories {
mavenCentral() mavenCentral()
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
package com.github.shadowsocks.database package com.github.shadowsocks.database
import android.net.Uri import androidx.core.net.toUri
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
...@@ -30,7 +30,7 @@ class ProfileTest { ...@@ -30,7 +30,7 @@ class ProfileTest {
val results = Profile.findAll("garble ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4#example-server garble") val results = Profile.findAll("garble ss://YmYtY2ZiOnRlc3RAMTkyLjE2OC4xMDAuMTo4ODg4#example-server garble")
.toList() .toList()
Assert.assertEquals(1, results.size) Assert.assertEquals(1, results.size)
Assert.assertEquals(Uri.parse("ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888#example-server"), Assert.assertEquals("ss://YmYtY2ZiOnRlc3Q@192.168.100.1:8888#example-server".toUri(),
results.single().toUri()) results.single().toUri())
} }
} }
...@@ -26,11 +26,9 @@ ...@@ -26,11 +26,9 @@
android:fullBackupContent="@xml/backup_descriptor" android:fullBackupContent="@xml/backup_descriptor"
android:fullBackupOnly="true" android:fullBackupOnly="true"
android:label="@string/app_name" android:label="@string/app_name"
android:theme="@style/Theme.Shadowsocks.App"
android:supportsRtl="true" android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:banner="@drawable/ic_service_active" android:banner="@drawable/ic_service_active">
tools:replace="android:theme">
<meta-data android:name="android.webkit.WebView.EnableSafeBrowsing" <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
android:value="true" /> android:value="true" />
......
/*******************************************************************************
* *
* Copyright (C) 2017 by Max Lv <max.c.lv@gmail.com> *
* Copyright (C) 2017 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
package android.support.design.animation
import android.animation.TimeInterpolator
object AnimationConsts {
val FAST_OUT_SLOW_IN_INTERPOLATOR: TimeInterpolator get() = AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR
}
...@@ -21,9 +21,7 @@ ...@@ -21,9 +21,7 @@
package com.github.shadowsocks package com.github.shadowsocks
import android.content.Intent import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.support.v4.text.HtmlCompat
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan import android.text.style.ClickableSpan
...@@ -32,6 +30,9 @@ import android.view.LayoutInflater ...@@ -32,6 +30,9 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.core.net.toUri
import androidx.core.text.HtmlCompat
import androidx.core.text.parseAsHtml
class AboutFragment : ToolbarFragment() { class AboutFragment : ToolbarFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
...@@ -41,16 +42,15 @@ class AboutFragment : ToolbarFragment() { ...@@ -41,16 +42,15 @@ class AboutFragment : ToolbarFragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
toolbar.title = getString(R.string.about_title, BuildConfig.VERSION_NAME) toolbar.title = getString(R.string.about_title, BuildConfig.VERSION_NAME)
view.findViewById<TextView>(R.id.tv_about).apply { view.findViewById<TextView>(R.id.tv_about).apply {
text = SpannableStringBuilder(HtmlCompat.fromHtml( text = SpannableStringBuilder(resources.openRawResource(R.raw.about).bufferedReader().readText()
resources.openRawResource(R.raw.about).bufferedReader().readText(), .parseAsHtml(HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM)).apply {
HtmlCompat.FROM_HTML_SEPARATOR_LINE_BREAK_LIST_ITEM)).apply {
for (span in getSpans(0, length, URLSpan::class.java)) { for (span in getSpans(0, length, URLSpan::class.java)) {
setSpan(object : ClickableSpan() { setSpan(object : ClickableSpan() {
override fun onClick(view: View) { override fun onClick(view: View) {
if (span.url.startsWith("mailto:")) { if (span.url.startsWith("mailto:")) {
startActivity(Intent.createChooser(Intent().apply { startActivity(Intent.createChooser(Intent().apply {
action = Intent.ACTION_SENDTO action = Intent.ACTION_SENDTO
data = Uri.parse(span.url) data = span.url.toUri()
}, getString(R.string.send_email))) }, getString(R.string.send_email)))
} else (activity as MainActivity).launchUrl(span.url) } else (activity as MainActivity).launchUrl(span.url)
} }
......
...@@ -35,9 +35,10 @@ import android.os.Build ...@@ -35,9 +35,10 @@ import android.os.Build
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.os.UserManager import android.os.UserManager
import android.support.annotation.RequiresApi import androidx.annotation.RequiresApi
import android.support.v7.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import android.util.Log import android.util.Log
import androidx.core.content.getSystemService
import androidx.work.WorkManager import androidx.work.WorkManager
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.acl.Acl import com.github.shadowsocks.acl.Acl
...@@ -51,7 +52,7 @@ import com.github.shadowsocks.utils.* ...@@ -51,7 +52,7 @@ import com.github.shadowsocks.utils.*
import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseApp
import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.remoteconfig.FirebaseRemoteConfig import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat import com.takisoft.preferencex.PreferenceFragmentCompat
import io.fabric.sdk.android.Fabric import io.fabric.sdk.android.Fabric
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
...@@ -68,8 +69,8 @@ class App : Application() { ...@@ -68,8 +69,8 @@ class App : Application() {
val analytics: FirebaseAnalytics by lazy { FirebaseAnalytics.getInstance(deviceContext) } val analytics: FirebaseAnalytics by lazy { FirebaseAnalytics.getInstance(deviceContext) }
val info: PackageInfo by lazy { getPackageInfo(packageName) } val info: PackageInfo by lazy { getPackageInfo(packageName) }
val directBootSupported by lazy { val directBootSupported by lazy {
Build.VERSION.SDK_INT >= 24 && getSystemService(DevicePolicyManager::class.java) Build.VERSION.SDK_INT >= 24 && getSystemService<DevicePolicyManager>()?.storageEncryptionStatus ==
.storageEncryptionStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER
} }
fun getPackageInfo(packageName: String) = packageManager.getPackageInfo(packageName, fun getPackageInfo(packageName: String) = packageManager.getPackageInfo(packageName,
...@@ -121,7 +122,7 @@ class App : Application() { ...@@ -121,7 +122,7 @@ class App : Application() {
// handle data restored/crash // handle data restored/crash
if (Build.VERSION.SDK_INT >= 24 && DataStore.directBootAware && if (Build.VERSION.SDK_INT >= 24 && DataStore.directBootAware &&
(getSystemService(Context.USER_SERVICE) as UserManager).isUserUnlocked) DirectBoot.flushTrafficStats() getSystemService<UserManager>()?.isUserUnlocked == true) DirectBoot.flushTrafficStats()
TcpFastOpen.enabledAsync(DataStore.publicStore.getBoolean(Key.tfo, TcpFastOpen.sendEnabled)) TcpFastOpen.enabledAsync(DataStore.publicStore.getBoolean(Key.tfo, TcpFastOpen.sendEnabled))
if (DataStore.publicStore.getLong(Key.assetUpdateTime, -1) != info.lastUpdateTime) { if (DataStore.publicStore.getLong(Key.assetUpdateTime, -1) != info.lastUpdateTime) {
val assetManager = assets val assetManager = assets
...@@ -146,7 +147,7 @@ class App : Application() { ...@@ -146,7 +147,7 @@ class App : Application() {
private fun updateNotificationChannels() { private fun updateNotificationChannels() {
if (Build.VERSION.SDK_INT >= 26) @RequiresApi(26) { if (Build.VERSION.SDK_INT >= 26) @RequiresApi(26) {
val nm = getSystemService(NotificationManager::class.java) val nm = getSystemService<NotificationManager>()!!
nm.createNotificationChannels(listOf( nm.createNotificationChannels(listOf(
NotificationChannel("service-vpn", getText(R.string.service_vpn), NotificationChannel("service-vpn", getText(R.string.service_vpn),
NotificationManager.IMPORTANCE_LOW), NotificationManager.IMPORTANCE_LOW),
......
...@@ -33,18 +33,17 @@ import android.content.pm.PackageManager ...@@ -33,18 +33,17 @@ import android.content.pm.PackageManager
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.Snackbar
import android.support.v4.app.TaskStackBuilder import androidx.core.app.TaskStackBuilder
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.support.v7.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.support.v7.widget.Toolbar import androidx.appcompat.widget.Toolbar
import android.view.* import android.view.*
import android.widget.ImageView import android.widget.ImageView
import android.widget.Switch import android.widget.Switch
import com.futuremind.recyclerviewfastscroll.FastScroller import androidx.core.content.getSystemService
import com.futuremind.recyclerviewfastscroll.SectionTitleProvider
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.database.ProfileManager import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
...@@ -113,7 +112,7 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { ...@@ -113,7 +112,7 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
} }
} }
private inner class AppsAdapter : RecyclerView.Adapter<AppViewHolder>(), SectionTitleProvider { private inner class AppsAdapter : RecyclerView.Adapter<AppViewHolder>() {
private var apps = listOf<ProxiedApp>() private var apps = listOf<ProxiedApp>()
fun reload() { fun reload() {
...@@ -125,18 +124,16 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { ...@@ -125,18 +124,16 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder = override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder =
AppViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_apps_item, parent, false)) AppViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_apps_item, parent, false))
override fun getItemCount(): Int = apps.size override fun getItemCount(): Int = apps.size
override fun getSectionTitle(position: Int): String = apps[position].name.substring(0, 1)
} }
private lateinit var proxiedApps: HashSet<String> private lateinit var proxiedApps: HashSet<String>
private lateinit var toolbar: Toolbar private lateinit var toolbar: Toolbar
private lateinit var bypassSwitch: Switch private lateinit var bypassSwitch: Switch
private lateinit var appListView: RecyclerView private lateinit var appListView: RecyclerView
private lateinit var fastScroller: FastScroller
private lateinit var loadingView: View private lateinit var loadingView: View
private val appsLoading = AtomicBoolean() private val appsLoading = AtomicBoolean()
private val handler = Handler() private val handler = Handler()
private val clipboard by lazy { systemService<ClipboardManager>() } private val clipboard by lazy { getSystemService<ClipboardManager>()!! }
private fun initProxiedApps(str: String = DataStore.individual) { private fun initProxiedApps(str: String = DataStore.individual) {
proxiedApps = str.split('\n').toHashSet() proxiedApps = str.split('\n').toHashSet()
...@@ -147,7 +144,6 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { ...@@ -147,7 +144,6 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
private fun loadAppsAsync() { private fun loadAppsAsync() {
if (!appsLoading.compareAndSet(false, true)) return if (!appsLoading.compareAndSet(false, true)) return
appListView.visibility = View.GONE appListView.visibility = View.GONE
fastScroller.visibility = View.GONE
loadingView.visibility = View.VISIBLE loadingView.visibility = View.VISIBLE
thread("AppManager-loader") { thread("AppManager-loader") {
val adapter = appListView.adapter as AppsAdapter val adapter = appListView.adapter as AppsAdapter
...@@ -161,9 +157,6 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { ...@@ -161,9 +157,6 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
appListView.alpha = 0F appListView.alpha = 0F
appListView.visibility = View.VISIBLE appListView.visibility = View.VISIBLE
appListView.animate().alpha(1F).duration = shortAnimTime.toLong() appListView.animate().alpha(1F).duration = shortAnimTime.toLong()
fastScroller.alpha = 0F
fastScroller.visibility = View.VISIBLE
fastScroller.animate().alpha(1F).duration = shortAnimTime.toLong()
loadingView.animate().alpha(0F).setListener(object : AnimatorListenerAdapter() { loadingView.animate().alpha(0F).setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) { override fun onAnimationEnd(animation: Animator) {
loadingView.visibility = View.GONE loadingView.visibility = View.GONE
...@@ -207,11 +200,9 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener { ...@@ -207,11 +200,9 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
initProxiedApps() initProxiedApps()
loadingView = findViewById(R.id.loading) loadingView = findViewById(R.id.loading)
appListView = findViewById(R.id.list) appListView = findViewById(R.id.list)
appListView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) appListView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
appListView.itemAnimator = DefaultItemAnimator() appListView.itemAnimator = DefaultItemAnimator()
appListView.adapter = AppsAdapter() appListView.adapter = AppsAdapter()
fastScroller = findViewById(R.id.fastscroller)
fastScroller.setRecyclerView(appListView)
instance = this instance = this
loadAppsAsync() loadAppsAsync()
......
...@@ -22,21 +22,20 @@ package com.github.shadowsocks ...@@ -22,21 +22,20 @@ package com.github.shadowsocks
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.Snackbar
import android.support.v14.preference.SwitchPreference import androidx.preference.SwitchPreference
import android.support.v7.preference.Preference import androidx.preference.Preference
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.DirectBoot import com.github.shadowsocks.utils.DirectBoot
import com.github.shadowsocks.utils.Key import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.TcpFastOpen import com.github.shadowsocks.utils.TcpFastOpen
import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat import com.takisoft.preferencex.PreferenceFragmentCompat
class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() { class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferencesFix(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.preferenceDataStore = DataStore.publicStore preferenceManager.preferenceDataStore = DataStore.publicStore
DataStore.initGlobal()
addPreferencesFromResource(R.xml.pref_global) addPreferencesFromResource(R.xml.pref_global)
val boot = findPreference(Key.isAutoConnect) as SwitchPreference val boot = findPreference(Key.isAutoConnect) as SwitchPreference
boot.setOnPreferenceChangeListener { _, value -> boot.setOnPreferenceChangeListener { _, value ->
......
...@@ -23,9 +23,9 @@ package com.github.shadowsocks ...@@ -23,9 +23,9 @@ package com.github.shadowsocks
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AlertDialog import androidx.appcompat.app.AlertDialog
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.support.v7.widget.Toolbar import androidx.appcompat.widget.Toolbar
import com.github.shadowsocks.plugin.PluginContract import com.github.shadowsocks.plugin.PluginContract
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
......
...@@ -26,13 +26,15 @@ import android.content.Intent ...@@ -26,13 +26,15 @@ import android.content.Intent
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.UserManager import android.os.UserManager
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.Snackbar
import android.support.v14.preference.SwitchPreference import androidx.preference.SwitchPreference
import android.support.v7.app.AlertDialog import androidx.appcompat.app.AlertDialog
import android.support.v7.preference.Preference import androidx.preference.Preference
import android.support.v7.preference.PreferenceDataStore import androidx.preference.PreferenceDataStore
import android.support.v7.widget.Toolbar import androidx.appcompat.widget.Toolbar
import android.view.MenuItem import android.view.MenuItem
import androidx.core.content.getSystemService
import androidx.core.os.bundleOf
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.database.Profile import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager import com.github.shadowsocks.database.ProfileManager
...@@ -47,8 +49,8 @@ import com.github.shadowsocks.preference.PluginConfigurationDialogFragment ...@@ -47,8 +49,8 @@ import com.github.shadowsocks.preference.PluginConfigurationDialogFragment
import com.github.shadowsocks.utils.Action import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.DirectBoot import com.github.shadowsocks.utils.DirectBoot
import com.github.shadowsocks.utils.Key import com.github.shadowsocks.utils.Key
import com.takisoft.fix.support.v7.preference.EditTextPreference import com.takisoft.preferencex.EditTextPreference
import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompat import com.takisoft.preferencex.PreferenceFragmentCompat
class ProfileConfigFragment : PreferenceFragmentCompat(), Toolbar.OnMenuItemClickListener, class ProfileConfigFragment : PreferenceFragmentCompat(), Toolbar.OnMenuItemClickListener,
Preference.OnPreferenceChangeListener, OnPreferenceDataStoreChangeListener { Preference.OnPreferenceChangeListener, OnPreferenceDataStoreChangeListener {
...@@ -68,7 +70,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), Toolbar.OnMenuItemClic ...@@ -68,7 +70,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), Toolbar.OnMenuItemClic
val activity = requireActivity() val activity = requireActivity()
profileId = activity.intent.getLongExtra(Action.EXTRA_PROFILE_ID, -1L) profileId = activity.intent.getLongExtra(Action.EXTRA_PROFILE_ID, -1L)
addPreferencesFromResource(R.xml.pref_profile) addPreferencesFromResource(R.xml.pref_profile)
if (Build.VERSION.SDK_INT >= 25 && activity.getSystemService(UserManager::class.java).isDemoUser) { if (Build.VERSION.SDK_INT >= 25 && activity.getSystemService<UserManager>()?.isDemoUser == true) {
findPreference(Key.host).summary = "shadowsocks.example.org" findPreference(Key.host).summary = "shadowsocks.example.org"
findPreference(Key.remotePort).summary = "1337" findPreference(Key.remotePort).summary = "1337"
findPreference(Key.password).summary = "\u2022".repeat(32) findPreference(Key.password).summary = "\u2022".repeat(32)
...@@ -116,12 +118,9 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), Toolbar.OnMenuItemClic ...@@ -116,12 +118,9 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), Toolbar.OnMenuItemClic
pluginConfigure.text = pluginConfiguration.selectedOptions.toString() pluginConfigure.text = pluginConfiguration.selectedOptions.toString()
} }
private fun showPluginEditor() { private fun showPluginEditor() = displayPreferenceDialog(PluginConfigurationDialogFragment(), Key.pluginConfigure,
val bundle = Bundle() bundleOf(Pair("key", Key.pluginConfigure),
bundle.putString("key", Key.pluginConfigure) Pair(PluginConfigurationDialogFragment.PLUGIN_ID_FRAGMENT_TAG, pluginConfiguration.selected)))
bundle.putString(PluginConfigurationDialogFragment.PLUGIN_ID_FRAGMENT_TAG, pluginConfiguration.selected)
displayPreferenceDialog(PluginConfigurationDialogFragment(), Key.pluginConfigure, bundle)
}
fun saveAndExit() { fun saveAndExit() {
val profile = ProfileManager.getProfile(profileId) ?: Profile() val profile = ProfileManager.getProfile(profileId) ?: Profile()
...@@ -182,10 +181,10 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), Toolbar.OnMenuItemClic ...@@ -182,10 +181,10 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), Toolbar.OnMenuItemClic
val activity = requireActivity() val activity = requireActivity()
AlertDialog.Builder(activity) AlertDialog.Builder(activity)
.setTitle(R.string.delete_confirm_prompt) .setTitle(R.string.delete_confirm_prompt)
.setPositiveButton(R.string.yes, { _, _ -> .setPositiveButton(R.string.yes) { _, _ ->
ProfileManager.delProfile(profileId) ProfileManager.delProfile(profileId)
activity.finish() activity.finish()
}) }
.setNegativeButton(R.string.no, null) .setNegativeButton(R.string.no, null)
.create() .create()
.show() .show()
......
...@@ -29,15 +29,17 @@ import android.nfc.NdefMessage ...@@ -29,15 +29,17 @@ import android.nfc.NdefMessage
import android.nfc.NdefRecord import android.nfc.NdefRecord
import android.nfc.NfcAdapter import android.nfc.NfcAdapter
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.Snackbar
import android.support.v4.app.DialogFragment import androidx.fragment.app.DialogFragment
import android.support.v7.widget.* import androidx.appcompat.widget.*
import android.support.v7.widget.helper.ItemTouchHelper
import android.text.format.Formatter import android.text.format.Formatter
import android.view.* import android.view.*
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.core.content.getSystemService
import androidx.core.os.bundleOf
import androidx.recyclerview.widget.*
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.database.Profile import com.github.shadowsocks.database.Profile
...@@ -45,7 +47,6 @@ import com.github.shadowsocks.database.ProfileManager ...@@ -45,7 +47,6 @@ import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.plugin.PluginConfiguration import com.github.shadowsocks.plugin.PluginConfiguration
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.Action import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.systemService
import com.github.shadowsocks.widget.UndoSnackbarManager import com.github.shadowsocks.widget.UndoSnackbarManager
import com.google.android.gms.ads.AdRequest import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdSize import com.google.android.gms.ads.AdSize
...@@ -79,9 +80,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -79,9 +80,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
class QRCodeDialog() : DialogFragment() { class QRCodeDialog() : DialogFragment() {
constructor(url: String) : this() { constructor(url: String) : this() {
val bundle = Bundle() arguments = bundleOf(Pair(KEY_URL, url))
bundle.putString(KEY_URL, url)
arguments = bundle
} }
private val url get() = arguments!!.getString(KEY_URL) private val url get() = arguments!!.getString(KEY_URL)
...@@ -152,20 +151,14 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -152,20 +151,14 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
rx += rxTotal rx += rxTotal
} }
text1.text = item.formattedName text1.text = item.formattedName
val t2 = ArrayList<String>() text2.text = ArrayList<String>().apply {
if (!item.name.isNullOrEmpty()) t2 += item.formattedAddress if (!item.name.isNullOrEmpty()) this += item.formattedAddress
val id = PluginConfiguration(item.plugin ?: "").selected val id = PluginConfiguration(item.plugin ?: "").selected
if (id.isNotEmpty()) t2 += app.getString(R.string.profile_plugin, id) if (id.isNotEmpty()) this += app.getString(R.string.profile_plugin, id)
if (t2.isEmpty()) text2.visibility = View.GONE else { }.joinToString("\n")
text2.visibility = View.VISIBLE
text2.text = t2.joinToString("\n")
}
val context = requireContext() val context = requireContext()
if (tx <= 0 && rx <= 0) traffic.visibility = View.GONE else { traffic.text = if (tx <= 0 && rx <= 0) null else getString(R.string.traffic,
traffic.visibility = View.VISIBLE Formatter.formatFileSize(context, tx), Formatter.formatFileSize(context, rx))
traffic.text = getString(R.string.traffic,
Formatter.formatFileSize(context, tx), Formatter.formatFileSize(context, rx))
}
if (item.id == DataStore.profileId) { if (item.id == DataStore.profileId) {
itemView.isSelected = true itemView.isSelected = true
...@@ -196,7 +189,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -196,7 +189,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
adView.loadAd(adBuilder.build()) adView.loadAd(adBuilder.build())
this.adView = adView this.adView = adView
} else adView.visibility = View.VISIBLE } else adView.visibility = View.VISIBLE
} else if (adView != null) adView.visibility = View.GONE } else adView?.visibility = View.GONE
} }
override fun onClick(v: View?) { override fun onClick(v: View?) {
...@@ -236,7 +229,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -236,7 +229,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder = ProfileViewHolder( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder = ProfileViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.layout_profile, parent, false)) LayoutInflater.from(parent.context).inflate(R.layout.layout_profile, parent, false))
override fun getItemCount(): Int = profiles.size override fun getItemCount(): Int = profiles.size
override fun getItemId(position: Int): Long = profiles[position].id.toLong() override fun getItemId(position: Int): Long = profiles[position].id
fun add(item: Profile) { fun add(item: Profile) {
undoManager.flush() undoManager.flush()
...@@ -309,7 +302,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -309,7 +302,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
private var txTotal: Long = 0L private var txTotal: Long = 0L
private var rxTotal: Long = 0L private var rxTotal: Long = 0L
private val clipboard by lazy { requireContext().systemService<ClipboardManager>() } private val clipboard by lazy { requireContext().getSystemService<ClipboardManager>()!! }
private fun startConfig(profile: Profile) { private fun startConfig(profile: Profile) {
profile.serialize() profile.serialize()
...@@ -327,7 +320,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -327,7 +320,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
if (!ProfileManager.isNotEmpty()) DataStore.profileId = ProfileManager.createProfile().id if (!ProfileManager.isNotEmpty()) DataStore.profileId = ProfileManager.createProfile().id
val profilesList = view.findViewById<RecyclerView>(R.id.list) val profilesList = view.findViewById<RecyclerView>(R.id.list)
val layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) val layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
profilesList.layoutManager = layoutManager profilesList.layoutManager = layoutManager
profilesList.addItemDecoration(DividerItemDecoration(context, layoutManager.orientation)) profilesList.addItemDecoration(DividerItemDecoration(context, layoutManager.orientation))
layoutManager.scrollToPosition(profilesAdapter.profiles.indexOfFirst { it.id == DataStore.profileId }) layoutManager.scrollToPosition(profilesAdapter.profiles.indexOfFirst { it.id == DataStore.profileId })
......
...@@ -25,9 +25,10 @@ import android.content.Intent ...@@ -25,9 +25,10 @@ import android.content.Intent
import android.content.pm.ShortcutManager import android.content.pm.ShortcutManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v4.content.pm.ShortcutInfoCompat import androidx.core.content.getSystemService
import android.support.v4.content.pm.ShortcutManagerCompat import androidx.core.content.pm.ShortcutInfoCompat
import android.support.v4.graphics.drawable.IconCompat import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.aidl.IShadowsocksService import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
...@@ -45,7 +46,7 @@ class QuickToggleShortcut : Activity(), ShadowsocksConnection.Interface { ...@@ -45,7 +46,7 @@ class QuickToggleShortcut : Activity(), ShadowsocksConnection.Interface {
finish() finish()
} else { } else {
connection.connect() connection.connect()
if (Build.VERSION.SDK_INT >= 25) getSystemService(ShortcutManager::class.java).reportShortcutUsed("toggle") if (Build.VERSION.SDK_INT >= 25) getSystemService<ShortcutManager>()!!.reportShortcutUsed("toggle")
} }
} }
......
...@@ -27,20 +27,20 @@ import android.hardware.camera2.CameraAccessException ...@@ -27,20 +27,20 @@ import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraManager import android.hardware.camera2.CameraManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.TaskStackBuilder import androidx.core.app.TaskStackBuilder
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.support.v7.widget.Toolbar import androidx.appcompat.widget.Toolbar
import android.util.Log import android.util.Log
import android.util.SparseArray import android.util.SparseArray
import android.view.MenuItem import android.view.MenuItem
import android.widget.Toast import android.widget.Toast
import androidx.core.content.getSystemService
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.database.Profile import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.utils.openBitmap import com.github.shadowsocks.utils.openBitmap
import com.github.shadowsocks.utils.printLog import com.github.shadowsocks.utils.printLog
import com.github.shadowsocks.utils.resolveResourceId import com.github.shadowsocks.utils.resolveResourceId
import com.github.shadowsocks.utils.systemService
import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.samples.vision.barcodereader.BarcodeCapture import com.google.android.gms.samples.vision.barcodereader.BarcodeCapture
import com.google.android.gms.samples.vision.barcodereader.BarcodeGraphic import com.google.android.gms.samples.vision.barcodereader.BarcodeGraphic
...@@ -85,12 +85,12 @@ class ScannerActivity : AppCompatActivity(), Toolbar.OnMenuItemClickListener, Ba ...@@ -85,12 +85,12 @@ class ScannerActivity : AppCompatActivity(), Toolbar.OnMenuItemClickListener, Ba
} }
return return
} }
if (Build.VERSION.SDK_INT >= 25) getSystemService(ShortcutManager::class.java).reportShortcutUsed("scan") if (Build.VERSION.SDK_INT >= 25) getSystemService<ShortcutManager>()!!.reportShortcutUsed("scan")
if (try { if (try {
systemService<CameraManager>().cameraIdList.isEmpty() getSystemService<CameraManager>()?.cameraIdList?.isEmpty()
} catch (_: CameraAccessException) { } catch (_: CameraAccessException) {
true true
}) { } != false) {
startImport() startImport()
return return
} }
......
...@@ -21,8 +21,9 @@ ...@@ -21,8 +21,9 @@
package com.github.shadowsocks package com.github.shadowsocks
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import android.view.Gravity
import android.support.v7.widget.Toolbar import androidx.fragment.app.Fragment
import androidx.appcompat.widget.Toolbar
import android.view.View import android.view.View
/** /**
...@@ -34,8 +35,8 @@ open class ToolbarFragment : Fragment() { ...@@ -34,8 +35,8 @@ open class ToolbarFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
toolbar = view.findViewById(R.id.toolbar) toolbar = view.findViewById(R.id.toolbar)
val activity = activity as MainActivity toolbar.setNavigationIcon(R.drawable.ic_navigation_menu)
activity.drawer.setToolbar(activity, toolbar, true) toolbar.setNavigationOnClickListener { (activity as MainActivity).drawer.openDrawer(Gravity.START) }
} }
open fun onTrafficUpdated(profileId: Long, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) { } open fun onTrafficUpdated(profileId: Long, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) { }
......
...@@ -26,15 +26,15 @@ import android.content.Intent ...@@ -26,15 +26,15 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.net.VpnService import android.net.VpnService
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.Snackbar
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.util.Log import android.util.Log
import androidx.core.content.getSystemService
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.aidl.IShadowsocksService import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.utils.broadcastReceiver import com.github.shadowsocks.utils.broadcastReceiver
import com.github.shadowsocks.utils.systemService
class VpnRequestActivity : AppCompatActivity(), ShadowsocksConnection.Interface { class VpnRequestActivity : AppCompatActivity(), ShadowsocksConnection.Interface {
companion object { companion object {
...@@ -50,7 +50,7 @@ class VpnRequestActivity : AppCompatActivity(), ShadowsocksConnection.Interface ...@@ -50,7 +50,7 @@ class VpnRequestActivity : AppCompatActivity(), ShadowsocksConnection.Interface
finish() finish()
return return
} }
if (systemService<KeyguardManager>().isKeyguardLocked) { if (getSystemService<KeyguardManager>()!!.isKeyguardLocked) {
receiver = broadcastReceiver { _, _ -> connection.connect() } receiver = broadcastReceiver { _, _ -> connection.connect() }
registerReceiver(receiver, IntentFilter(Intent.ACTION_USER_PRESENT)) registerReceiver(receiver, IntentFilter(Intent.ACTION_USER_PRESENT))
} else connection.connect() } else connection.connect()
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
package com.github.shadowsocks.acl package com.github.shadowsocks.acl
import android.content.Context import android.content.Context
import android.support.v7.util.SortedList import androidx.recyclerview.widget.SortedList
import android.util.Log import android.util.Log
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
......
...@@ -25,21 +25,20 @@ import android.content.ClipboardManager ...@@ -25,21 +25,20 @@ import android.content.ClipboardManager
import android.content.res.Configuration import android.content.res.Configuration
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.Snackbar
import android.support.design.widget.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import android.support.v4.content.ContextCompat import androidx.core.content.ContextCompat
import android.support.v7.app.AlertDialog import androidx.appcompat.app.AlertDialog
import android.support.v7.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.support.v7.widget.Toolbar import androidx.appcompat.widget.Toolbar
import android.support.v7.widget.helper.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.view.* import android.view.*
import android.widget.* import android.widget.*
import com.futuremind.recyclerviewfastscroll.FastScroller import androidx.core.content.getSystemService
import com.futuremind.recyclerviewfastscroll.SectionTitleProvider
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.MainActivity import com.github.shadowsocks.MainActivity
import com.github.shadowsocks.R import com.github.shadowsocks.R
...@@ -162,9 +161,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -162,9 +161,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
private val text = view.findViewById<TextView>(android.R.id.text1) private val text = view.findViewById<TextView>(android.R.id.text1)
init { init {
view.setPaddingRelative(view.paddingStart, view.paddingTop,
Math.max(view.paddingEnd, resources.getDimensionPixelSize(R.dimen.fastscroll__bubble_corner)),
view.paddingBottom)
view.setOnClickListener(this) view.setOnClickListener(this)
view.setOnLongClickListener(this) view.setOnLongClickListener(this)
view.setBackgroundResource(R.drawable.background_selectable) view.setBackgroundResource(R.drawable.background_selectable)
...@@ -190,15 +186,15 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -190,15 +186,15 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
if (selectedItems.isNotEmpty()) onLongClick(v) else { if (selectedItems.isNotEmpty()) onLongClick(v) else {
val dialog = AclRuleDialog(item) val dialog = AclRuleDialog(item)
dialog.builder dialog.builder
.setNeutralButton(R.string.delete, { _, _ -> .setNeutralButton(R.string.delete) { _, _ ->
adapter.remove(item) adapter.remove(item)
undoManager.remove(Pair(-1, item)) undoManager.remove(Pair(-1, item))
}) }
.setPositiveButton(android.R.string.ok, { _, _ -> .setPositiveButton(android.R.string.ok) { _, _ ->
adapter.remove(item) adapter.remove(item)
val index = dialog.add() ?: adapter.add(item) val index = dialog.add() ?: adapter.add(item)
if (index != null) list.post { list.scrollToPosition(index) } if (index != null) list.post { list.scrollToPosition(index) }
}) }
dialog.show() dialog.show()
} }
} }
...@@ -210,7 +206,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -210,7 +206,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
} }
} }
private inner class AclRulesAdapter : RecyclerView.Adapter<AclRuleViewHolder>(), SectionTitleProvider { private inner class AclRulesAdapter : RecyclerView.Adapter<AclRuleViewHolder>() {
private val acl = Acl.customRules private val acl = Acl.customRules
private var savePending = false private var savePending = false
...@@ -224,17 +220,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -224,17 +220,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = AclRuleViewHolder(LayoutInflater override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = AclRuleViewHolder(LayoutInflater
.from(parent.context).inflate(android.R.layout.simple_list_item_1, parent, false)) .from(parent.context).inflate(android.R.layout.simple_list_item_1, parent, false))
override fun getItemCount(): Int = acl.subnets.size() + acl.hostnames.size() + acl.urls.size() override fun getItemCount(): Int = acl.subnets.size() + acl.hostnames.size() + acl.urls.size()
override fun getSectionTitle(i: Int): String {
val j = i - acl.subnets.size()
return (if (j < 0) acl.subnets[i].address.hostAddress.substring(0, 1) else {
val k = j - acl.hostnames.size()
if (k < 0) {
val hostname = acl.hostnames[j]
// don't convert IDN yet
PATTERN_DOMAIN.find(hostname)?.value?.replace("\\.", ".") ?: hostname
} else acl.urls[k].host
}).firstOrNull()?.toString() ?: " "
}
private fun apply() { private fun apply() {
if (!savePending) { if (!savePending) {
...@@ -358,7 +343,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -358,7 +343,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
private lateinit var list: RecyclerView private lateinit var list: RecyclerView
private var mode: ActionMode? = null private var mode: ActionMode? = null
private lateinit var undoManager: UndoSnackbarManager<Any> private lateinit var undoManager: UndoSnackbarManager<Any>
private val clipboard by lazy { requireContext().systemService<ClipboardManager>() } private val clipboard by lazy { requireContext().getSystemService<ClipboardManager>()!! }
private fun onSelectedItemsUpdated() { private fun onSelectedItemsUpdated() {
if (selectedItems.isEmpty()) mode?.finish() else if (mode == null) mode = toolbar.startActionMode(this) if (selectedItems.isEmpty()) mode?.finish() else if (mode == null) mode = toolbar.startActionMode(this)
...@@ -383,10 +368,9 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -383,10 +368,9 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
toolbar.setOnMenuItemClickListener(this) toolbar.setOnMenuItemClickListener(this)
val activity = requireActivity() val activity = requireActivity()
list = view.findViewById(R.id.list) list = view.findViewById(R.id.list)
list.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false) list.layoutManager = LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
list.itemAnimator = DefaultItemAnimator() list.itemAnimator = DefaultItemAnimator()
list.adapter = adapter list.adapter = adapter
view.findViewById<FastScroller>(R.id.fastscroller).setRecyclerView(list)
undoManager = UndoSnackbarManager(activity.findViewById(R.id.snackbar), adapter::undo) undoManager = UndoSnackbarManager(activity.findViewById(R.id.snackbar), adapter::undo)
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.START or ItemTouchHelper.END) { ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.START or ItemTouchHelper.END) {
override fun getSwipeDirs(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int = override fun getSwipeDirs(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int =
...@@ -430,7 +414,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -430,7 +414,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) { override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) {
R.id.action_manual_settings -> { R.id.action_manual_settings -> {
val dialog = AclRuleDialog() val dialog = AclRuleDialog()
dialog.builder.setPositiveButton(android.R.string.ok, { _, _ -> dialog.add() }) dialog.builder.setPositiveButton(android.R.string.ok) { _, _ -> dialog.add() }
dialog.show() dialog.show()
true true
} }
...@@ -467,7 +451,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ...@@ -467,7 +451,7 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener,
// for dark mode, it's roughly 850? (#303030) // for dark mode, it's roughly 850? (#303030)
window.statusBarColor = ContextCompat.getColor(activity, when { window.statusBarColor = ContextCompat.getColor(activity, when {
resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES -> resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES ->
R.color.md_black_1000 android.R.color.black
Build.VERSION.SDK_INT >= 23 -> { Build.VERSION.SDK_INT >= 23 -> {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
R.color.material_grey_300 R.color.material_grey_300
......
...@@ -26,12 +26,12 @@ import android.content.Context ...@@ -26,12 +26,12 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.os.Build import android.os.Build
import android.os.Bundle
import android.os.IBinder import android.os.IBinder
import android.os.RemoteCallbackList import android.os.RemoteCallbackList
import android.support.v4.os.UserManagerCompat
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import androidx.core.os.UserManagerCompat
import androidx.core.os.bundleOf
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.R import com.github.shadowsocks.R
...@@ -293,7 +293,7 @@ object BaseService { ...@@ -293,7 +293,7 @@ object BaseService {
val data = data val data = data
data.changeState(STOPPING) data.changeState(STOPPING)
app.analytics.logEvent("stop", Bundle().put(FirebaseAnalytics.Param.METHOD, tag)) app.analytics.logEvent("stop", bundleOf(Pair(FirebaseAnalytics.Param.METHOD, tag)))
killProcesses() killProcesses()
...@@ -357,7 +357,7 @@ object BaseService { ...@@ -357,7 +357,7 @@ object BaseService {
} }
data.notification = createNotification(profile.formattedName) data.notification = createNotification(profile.formattedName)
app.analytics.logEvent("start", Bundle().put(FirebaseAnalytics.Param.METHOD, tag)) app.analytics.logEvent("start", bundleOf(Pair(FirebaseAnalytics.Param.METHOD, tag)))
data.changeState(CONNECTING) data.changeState(CONNECTING)
......
...@@ -29,15 +29,15 @@ import android.content.Intent ...@@ -29,15 +29,15 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.os.Build import android.os.Build
import android.os.PowerManager import android.os.PowerManager
import android.support.v4.app.NotificationCompat import androidx.core.app.NotificationCompat
import android.support.v4.content.ContextCompat import androidx.core.content.ContextCompat
import android.text.format.Formatter import android.text.format.Formatter
import com.github.shadowsocks.MainActivity import com.github.shadowsocks.MainActivity
import com.github.shadowsocks.R import com.github.shadowsocks.R
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
import com.github.shadowsocks.utils.Action import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.broadcastReceiver import com.github.shadowsocks.utils.broadcastReceiver
import com.github.shadowsocks.utils.systemService import androidx.core.content.getSystemService
import java.util.* import java.util.*
/** /**
...@@ -48,10 +48,8 @@ import java.util.* ...@@ -48,10 +48,8 @@ import java.util.*
*/ */
class ServiceNotification(private val service: BaseService.Interface, profileName: String, class ServiceNotification(private val service: BaseService.Interface, profileName: String,
channel: String, private val visible: Boolean = false) { channel: String, private val visible: Boolean = false) {
private val keyGuard = (service as Context).systemService<KeyguardManager>() private val keyGuard = (service as Context).getSystemService<KeyguardManager>()!!
private val nm by lazy { private val nm by lazy { (service as Context).getSystemService<NotificationManager>()!! }
(service as Context).getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
private val callback by lazy { private val callback by lazy {
object : IShadowsocksServiceCallback.Stub() { object : IShadowsocksServiceCallback.Stub() {
override fun stateChanged(state: Int, profileName: String?, msg: String?) { } // ignore override fun stateChanged(state: Int, profileName: String?, msg: String?) { } // ignore
...@@ -84,8 +82,8 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam ...@@ -84,8 +82,8 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam
service as Context service as Context
if (Build.VERSION.SDK_INT < 24) builder.addAction(R.drawable.ic_navigation_close, if (Build.VERSION.SDK_INT < 24) builder.addAction(R.drawable.ic_navigation_close,
service.getString(R.string.stop), PendingIntent.getBroadcast(service, 0, Intent(Action.CLOSE), 0)) service.getString(R.string.stop), PendingIntent.getBroadcast(service, 0, Intent(Action.CLOSE), 0))
val power = service.systemService<PowerManager>() update(if (service.getSystemService<PowerManager>()?.isInteractive != false)
update(if (power.isInteractive) Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true) Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true)
val screenFilter = IntentFilter() val screenFilter = IntentFilter()
screenFilter.addAction(Intent.ACTION_SCREEN_ON) screenFilter.addAction(Intent.ACTION_SCREEN_ON)
screenFilter.addAction(Intent.ACTION_SCREEN_OFF) screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
......
...@@ -23,14 +23,14 @@ package com.github.shadowsocks.bg ...@@ -23,14 +23,14 @@ package com.github.shadowsocks.bg
import android.app.KeyguardManager import android.app.KeyguardManager
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.service.quicksettings.Tile import android.service.quicksettings.Tile
import android.support.annotation.RequiresApi import androidx.annotation.RequiresApi
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.R import com.github.shadowsocks.R
import com.github.shadowsocks.ShadowsocksConnection import com.github.shadowsocks.ShadowsocksConnection
import com.github.shadowsocks.aidl.IShadowsocksService import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.systemService import androidx.core.content.getSystemService
import android.service.quicksettings.TileService as BaseTileService import android.service.quicksettings.TileService as BaseTileService
@RequiresApi(24) @RequiresApi(24)
...@@ -38,7 +38,7 @@ class TileService : BaseTileService(), ShadowsocksConnection.Interface { ...@@ -38,7 +38,7 @@ class TileService : BaseTileService(), ShadowsocksConnection.Interface {
private val iconIdle by lazy { Icon.createWithResource(this, R.drawable.ic_service_idle) } private val iconIdle by lazy { Icon.createWithResource(this, R.drawable.ic_service_idle) }
private val iconBusy by lazy { Icon.createWithResource(this, R.drawable.ic_service_busy) } private val iconBusy by lazy { Icon.createWithResource(this, R.drawable.ic_service_busy) }
private val iconConnected by lazy { Icon.createWithResource(this, R.drawable.ic_service_active) } private val iconConnected by lazy { Icon.createWithResource(this, R.drawable.ic_service_active) }
private val keyguard by lazy { systemService<KeyguardManager>() } private val keyguard by lazy { getSystemService<KeyguardManager>()!! }
override val serviceCallback: IShadowsocksServiceCallback.Stub by lazy { override val serviceCallback: IShadowsocksServiceCallback.Stub by lazy {
@RequiresApi(24) @RequiresApi(24)
......
...@@ -38,7 +38,7 @@ import com.github.shadowsocks.preference.DataStore ...@@ -38,7 +38,7 @@ import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.Subnet import com.github.shadowsocks.utils.Subnet
import com.github.shadowsocks.utils.parseNumericAddress import com.github.shadowsocks.utils.parseNumericAddress
import com.github.shadowsocks.utils.printLog import com.github.shadowsocks.utils.printLog
import com.github.shadowsocks.utils.systemService import androidx.core.content.getSystemService
import java.io.File import java.io.File
import java.io.FileDescriptor import java.io.FileDescriptor
import java.io.IOException import java.io.IOException
...@@ -111,7 +111,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -111,7 +111,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
field = value field = value
} }
private val connectivity by lazy { systemService<ConnectivityManager>() } private val connectivity by lazy { getSystemService<ConnectivityManager>()!! }
@TargetApi(28) @TargetApi(28)
private val defaultNetworkCallback = object : ConnectivityManager.NetworkCallback() { private val defaultNetworkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) { override fun onAvailable(network: Network) {
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
package com.github.shadowsocks.database package com.github.shadowsocks.database
import android.arch.persistence.room.* import androidx.room.*
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer import java.nio.ByteBuffer
...@@ -37,7 +37,7 @@ class KeyValuePair() { ...@@ -37,7 +37,7 @@ class KeyValuePair() {
const val TYPE_STRING_SET = 6 const val TYPE_STRING_SET = 6
} }
@android.arch.persistence.room.Dao @androidx.room.Dao
interface Dao { interface Dao {
@Query("SELECT * FROM `KeyValuePair` WHERE `key` = :key") @Query("SELECT * FROM `KeyValuePair` WHERE `key` = :key")
operator fun get(key: String): KeyValuePair? operator fun get(key: String): KeyValuePair?
......
...@@ -20,10 +20,10 @@ ...@@ -20,10 +20,10 @@
package com.github.shadowsocks.database package com.github.shadowsocks.database
import android.arch.persistence.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import android.arch.persistence.room.Database import androidx.room.Database
import android.arch.persistence.room.Room import androidx.room.Room
import android.arch.persistence.room.RoomDatabase import androidx.room.RoomDatabase
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.database.migration.RecreateSchemaMigration import com.github.shadowsocks.database.migration.RecreateSchemaMigration
import com.github.shadowsocks.utils.Key import com.github.shadowsocks.utils.Key
......
...@@ -20,10 +20,11 @@ ...@@ -20,10 +20,11 @@
package com.github.shadowsocks.database package com.github.shadowsocks.database
import android.arch.persistence.room.* import androidx.room.*
import android.net.Uri import android.net.Uri
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import androidx.core.net.toUri
import com.github.shadowsocks.plugin.PluginConfiguration import com.github.shadowsocks.plugin.PluginConfiguration
import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.Key import com.github.shadowsocks.utils.Key
...@@ -43,7 +44,7 @@ class Profile : Serializable { ...@@ -43,7 +44,7 @@ class Profile : Serializable {
private val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)$".toRegex() private val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)$".toRegex()
fun findAll(data: CharSequence?) = pattern.findAll(data ?: "").map { fun findAll(data: CharSequence?) = pattern.findAll(data ?: "").map {
val uri = Uri.parse(it.value) val uri = it.value.toUri()
try { try {
if (uri.userInfo == null) { if (uri.userInfo == null) {
val match = legacyPattern.matchEntire(String(Base64.decode(uri.host, Base64.NO_PADDING))) val match = legacyPattern.matchEntire(String(Base64.decode(uri.host, Base64.NO_PADDING)))
...@@ -93,7 +94,7 @@ class Profile : Serializable { ...@@ -93,7 +94,7 @@ class Profile : Serializable {
}.filterNotNull() }.filterNotNull()
} }
@android.arch.persistence.room.Dao @androidx.room.Dao
interface Dao { interface Dao {
@Query("SELECT * FROM `Profile` WHERE `id` = :id") @Query("SELECT * FROM `Profile` WHERE `id` = :id")
operator fun get(id: Long): Profile? operator fun get(id: Long): Profile?
......
...@@ -20,9 +20,9 @@ ...@@ -20,9 +20,9 @@
package com.github.shadowsocks.database package com.github.shadowsocks.database
import android.arch.persistence.room.Database import androidx.room.Database
import android.arch.persistence.room.Room import androidx.room.Room
import android.arch.persistence.room.RoomDatabase import androidx.room.RoomDatabase
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.database.migration.RecreateSchemaMigration import com.github.shadowsocks.database.migration.RecreateSchemaMigration
import com.github.shadowsocks.utils.Key import com.github.shadowsocks.utils.Key
......
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
package com.github.shadowsocks.database.migration package com.github.shadowsocks.database.migration
import android.arch.persistence.db.SupportSQLiteDatabase import androidx.sqlite.db.SupportSQLiteDatabase
import android.arch.persistence.room.migration.Migration import androidx.room.migration.Migration
open class RecreateSchemaMigration(oldVersion: Int, newVersion: Int, private val table: String, open class RecreateSchemaMigration(oldVersion: Int, newVersion: Int, private val table: String,
private val schema: String, private val keys: String) : private val schema: String, private val keys: String) :
......
...@@ -27,9 +27,9 @@ import android.content.Intent ...@@ -27,9 +27,9 @@ import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.pm.Signature import android.content.pm.Signature
import android.net.Uri import android.net.Uri
import android.os.Bundle
import android.util.Base64 import android.util.Base64
import android.util.Log import android.util.Log
import androidx.core.os.bundleOf
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.utils.Commandline import com.github.shadowsocks.utils.Commandline
...@@ -151,10 +151,8 @@ object PluginManager { ...@@ -151,10 +151,8 @@ object PluginManager {
} }
private fun initNativeFast(cr: ContentResolver, options: PluginOptions, uri: Uri): String { private fun initNativeFast(cr: ContentResolver, options: PluginOptions, uri: Uri): String {
val out = Bundle() val result = cr.call(uri, PluginContract.METHOD_GET_EXECUTABLE, null,
out.putString(PluginContract.EXTRA_OPTIONS, options.id) bundleOf(Pair(PluginContract.EXTRA_OPTIONS, options.id))).getString(PluginContract.EXTRA_ENTRY)
val result = cr.call(uri, PluginContract.METHOD_GET_EXECUTABLE, null, out)
.getString(PluginContract.EXTRA_ENTRY)
check(File(result).canExecute()) check(File(result).canExecute())
return result return result
} }
......
...@@ -27,16 +27,17 @@ import android.graphics.Typeface ...@@ -27,16 +27,17 @@ import android.graphics.Typeface
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.provider.Settings import android.provider.Settings
import android.support.design.widget.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import android.support.v7.preference.PreferenceDialogFragmentCompat import androidx.preference.PreferenceDialogFragmentCompat
import android.support.v7.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
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 android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.view.isVisible
import com.github.shadowsocks.R import com.github.shadowsocks.R
class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() { class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
...@@ -58,8 +59,8 @@ class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() { ...@@ -58,8 +59,8 @@ class BottomSheetPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
val typeface = if (selected) Typeface.BOLD else Typeface.NORMAL val typeface = if (selected) Typeface.BOLD else Typeface.NORMAL
text1.setTypeface(null, typeface) text1.setTypeface(null, typeface)
text2.setTypeface(null, typeface) text2.setTypeface(null, typeface)
text2.visibility = if (preference.entryValues[i].isNotEmpty() && text2.isVisible = preference.entryValues[i].isNotEmpty() &&
preference.entries[i] != preference.entryValues[i]) View.VISIBLE else View.GONE preference.entries[i] != preference.entryValues[i]
icon.setImageDrawable(preference.entryIcons?.get(i)) icon.setImageDrawable(preference.entryIcons?.get(i))
index = i index = i
} }
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
package com.github.shadowsocks.preference package com.github.shadowsocks.preference
import android.os.Binder import android.os.Binder
import android.support.v7.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.database.PrivateDatabase import com.github.shadowsocks.database.PrivateDatabase
import com.github.shadowsocks.database.PublicDatabase import com.github.shadowsocks.database.PublicDatabase
...@@ -52,37 +52,17 @@ object DataStore { ...@@ -52,37 +52,17 @@ object DataStore {
} }
val canToggleLocked: Boolean get() = publicStore.getBoolean(Key.directBootAware) == true val canToggleLocked: Boolean get() = publicStore.getBoolean(Key.directBootAware) == true
val directBootAware: Boolean get() = app.directBootSupported && canToggleLocked val directBootAware: Boolean get() = app.directBootSupported && canToggleLocked
private var nightModeString: String
get() = publicStore.getString(Key.nightMode) ?: Key.nightModeSystem
set(value) = publicStore.putString(Key.nightMode, value)
@AppCompatDelegate.NightMode @AppCompatDelegate.NightMode
val nightMode: Int get() = when (nightModeString) { val nightMode get() = when (publicStore.getString(Key.nightMode)) {
Key.nightModeAuto -> AppCompatDelegate.MODE_NIGHT_AUTO Key.nightModeAuto -> AppCompatDelegate.MODE_NIGHT_AUTO
Key.nightModeOff -> AppCompatDelegate.MODE_NIGHT_NO Key.nightModeOff -> AppCompatDelegate.MODE_NIGHT_NO
Key.nightModeOn -> AppCompatDelegate.MODE_NIGHT_YES Key.nightModeOn -> AppCompatDelegate.MODE_NIGHT_YES
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
} }
var serviceMode: String val serviceMode get() = publicStore.getString(Key.serviceMode) ?: Key.modeVpn
get() = publicStore.getString(Key.serviceMode) ?: Key.modeVpn val portProxy get() = getLocalPort(Key.portProxy, 1080)
set(value) = publicStore.putString(Key.serviceMode, value) val portLocalDns get() = getLocalPort(Key.portLocalDns, 5450)
var portProxy: Int val portTransproxy get() = getLocalPort(Key.portTransproxy, 8200)
get() = getLocalPort(Key.portProxy, 1080)
set(value) = publicStore.putString(Key.portProxy, value.toString())
var portLocalDns: Int
get() = getLocalPort(Key.portLocalDns, 5450)
set(value) = publicStore.putString(Key.portLocalDns, value.toString())
var portTransproxy: Int
get() = getLocalPort(Key.portTransproxy, 8200)
set(value) = publicStore.putString(Key.portTransproxy, value.toString())
fun initGlobal() {
// temporary workaround for support lib bug
if (publicStore.getString(Key.nightMode) == null) nightModeString = nightModeString
if (publicStore.getString(Key.serviceMode) == null) serviceMode = serviceMode
if (publicStore.getString(Key.portProxy) == null) portProxy = portProxy
if (publicStore.getString(Key.portLocalDns) == null) portLocalDns = portLocalDns
if (publicStore.getString(Key.portTransproxy) == null) portTransproxy = portTransproxy
}
var proxyApps: Boolean var proxyApps: Boolean
get() = privateStore.getBoolean(Key.proxyApps) ?: false get() = privateStore.getBoolean(Key.proxyApps) ?: false
......
...@@ -22,7 +22,7 @@ package com.github.shadowsocks.preference ...@@ -22,7 +22,7 @@ package com.github.shadowsocks.preference
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.support.v7.preference.ListPreference import androidx.preference.ListPreference
import android.util.AttributeSet import android.util.AttributeSet
class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPreference(context, attrs) { class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPreference(context, attrs) {
...@@ -68,8 +68,8 @@ class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPr ...@@ -68,8 +68,8 @@ class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPr
fun init() { fun init() {
icon = entryIcon icon = entryIcon
} }
override fun onSetInitialValue(restoreValue: Boolean, defaultValue: Any?) { override fun onSetInitialValue(defaultValue: Any?) {
super.onSetInitialValue(restoreValue, defaultValue) super.onSetInitialValue(defaultValue)
init() init()
} }
} }
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
package com.github.shadowsocks.preference package com.github.shadowsocks.preference
import android.support.v7.preference.PreferenceDataStore import androidx.preference.PreferenceDataStore
interface OnPreferenceDataStoreChangeListener { interface OnPreferenceDataStoreChangeListener {
fun onPreferenceDataStoreChanged(store: PreferenceDataStore, key: String?) fun onPreferenceDataStoreChanged(store: PreferenceDataStore, key: String?)
......
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
package com.github.shadowsocks.preference package com.github.shadowsocks.preference
import android.support.v7.app.AlertDialog import androidx.appcompat.app.AlertDialog
import android.view.View import android.view.View
import android.widget.EditText import android.widget.EditText
import com.github.shadowsocks.ProfileConfigActivity import com.github.shadowsocks.ProfileConfigActivity
import com.github.shadowsocks.plugin.PluginContract import com.github.shadowsocks.plugin.PluginContract
import com.github.shadowsocks.plugin.PluginManager import com.github.shadowsocks.plugin.PluginManager
import com.takisoft.fix.support.v7.preference.EditTextPreferenceDialogFragmentCompat import com.takisoft.preferencex.EditTextPreferenceDialogFragmentCompat
class PluginConfigurationDialogFragment : EditTextPreferenceDialogFragmentCompat() { class PluginConfigurationDialogFragment : EditTextPreferenceDialogFragmentCompat() {
companion object { companion object {
...@@ -41,10 +41,10 @@ class PluginConfigurationDialogFragment : EditTextPreferenceDialogFragmentCompat ...@@ -41,10 +41,10 @@ class PluginConfigurationDialogFragment : EditTextPreferenceDialogFragmentCompat
val intent = PluginManager.buildIntent(arguments!!.getString(PLUGIN_ID_FRAGMENT_TAG), val intent = PluginManager.buildIntent(arguments!!.getString(PLUGIN_ID_FRAGMENT_TAG),
PluginContract.ACTION_HELP) PluginContract.ACTION_HELP)
val activity = requireActivity() val activity = requireActivity()
if (intent.resolveActivity(activity.packageManager) != null) builder.setNeutralButton("?", { _, _ -> if (intent.resolveActivity(activity.packageManager) != null) builder.setNeutralButton("?") { _, _ ->
activity.startActivityForResult(intent.putExtra(PluginContract.EXTRA_OPTIONS, editText.text.toString()), activity.startActivityForResult(intent.putExtra(PluginContract.EXTRA_OPTIONS, editText.text.toString()),
ProfileConfigActivity.REQUEST_CODE_PLUGIN_HELP) ProfileConfigActivity.REQUEST_CODE_PLUGIN_HELP)
}) }
} }
override fun onBindDialogView(view: View) { override fun onBindDialogView(view: View) {
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
package com.github.shadowsocks.preference package com.github.shadowsocks.preference
import android.support.v7.preference.PreferenceDataStore import androidx.preference.PreferenceDataStore
import com.github.shadowsocks.database.KeyValuePair import com.github.shadowsocks.database.KeyValuePair
import java.util.HashSet import java.util.HashSet
......
...@@ -23,11 +23,11 @@ package com.github.shadowsocks.tasker ...@@ -23,11 +23,11 @@ package com.github.shadowsocks.tasker
import android.app.Activity import android.app.Activity
import android.content.res.Resources import android.content.res.Resources
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.support.v7.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.support.v7.widget.Toolbar import androidx.appcompat.widget.Toolbar
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
...@@ -101,7 +101,7 @@ class ConfigActivity : AppCompatActivity() { ...@@ -101,7 +101,7 @@ class ConfigActivity : AppCompatActivity() {
switch = findViewById(R.id.serviceSwitch) switch = findViewById(R.id.serviceSwitch)
switch.isChecked = taskerOption.switchOn switch.isChecked = taskerOption.switchOn
val profilesList = findViewById<RecyclerView>(R.id.list) val profilesList = findViewById<RecyclerView>(R.id.list)
val lm = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) val lm = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
profilesList.layoutManager = lm profilesList.layoutManager = lm
profilesList.itemAnimator = DefaultItemAnimator() profilesList.itemAnimator = DefaultItemAnimator()
profilesList.adapter = profilesAdapter profilesList.adapter = profilesAdapter
......
...@@ -23,6 +23,7 @@ package com.github.shadowsocks.tasker ...@@ -23,6 +23,7 @@ package com.github.shadowsocks.tasker
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.core.os.bundleOf
import com.github.shadowsocks.R import com.github.shadowsocks.R
import com.github.shadowsocks.database.ProfileManager import com.github.shadowsocks.database.ProfileManager
import com.twofortyfouram.locale.api.Intent as ApiIntent import com.twofortyfouram.locale.api.Intent as ApiIntent
...@@ -44,13 +45,13 @@ class Settings(bundle: Bundle?) { ...@@ -44,13 +45,13 @@ class Settings(bundle: Bundle?) {
} }
fun toIntent(context: Context): Intent { fun toIntent(context: Context): Intent {
val bundle = Bundle()
if (!switchOn) bundle.putBoolean(KEY_SWITCH_ON, false)
if (profileId >= 0) bundle.putLong(KEY_PROFILE_ID, profileId)
val profile = ProfileManager.getProfile(profileId) val profile = ProfileManager.getProfile(profileId)
return Intent().putExtra(ApiIntent.EXTRA_BUNDLE, bundle).putExtra(ApiIntent.EXTRA_STRING_BLURB, return Intent()
if (profile != null) context.getString(if (switchOn) R.string.start_service else R.string.stop_service, .putExtra(ApiIntent.EXTRA_BUNDLE, bundleOf(Pair(KEY_SWITCH_ON, switchOn),
profile.formattedName) Pair(KEY_PROFILE_ID, profileId)))
else context.getString(if (switchOn) R.string.start_service_default else R.string.stop)) .putExtra(ApiIntent.EXTRA_STRING_BLURB,
if (profile != null) context.getString(
if (switchOn) R.string.start_service else R.string.stop_service, profile.formattedName)
else context.getString(if (switchOn) R.string.start_service_default else R.string.stop))
} }
} }
...@@ -10,11 +10,9 @@ import android.graphics.BitmapFactory ...@@ -10,11 +10,9 @@ import android.graphics.BitmapFactory
import android.graphics.ImageDecoder import android.graphics.ImageDecoder
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle
import android.support.annotation.AttrRes
import android.support.v4.content.ContextCompat
import android.support.v7.util.SortedList
import android.util.TypedValue import android.util.TypedValue
import androidx.annotation.AttrRes
import androidx.recyclerview.widget.SortedList
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.JniHelper import com.github.shadowsocks.JniHelper
import java.net.InetAddress import java.net.InetAddress
...@@ -49,8 +47,6 @@ fun thread(name: String? = null, start: Boolean = true, isDaemon: Boolean = fals ...@@ -49,8 +47,6 @@ fun thread(name: String? = null, start: Boolean = true, isDaemon: Boolean = fals
val URLConnection.responseLength: Long val URLConnection.responseLength: Long
get() = if (Build.VERSION.SDK_INT >= 24) contentLengthLong else contentLength.toLong() get() = if (Build.VERSION.SDK_INT >= 24) contentLengthLong else contentLength.toLong()
inline fun <reified T> Context.systemService() = ContextCompat.getSystemService(this, T::class.java)!!
fun ContentResolver.openBitmap(uri: Uri) = fun ContentResolver.openBitmap(uri: Uri) =
if (Build.VERSION.SDK_INT >= 28) ImageDecoder.decodeBitmap(ImageDecoder.createSource(this, uri)) if (Build.VERSION.SDK_INT >= 28) ImageDecoder.decodeBitmap(ImageDecoder.createSource(this, uri))
else BitmapFactory.decodeStream(openInputStream(uri)) else BitmapFactory.decodeStream(openInputStream(uri))
...@@ -81,8 +77,3 @@ fun printLog(t: Throwable) { ...@@ -81,8 +77,3 @@ fun printLog(t: Throwable) {
Crashlytics.logException(t) Crashlytics.logException(t)
t.printStackTrace() t.printStackTrace()
} }
fun Bundle.put(key: String, value: String): Bundle {
putString(key, value)
return this
}
...@@ -22,13 +22,21 @@ package com.github.shadowsocks.widget ...@@ -22,13 +22,21 @@ package com.github.shadowsocks.widget
import android.content.Context import android.content.Context
import android.graphics.Rect import android.graphics.Rect
import android.support.v7.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import androidx.core.view.isGone
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
class HackyTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : class AutoCollapseTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
defStyleAttr: Int = 0) :
AppCompatTextView(context, attrs, defStyleAttr) { AppCompatTextView(context, attrs, defStyleAttr) {
override fun onTextChanged(text: CharSequence?, start: Int, lengthBefore: Int, lengthAfter: Int) {
super.onTextChanged(text, start, lengthBefore, lengthAfter)
isGone = text.isNullOrEmpty()
}
// #1874
override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) = try { override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) = try {
super.onFocusChanged(focused, direction, previouslyFocusedRect) super.onFocusChanged(focused, direction, previouslyFocusedRect)
} catch (e: IndexOutOfBoundsException) { } catch (e: IndexOutOfBoundsException) {
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
package com.github.shadowsocks.widget package com.github.shadowsocks.widget
import android.content.Context import android.content.Context
import android.support.v7.widget.GridLayout import androidx.gridlayout.widget.GridLayout
import android.util.AttributeSet import android.util.AttributeSet
import com.github.shadowsocks.R import com.github.shadowsocks.R
......
...@@ -22,11 +22,11 @@ package com.github.shadowsocks.widget ...@@ -22,11 +22,11 @@ package com.github.shadowsocks.widget
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.support.annotation.DrawableRes import androidx.annotation.DrawableRes
import android.support.design.widget.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
import android.support.graphics.drawable.Animatable2Compat import androidx.vectordrawable.graphics.drawable.Animatable2Compat
import android.support.graphics.drawable.AnimatedVectorDrawableCompat import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
import android.support.v7.widget.TooltipCompat import androidx.appcompat.widget.TooltipCompat
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import com.github.shadowsocks.R import com.github.shadowsocks.R
......
...@@ -22,20 +22,20 @@ package com.github.shadowsocks.widget ...@@ -22,20 +22,20 @@ package com.github.shadowsocks.widget
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.support.design.animation.AnimationConsts import androidx.coordinatorlayout.widget.CoordinatorLayout
import android.support.design.widget.CoordinatorLayout import com.google.android.material.snackbar.Snackbar
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.SnackbarConsts
import android.support.design.widget.SnackbarConsts
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import android.view.accessibility.AccessibilityManager import android.view.accessibility.AccessibilityManager
import com.github.shadowsocks.utils.systemService import androidx.core.content.getSystemService
import com.google.android.material.animation.AnimationUtils
/** /**
* Full credits go to: https://stackoverflow.com/a/35904421/2245107 * Full credits go to: https://stackoverflow.com/a/35904421/2245107
*/ */
class ShrinkUpwardBehavior(context: Context, attrs: AttributeSet?) : CoordinatorLayout.Behavior<View>(context, attrs) { class ShrinkUpwardBehavior(context: Context, attrs: AttributeSet?) : CoordinatorLayout.Behavior<View>(context, attrs) {
private val accessibility = context.systemService<AccessibilityManager>() private val accessibility = context.getSystemService<AccessibilityManager>()!!
override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean = override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean =
dependency is Snackbar.SnackbarLayout dependency is Snackbar.SnackbarLayout
...@@ -54,11 +54,10 @@ class ShrinkUpwardBehavior(context: Context, attrs: AttributeSet?) : Coordinator ...@@ -54,11 +54,10 @@ class ShrinkUpwardBehavior(context: Context, attrs: AttributeSet?) : Coordinator
val animator = ValueAnimator() val animator = ValueAnimator()
val start = child.height val start = child.height
animator.setIntValues(start, parent.height) animator.setIntValues(start, parent.height)
animator.interpolator = AnimationConsts.FAST_OUT_SLOW_IN_INTERPOLATOR animator.interpolator = AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR
animator.duration = SnackbarConsts.ANIMATION_DURATION animator.duration = SnackbarConsts.ANIMATION_DURATION
@Suppress("NAME_SHADOWING") animator.addUpdateListener {
animator.addUpdateListener { animator -> child.layoutParams.height = it.animatedValue as Int
child.layoutParams.height = animator.animatedValue as Int
child.requestLayout() child.requestLayout()
} }
animator.start() animator.start()
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
package com.github.shadowsocks.widget package com.github.shadowsocks.widget
import android.support.design.widget.Snackbar import com.google.android.material.snackbar.Snackbar
import android.view.View import android.view.View
import com.github.shadowsocks.R import com.github.shadowsocks.R
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* * * *
*******************************************************************************/ *******************************************************************************/
package android.support.design.widget package com.google.android.material.snackbar
object SnackbarConsts { object SnackbarConsts {
const val ANIMATION_DURATION = BaseTransientBottomBar.ANIMATION_DURATION.toLong() const val ANIMATION_DURATION = BaseTransientBottomBar.ANIMATION_DURATION.toLong()
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<!-- android:start not available until API 23 --> <!-- android:start not available until API 23 -->
<item android:left="8dp"> <item android:left="8dp">
<shape android:shape="rectangle"> <shape android:shape="rectangle">
<solid android:color="@color/background" /> <solid android:color="?android:colorBackground" />
</shape> </shape>
</item> </item>
<item android:drawable="?android:attr/selectableItemBackground"/> <item android:drawable="?android:attr/selectableItemBackground"/>
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/darker_gray" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<corners
android:topLeftRadius="44dp"
android:topRightRadius="44dp"
android:bottomLeftRadius="44dp" />
<padding
android:paddingLeft="22dp"
android:paddingRight="22dp" />
<solid android:color="@color/color_primary_dark" />
</shape>
</item>
</selector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFF"
android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z"/>
</vector>
...@@ -10,15 +10,15 @@ ...@@ -10,15 +10,15 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:labelFor="@+id/content" android:labelFor="@+id/content"
android:entries="@array/acl_rule_templates"/> android:entries="@array/acl_rule_templates"/>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/content_layout" android:id="@+id/content_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:errorEnabled="true"> app:errorEnabled="true">
<android.support.design.widget.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/content" android:id="@+id/content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="textNoSuggestions|textMultiLine"/> android:inputType="textNoSuggestions|textMultiLine"/>
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
</LinearLayout> </LinearLayout>
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:scrollbars="vertical"> android:scrollbars="vertical">
<com.github.shadowsocks.widget.HackyTextView <com.github.shadowsocks.widget.AutoCollapseTextView
android:id="@+id/tv_about" android:id="@+id/tv_about"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<LinearLayout android:layout_width="fill_parent" <LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:elevation="1dp" android:elevation="1dp"
android:background="@color/background" android:background="?android:colorBackground"
android:orientation="vertical" android:orientation="vertical"
tools:ignore="RtlSymmetry"> tools:ignore="RtlSymmetry">
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="true" android:checked="true"
android:paddingBottom="12dp" android:paddingBottom="12dp"
android:paddingEnd="@dimen/fastscroll__bubble_corner" android:paddingEnd="16dp"
android:paddingStart="72dp" android:paddingStart="72dp"
android:paddingTop="12dp" android:paddingTop="12dp"
android:text="@string/on" android:text="@string/on"
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="true" android:checked="true"
android:paddingBottom="12dp" android:paddingBottom="12dp"
android:paddingEnd="@dimen/fastscroll__bubble_corner" android:paddingEnd="16dp"
android:paddingStart="72dp" android:paddingStart="72dp"
android:paddingTop="12dp" android:paddingTop="12dp"
android:text="@string/bypass_apps" android:text="@string/bypass_apps"
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
android:textSize="18sp" android:textSize="18sp"
android:tooltipText="@string/bypass_apps_summary"/> android:tooltipText="@string/bypass_apps_summary"/>
</LinearLayout> </LinearLayout>
<android.support.design.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/snackbar" android:id="@+id/snackbar"
android:background="@color/material_primary_700" android:background="@color/material_primary_700"
android:layout_width="match_parent" android:layout_width="match_parent"
...@@ -56,22 +56,16 @@ ...@@ -56,22 +56,16 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" /> android:layout_gravity="center" />
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:id="@+id/list" android:id="@+id/list"
app:fastScrollEnabled="true"
app:fastScrollHorizontalThumbDrawable="@drawable/fastscroll_thumb"
app:fastScrollHorizontalTrackDrawable="@drawable/fastscroll_line"
app:fastScrollVerticalThumbDrawable="@drawable/fastscroll_thumb"
app:fastScrollVerticalTrackDrawable="@drawable/fastscroll_line"
tools:listitem="@layout/layout_apps_item"/> tools:listitem="@layout/layout_apps_item"/>
<com.futuremind.recyclerviewfastscroll.FastScroller
android:id="@+id/fastscroller"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:fastscroll__handleColor="@color/material_primary_500"
app:fastscroll__bubbleColor="@color/material_primary_500"
app:fastscroll__bubbleTextAppearance="@style/StyledScrollerTextAppearance"/>
</FrameLayout> </FrameLayout>
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout> </LinearLayout>
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
android:id="@+id/itemcheck" android:id="@+id/itemcheck"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:layout_marginEnd="@dimen/fastscroll__bubble_corner" android:layout_marginEnd="16dp"
android:layout_weight="1" android:layout_weight="1"
android:clickable="false" android:clickable="false"
android:ellipsize="end" android:ellipsize="end"
......
...@@ -9,22 +9,17 @@ ...@@ -9,22 +9,17 @@
<FrameLayout android:layout_width="match_parent" <FrameLayout android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1"> android:layout_weight="1">
<android.support.v7.widget.RecyclerView android:id="@+id/list" <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent" android:id="@+id/list"
android:layout_height="match_parent" android:layout_width="match_parent"
android:paddingBottom="32dp" android:layout_height="match_parent"
tools:listitem="@android:layout/simple_list_item_1" android:paddingBottom="32dp"
android:clipToPadding="false"/> android:clipToPadding="false"
<com.futuremind.recyclerviewfastscroll.FastScroller app:fastScrollEnabled="true"
android:id="@+id/fastscroller" app:fastScrollHorizontalThumbDrawable="@drawable/fastscroll_thumb"
android:orientation="vertical" app:fastScrollHorizontalTrackDrawable="@drawable/fastscroll_line"
android:layout_width="wrap_content" app:fastScrollVerticalThumbDrawable="@drawable/fastscroll_thumb"
android:layout_height="match_parent" app:fastScrollVerticalTrackDrawable="@drawable/fastscroll_line"
android:layout_gravity="end" tools:listitem="@android:layout/simple_list_item_1"/>
android:layout_marginTop="8dp"
android:layout_marginBottom="32dp"
app:fastscroll__handleColor="@color/material_primary_500"
app:fastscroll__bubbleColor="@color/material_primary_500"
app:fastscroll__bubbleTextAppearance="@style/StyledScrollerTextAppearance"/>
</FrameLayout> </FrameLayout>
</LinearLayout> </LinearLayout>
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/toolbar_light_dark"/> <include layout="@layout/toolbar_light_dark"/>
<android.support.v7.widget.RecyclerView android:id="@+id/list" <androidx.recyclerview.widget.RecyclerView android:id="@+id/list"
tools:listitem="@layout/layout_profile" tools:listitem="@layout/layout_profile"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
......
This diff is collapsed.
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
android:textStyle="bold" android:textStyle="bold"
tools:text="@string/profile_name"/> tools:text="@string/profile_name"/>
<android.support.v7.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/share" android:id="@+id/share"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
android:padding="12dp" android:padding="12dp"
app:srcCompat="@drawable/ic_social_share"/> app:srcCompat="@drawable/ic_social_share"/>
<android.support.v7.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/edit" android:id="@+id/edit"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
> >
<TextView <com.github.shadowsocks.widget.AutoCollapseTextView
android:id="@android:id/text2" android:id="@android:id/text2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
tools:text="@string/profile_plugin"/> tools:text="@string/profile_plugin"/>
<TextView <com.github.shadowsocks.widget.AutoCollapseTextView
android:id="@+id/traffic" android:id="@+id/traffic"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
android:textSize="18sp" android:textSize="18sp"
android:padding="16dp"/> android:padding="16dp"/>
</FrameLayout> </FrameLayout>
<android.support.v7.widget.RecyclerView android:id="@+id/list" <androidx.recyclerview.widget.RecyclerView android:id="@+id/list"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:itemview="@android:layout/select_dialog_singlechoice_material" tools:itemview="@android:layout/select_dialog_singlechoice_material"
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<ImageView android:layout_width="match_parent" <ImageView android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:scaleType="centerCrop" android:scaleType="centerCrop"
android:src="@drawable/background_header"/> android:src="@drawable/background_header"/>
<TextView android:id="@+id/drawer_title" <TextView android:id="@+id/drawer_title"
android:layout_width="match_parent" android:layout_width="match_parent"
......
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/main"
android:checkableBehavior="single">
<item android:id="@+id/profiles"
android:title="@string/profiles"
android:icon="@drawable/ic_action_description"/>
<item android:id="@+id/customRules"
android:title="@string/custom_rules"
android:icon="@drawable/ic_action_assignment"/>
<item android:id="@+id/globalSettings"
android:title="@string/settings"
android:icon="@drawable/ic_action_settings"/>
</group>
<group android:id="@+id/misc"
android:checkableBehavior="single">
<item android:id="@+id/faq"
android:checkable="false"
android:title="@string/faq"
android:icon="@drawable/ic_action_help_outline"/>
<item android:id="@+id/about"
android:title="@string/about"
android:icon="@drawable/ic_action_copyright"/>
</group>
</menu>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="background">@color/md_dark_background</color>
<color name="background_selected">@color/material_primary_800</color> <color name="background_selected">@color/material_primary_800</color>
<color name="primary_drawable">@android:color/white</color> <color name="primary_drawable">@android:color/white</color>
<color name="background_stat">@color/material_primary_600</color> <color name="background_stat">@color/material_primary_600</color>
<!-- MaterialDrawer colors -->
<color name="drawer_background">@color/material_drawer_dark_background</color>
<color name="drawer_primary_text">@color/material_drawer_dark_primary_text</color>
<color name="drawer_primary_icon">@color/material_drawer_dark_primary_icon</color>
<color name="drawer_secondary_text">@color/material_drawer_dark_secondary_text</color>
<color name="drawer_hint_text">@color/material_drawer_dark_hint_text</color>
<color name="drawer_divider">@color/material_drawer_dark_divider</color>
<color name="drawer_selected">@color/material_drawer_dark_selected</color>
<color name="drawer_selected_text">@color/material_accent_200</color>
<color name="drawer_header_selection_text">@color/material_drawer_dark_header_selection_text</color>
</resources> </resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Design.DayNight.BottomSheetDialog" parent="@style/Theme.Design.BottomSheetDialog"/>
</resources>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="ic_launcher_background">#7488A1</color> <color name="ic_launcher_background">#7488A1</color>
<color name="material_drawer_selected_text">@color/material_accent_200</color>
<color name="background">@color/md_light_background</color>
<color name="background_selected">@color/material_primary_100</color> <color name="background_selected">@color/material_primary_100</color>
<color name="primary_drawable">@android:color/black</color> <color name="primary_drawable">@android:color/black</color>
<color name="background_stat">@color/material_primary_300</color> <color name="background_stat">@color/material_primary_300</color>
<!-- MaterialDrawer colors -->
<color name="drawer_background">@color/material_drawer_background</color>
<color name="drawer_primary_text">@color/material_drawer_primary_text</color>
<color name="drawer_primary_icon">@color/material_drawer_primary_icon</color>
<color name="drawer_secondary_text">@color/material_drawer_secondary_text</color>
<color name="drawer_hint_text">@color/material_drawer_hint_text</color>
<color name="drawer_divider">@color/material_drawer_divider</color>
<color name="drawer_selected">@color/material_drawer_selected</color>
<color name="drawer_selected_text">@color/material_accent_200</color>
<color name="drawer_header_selection_text">@color/material_drawer_header_selection_text</color>
</resources> </resources>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="Theme.Shadowsocks.App">
<item name="bottomSheetDialogTheme">@style/Theme.Design.DayNight.BottomSheetDialog</item>
<!-- MaterialDrawer specific values -->
<item name="material_drawer_background">@color/drawer_background</item>
<item name="material_drawer_primary_text">@color/drawer_primary_text</item>
<item name="material_drawer_primary_icon">@color/drawer_primary_icon</item>
<item name="material_drawer_secondary_text">@color/drawer_secondary_text</item>
<item name="material_drawer_hint_text">@color/drawer_hint_text</item>
<item name="material_drawer_divider">@color/drawer_divider</item>
<item name="material_drawer_selected">@color/drawer_selected</item>
<item name="material_drawer_selected_text">@color/drawer_selected_text</item>
<item name="material_drawer_header_selection_text">@color/drawer_header_selection_text</item>
</style>
<style name="Theme.Design.DayNight.BottomSheetDialog" parent="@style/Theme.Design.Light.BottomSheetDialog"/>
<!-- https://github.com/Gericop/Android-Support-Preference-V7-Fix/issues/111 -->
<style name="Preference.SimpleMenuPreference">
<item name="android:layout">@layout/preference_simplemenu</item>
<item name="allowDividerAbove">false</item>
<item name="allowDividerBelow">true</item>
<item name="iconSpaceReserved">@bool/config_materialPreferenceIconSpaceReserved</item>
<item name="pref_popupStyle">@style/Preference.SimpleMenuPreference.Popup</item>
</style>
<style name="StyledScrollerTextAppearance" parent="@android:style/TextAppearance"> <style name="StyledScrollerTextAppearance" parent="@android:style/TextAppearance">
<item name="android:textSize">24sp</item> <item name="android:textSize">24sp</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
......
* 0.2.0:
* Refactor to AndroidX.
* 0.1.1: * 0.1.1:
* Rewritten in Kotlin; * Rewritten in Kotlin;
* Fix assert not working; * Fix assert not working;
......
...@@ -10,10 +10,10 @@ android { ...@@ -10,10 +10,10 @@ android {
defaultConfig { defaultConfig {
minSdkVersion rootProject.minSdkVersion minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.sdkVersion targetSdkVersion rootProject.sdkVersion
versionCode 6 versionCode 7
versionName "0.1.1" versionName "0.2.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
...@@ -24,12 +24,14 @@ android { ...@@ -24,12 +24,14 @@ android {
} }
dependencies { dependencies {
api "com.android.support:preference-v14:$supportLibraryVersion" api "androidx.core:core-ktx:$androidxVersion"
api "com.takisoft.fix:preference-v7:$takisoftFixVersion" api "androidx.preference:preference:$androidxVersion"
api "com.google.android.material:material:$androidxVersion"
api 'com.takisoft.preferencex:preferencex:1.0.0-alpha1'
api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
testImplementation "junit:junit:$junitVersion" testImplementation "junit:junit:$junitVersion"
androidTestImplementation "com.android.support.test:runner:$androidTestVersion" androidTestImplementation "androidx.test:runner:$androidTestVersion"
androidTestImplementation "com.android.support.test.espresso:espresso-core:$androidEspressoVersion" androidTestImplementation "androidx.test.espresso:espresso-core:$androidEspressoVersion"
} }
repositories { repositories {
mavenCentral() mavenCentral()
......
package com.github.shadowsocks.plugin; package com.github.shadowsocks.plugin;
import android.content.Context; import android.content.Context;
import android.support.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
......
...@@ -27,6 +27,7 @@ import android.database.MatrixCursor ...@@ -27,6 +27,7 @@ import android.database.MatrixCursor
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor
import androidx.core.os.bundleOf
/** /**
* Base class for a native plugin provider. A native plugin provider offers read-only access to files that are required * Base class for a native plugin provider. A native plugin provider offers read-only access to files that are required
...@@ -83,12 +84,8 @@ abstract class NativePluginProvider : ContentProvider() { ...@@ -83,12 +84,8 @@ abstract class NativePluginProvider : ContentProvider() {
return openFile(uri) return openFile(uri)
} }
override fun call(method: String?, arg: String?, extras: Bundle?): Bundle = when (method) { override fun call(method: String?, arg: String?, extras: Bundle?): Bundle? = when (method) {
PluginContract.METHOD_GET_EXECUTABLE -> { PluginContract.METHOD_GET_EXECUTABLE -> bundleOf(Pair(PluginContract.EXTRA_ENTRY, getExecutable()))
val out = Bundle()
out.putString(PluginContract.EXTRA_ENTRY, getExecutable())
out
}
else -> super.call(method, arg, extras) else -> super.call(method, arg, extras)
} }
......
...@@ -22,8 +22,8 @@ package com.github.shadowsocks.plugin ...@@ -22,8 +22,8 @@ package com.github.shadowsocks.plugin
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.support.v7.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import android.widget.Toast import android.widget.Toast
/** /**
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
package com.github.shadowsocks.plugin package com.github.shadowsocks.plugin
import android.support.v7.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
/** /**
* The contract between the plugin provider and host. Contains definitions for the supported actions, extras, etc. * The contract between the plugin provider and host. Contains definitions for the supported actions, extras, etc.
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="Theme.Shadowsocks" parent="Theme.MaterialComponents.NoActionBar">
<item name="android:navigationBarColor">@color/color_primary_dark</item>
<item name="actionModeCloseDrawable">@drawable/ic_navigation_close</item>
<item name="bottomSheetDialogTheme">@style/Theme.MaterialComponents.DayNight.BottomSheetDialog</item>
<item name="colorAccent">@color/material_accent_200</item>
<item name="colorButtonNormal">@color/material_accent_200</item>
<item name="colorPrimary">@color/color_primary</item>
<item name="colorPrimaryDark">@color/color_primary_dark</item>
<item name="windowActionModeOverlay">true</item>
</style>
<style name="Theme.MaterialComponents.DayNight.BottomSheetDialog"
parent="@style/Theme.MaterialComponents.BottomSheetDialog"/>
<style name="ThemeOverlay.AppCompat.DayNight" parent="ThemeOverlay.AppCompat.Dark"/> <style name="ThemeOverlay.AppCompat.DayNight" parent="ThemeOverlay.AppCompat.Dark"/>
</resources> </resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="Theme.Shadowsocks" parent="Theme.AppCompat.DayNight.NoActionBar"> <style name="Theme.Shadowsocks" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:navigationBarColor">@color/color_primary_dark</item> <item name="android:navigationBarColor">@color/color_primary_dark</item>
<item name="actionModeCloseDrawable">@drawable/ic_navigation_close</item> <item name="actionModeCloseDrawable">@drawable/ic_navigation_close</item>
<item name="bottomSheetDialogTheme">@style/Theme.MaterialComponents.DayNight.BottomSheetDialog</item>
<item name="colorAccent">@color/material_accent_200</item> <item name="colorAccent">@color/material_accent_200</item>
<item name="colorButtonNormal">@color/material_accent_200</item> <item name="colorButtonNormal">@color/material_accent_200</item>
<item name="colorPrimary">@color/color_primary</item> <item name="colorPrimary">@color/color_primary</item>
<item name="colorPrimaryDark">@color/color_primary_dark</item> <item name="colorPrimaryDark">@color/color_primary_dark</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material.Fix</item>
<item name="preferenceCategory_marginBottom">8dp</item>
<item name="windowActionModeOverlay">true</item> <item name="windowActionModeOverlay">true</item>
</style> </style>
<style name="Theme.MaterialComponents.DayNight.BottomSheetDialog"
parent="@style/Theme.MaterialComponents.Light.BottomSheetDialog"/>
<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.Dialog"> <style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item> <item name="android:windowFrame">@null</item>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment