Commit 7d9686b5 authored by Mygod's avatar Mygod Committed by Max Lv

UI fixes

* Refine exceptions handling when parsing per-app config string

* Remove redundant profiles Preference

* Move Network Traffic to title bar

* Add ripple to title text

* Animate using animateLayoutChanges

* Hide connection test in NAT mode

* Refine UI.

* Change notification action button icon for hidpi device

* Fix FAB ripple

* Fix usability problem

* Fix changes not commited when snackbar being swiped

* Show import/export as action

* Drop unused drawables

* Move TaskerSettings

* Fix action icons

* Prevent switching to an invalid profile

* Fix line wrap when screen width is small
parent 84532679
<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 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
</vector>
<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="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/>
</vector>
<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.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content">
<TextView android:text="@string/stat" android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary" android:ellipsize="marquee"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<TextView android:id="@+id/connection_test" android:gravity="end"
android:textSize="14sp" android:textColor="?android:attr/textColorSecondary"
android:background="?attr/selectableItemBackgroundBorderless"
android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/>
</LinearLayout>
......@@ -14,16 +14,7 @@
android:paddingLeft="16dip" android:paddingRight="88dip"
android:paddingTop="16dip" android:paddingBottom="16dip"
android:background="@color/material_accent_300" android:orientation="vertical">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<TextView android:text="@string/stat" android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary" android:ellipsize="marquee"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<TextView android:id="@+id/connection_test"
android:textSize="14sp" android:textColor="?android:attr/textColorSecondary"
android:ellipsize="marquee" android:gravity="end"
android:background="?attr/selectableItemBackgroundBorderless"
android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/>
</LinearLayout>
<include layout="@layout/layout_main_stat_title"/>
<android.support.v7.widget.GridLayout android:layout_width="match_parent"
android:layout_height="wrap_content" app:columnCount="4">
<TextView app:layout_column="0" style="@style/TextAppearance.AppCompat.Body2"
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="match_parent" android:layout_height="wrap_content">
<TextView android:text="@string/stat" android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary" android:ellipsize="marquee"
android:layout_width="match_parent" android:layout_height="wrap_content"/>
<TextView android:id="@+id/connection_test"
android:textSize="14sp" android:textColor="?android:attr/textColorSecondary"
android:background="?attr/selectableItemBackgroundBorderless"
android:layout_width="match_parent" android:layout_height="wrap_content"/>
</LinearLayout>
......@@ -6,11 +6,10 @@
android:layout_height="match_parent">
<include layout="@layout/toolbar_light_dark" />
<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="0dp" android:layout_weight="1">
<android.support.v7.widget.RecyclerView android:id="@+id/profilesList"
app:layout_behavior="com.github.shadowsocks.widget.AutoPaddingBehavior"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"/>
<com.github.clans.fab.FloatingActionMenu
android:id="@+id/menu"
android:layout_width="match_parent"
......@@ -21,8 +20,8 @@
android:layout_marginEnd="16dp"
app:menu_colorNormal="@color/material_accent_500"
app:menu_colorPressed="@color/material_accent_700"
app:menu_colorRipple="@color/material_accent_500"
>
app:fab_colorRipple="@android:color/white"
app:layout_behavior="com.github.shadowsocks.widget.FloatingActionMenuBehavior">
<com.github.clans.fab.FloatingActionButton
android:id="@+id/fab_manual_add"
......@@ -31,7 +30,7 @@
android:src="@drawable/ic_create"
app:fab_colorNormal="@color/material_accent_500"
app:fab_colorPressed="@color/material_accent_700"
app:fab_colorRipple="@color/material_accent_500"
app:fab_colorRipple="@android:color/white"
app:fab_size="mini"
app:fab_label="@string/add_profile_methods_manual_settings"
/>
......@@ -42,7 +41,7 @@
android:src="@drawable/ic_camera_alt"
app:fab_colorNormal="@color/material_accent_500"
app:fab_colorPressed="@color/material_accent_700"
app:fab_colorRipple="@color/material_accent_500"
app:fab_colorRipple="@android:color/white"
app:fab_size="mini"
app:fab_label="@string/add_profile_methods_scan_qr_code"
/>
......@@ -53,7 +52,7 @@
android:src="@drawable/ic_nfc"
app:fab_colorNormal="@color/material_accent_500"
app:fab_colorPressed="@color/material_accent_700"
app:fab_colorRipple="@color/material_accent_500"
app:fab_colorRipple="@android:color/white"
app:fab_size="mini"
app:fab_label="NFC"
/>
......@@ -64,7 +63,7 @@
android:src="@drawable/ic_content_paste"
app:fab_colorNormal="@color/material_accent_500"
app:fab_colorPressed="@color/material_accent_700"
app:fab_colorRipple="@color/material_accent_500"
app:fab_colorRipple="@android:color/white"
app:fab_size="mini"
app:fab_label="@string/action_import"
/>
......
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/action_import"
android:title="@string/action_import"
android:showAsAction="never"
android:alphabeticShortcut="i"
android:numericShortcut="1"/>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_export"
android:title="@string/action_export"
android:showAsAction="never"
android:icon="@drawable/ic_content_copy"
app:showAsAction="ifRoom"
android:alphabeticShortcut="e"
android:numericShortcut="1"/>
<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="2"/>
</menu>
......@@ -4,5 +4,7 @@
<item android:id="@+id/action_export"
android:title="@string/action_export"
android:alphabeticShortcut="e"
app:showAsAction="never" />
android:numericShortcut="1"
android:icon="@drawable/ic_content_copy"
app:showAsAction="always"/>
</menu>
......@@ -44,6 +44,7 @@ import java.util.{Timer, TimerTask}
import android.app.Service
import android.content.{BroadcastReceiver, Context, Intent, IntentFilter}
import android.os.{Handler, RemoteCallbackList}
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import com.github.shadowsocks.aidl.{Config, IShadowsocksService, IShadowsocksServiceCallback}
......@@ -104,9 +105,10 @@ trait BaseService extends Service {
}
override def use(config: Config) = synchronized(state match {
case State.STOPPED => if (config != null) startRunner(config)
case State.STOPPED => if (config != null && checkConfig(config)) startRunner(config)
case State.CONNECTED =>
if (config == null) stopRunner(true) else if (config.profileId != BaseService.this.config.profileId) {
if (config == null) stopRunner(true)
else if (config.profileId != BaseService.this.config.profileId && checkConfig(config)) {
stopRunner(false)
startRunner(config)
}
......@@ -114,6 +116,12 @@ trait BaseService extends Service {
})
}
def checkConfig(config: Config) = if (TextUtils.isEmpty(config.proxy) || TextUtils.isEmpty(config.sitekey)) {
changeState(State.STOPPED)
stopRunner(true)
false
} else true
def startRunner(config: Config) {
this.config = config
......
......@@ -39,11 +39,11 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
.setContentIntent(PendingIntent.getActivity(service, 0, new Intent(service, classOf[Shadowsocks])
.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT), 0))
.setSmallIcon(R.drawable.ic_stat_shadowsocks)
.addAction(android.R.drawable.ic_menu_close_clear_cancel, service.getString(R.string.stop),
.addAction(R.drawable.ic_close, service.getString(R.string.stop),
PendingIntent.getBroadcast(service, 0, new Intent(Action.CLOSE), 0))
ShadowsocksApplication.profileManager.getAllProfiles match {
case Some(profiles) => if (profiles.length > 1)
builder.addAction(android.R.drawable.ic_menu_manage, service.getString(R.string.quick_switch),
builder.addAction(R.drawable.ic_settings, service.getString(R.string.quick_switch),
PendingIntent.getActivity(service, 0, new Intent(Action.QUICK_SWITCH), 0))
case _ =>
}
......
......@@ -44,9 +44,9 @@ import android.os.{Build, Bundle}
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.{DefaultItemAnimator, LinearLayoutManager, RecyclerView, Toolbar}
import android.view.{LayoutInflater, View, ViewGroup}
import android.widget.{Switch, CheckedTextView}
import android.widget.{CheckedTextView, Switch}
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.helper.TaskerSettings
import com.github.shadowsocks.utils.TaskerSettings
/**
* @author CzBiX
......
......@@ -39,8 +39,7 @@
package com.github.shadowsocks
import android.content.{BroadcastReceiver, Context, Intent}
import com.github.shadowsocks.helper.TaskerSettings
import com.github.shadowsocks.utils.Utils
import com.github.shadowsocks.utils.{TaskerSettings, Utils}
/**
* @author CzBiX
......
......@@ -36,7 +36,7 @@
* HERE BE DRAGONS
*
*/
package com.github.shadowsocks.helper
package com.github.shadowsocks.utils
import android.content.{Context, Intent}
import android.os.Bundle
......
package com.github.shadowsocks.widget
import android.content.Context
import android.support.design.widget.CoordinatorLayout
import android.support.design.widget.CoordinatorLayout.Behavior
import android.support.design.widget.Snackbar.SnackbarLayout
import android.util.AttributeSet
import android.view.View
/**
* @author Mygod
*/
class AutoPaddingBehavior(context: Context, attrs: AttributeSet) extends Behavior[View] {
override def layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View) =
dependency.isInstanceOf[SnackbarLayout]
override def onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View) =
dependency match {
case sl: SnackbarLayout =>
child.setPadding(0, 0, 0, dependency.getHeight)
true
case _ => super.onDependentViewChanged(parent, child, dependency)
}
override def onDependentViewRemoved(parent: CoordinatorLayout, child: View, dependency: View) =
dependency match {
case sl: SnackbarLayout => child.setPadding(0, 0, 0, 0)
case _ => super.onDependentViewRemoved(parent, child, dependency)
}
}
package com.github.shadowsocks.widget
import android.animation.ValueAnimator
import android.content.Context
import android.support.design.widget.CoordinatorLayout
import android.support.design.widget.CoordinatorLayout.Behavior
import android.support.design.widget.Snackbar.SnackbarLayout
import android.support.v4.view.animation.FastOutSlowInInterpolator
import android.util.AttributeSet
import android.view.View
import com.github.clans.fab.FloatingActionMenu
import scala.collection.JavaConverters._
/**
* Behavior for com.github.clans.fab.FloatingActionMenu that is aware of Snackbars and scrolling.
*
* @author Mygod
*/
class FloatingActionMenuBehavior(context: Context, attrs: AttributeSet)
extends Behavior[FloatingActionMenu](context, attrs) {
private var fabTranslationYAnimator: ValueAnimator = _
private var fabTranslationY: Float = _
override def layoutDependsOn(parent: CoordinatorLayout, child: FloatingActionMenu, dependency: View) =
dependency.isInstanceOf[SnackbarLayout]
override def onDependentViewChanged(parent: CoordinatorLayout, child: FloatingActionMenu, dependency: View) = {
dependency match {
case _: SnackbarLayout =>
var targetTransY = parent.getDependencies(child).asScala
.filter(view => view.isInstanceOf[SnackbarLayout] && parent.doViewsOverlap(child, view))
.map(view => view.getTranslationY - view.getHeight).reduceOption(_ min _).getOrElse(0F)
if (targetTransY > 0) targetTransY = 0
if (fabTranslationY != targetTransY) {
val currentTransY = child.getTranslationY
if (fabTranslationYAnimator != null && fabTranslationYAnimator.isRunning) fabTranslationYAnimator.cancel
if (child.isShown && Math.abs(currentTransY - targetTransY) > child.getHeight * 0.667F) {
if (fabTranslationYAnimator == null) {
fabTranslationYAnimator = new ValueAnimator
fabTranslationYAnimator.setInterpolator(new FastOutSlowInInterpolator)
fabTranslationYAnimator.addUpdateListener(animation =>
child.setTranslationY(animation.getAnimatedValue.asInstanceOf[Float]))
}
fabTranslationYAnimator.setFloatValues(currentTransY, targetTransY)
fabTranslationYAnimator.start
} else child.setTranslationY(targetTransY)
fabTranslationY = targetTransY
}
}
false
}
override def onStartNestedScroll(parent: CoordinatorLayout, child: FloatingActionMenu, directTargetChild: View,
target: View, nestedScrollAxes: Int) = true
override def onNestedScroll(parent: CoordinatorLayout, child: FloatingActionMenu, target: View, dxConsumed: Int,
dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int) = {
super.onNestedScroll(parent, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed)
val dy = dyConsumed + dyUnconsumed
if (child.isMenuButtonHidden) {
if (dy < 0) child.showMenuButton(true)
} else if (dy > 0) child.hideMenuButton(true)
}
}
......@@ -19,7 +19,8 @@ class UndoSnackbarManager[T](view: View, undo: Iterator[(Int, T)] => Unit,
private val removedCallback = new Snackbar.Callback {
override def onDismissed(snackbar: Snackbar, event: Int) = {
event match {
case Snackbar.Callback.DISMISS_EVENT_MANUAL | Snackbar.Callback.DISMISS_EVENT_TIMEOUT =>
case Snackbar.Callback.DISMISS_EVENT_SWIPE | Snackbar.Callback.DISMISS_EVENT_MANUAL |
Snackbar.Callback.DISMISS_EVENT_TIMEOUT =>
if (commit != null) commit(recycleBin.iterator)
recycleBin.clear
case _ =>
......
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