Misc refinements
* Refine Kotlin codes; * Support RTL; * Use VectorDrawable for notification; * Remove redundant resources; * Better IDE integration.
@@ -110,13 +110,17 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
|
||||
}
|
||||
|
||||
private inner class AppsAdapter : RecyclerView.Adapter<AppViewHolder>(), SectionTitleProvider {
|
||||
private val apps = getApps(packageManager).sortedWith(Comparator { a, b ->
|
||||
when (Pair(proxiedApps.contains(a.packageName), proxiedApps.contains(b.packageName))) {
|
||||
Pair(true, false) -> -1
|
||||
Pair(false, true) -> 1
|
||||
else -> a.name.compareTo(b.name, true)
|
||||
}
|
||||
})
|
||||
private var apps = listOf<ProxiedApp>()
|
||||
|
||||
fun reload() {
|
||||
apps = getApps(packageManager).sortedWith(Comparator { a, b ->
|
||||
when (Pair(proxiedApps.contains(a.packageName), proxiedApps.contains(b.packageName))) {
|
||||
Pair(true, false) -> -1
|
||||
Pair(false, true) -> 1
|
||||
else -> a.name.compareTo(b.name, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: AppViewHolder, position: Int) = holder.bind(apps[position])
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder =
|
||||
@@ -143,15 +147,17 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
|
||||
}
|
||||
private fun loadAppsAsync() {
|
||||
if (!appsLoading.compareAndSet(false, true)) return
|
||||
appListView.visibility = View.GONE
|
||||
fastScroller.visibility = View.GONE
|
||||
loadingView.visibility = View.VISIBLE
|
||||
thread {
|
||||
var adapter: AppsAdapter?
|
||||
val adapter = appListView.adapter as AppsAdapter
|
||||
do {
|
||||
appsLoading.set(true)
|
||||
adapter = AppsAdapter()
|
||||
adapter.reload()
|
||||
} while (!appsLoading.compareAndSet(true, false))
|
||||
handler.post {
|
||||
appListView.adapter = adapter
|
||||
fastScroller.setRecyclerView(appListView)
|
||||
adapter.notifyDataSetChanged()
|
||||
val shortAnimTime = resources.getInteger(android.R.integer.config_shortAnimTime)
|
||||
appListView.alpha = 0F
|
||||
appListView.visibility = View.VISIBLE
|
||||
@@ -204,7 +210,9 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
|
||||
appListView = findViewById(R.id.list)
|
||||
appListView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||
appListView.itemAnimator = DefaultItemAnimator()
|
||||
appListView.adapter = AppsAdapter()
|
||||
fastScroller = findViewById(R.id.fastscroller)
|
||||
fastScroller.setRecyclerView(appListView)
|
||||
|
||||
instance = this
|
||||
loadAppsAsync()
|
||||
@@ -241,9 +249,6 @@ class AppManager : AppCompatActivity(), Toolbar.OnMenuItemClickListener {
|
||||
DataStore.individual = apps
|
||||
DataStore.dirty = true
|
||||
Toast.makeText(this, R.string.action_import_msg, Toast.LENGTH_SHORT).show()
|
||||
appListView.visibility = View.GONE
|
||||
fastScroller.visibility = View.GONE
|
||||
loadingView.visibility = View.VISIBLE
|
||||
initProxiedApps(apps)
|
||||
reloadApps()
|
||||
return true
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.IBinder
|
||||
import android.os.RemoteException
|
||||
import com.github.shadowsocks.App.Companion.app
|
||||
import com.github.shadowsocks.aidl.IShadowsocksService
|
||||
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
|
||||
import com.github.shadowsocks.bg.BaseService
|
||||
|
||||
@@ -33,7 +33,7 @@ open class ToolbarFragment : Fragment() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
toolbar = view.findViewById<Toolbar>(R.id.toolbar)
|
||||
toolbar = view.findViewById(R.id.toolbar)
|
||||
val activity = activity as MainActivity
|
||||
if (activity.crossfader == null) activity.drawer.setToolbar(activity, toolbar, true)
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.github.shadowsocks.ToolbarFragment
|
||||
import com.github.shadowsocks.bg.BaseService
|
||||
import com.github.shadowsocks.utils.Subnet
|
||||
import com.github.shadowsocks.utils.asIterable
|
||||
import com.github.shadowsocks.utils.dp
|
||||
import com.github.shadowsocks.widget.UndoSnackbarManager
|
||||
import java.net.IDN
|
||||
import java.net.URL
|
||||
@@ -76,6 +77,8 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
|
||||
private val text = view.findViewById<TextView>(android.R.id.text1)
|
||||
|
||||
init {
|
||||
view.setPaddingRelative(view.paddingStart, view.paddingTop,
|
||||
Math.max(view.paddingEnd, 20f.dp().toInt()), view.paddingBottom)
|
||||
view.setOnClickListener(this)
|
||||
view.setOnLongClickListener(this)
|
||||
view.setBackgroundResource(R.drawable.background_selectable)
|
||||
|
||||
@@ -28,13 +28,12 @@ import java.io.File
|
||||
|
||||
object Executable {
|
||||
const val REDSOCKS = "libredsocks.so"
|
||||
const val PDNSD = "libpdnsd.so"
|
||||
const val SS_LOCAL = "libss-local.so"
|
||||
const val SS_TUNNEL = "libss-tunnel.so"
|
||||
const val TUN2SOCKS = "libtun2socks.so"
|
||||
const val OVERTURE = "liboverture.so"
|
||||
|
||||
val EXECUTABLES = setOf(SS_LOCAL, SS_TUNNEL, PDNSD, REDSOCKS, TUN2SOCKS, OVERTURE)
|
||||
val EXECUTABLES = setOf(SS_LOCAL, SS_TUNNEL, REDSOCKS, TUN2SOCKS, OVERTURE)
|
||||
|
||||
fun killAll() {
|
||||
for (process in File("/proc").listFiles { _, name -> TextUtils.isDigitsOnly(name) }) {
|
||||
|
||||
@@ -69,7 +69,7 @@ class ServiceNotification(private val service: BaseService.Interface, profileNam
|
||||
.setContentTitle(profileName)
|
||||
.setContentIntent(PendingIntent.getActivity(service, 0, Intent(service, MainActivity::class.java)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT), 0))
|
||||
.setSmallIcon(R.drawable.ic_stat_shadowsocks)
|
||||
.setSmallIcon(R.drawable.ic_start_connected)
|
||||
private val style = NotificationCompat.BigTextStyle(builder)
|
||||
private var isVisible = true
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ object TrafficMonitor {
|
||||
var rxTotal = 0L
|
||||
|
||||
// Bytes for the last query
|
||||
var txLast = 0L
|
||||
var rxLast = 0L
|
||||
var timestampLast = 0L
|
||||
private var txLast = 0L
|
||||
private var rxLast = 0L
|
||||
private var timestampLast = 0L
|
||||
@Volatile
|
||||
var dirty = true
|
||||
private var dirty = true
|
||||
|
||||
private val units = arrayOf("KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", "BB", "NB", "DB", "CB")
|
||||
private val numberFormat = DecimalFormat("@@@")
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.github.shadowsocks.App.Companion.app
|
||||
import com.github.shadowsocks.ProfilesFragment
|
||||
|
||||
object ProfileManager {
|
||||
const val TAG = "ProfileManager"
|
||||
private const val TAG = "ProfileManager"
|
||||
|
||||
fun createProfile(p: Profile? = null): Profile {
|
||||
val profile = p ?: Profile()
|
||||
|
||||
@@ -21,12 +21,13 @@
|
||||
package com.github.shadowsocks.plugin
|
||||
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.os.Bundle
|
||||
|
||||
class NativePlugin(resolveInfo: ResolveInfo) : ResolvedPlugin(resolveInfo) {
|
||||
init {
|
||||
assert(resolveInfo.providerInfo != null)
|
||||
}
|
||||
|
||||
override val metaData get() = resolveInfo.providerInfo.metaData
|
||||
override val packageName get() = resolveInfo.providerInfo.packageName
|
||||
override val metaData: Bundle get() = resolveInfo.providerInfo.metaData
|
||||
override val packageName: String get() = resolveInfo.providerInfo.packageName
|
||||
}
|
||||
|
||||
@@ -36,9 +36,11 @@ class PluginConfiguration(val pluginsOptions: Map<String, PluginOptions>, val se
|
||||
val iterator = Commandline.translateCommandline(line).drop(1).iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val option = iterator.next()
|
||||
if (option == "--nocomp") opt.put("nocomp", null)
|
||||
else if (option.startsWith("--")) opt.put(option.substring(2), iterator.next())
|
||||
else throw IllegalArgumentException("Unknown kcptun parameter: " + option)
|
||||
when {
|
||||
option == "--nocomp" -> opt.put("nocomp", null)
|
||||
option.startsWith("--") -> opt.put(option.substring(2), iterator.next())
|
||||
else -> throw IllegalArgumentException("Unknown kcptun parameter: " + option)
|
||||
}
|
||||
}
|
||||
} catch (exc: Exception) {
|
||||
Log.w("PluginConfiguration", exc.message)
|
||||
@@ -55,6 +57,6 @@ class PluginConfiguration(val pluginsOptions: Map<String, PluginOptions>, val se
|
||||
val result = LinkedList<PluginOptions>()
|
||||
for ((id, opt) in pluginsOptions) if (id == this.selected) result.addFirst(opt) else result.addLast(opt)
|
||||
if (!pluginsOptions.contains(selected)) result.addFirst(selectedOptions)
|
||||
return result.map { it.toString(false) }.joinToString("\n")
|
||||
return result.joinToString("\n") { it.toString(false) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ import com.github.shadowsocks.App.Companion.app
|
||||
abstract class ResolvedPlugin(protected val resolveInfo: ResolveInfo) : Plugin() {
|
||||
protected abstract val metaData: Bundle
|
||||
|
||||
override val id by lazy { metaData.getString(PluginContract.METADATA_KEY_ID) }
|
||||
override val label by lazy { resolveInfo.loadLabel(app.packageManager) }
|
||||
override val icon by lazy { resolveInfo.loadIcon(app.packageManager) }
|
||||
override val defaultConfig by lazy { metaData.getString(PluginContract.METADATA_KEY_DEFAULT_CONFIG) }
|
||||
override val packageName get() = resolveInfo.resolvePackageName
|
||||
override val id: String by lazy { metaData.getString(PluginContract.METADATA_KEY_ID) }
|
||||
override val label: CharSequence by lazy { resolveInfo.loadLabel(app.packageManager) }
|
||||
override val icon: Drawable by lazy { resolveInfo.loadIcon(app.packageManager) }
|
||||
override val defaultConfig: String by lazy { metaData.getString(PluginContract.METADATA_KEY_DEFAULT_CONFIG) }
|
||||
override val packageName: String get() = resolveInfo.resolvePackageName
|
||||
override val trusted by lazy { app.info.signatures.any(PluginManager.trustedSignatures::contains) }
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.github.shadowsocks.utils.Key
|
||||
import com.github.shadowsocks.utils.parsePort
|
||||
import java.util.*
|
||||
|
||||
@Suppress("MemberVisibilityCanPrivate", "unused")
|
||||
object DataStore : PreferenceDataStore() {
|
||||
fun getBoolean(key: String?) = DBHelper.kvPairDao.queryForId(key)?.boolean
|
||||
fun getFloat(key: String?) = DBHelper.kvPairDao.queryForId(key)?.float
|
||||
|
||||
@@ -22,7 +22,6 @@ package com.github.shadowsocks.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.preference.Preference.OnPreferenceChangeListener
|
||||
import android.support.v7.preference.ListPreference
|
||||
import android.util.AttributeSet
|
||||
|
||||
@@ -43,19 +42,19 @@ class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPr
|
||||
var unknownValueSummary: String? = null
|
||||
var entryPackageNames: Array<String>? = null
|
||||
|
||||
var listener: OnPreferenceChangeListener? = null
|
||||
private var listener: OnPreferenceChangeListener? = null
|
||||
override fun getOnPreferenceChangeListener(): OnPreferenceChangeListener? = listener
|
||||
override fun setOnPreferenceChangeListener(listener: OnPreferenceChangeListener?) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
init {
|
||||
super.setOnPreferenceChangeListener(OnPreferenceChangeListener { preference, newValue ->
|
||||
super.setOnPreferenceChangeListener({ preference, newValue ->
|
||||
val listener = listener
|
||||
if (listener == null || listener.onPreferenceChange(preference, newValue)) {
|
||||
setValue(newValue.toString())
|
||||
value = newValue.toString()
|
||||
checkSummary()
|
||||
if (entryIcons != null) setIcon(entryIcon)
|
||||
if (entryIcons != null) icon = entryIcon
|
||||
true
|
||||
} else false
|
||||
})
|
||||
@@ -70,7 +69,9 @@ class IconListPreference(context: Context, attrs: AttributeSet? = null) : ListPr
|
||||
if (unknownValueSummary != null) summary = if (selectedEntry < 0) unknownValueSummary.format(value) else "%s"
|
||||
}
|
||||
|
||||
fun init() = setIcon(entryIcon)
|
||||
fun init() {
|
||||
icon = entryIcon
|
||||
}
|
||||
override fun onSetInitialValue(restoreValue: Boolean, defaultValue: Any?) {
|
||||
super.onSetInitialValue(restoreValue, defaultValue)
|
||||
init()
|
||||
|
||||
@@ -9,6 +9,7 @@ import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v7.util.SortedList
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
@@ -77,6 +78,8 @@ fun Toast.position(view: View, window: Window, offsetX: Int = 0, offsetY: Int =
|
||||
return this
|
||||
}
|
||||
|
||||
fun Float.dp(): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, app.resources.displayMetrics)
|
||||
|
||||
/**
|
||||
* Based on: https://stackoverflow.com/a/15656428/2245107
|
||||
*/
|
||||
|
||||
@@ -30,8 +30,8 @@ import com.github.shadowsocks.R
|
||||
* @param commit Callback for committing removals.
|
||||
* @tparam T Item type.
|
||||
*/
|
||||
class UndoSnackbarManager<T>(private val view: View, private val undo: (List<Pair<Int, T>>) -> Unit,
|
||||
commit: ((List<Pair<Int, T>>) -> Unit)? = null) {
|
||||
class UndoSnackbarManager<in T>(private val view: View, private val undo: (List<Pair<Int, T>>) -> Unit,
|
||||
commit: ((List<Pair<Int, T>>) -> Unit)? = null) {
|
||||
private val recycleBin = ArrayList<Pair<Int, T>>()
|
||||
private val removedCallback = object : Snackbar.Callback() {
|
||||
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
|
||||
|
||||
|
Before Width: | Height: | Size: 806 B After Width: | Height: | Size: 806 B |
|
Before Width: | Height: | Size: 556 B After Width: | Height: | Size: 556 B |
@@ -15,6 +15,7 @@
|
||||
</item>
|
||||
</selector>
|
||||
</item>
|
||||
<!-- android:start not available until API 23 -->
|
||||
<item android:left="8dp">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/white" />
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -1,6 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<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="#FFFFFFFF"
|
||||
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
|
||||
</vector>
|
||||
@@ -1,9 +0,0 @@
|
||||
<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="#FFFFFFFF"
|
||||
android:pathData="M19,2h-4.18C14.4,0.84 13.3,0 12,0c-1.3,0 -2.4,0.84 -2.82,2L5,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM12,2c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM19,20L5,20L5,4h2v3h10L17,4h2v16z"/>
|
||||
</vector>
|
||||
@@ -1,6 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
|
||||
@@ -14,28 +14,32 @@
|
||||
android:background="@android:color/white"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="RtlSymmetry">
|
||||
<Switch android:checked="true"
|
||||
android:id="@+id/onSwitch"
|
||||
android:text="@string/on"
|
||||
android:textSize="18sp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:paddingStart="60dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
<Switch android:checked="true"
|
||||
android:id="@+id/bypassSwitch"
|
||||
android:text="@string/bypass_apps"
|
||||
android:textSize="18sp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:paddingStart="60dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/onSwitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingStart="60dp"
|
||||
android:paddingTop="12dp"
|
||||
android:text="@string/on"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="18sp"/>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/bypassSwitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingStart="60dp"
|
||||
android:paddingTop="12dp"
|
||||
android:text="@string/bypass_apps"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="18sp"/>
|
||||
</LinearLayout>
|
||||
<FrameLayout android:layout_width="fill_parent"
|
||||
android:layout_height="0dp"
|
||||
@@ -48,7 +52,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/list"
|
||||
android:visibility="gone"/>
|
||||
tools:listitem="@layout/layout_apps_item"/>
|
||||
<com.futuremind.recyclerviewfastscroll.FastScroller
|
||||
android:id="@+id/fastscroller"
|
||||
android:orientation="vertical"
|
||||
@@ -57,7 +61,6 @@
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
app:fastscroll__handleColor="@color/material_primary_500"
|
||||
app:fastscroll__bubbleColor="@color/material_primary_500"
|
||||
app:fastscroll__bubbleTextAppearance="@style/StyledScrollerTextAppearance"/>
|
||||
|
||||
@@ -9,25 +9,25 @@
|
||||
<ImageView
|
||||
android:id="@+id/itemicon"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="48dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_height="52dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp"/>
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/itemcheck"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_weight="1"
|
||||
android:clickable="false"
|
||||
android:ellipsize="end"
|
||||
android:textSize="18sp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:clickable="false"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="18sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
@@ -12,6 +13,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="32dp"
|
||||
tools:listitem="@android:layout/simple_list_item_1"
|
||||
android:clipToPadding="false"/>
|
||||
<com.futuremind.recyclerviewfastscroll.FastScroller
|
||||
android:id="@+id/fastscroller"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<include layout="@layout/toolbar_light_dark"/>
|
||||
<android.support.v7.widget.RecyclerView android:id="@+id/list"
|
||||
tools:listitem="@android:layout/simple_list_item_1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@@ -18,5 +19,6 @@
|
||||
<android.support.v7.widget.RecyclerView android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:itemview="@android:layout/select_dialog_singlechoice_material"
|
||||
android:scrollbars="vertical"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item android:id="@+id/action_apply_all"
|
||||
android:title="@string/action_apply_all"
|
||||
android:alphabeticShortcut="a"
|
||||
android:numericShortcut="1"
|
||||
app:showAsAction="never"/>
|
||||
<item android:id="@+id/action_export"
|
||||
android:title="@string/action_export"
|
||||
android:icon="@drawable/ic_content_copy"
|
||||
app:showAsAction="ifRoom"
|
||||
android:alphabeticShortcut="e"
|
||||
android:numericShortcut="2"/>
|
||||
<item android:id="@+id/action_import"
|
||||
android:title="@string/action_import"
|
||||
android:icon="@drawable/ic_content_paste"
|
||||
app:showAsAction="ifRoom"
|
||||
android:alphabeticShortcut="i"
|
||||
android:numericShortcut="3"/>
|
||||
<item
|
||||
android:id="@+id/action_export"
|
||||
android:alphabeticShortcut="e"
|
||||
android:icon="?attr/actionModeCopyDrawable"
|
||||
android:numericShortcut="2"
|
||||
android:title="@string/action_export"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/action_import"
|
||||
android:alphabeticShortcut="i"
|
||||
android:icon="?attr/actionModePasteDrawable"
|
||||
android:numericShortcut="3"
|
||||
android:title="@string/action_import"
|
||||
app:showAsAction="ifRoom"/>
|
||||
</menu>
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item android:title="@string/add_profile"
|
||||
android:icon="@drawable/ic_action_note_add"
|
||||
android:alphabeticShortcut="a"
|
||||
android:numericShortcut="0"
|
||||
app:showAsAction="always">
|
||||
<item
|
||||
android:alphabeticShortcut="a"
|
||||
android:icon="@drawable/ic_action_note_add"
|
||||
android:numericShortcut="0"
|
||||
android:title="@string/add_profile"
|
||||
app:showAsAction="always">
|
||||
<menu>
|
||||
<item android:id="@+id/action_scan_qr_code"
|
||||
android:title="@string/add_profile_methods_scan_qr_code"
|
||||
android:alphabeticShortcut="s"
|
||||
android:numericShortcut="1"/>
|
||||
<item android:id="@+id/action_import"
|
||||
android:title="@string/action_import"
|
||||
android:alphabeticShortcut="i"
|
||||
android:numericShortcut="2"/>
|
||||
<item android:id="@+id/action_manual_settings"
|
||||
android:title="@string/add_profile_methods_manual_settings"
|
||||
android:alphabeticShortcut="m"
|
||||
android:numericShortcut="3"/>
|
||||
<item
|
||||
android:id="@+id/action_scan_qr_code"
|
||||
android:alphabeticShortcut="s"
|
||||
android:numericShortcut="1"
|
||||
android:title="@string/add_profile_methods_scan_qr_code"/>
|
||||
<item
|
||||
android:id="@+id/action_import"
|
||||
android:alphabeticShortcut="i"
|
||||
android:numericShortcut="2"
|
||||
android:title="@string/action_import"/>
|
||||
<item
|
||||
android:id="@+id/action_manual_settings"
|
||||
android:alphabeticShortcut="m"
|
||||
android:numericShortcut="3"
|
||||
android:title="@string/add_profile_methods_manual_settings"/>
|
||||
</menu>
|
||||
</item>
|
||||
<item android:id="@+id/action_export"
|
||||
android:title="@string/action_export"
|
||||
android:alphabeticShortcut="e"
|
||||
android:numericShortcut="1"
|
||||
android:icon="@drawable/ic_content_copy"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_export"
|
||||
android:alphabeticShortcut="e"
|
||||
android:icon="?attr/actionModeCopyDrawable"
|
||||
android:numericShortcut="1"
|
||||
android:title="@string/action_export"
|
||||
app:showAsAction="always"/>
|
||||
</menu>
|
||||
|
||||