From a2848ce53842eeab5d41d0b84e980e35fc51e0bb Mon Sep 17 00:00:00 2001 From: Max Lv Date: Sun, 29 Sep 2013 15:35:49 +0800 Subject: [PATCH] update UI --- src/main/res/layout/layout_switch.xml | 3 +- src/main/res/values/strings.xml | 3 + src/main/res/xml/pref_proxy.xml | 6 + .../com/github/shadowsocks/AppManager.scala | 5 +- .../com/github/shadowsocks/Shadowsocks.scala | 408 ++++++++++++------ .../shadowsocks/ShadowsocksApplication.scala | 1 - .../shadowsocks/ShadowsocksService.scala | 14 +- .../scala/com/github/shadowsocks/Utils.scala | 49 ++- .../shadowsocks/database/DBHelper.scala | 2 +- .../shadowsocks/database/MenuAdapter.scala | 48 ++- .../github/shadowsocks/database/Profile.scala | 24 +- .../shadowsocks/database/ProfileManager.scala | 82 +++- 12 files changed, 450 insertions(+), 195 deletions(-) diff --git a/src/main/res/layout/layout_switch.xml b/src/main/res/layout/layout_switch.xml index 51ca4b72..3d0aabc6 100644 --- a/src/main/res/layout/layout_switch.xml +++ b/src/main/res/layout/layout_switch.xml @@ -9,7 +9,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" - android:textSize="22sp" + android:textSize="24sp" android:textColor="@color/title" android:text="@string/app_name" android:layout_alignParentLeft="true" @@ -20,6 +20,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" + android:layout_marginRight = "10dp" android:layout_centerVertical="true"/> diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 2838123b..dd1e3d8d 100755 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -10,6 +10,8 @@ Server Settings + Profile + Profile name Server Hostname or IP Address of your Shadowsocks server Remote Port @@ -73,5 +75,6 @@ Shadowsocks %s Flush DNS Cache Flushing + Add Profile diff --git a/src/main/res/xml/pref_proxy.xml b/src/main/res/xml/pref_proxy.xml index 08f15dbc..5c9b61cf 100755 --- a/src/main/res/xml/pref_proxy.xml +++ b/src/main/res/xml/pref_proxy.xml @@ -1,6 +1,12 @@ + + updateSummaryEditTextPreference(pref, profile.name) + case Key.proxy => updateSummaryEditTextPreference(pref, profile.host) + case Key.remotePort => updateSummaryEditTextPreference(pref, profile.remotePort.toString) + case Key.localPort => updateSummaryEditTextPreference(pref, profile.localPort.toString) + case Key.sitekey => updatePasswordEditTextPreference(pref, profile.password) + case Key.encMethod => updateListPreference(pref, profile.method) + case Key.isGFWList => updateCheckBoxPreference(pref, profile.chnroute) + case Key.isGlobalProxy => updateCheckBoxPreference(pref, profile.global) + case Key.isTrafficStat => updateCheckBoxPreference(pref, profile.traffic) + case _ => + } + } + + def isServiceStarted(context: Context): Boolean = { + ShadowsocksService.isServiceStarted(context) || ShadowVpnService.isServiceStarted(context) + } + + class ProxyFragment extends UnifiedPreferenceFragment { + + var receiver: BroadcastReceiver = null + + private def setPreferenceEnabled() { + val state = getActivity.asInstanceOf[Shadowsocks].state + val enabled = state != State.CONNECTED && state != State.CONNECTING + for (name <- PROXY_PREFS) { + val pref: Preference = findPreference(name) + if (pref != null) { + pref.setEnabled(enabled) + } + } + } + + private def updatePreferenceScreen() { + for (name <- Shadowsocks.PROXY_PREFS) { + val pref = findPreference(name) + Shadowsocks.updatePreference(pref, name, Shadowsocks.currentProfile) + } + } + + override def onCreate(bundle: Bundle) { + super.onCreate(bundle) + val filter = new IntentFilter() + filter.addAction(Action.UPDATE_FRAGMENT) + receiver = new BroadcastReceiver { + def onReceive(p1: Context, p2: Intent) { + setPreferenceEnabled() + updatePreferenceScreen() + } + } + getActivity.getApplicationContext.registerReceiver(receiver, filter) + } + + override def onDestroy() { + super.onDestroy() + getActivity.getApplicationContext.unregisterReceiver(receiver) + } + + override def onResume() { + super.onResume() + setPreferenceEnabled() + } + + override def onPause() { + super.onPause() + } + } + + class FeatureFragment extends UnifiedPreferenceFragment { + + var receiver: BroadcastReceiver = null + + private def setPreferenceEnabled() { + val state = getActivity.asInstanceOf[Shadowsocks].state + val enabled: Boolean = state != State.CONNECTED && state != State.CONNECTING + for (name <- Shadowsocks.FEATRUE_PREFS) { + val pref: Preference = findPreference(name) + if (pref != null) { + val status = getActivity.getSharedPreferences(Key.status, Context.MODE_PRIVATE) + val isRoot = status.getBoolean(Key.isRoot, false) + if (Seq(Key.isAutoConnect, Key.isGlobalProxy, Key.isTrafficStat, Key.proxyedApps) + .contains(name)) { + pref.setEnabled(enabled && isRoot) + } else { + pref.setEnabled(enabled) + } + } + } + } + + private def updatePreferenceScreen() { + for (name <- Shadowsocks.FEATRUE_PREFS) { + val pref = findPreference(name) + Shadowsocks.updatePreference(pref, name, Shadowsocks.currentProfile) + } + } + + override def onCreate(bundle: Bundle) { + super.onCreate(bundle) + val filter = new IntentFilter() + filter.addAction(Action.UPDATE_FRAGMENT) + receiver = new BroadcastReceiver { + def onReceive(p1: Context, p2: Intent) { + setPreferenceEnabled() + updatePreferenceScreen() + } + } + getActivity.getApplicationContext.registerReceiver(receiver, filter) + } + + override def onDestroy() { + super.onDestroy() + getActivity.getApplicationContext.unregisterReceiver(receiver) + } + + override def onResume() { + super.onResume() + setPreferenceEnabled() + } + + override def onPause() { + super.onPause() + } + } + +} + class Shadowsocks extends UnifiedSherlockPreferenceActivity with CompoundButton.OnCheckedChangeListener - with OnSharedPreferenceChangeListener { + with OnSharedPreferenceChangeListener + with MenuAdapter.MenuListener{ private val MSG_CRASH_RECOVER: Int = 1 private val MSG_INITIAL_FINISH: Int = 2 @@ -227,9 +299,9 @@ class Shadowsocks lazy val status = getSharedPreferences(Key.status, Context.MODE_PRIVATE) lazy val receiver = new StateBroadcastReceiver lazy val drawer = MenuDrawer.attach(this) - lazy val listView = new ListView(this) lazy val menuAdapter = new MenuAdapter(this, getMenuList) - lazy val profileManager = getApplication.asInstanceOf[ShadowsocksApplication].profileManager + lazy val listView = new ListView(this) + lazy val profileManager = new ProfileManager(settings, getApplication.asInstanceOf[ShadowsocksApplication].dbHelper) private val handler: Handler = new Handler { override def handleMessage(msg: Message) { @@ -291,10 +363,10 @@ class Shadowsocks } } - def onSharedPreferenceChanged(prefs: SharedPreferences, key: String) { - if (key == Key.isGlobalProxy) { - val enabled = state != State.CONNECTED && state != State.CONNECTING - setPreferenceEnabled(enabled) + override def onSharedPreferenceChanged(prefs: SharedPreferences, key: String) { + if (key == Key.profileName) { + profileManager.save() + menuAdapter.updateList(getMenuList, Shadowsocks.currentProfile.id) } } @@ -407,6 +479,10 @@ class Shadowsocks setHeaderRes(R.xml.shadowsocks_headers) super.onCreate(savedInstanceState) + Shadowsocks.currentProfile = { + profileManager.getProfile(settings.getInt(Key.profileId, -1)) getOrElse new Profile() + } + listView.setAdapter(menuAdapter) drawer.setMenuView(listView) @@ -422,7 +498,6 @@ class Shadowsocks getSupportActionBar.setDisplayShowTitleEnabled(false) getSupportActionBar.setDisplayShowCustomEnabled(true) // getSupportActionBar.setDisplayShowHomeEnabled(false) - val title: TextView = switchLayout.findViewById(R.id.title).asInstanceOf[TextView] val tf: Typeface = Typefaces.get(this, "fonts/Iceland.ttf") if (tf != null) title.setTypeface(tf) @@ -445,16 +520,49 @@ class Shadowsocks handler.sendEmptyMessage(MSG_INITIAL_FINISH) } } + } + override def onActiveViewChanged(v: View, pos: Int) { + drawer.setActiveView(v, pos) } def updateProfile(id: Int) { + drawer.closeMenu(true) + handler.postDelayed(new Runnable { + def run() { + Shadowsocks.currentProfile = profileManager.load(id) + updatePreferenceScreen() + } + }, 600) + + if (!isSinglePane) sendBroadcast(new Intent(Action.UPDATE_FRAGMENT)) + } + + def delProfile(id: Int): Boolean = { + drawer.closeMenu(true) + + handler.postDelayed(new Runnable { + def run() { + profileManager.delProfile(id) + val profileId = { + val profiles = profileManager.getAllProfiles.getOrElse(List[Profile]()) + if (profiles.isEmpty) -1 else profiles(0).id + } + Shadowsocks.currentProfile = profileManager.load(profileId) + updatePreferenceScreen() + menuAdapter.updateList(getMenuList, Shadowsocks.currentProfile.id) + } + }, 600) + + if (!isSinglePane) sendBroadcast(new Intent(Action.UPDATE_FRAGMENT)) + + true } def getProfileList: List[Item] = { val list = profileManager.getAllProfiles getOrElse List[Profile]() - list.map(p => new Item(p.id, p.name, -1, updateProfile)) + list.map(p => new Item(p.id, p.name, -1, updateProfile, delProfile)) } def getMenuList: List[Any] = { @@ -465,28 +573,31 @@ class Shadowsocks buf ++= getProfileList + buf += new Item(-1, getString(R.string.add_profile), android.R.drawable.ic_menu_add, _ => { + updateProfile(-1) + profileManager.save() + menuAdapter.updateList(getMenuList, Shadowsocks.currentProfile.id) + }) + buf += new Category("Settings") - buf += new Item(-1, getString(R.string.recovery), android.R.drawable.ic_menu_revert, - _ => { - EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "reset", getVersionName, 0L) - recovery() - }) + buf += new Item(-100, getString(R.string.recovery), android.R.drawable.ic_menu_revert, _ => { + EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "reset", getVersionName, 0L) + recovery() + }) - buf += new Item(-2, getString(R.string.flush_dnscache), android.R.drawable.ic_menu_delete, - _ => { + buf += + new Item(-200, getString(R.string.flush_dnscache), android.R.drawable.ic_menu_delete, _ => { EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "flush_dnscache", getVersionName, 0L) flushDnsCache() }) - buf += new Item(-3, getString(R.string.about), android.R.drawable.ic_menu_info_details, - _ => { - EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "about", getVersionName, 0L) - showAbout() - }) + buf += new Item(-300, getString(R.string.about), android.R.drawable.ic_menu_info_details, _ => { + EasyTracker.getTracker.sendEvent(Shadowsocks.TAG, "about", getVersionName, 0L) + showAbout() + }) buf.toList - } override def onKeyDown(keyCode: Int, event: KeyEvent): Boolean = { @@ -516,6 +627,7 @@ class Shadowsocks protected override def onPause() { super.onPause() prepared = false + settings.unregisterOnSharedPreferenceChangeListener(this) } protected override def onResume() { @@ -549,6 +661,8 @@ class Shadowsocks } switchButton.setOnCheckedChangeListener(this) + + settings.registerOnSharedPreferenceChangeListener(this) } private def setPreferenceEnabled(enabled: Boolean) { @@ -562,8 +676,8 @@ class Shadowsocks for (name <- Shadowsocks.FEATRUE_PREFS) { val pref = findPreference(name) if (pref != null) { - if (Seq(Key.isAutoConnect, Key.isGlobalProxy, Key.isTrafficStat, - Key.proxyedApps).contains(name)) { + if (Seq(Key.isAutoConnect, Key.isGlobalProxy, Key.isTrafficStat, Key.proxyedApps) + .contains(name)) { pref.setEnabled(enabled && isRoot) } else { pref.setEnabled(enabled) @@ -572,6 +686,18 @@ class Shadowsocks } } + private def updatePreferenceScreen() { + val profile = Shadowsocks.currentProfile + for (name <- Shadowsocks.PROXY_PREFS) { + val pref = findPreference(name) + Shadowsocks.updatePreference(pref, name, profile) + } + for (name <- Shadowsocks.FEATRUE_PREFS) { + val pref = findPreference(name) + Shadowsocks.updatePreference(pref, name, profile) + } + } + override def onStart() { super.onStart() EasyTracker.getInstance.activityStart(this) @@ -790,7 +916,7 @@ class Shadowsocks setPreferenceEnabled(enabled = true) } } - sendBroadcast(new Intent(Action.UPDATE_FRAGMENT)) + if (!isSinglePane) sendBroadcast(new Intent(Action.UPDATE_FRAGMENT)) } } diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala index 51548324..9a3703ab 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala @@ -44,7 +44,6 @@ import com.github.shadowsocks.database.{ProfileManager, DBHelper} class ShadowsocksApplication extends Application { lazy val dbHelper = new DBHelper(this) - lazy val profileManager = new ProfileManager(dbHelper) override def onCreate() { EasyTracker.getInstance.setContext(this) diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksService.scala index 242e5ff0..2dd7b27a 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksService.scala @@ -324,18 +324,8 @@ class ShadowsocksService extends Service { val icon = getResources.getDrawable(R.drawable.ic_stat_shadowsocks) if (rate >= 0) { - val bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth * 4, - icon.getIntrinsicHeight * 4, Bitmap.Config.ARGB_8888) - val r = rate.toString - val size = bitmap.getHeight / 4 - val canvas = new Canvas(bitmap) - val paint = new Paint() - paint.setColor(Color.WHITE) - paint.setTextSize(size) - val bounds = new Rect() - paint.getTextBounds(r, 0, r.length, bounds) - canvas.drawText(r, (bitmap.getWidth - bounds.width()) / 2, - bitmap.getHeight - (bitmap.getHeight - bounds.height()) / 2, paint) + val bitmap =Utils.getBitmap(rate.toString, icon.getIntrinsicWidth * 4, + icon.getIntrinsicHeight * 4, Color.TRANSPARENT) builder.setLargeIcon(bitmap) if (rate < 1000) { diff --git a/src/main/scala/com/github/shadowsocks/Utils.scala b/src/main/scala/com/github/shadowsocks/Utils.scala index dc9dc6a3..e3e63e9c 100644 --- a/src/main/scala/com/github/shadowsocks/Utils.scala +++ b/src/main/scala/com/github/shadowsocks/Utils.scala @@ -49,10 +49,11 @@ import org.apache.http.conn.util.InetAddressUtils import scala.collection.mutable.ArrayBuffer import org.xbill.DNS._ import scala.Some -import android.graphics.{Canvas, Bitmap} +import android.graphics._ import android.app.ActivityManager import android.os.Build import android.provider.Settings +import scala.Some object Config { val SHADOWSOCKS = "{\"server\": [%s], \"server_port\": %d, \"local_port\": %d, \"password\": %s, \"timeout\": %d}" @@ -112,10 +113,13 @@ object Config { } case class Config(isGlobalProxy: Boolean, isGFWList: Boolean, isBypassApps: Boolean, isTrafficStat: Boolean, - var proxy: String, sitekey: String, encMethod: String, remotePort: Int, + profileName: String, var proxy: String, sitekey: String, encMethod: String, remotePort: Int, localPort: Int, proxiedAppString: String) object Key { + val profileId = "profileId" + val profileName = "profileName" + val proxied = "Proxyed" val isRoot = "isRoot" @@ -137,6 +141,11 @@ object Key { val localPort = "port" } +object Scheme { + val APP = "app://" + val PROFILE = "profile://" +} + object State { val INIT = 0 val CONNECTING = 1 @@ -162,6 +171,7 @@ object Extra { edit.putBoolean(Key.isBypassApps, config.isBypassApps) edit.putBoolean(Key.isTrafficStat, config.isTrafficStat) + edit.putString(Key.profileName, config.profileName) edit.putString(Key.proxy, config.proxy) edit.putString(Key.sitekey, config.sitekey) edit.putString(Key.encMethod, config.encMethod) @@ -177,6 +187,7 @@ object Extra { val isBypassApps = intent.getBooleanExtra(Key.isBypassApps, false) val isTrafficStat = intent.getBooleanExtra(Key.isTrafficStat, false) + val profileName = intent.getStringExtra(Key.profileName) val proxy = intent.getStringExtra(Key.proxy) val sitekey = intent.getStringExtra(Key.sitekey) val encMethod = intent.getStringExtra(Key.encMethod) @@ -184,7 +195,7 @@ object Extra { val localPort = intent.getIntExtra(Key.localPort, 1984) val proxiedString = intent.getStringExtra(Key.proxied) - new Config(isGlobalProxy, isGFWList, isBypassApps, isTrafficStat, proxy, sitekey, encMethod, remotePort, + new Config(isGlobalProxy, isGFWList, isBypassApps, isTrafficStat, profileName, proxy, sitekey, encMethod, remotePort, localPort, proxiedString) } @@ -194,6 +205,7 @@ object Extra { val isBypassApps = settings.getBoolean(Key.isBypassApps, false) val isTrafficStat = settings.getBoolean(Key.isTrafficStat, false) + val profileName = settings.getString(Key.profileName, "default") val proxy = settings.getString(Key.proxy, "127.0.0.1") match { case "198.199.101.152" => BuildConfig.SERVER case s: String => s @@ -232,6 +244,7 @@ object Extra { intent.putExtra(Key.isBypassApps, isBypassApps) intent.putExtra(Key.isTrafficStat, isTrafficStat) + intent.putExtra(Key.profileName, profileName) intent.putExtra(Key.proxy, proxy) intent.putExtra(Key.sitekey, sitekey) intent.putExtra(Key.encMethod, encMethod) @@ -265,6 +278,36 @@ object Utils { var data_path: String = null var rootTries = 0 + /* + * round or floor depending on whether you are using offsets(floor) or + * widths(round) + */ + def dpToPx (context: Context, dp: Float): Float = { + val density = context.getResources.getDisplayMetrics.density + dp * density + } + + def pxToDp (context: Context, px: Float): Float = { + val density = context.getResources.getDisplayMetrics.density + px / density + } + + def getBitmap(text: String, width: Int, height: Int, background: Int): Bitmap = { + val bitmap = Bitmap.createBitmap(width, + height, Bitmap.Config.ARGB_8888) + val size = bitmap.getHeight / 4 + val canvas = new Canvas(bitmap) + canvas.drawColor(background) + val paint = new Paint() + paint.setColor(Color.WHITE) + paint.setTextSize(size) + val bounds = new Rect() + paint.getTextBounds(text, 0, text.length, bounds) + canvas.drawText(text, (bitmap.getWidth - bounds.width()) / 2, + bitmap.getHeight - (bitmap.getHeight - bounds.height()) / 2, paint) + bitmap + } + // Blocked > 3 seconds def toggleAirplaneMode(context: Context) { if (Build.VERSION.SDK_INT >= 17) { diff --git a/src/main/scala/com/github/shadowsocks/database/DBHelper.scala b/src/main/scala/com/github/shadowsocks/database/DBHelper.scala index 00b91314..9ed987e4 100644 --- a/src/main/scala/com/github/shadowsocks/database/DBHelper.scala +++ b/src/main/scala/com/github/shadowsocks/database/DBHelper.scala @@ -46,7 +46,7 @@ import com.j256.ormlite.support.ConnectionSource import com.j256.ormlite.table.TableUtils import com.j256.ormlite.dao.Dao -class DBHelper(val context: Context) extends OrmLiteSqliteOpenHelper(context, "profile.db", null, 3) { +class DBHelper(val context: Context) extends OrmLiteSqliteOpenHelper(context, "profile.db", null, 7) { lazy val profileDao:Dao[Profile,Int] = getDao(classOf[Profile]) diff --git a/src/main/scala/com/github/shadowsocks/database/MenuAdapter.scala b/src/main/scala/com/github/shadowsocks/database/MenuAdapter.scala index 096f3564..ef2d1077 100644 --- a/src/main/scala/com/github/shadowsocks/database/MenuAdapter.scala +++ b/src/main/scala/com/github/shadowsocks/database/MenuAdapter.scala @@ -39,39 +39,39 @@ package com.github.shadowsocks.database -import android.content.{DialogInterface, Context} +import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.TextView -import com.github.shadowsocks.R -import android.view.View.OnClickListener +import com.github.shadowsocks.{Shadowsocks, R} +import android.view.View.{OnLongClickListener, OnClickListener} -case class Item(id: Int, title: String, iconRes: Int, action: Int => Unit) +case class Item(id: Int, title: String, iconRes: Int, + click: Int => Unit, longClick: Int => Boolean = _ => false) -case class Category (title: String) +case class Category(title: String) object MenuAdapter { trait MenuListener { - def onActiveViewChanged(v: View) + def onActiveViewChanged(v: View, pos: Int) } val UNDEFINED = -1 val CATEGORY = 0 val ITEM = 1 - } -class MenuAdapter (context: Context, var items: List[Any]) extends BaseAdapter { +class MenuAdapter(context: Context, var items: List[Any]) extends BaseAdapter { def setListener(listener: MenuAdapter.MenuListener) { - mListener = listener + this.listener = listener } def setActivePosition(activePosition: Int) { - mActivePosition = activePosition + this.activePosition = activePosition } @Override def getCount: Int = { @@ -121,32 +121,46 @@ class MenuAdapter (context: Context, var items: List[Any]) extends BaseAdapter { } val tv: TextView = v.asInstanceOf[TextView] tv.setText(value.title) - tv.setCompoundDrawablesWithIntrinsicBounds(value.iconRes, 0, 0, 0) + if (value.iconRes != -1) { + tv.setCompoundDrawablesWithIntrinsicBounds(value.iconRes, 0, 0, 0) + } tv.setOnClickListener(new OnClickListener { def onClick(view: View) { val item = view.getTag(R.id.mdItem).asInstanceOf[Item] - item.action(item.id) + item.click(item.id) + } + }) + tv.setOnLongClickListener(new OnLongClickListener { + def onLongClick(view: View): Boolean = { + val item = view.getTag(R.id.mdItem).asInstanceOf[Item] + item.longClick(item.id) } }) v.setTag(R.id.mdItem, value) + case _ => } v.setTag(R.id.mdActiveViewPosition, position) - if (position == mActivePosition) { - if (mListener != null) mListener.onActiveViewChanged(v) + if (position == activePosition) { + if (listener != null) listener.onActiveViewChanged(v, position) } + v } - def updateList(list: List[Any]) { + def updateList(list: List[Any], activeId: Int) { items = list + activePosition = items.indexWhere{ + case item: Item => item.id == activeId + case _ => false + } notifyDataSetChanged() } - private var mListener: MenuAdapter.MenuListener = null - private var mActivePosition: Int = 0 + private var listener: MenuAdapter.MenuListener = null + private var activePosition: Int = -1 } diff --git a/src/main/scala/com/github/shadowsocks/database/Profile.scala b/src/main/scala/com/github/shadowsocks/database/Profile.scala index 8b4aca78..38f7d711 100644 --- a/src/main/scala/com/github/shadowsocks/database/Profile.scala +++ b/src/main/scala/com/github/shadowsocks/database/Profile.scala @@ -42,14 +42,14 @@ package com.github.shadowsocks.database import com.j256.ormlite.field.{DataType, DatabaseField} class Profile { - @DatabaseField(id = true) + @DatabaseField(generatedId = true) var id: Int = 0 @DatabaseField - var name: String = null + var name: String = "Untitled" @DatabaseField - var host: String = null + var host: String = "" @DatabaseField var localPort: Int = 0 @@ -58,13 +58,13 @@ class Profile { var remotePort: Int = 0 @DatabaseField - var password: String = null + var password: String = "" @DatabaseField - var method: String = null + var method: String = "" @DatabaseField - var date: String = null + var date: String = "" @DatabaseField var upload: Int = 0 @@ -78,9 +78,15 @@ class Profile { @DatabaseField var global: Boolean = false - @DatabaseField(dataType = DataType.LONG_STRING) - var individual: String = null + @DatabaseField + var bypass: Boolean = false + + @DatabaseField + var traffic: Boolean = false @DatabaseField(dataType = DataType.LONG_STRING) - var description: String = null + var individual: String = "" + + @DatabaseField(dataType = DataType.LONG_STRING) + var description: String = "" } diff --git a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala index d456a268..4b0b667d 100644 --- a/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala +++ b/src/main/scala/com/github/shadowsocks/database/ProfileManager.scala @@ -40,18 +40,20 @@ package com.github.shadowsocks.database import android.util.Log -import com.github.shadowsocks.Shadowsocks +import com.github.shadowsocks._ +import android.content.{SharedPreferences, Context} -class ProfileManager(dbHelper: DBHelper) { - def addProfile(profile: Profile): Boolean = { +class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) { + + def createOrUpdateProfile(profile: Profile): Boolean = { try { dbHelper.profileDao.createOrUpdate(profile) + true } catch { case ex: Exception => Log.e(Shadowsocks.TAG, "addProfile", ex) - return false + false } - true } def getProfile(id: Int): Option[Profile] = { @@ -70,12 +72,12 @@ class ProfileManager(dbHelper: DBHelper) { def delProfile(id: Int): Boolean = { try { dbHelper.profileDao.deleteById(id) + true } catch { case ex: Exception => Log.e(Shadowsocks.TAG, "delProfile", ex) - return false + false } - true } def getAllProfiles: Option[List[Profile]] = { @@ -88,4 +90,70 @@ class ProfileManager(dbHelper: DBHelper) { None } } + + def load(id: Int): Profile = { + + Log.d(Shadowsocks.TAG, id + " ") + + save() + + val profile = getProfile(id) getOrElse { + val p = new Profile() + createOrUpdateProfile(p) + p + } + + Log.d(Shadowsocks.TAG, "load " + profile.id + " " + profile.name) + + val edit = settings.edit() + edit.putBoolean(Key.isGlobalProxy, profile.global) + edit.putBoolean(Key.isGFWList, profile.chnroute) + edit.putBoolean(Key.isBypassApps, profile.bypass) + edit.putBoolean(Key.isTrafficStat, profile.traffic) + edit.putString(Key.profileName, profile.name) + edit.putString(Key.proxy, profile.host) + edit.putString(Key.sitekey, profile.password) + edit.putString(Key.encMethod, profile.method) + edit.putString(Key.remotePort, profile.remotePort.toString) + edit.putString(Key.localPort, profile.localPort.toString) + edit.putString(Key.proxied, profile.individual) + edit.putInt(Key.profileId, profile.id) + edit.commit() + + profile + } + + def save() { + val profile = new Profile() + + profile.global = settings.getBoolean(Key.isGlobalProxy, false) + profile.chnroute = settings.getBoolean(Key.isGFWList, false) + profile.bypass = settings.getBoolean(Key.isBypassApps, false) + profile.traffic = settings.getBoolean(Key.isTrafficStat, false) + profile.name = settings.getString(Key.profileName, "default") + profile.host = settings.getString(Key.proxy, "127.0.0.1") + profile.password = settings.getString(Key.sitekey, "default") + profile.method = settings.getString(Key.encMethod, "table") + profile.remotePort = try { + Integer.valueOf(settings.getString(Key.remotePort, "1984")) + } catch { + case ex: NumberFormatException => { + 1984 + } + } + profile.localPort = try { + Integer.valueOf(settings.getString(Key.localPort, "1984")) + } catch { + case ex: NumberFormatException => { + 1984 + } + } + profile.individual = settings.getString(Key.proxied, "") + + profile.id = settings.getInt(Key.profileId, -1) + + Log.d(Shadowsocks.TAG, "save " + profile.id + " " + profile.name) + + createOrUpdateProfile(profile) + } }