Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
com.ccwangluo.accelerator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sheteng
com.ccwangluo.accelerator
Commits
0282975e
Commit
0282975e
authored
Dec 25, 2015
by
Max Lv
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #490 from Mygod/master
Enhancements for profile selector, and bugfixes
parents
2a5d8846
c4583bea
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
196 additions
and
115 deletions
+196
-115
build.sbt
build.sbt
+4
-4
src/main/res/values-zh/strings.xml
src/main/res/values-zh/strings.xml
+4
-0
src/main/res/values/colors.xml
src/main/res/values/colors.xml
+1
-1
src/main/res/values/strings.xml
src/main/res/values/strings.xml
+4
-0
src/main/scala/com/github/shadowsocks/BaseService.scala
src/main/scala/com/github/shadowsocks/BaseService.scala
+1
-0
src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala
...scala/com/github/shadowsocks/ProfileManagerActivity.scala
+48
-7
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
+20
-93
src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
...in/scala/com/github/shadowsocks/ShadowsocksSettings.scala
+84
-6
src/main/scala/com/github/shadowsocks/database/DBHelper.scala
...main/scala/com/github/shadowsocks/database/DBHelper.scala
+10
-1
src/main/scala/com/github/shadowsocks/database/Profile.scala
src/main/scala/com/github/shadowsocks/database/Profile.scala
+5
-2
src/main/scala/com/github/shadowsocks/database/ProfileManager.scala
...cala/com/github/shadowsocks/database/ProfileManager.scala
+15
-1
No files found.
build.sbt
View file @
0282975e
...
...
@@ -29,13 +29,13 @@ resolvers += "JRAF" at "http://JRAF.org/static/maven/2"
libraryDependencies
++=
Seq
(
"dnsjava"
%
"dnsjava"
%
"2.1.7"
,
"com.github.kevinsawicki"
%
"http-request"
%
"6.0"
,
"commons-net"
%
"commons-net"
%
"3.
3
"
,
"commons-net"
%
"commons-net"
%
"3.
4
"
,
"eu.chainfire"
%
"libsuperuser"
%
"1.0.0.201510071325"
,
"com.google.zxing"
%
"android-integration"
%
"3.2.1"
,
"net.glxn.qrgen"
%
"android"
%
"2.0"
,
"com.google.android.gms"
%
"play-services-base"
%
"8.
3
.0"
,
"com.google.android.gms"
%
"play-services-ads"
%
"8.
3
.0"
,
"com.google.android.gms"
%
"play-services-analytics"
%
"8.
3
.0"
,
"com.google.android.gms"
%
"play-services-base"
%
"8.
4
.0"
,
"com.google.android.gms"
%
"play-services-ads"
%
"8.
4
.0"
,
"com.google.android.gms"
%
"play-services-analytics"
%
"8.
4
.0"
,
"com.android.support"
%
"design"
%
"23.1.1"
,
"com.github.jorgecastilloprz"
%
"fabprogresscircle"
%
"1.01"
,
"com.j256.ormlite"
%
"ormlite-core"
%
"4.48"
,
...
...
src/main/res/values-zh/strings.xml
View file @
0282975e
...
...
@@ -85,6 +85,10 @@
<string
name=
"connection_test_error_status_code"
>
状态码无效。(#%d)
</string>
<!-- profile -->
<string
name=
"profile_manager_dialog"
>
配置文件
</string>
<string
name=
"profile_manager_dialog_content"
>
•
点击选择配置文件;\n
•
滑动删除;\n
•
长按拖动改变顺序。
</string>
<string
name=
"gotcha"
>
好的
</string>
<string
name=
"add_profile_dialog"
>
为影梭添加此配置文件?
</string>
<string
name=
"add_profile_methods_scan_qr_code"
>
扫描二维码
</string>
<string
name=
"add_profile_methods_manual_settings"
>
手动设置
</string>
...
...
src/main/res/values/colors.xml
View file @
0282975e
...
...
@@ -2,7 +2,7 @@
<resources>
<color
name=
"material_green_
a700"
>
#64DD17
</color>
<color
name=
"material_green_
700"
>
#388E3C
</color>
<color
name=
"material_blue_grey_300"
>
#90A4AE
</color>
<color
name=
"material_blue_grey_500"
>
#607D8B
</color>
<color
name=
"material_blue_grey_700"
>
#455A64
</color>
...
...
src/main/res/values/strings.xml
View file @
0282975e
...
...
@@ -103,6 +103,10 @@
<string
name=
"action_import_err"
>
Failed to import.
</string>
<!-- profile -->
<string
name=
"profile_manager_dialog"
>
Profiles
</string>
<string
name=
"profile_manager_dialog_content"
>
•
Tap to select a profile;\n
•
Swipe to remove;\n
•
Long press to reorder profiles.
</string>
<string
name=
"gotcha"
>
Gotcha!
</string>
<string
name=
"add_profile_dialog"
>
Add this Shadowsocks Profile?
</string>
<string
name=
"add_profile_methods_scan_qr_code"
>
Scan QR code
</string>
<string
name=
"add_profile_methods_manual_settings"
>
Manual Settings
</string>
...
...
src/main/scala/com/github/shadowsocks/BaseService.scala
View file @
0282975e
...
...
@@ -134,6 +134,7 @@ trait BaseService extends Service {
def
updateTrafficTotal
(
tx
:
Long
,
rx
:
Long
)
{
val
handler
=
new
Handler
(
getContext
.
getMainLooper
)
handler
.
post
(()
=>
{
val
config
=
this
.
config
// avoid race conditions without locking
if
(
config
!=
null
)
{
ShadowsocksApplication
.
profileManager
.
getProfile
(
config
.
profileId
)
match
{
case
Some
(
profile
)
=>
...
...
src/main/scala/com/github/shadowsocks/ProfileManagerActivity.scala
View file @
0282975e
package
com.github.shadowsocks
import
android.content.Intent
import
android.os.
{
Handler
,
Bundle
}
import
android.os.
{
Bundle
,
Handler
}
import
android.support.design.widget.Snackbar
import
android.support.v7.app.
{
AlertDialog
,
AppCompatActivity
}
import
android.support.v7.widget.RecyclerView.ViewHolder
...
...
@@ -25,7 +25,13 @@ import scala.collection.mutable.ArrayBuffer
/**
* @author Mygod
*/
object
ProfileManagerActivity
{
private
final
val
profileTip
=
"profileTip"
}
class
ProfileManagerActivity
extends
AppCompatActivity
with
OnMenuItemClickListener
with
ServiceBoundContext
{
import
ProfileManagerActivity._
private
class
ProfileViewHolder
(
val
view
:
View
)
extends
RecyclerView
.
ViewHolder
(
view
)
with
View
.
OnClickListener
{
private
var
item
:
Profile
=
_
private
val
text
=
itemView
.
findViewById
(
android
.
R
.
id
.
text1
).
asInstanceOf
[
CheckedTextView
]
...
...
@@ -72,11 +78,12 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
handler
.
post
(()
=>
text
.
setText
(
builder
))
}
def
bind
(
item
:
Profile
)
{
def
bind
(
item
:
Profile
,
i
:
Int
)
{
this
.
item
=
item
updateText
()
if
(
item
.
id
==
ShadowsocksApplication
.
profileId
)
{
text
.
setChecked
(
true
)
selectedIndex
=
i
selectedItem
=
this
}
else
{
text
.
setChecked
(
false
)
...
...
@@ -92,12 +99,12 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
private
class
ProfilesAdapter
extends
RecyclerView
.
Adapter
[
ProfileViewHolder
]
{
private
val
recycleBin
=
new
ArrayBuffer
[(
Int
,
Profile
)]
private
var
profiles
=
new
ArrayBuffer
[
Profile
]
var
profiles
=
new
ArrayBuffer
[
Profile
]
profiles
++=
ShadowsocksApplication
.
profileManager
.
getAllProfiles
.
getOrElse
(
List
.
empty
[
Profile
])
def
getItemCount
=
profiles
.
length
def
onBindViewHolder
(
vh
:
ProfileViewHolder
,
i
:
Int
)
=
vh
.
bind
(
profiles
(
i
))
def
onBindViewHolder
(
vh
:
ProfileViewHolder
,
i
:
Int
)
=
vh
.
bind
(
profiles
(
i
)
,
i
)
def
onCreateViewHolder
(
vg
:
ViewGroup
,
i
:
Int
)
=
new
ProfileViewHolder
(
LayoutInflater
.
from
(
vg
.
getContext
).
inflate
(
R
.
layout
.
layout_profiles_item
,
vg
,
false
))
...
...
@@ -110,6 +117,24 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
notifyItemInserted
(
pos
)
}
def
move
(
from
:
Int
,
to
:
Int
)
{
val
step
=
if
(
from
<
to
)
1
else
-
1
val
first
=
profiles
(
from
)
var
previousOrder
=
profiles
(
from
).
userOrder
for
(
i
<-
from
until
to
by
step
)
{
val
next
=
profiles
(
i
+
step
)
val
order
=
next
.
userOrder
next
.
userOrder
=
previousOrder
previousOrder
=
order
profiles
(
i
)
=
next
ShadowsocksApplication
.
profileManager
.
updateProfile
(
next
)
}
first
.
userOrder
=
previousOrder
profiles
(
to
)
=
first
ShadowsocksApplication
.
profileManager
.
updateProfile
(
first
)
notifyItemMoved
(
from
,
to
)
}
def
remove
(
pos
:
Int
)
{
recycleBin
.
append
((
pos
,
profiles
(
pos
)))
profiles
.
remove
(
pos
)
...
...
@@ -131,6 +156,7 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
}
}
private
var
selectedIndex
=
-
1
private
var
selectedItem
:
ProfileViewHolder
=
_
private
val
handler
=
new
Handler
...
...
@@ -153,21 +179,30 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
ShadowsocksApplication
.
profileManager
.
setProfileAddedListener
(
profilesAdapter
.
add
)
val
profilesList
=
findViewById
(
R
.
id
.
profilesList
).
asInstanceOf
[
RecyclerView
]
profilesList
.
setLayoutManager
(
new
LinearLayoutManager
(
this
))
val
layoutManager
=
new
LinearLayoutManager
(
this
)
profilesList
.
setLayoutManager
(
layoutManager
)
profilesList
.
setItemAnimator
(
new
DefaultItemAnimator
)
profilesList
.
setAdapter
(
profilesAdapter
)
if
(
selectedIndex
<
0
)
selectedIndex
=
profilesAdapter
.
profiles
.
zipWithIndex
.
collectFirst
{
case
(
profile
,
i
)
if
profile
.
id
==
ShadowsocksApplication
.
profileId
=>
i
}.
getOrElse
(-
1
)
layoutManager
.
scrollToPosition
(
selectedIndex
)
removedSnackbar
=
Snackbar
.
make
(
profilesList
,
R
.
string
.
removed
,
Snackbar
.
LENGTH_LONG
)
.
setAction
(
R
.
string
.
undo
,
((
v
:
View
)
=>
profilesAdapter
.
undoRemoves
)
:
OnClickListener
)
removedSnackbar
.
getView
.
addOnAttachStateChangeListener
(
new
OnAttachStateChangeListener
{
def
onViewDetachedFromWindow
(
v
:
View
)
=
profilesAdapter
.
commitRemoves
def
onViewAttachedToWindow
(
v
:
View
)
=
()
})
new
ItemTouchHelper
(
new
SimpleCallback
(
0
,
ItemTouchHelper
.
START
|
ItemTouchHelper
.
END
)
{
new
ItemTouchHelper
(
new
SimpleCallback
(
ItemTouchHelper
.
UP
|
ItemTouchHelper
.
DOWN
,
ItemTouchHelper
.
START
|
ItemTouchHelper
.
END
)
{
def
onSwiped
(
viewHolder
:
ViewHolder
,
direction
:
Int
)
=
{
profilesAdapter
.
remove
(
viewHolder
.
getAdapterPosition
)
removedSnackbar
.
show
}
def
onMove
(
recyclerView
:
RecyclerView
,
viewHolder
:
ViewHolder
,
target
:
ViewHolder
)
=
false
// TODO?
def
onMove
(
recyclerView
:
RecyclerView
,
viewHolder
:
ViewHolder
,
target
:
ViewHolder
)
=
{
profilesAdapter
.
move
(
viewHolder
.
getAdapterPosition
,
target
.
getAdapterPosition
)
true
}
}).
attachToRecyclerView
(
profilesList
)
attachService
(
new
IShadowsocksServiceCallback
.
Stub
{
...
...
@@ -175,6 +210,12 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
def
trafficUpdated
(
txRate
:
String
,
rxRate
:
String
,
txTotal
:
String
,
rxTotal
:
String
)
=
if
(
selectedItem
!=
null
)
selectedItem
.
updateText
(
true
)
})
if
(
ShadowsocksApplication
.
settings
.
getBoolean
(
profileTip
,
true
))
{
ShadowsocksApplication
.
settings
.
edit
.
putBoolean
(
profileTip
,
false
).
commit
new
AlertDialog
.
Builder
(
this
).
setTitle
(
R
.
string
.
profile_manager_dialog
)
.
setMessage
(
R
.
string
.
profile_manager_dialog_content
).
setPositiveButton
(
R
.
string
.
gotcha
,
null
).
create
.
show
}
}
override
def
onDestroy
{
...
...
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
View file @
0282975e
...
...
@@ -49,7 +49,6 @@ import android.content.res.AssetManager
import
android.graphics.Typeface
import
android.net.VpnService
import
android.os._
import
android.preference.
{
Preference
,
SwitchPreference
}
import
android.support.design.widget.
{
FloatingActionButton
,
Snackbar
}
import
android.support.v4.content.ContextCompat
import
android.support.v7.app.AppCompatActivity
...
...
@@ -60,7 +59,6 @@ import android.widget._
import
com.github.jorgecastilloprz.FABProgressCircle
import
com.github.shadowsocks.aidl.IShadowsocksServiceCallback
import
com.github.shadowsocks.database._
import
com.github.shadowsocks.preferences.
{
DropDownPreference
,
NumberPickerPreference
,
PasswordEditTextPreference
,
SummaryEditTextPreference
}
import
com.github.shadowsocks.utils._
import
com.google.android.gms.ads.
{
AdRequest
,
AdSize
,
AdView
}
...
...
@@ -91,52 +89,9 @@ object Shadowsocks {
// Constants
val
TAG
=
"Shadowsocks"
val
REQUEST_CONNECT
=
1
val
PREFS_NAME
=
"Shadowsocks"
val
PROXY_PREFS
=
Array
(
Key
.
profileName
,
Key
.
proxy
,
Key
.
remotePort
,
Key
.
localPort
,
Key
.
sitekey
,
Key
.
encMethod
,
Key
.
isAuth
)
val
FEATURE_PREFS
=
Array
(
Key
.
route
,
Key
.
isProxyApps
,
Key
.
isUdpDns
,
Key
.
isIpv6
)
val
EXECUTABLES
=
Array
(
Executable
.
PDNSD
,
Executable
.
REDSOCKS
,
Executable
.
SS_TUNNEL
,
Executable
.
SS_LOCAL
,
Executable
.
TUN2SOCKS
)
// Helper functions
def
updateDropDownPreference
(
pref
:
Preference
,
value
:
String
)
{
pref
.
asInstanceOf
[
DropDownPreference
].
setValue
(
value
)
}
def
updatePasswordEditTextPreference
(
pref
:
Preference
,
value
:
String
)
{
pref
.
setSummary
(
value
)
pref
.
asInstanceOf
[
PasswordEditTextPreference
].
setText
(
value
)
}
def
updateNumberPickerPreference
(
pref
:
Preference
,
value
:
Int
)
{
pref
.
asInstanceOf
[
NumberPickerPreference
].
setValue
(
value
)
}
def
updateSummaryEditTextPreference
(
pref
:
Preference
,
value
:
String
)
{
pref
.
setSummary
(
value
)
pref
.
asInstanceOf
[
SummaryEditTextPreference
].
setText
(
value
)
}
def
updateSwitchPreference
(
pref
:
Preference
,
value
:
Boolean
)
{
pref
.
asInstanceOf
[
SwitchPreference
].
setChecked
(
value
)
}
def
updatePreference
(
pref
:
Preference
,
name
:
String
,
profile
:
Profile
)
{
name
match
{
case
Key
.
profileName
=>
updateSummaryEditTextPreference
(
pref
,
profile
.
name
)
case
Key
.
proxy
=>
updateSummaryEditTextPreference
(
pref
,
profile
.
host
)
case
Key
.
remotePort
=>
updateNumberPickerPreference
(
pref
,
profile
.
remotePort
)
case
Key
.
localPort
=>
updateNumberPickerPreference
(
pref
,
profile
.
localPort
)
case
Key
.
sitekey
=>
updatePasswordEditTextPreference
(
pref
,
profile
.
password
)
case
Key
.
encMethod
=>
updateDropDownPreference
(
pref
,
profile
.
method
)
case
Key
.
route
=>
updateDropDownPreference
(
pref
,
profile
.
route
)
case
Key
.
isProxyApps
=>
updateSwitchPreference
(
pref
,
profile
.
proxyApps
)
case
Key
.
isUdpDns
=>
updateSwitchPreference
(
pref
,
profile
.
udpdns
)
case
Key
.
isAuth
=>
updateSwitchPreference
(
pref
,
profile
.
auth
)
case
Key
.
isIpv6
=>
updateSwitchPreference
(
pref
,
profile
.
ipv6
)
}
}
}
class
Shadowsocks
...
...
@@ -166,7 +121,7 @@ class Shadowsocks
fab
.
setImageResource
(
R
.
drawable
.
ic_cloud_queue
)
fab
.
setEnabled
(
false
)
fabProgressCircle
.
show
()
setPreferenceEnabled
(
enabled
=
false
)
preferences
.
setEnabled
(
false
)
case
State
.
CONNECTED
=>
fab
.
setBackgroundTintList
(
greenTint
)
if
(
state
==
State
.
CONNECTING
)
{
...
...
@@ -176,7 +131,7 @@ class Shadowsocks
}
fab
.
setEnabled
(
true
)
changeSwitch
(
checked
=
true
)
setPreferenceEnabled
(
enabled
=
false
)
preferences
.
setEnabled
(
false
)
case
State
.
STOPPED
=>
fab
.
setBackgroundTintList
(
greyTint
)
handler
.
postDelayed
(()
=>
fabProgressCircle
.
hide
(),
1000
)
...
...
@@ -189,13 +144,13 @@ class Shadowsocks
(
_
=>
preferences
.
natSwitch
.
setChecked
(
false
))
:
View.OnClickListener
)
snackbar
.
show
}
setPreferenceEnabled
(
enabled
=
true
)
preferences
.
setEnabled
(
true
)
case
State
.
STOPPING
=>
fab
.
setBackgroundTintList
(
greyTint
)
fab
.
setImageResource
(
R
.
drawable
.
ic_cloud_queue
)
fab
.
setEnabled
(
false
)
if
(
state
==
State
.
CONNECTED
)
fabProgressCircle
.
show
()
// ignore for stopped
setPreferenceEnabled
(
enabled
=
false
)
preferences
.
setEnabled
(
false
)
}
state
=
s
})
...
...
@@ -255,7 +210,7 @@ class Shadowsocks
getFragmentManager
.
findFragmentById
(
android
.
R
.
id
.
content
).
asInstanceOf
[
ShadowsocksSettings
]
private
var
adView
:
AdView
=
_
private
lazy
val
greyTint
=
ContextCompat
.
getColorStateList
(
this
,
R
.
color
.
material_blue_grey_700
)
private
lazy
val
greenTint
=
ContextCompat
.
getColorStateList
(
this
,
R
.
color
.
material_green_
a
700
)
private
lazy
val
greenTint
=
ContextCompat
.
getColorStateList
(
this
,
R
.
color
.
material_green_700
)
var
handler
=
new
Handler
()
...
...
@@ -367,12 +322,7 @@ class Shadowsocks
changeSwitch
(
checked
=
false
)
}
def
isReady
:
Boolean
=
{
if
(!
checkText
(
Key
.
proxy
))
return
false
if
(!
checkText
(
Key
.
sitekey
))
return
false
if
(
bgService
==
null
)
return
false
true
}
def
isReady
:
Boolean
=
checkText
(
Key
.
proxy
)
&&
checkText
(
Key
.
sitekey
)
&&
bgService
!=
null
def
prepareStartService
()
{
ThrowableFuture
{
...
...
@@ -438,9 +388,10 @@ class Shadowsocks
currentProfile
=
ShadowsocksApplication
.
currentProfile
match
{
case
Some
(
profile
)
=>
profile
// updated
case
None
=>
// removed
val
profiles
=
ShadowsocksApplication
.
profileManager
.
getAllProfiles
.
getOrElse
(
List
[
Profile
]())
if
(
profiles
.
isEmpty
)
ShadowsocksApplication
.
profileManager
.
createDefault
()
else
ShadowsocksApplication
.
switchProfile
(
profiles
.
head
.
id
)
ShadowsocksApplication
.
profileManager
.
getFirstProfile
match
{
case
Some
(
first
)
=>
ShadowsocksApplication
.
switchProfile
(
first
.
id
)
case
None
=>
ShadowsocksApplication
.
profileManager
.
createDefault
()
}
}
updatePreferenceScreen
()
...
...
@@ -461,25 +412,25 @@ class Shadowsocks
fab
.
setBackgroundTintList
(
greyTint
)
serviceStarted
=
false
fab
.
setImageResource
(
R
.
drawable
.
ic_cloud_queue
)
setPreference
Enabled
(
false
)
preferences
.
set
Enabled
(
false
)
fabProgressCircle
.
show
()
case
State
.
CONNECTED
=>
fab
.
setBackgroundTintList
(
greenTint
)
serviceStarted
=
true
fab
.
setImageResource
(
R
.
drawable
.
ic_cloud
)
setPreference
Enabled
(
false
)
preferences
.
set
Enabled
(
false
)
fabProgressCircle
.
postDelayed
(
fabProgressCircle
.
hide
,
100
)
case
State
.
STOPPING
=>
fab
.
setBackgroundTintList
(
greyTint
)
serviceStarted
=
false
fab
.
setImageResource
(
R
.
drawable
.
ic_cloud_queue
)
setPreference
Enabled
(
false
)
preferences
.
set
Enabled
(
false
)
fabProgressCircle
.
show
()
case
_
=>
fab
.
setBackgroundTintList
(
greyTint
)
serviceStarted
=
false
fab
.
setImageResource
(
R
.
drawable
.
ic_cloud_off
)
setPreference
Enabled
(
true
)
preferences
.
set
Enabled
(
true
)
fabProgressCircle
.
postDelayed
(
fabProgressCircle
.
hide
,
100
)
}
state
=
bgService
.
getState
...
...
@@ -497,26 +448,6 @@ class Shadowsocks
updateTraffic
()
}
private
def
setPreferenceEnabled
(
enabled
:
Boolean
)
{
preferences
.
findPreference
(
Key
.
isNAT
).
setEnabled
(
enabled
)
for
(
name
<-
Shadowsocks
.
PROXY_PREFS
)
{
val
pref
=
preferences
.
findPreference
(
name
)
if
(
pref
!=
null
)
{
pref
.
setEnabled
(
enabled
)
}
}
for
(
name
<-
Shadowsocks
.
FEATURE_PREFS
)
{
val
pref
=
preferences
.
findPreference
(
name
)
if
(
pref
!=
null
)
{
if
(
name
==
Key
.
isProxyApps
)
{
pref
.
setEnabled
(
enabled
&&
(
Utils
.
isLollipopOrAbove
||
!
ShadowsocksApplication
.
isVpnEnabled
))
}
else
{
pref
.
setEnabled
(
enabled
)
}
}
}
}
private
def
updatePreferenceScreen
()
{
val
profile
=
currentProfile
if
(
profile
.
host
==
"198.199.101.152"
&&
adView
==
null
)
{
...
...
@@ -527,14 +458,7 @@ class Shadowsocks
adView
.
loadAd
(
new
AdRequest
.
Builder
().
build
())
}
for
(
name
<-
Shadowsocks
.
PROXY_PREFS
)
{
val
pref
=
preferences
.
findPreference
(
name
)
Shadowsocks
.
updatePreference
(
pref
,
name
,
profile
)
}
for
(
name
<-
Shadowsocks
.
FEATURE_PREFS
)
{
val
pref
=
preferences
.
findPreference
(
name
)
Shadowsocks
.
updatePreference
(
pref
,
name
,
profile
)
}
preferences
.
update
(
profile
)
}
override
def
onStop
()
{
...
...
@@ -542,8 +466,11 @@ class Shadowsocks
clearDialog
()
}
private
var
_isDestroyed
:
Boolean
=
_
override
def
isDestroyed
=
if
(
Build
.
VERSION
.
SDK_INT
>=
17
)
super
.
isDestroyed
else
_isDestroyed
override
def
onDestroy
()
{
super
.
onDestroy
()
_isDestroyed
=
true
deattachService
()
new
BackupManager
(
this
).
dataChanged
()
handler
.
removeCallbacksAndMessages
(
null
)
...
...
@@ -613,8 +540,8 @@ class Shadowsocks
}
def
clearDialog
()
{
if
(
progressDialog
!=
null
)
{
progressDialog
.
dismiss
()
if
(
progressDialog
!=
null
&&
progressDialog
.
isShowing
)
{
if
(!
isDestroyed
)
progressDialog
.
dismiss
()
progressDialog
=
null
progressTag
=
-
1
}
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksSettings.scala
View file @
0282975e
...
...
@@ -11,11 +11,61 @@ import android.os.{Build, Bundle}
import
android.preference.
{
Preference
,
PreferenceFragment
,
SwitchPreference
}
import
android.support.v7.app.AlertDialog
import
android.webkit.
{
WebView
,
WebViewClient
}
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.preferences.
{
DropDownPreference
,
NumberPickerPreference
,
PasswordEditTextPreference
,
SummaryEditTextPreference
}
import
com.github.shadowsocks.utils.CloseUtils._
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.
{
Key
,
Utils
}
object
ShadowsocksSettings
{
// Constants
val
PREFS_NAME
=
"Shadowsocks"
val
PROXY_PREFS
=
Array
(
Key
.
profileName
,
Key
.
proxy
,
Key
.
remotePort
,
Key
.
localPort
,
Key
.
sitekey
,
Key
.
encMethod
,
Key
.
isAuth
)
val
FEATURE_PREFS
=
Array
(
Key
.
route
,
Key
.
isProxyApps
,
Key
.
isUdpDns
,
Key
.
isIpv6
)
// Helper functions
def
updateDropDownPreference
(
pref
:
Preference
,
value
:
String
)
{
pref
.
asInstanceOf
[
DropDownPreference
].
setValue
(
value
)
}
def
updatePasswordEditTextPreference
(
pref
:
Preference
,
value
:
String
)
{
pref
.
setSummary
(
value
)
pref
.
asInstanceOf
[
PasswordEditTextPreference
].
setText
(
value
)
}
def
updateNumberPickerPreference
(
pref
:
Preference
,
value
:
Int
)
{
pref
.
asInstanceOf
[
NumberPickerPreference
].
setValue
(
value
)
}
def
updateSummaryEditTextPreference
(
pref
:
Preference
,
value
:
String
)
{
pref
.
setSummary
(
value
)
pref
.
asInstanceOf
[
SummaryEditTextPreference
].
setText
(
value
)
}
def
updateSwitchPreference
(
pref
:
Preference
,
value
:
Boolean
)
{
pref
.
asInstanceOf
[
SwitchPreference
].
setChecked
(
value
)
}
def
updatePreference
(
pref
:
Preference
,
name
:
String
,
profile
:
Profile
)
{
name
match
{
case
Key
.
profileName
=>
updateSummaryEditTextPreference
(
pref
,
profile
.
name
)
case
Key
.
proxy
=>
updateSummaryEditTextPreference
(
pref
,
profile
.
host
)
case
Key
.
remotePort
=>
updateNumberPickerPreference
(
pref
,
profile
.
remotePort
)
case
Key
.
localPort
=>
updateNumberPickerPreference
(
pref
,
profile
.
localPort
)
case
Key
.
sitekey
=>
updatePasswordEditTextPreference
(
pref
,
profile
.
password
)
case
Key
.
encMethod
=>
updateDropDownPreference
(
pref
,
profile
.
method
)
case
Key
.
route
=>
updateDropDownPreference
(
pref
,
profile
.
route
)
case
Key
.
isProxyApps
=>
updateSwitchPreference
(
pref
,
profile
.
proxyApps
)
case
Key
.
isUdpDns
=>
updateSwitchPreference
(
pref
,
profile
.
udpdns
)
case
Key
.
isAuth
=>
updateSwitchPreference
(
pref
,
profile
.
auth
)
case
Key
.
isIpv6
=>
updateSwitchPreference
(
pref
,
profile
.
ipv6
)
}
}
}
// TODO: Move related logic here
class
ShadowsocksSettings
extends
PreferenceFragment
with
OnSharedPreferenceChangeListener
{
import
ShadowsocksSettings._
private
def
activity
=
getActivity
.
asInstanceOf
[
Shadowsocks
]
lazy
val
natSwitch
=
findPreference
(
Key
.
isNAT
).
asInstanceOf
[
SwitchPreference
]
var
stat
:
Preference
=
_
...
...
@@ -122,10 +172,38 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
}
def
onSharedPreferenceChanged
(
sharedPreferences
:
SharedPreferences
,
key
:
String
)
=
key
match
{
case
Key
.
isNAT
=>
activity
.
handler
.
post
(()
=>
{
case
Key
.
isNAT
=>
activity
.
handler
.
post
(()
=>
{
activity
.
deattachService
activity
.
attachService
})
setEnabled
(
enabled
)
case
_
=>
}
private
var
enabled
=
true
def
setEnabled
(
enabled
:
Boolean
)
{
this
.
enabled
=
enabled
findPreference
(
Key
.
isNAT
).
setEnabled
(
enabled
)
for
(
name
<-
PROXY_PREFS
)
{
val
pref
=
findPreference
(
name
)
if
(
pref
!=
null
)
pref
.
setEnabled
(
enabled
)
}
for
(
name
<-
FEATURE_PREFS
)
{
val
pref
=
findPreference
(
name
)
if
(
pref
!=
null
)
pref
.
setEnabled
(
enabled
&&
(
name
!=
Key
.
isProxyApps
||
Utils
.
isLollipopOrAbove
||
!
ShadowsocksApplication
.
isVpnEnabled
))
}
}
def
update
(
profile
:
Profile
)
{
for
(
name
<-
PROXY_PREFS
)
{
val
pref
=
findPreference
(
name
)
updatePreference
(
pref
,
name
,
profile
)
}
for
(
name
<-
FEATURE_PREFS
)
{
val
pref
=
findPreference
(
name
)
updatePreference
(
pref
,
name
,
profile
)
}
}
}
src/main/scala/com/github/shadowsocks/database/DBHelper.scala
View file @
0282975e
...
...
@@ -64,7 +64,7 @@ object DBHelper {
}
class
DBHelper
(
val
context
:
Context
)
extends
OrmLiteSqliteOpenHelper
(
context
,
DBHelper
.
PROFILE
,
null
,
1
4
)
{
extends
OrmLiteSqliteOpenHelper
(
context
,
DBHelper
.
PROFILE
,
null
,
1
5
)
{
import
DBHelper._
lazy
val
profileDao
:
Dao
[
Profile
,
Int
]
=
getDao
(
classOf
[
Profile
])
...
...
@@ -116,6 +116,15 @@ class DBHelper(val context: Context)
profileDao
.
update
(
profile
)
}
}
if
(
oldVersion
<
15
)
{
profileDao
.
executeRawNoArgs
(
"ALTER TABLE `profile` ADD COLUMN userOrder LONG;"
)
var
i
=
0
for
(
profile
<-
profileDao
.
queryForAll
.
asScala
)
{
profile
.
userOrder
=
i
profileDao
.
update
(
profile
)
i
+=
1
}
}
}
}
}
src/main/scala/com/github/shadowsocks/database/Profile.scala
View file @
0282975e
...
...
@@ -55,13 +55,13 @@ class Profile {
var
localPort
:
Int
=
1080
@DatabaseField
var
remotePort
:
Int
=
83
3
8
var
remotePort
:
Int
=
83
8
8
@DatabaseField
var
password
:
String
=
""
@DatabaseField
var
method
:
String
=
"
rc4
"
var
method
:
String
=
"
aes-256-cfb
"
@DatabaseField
var
route
:
String
=
"all"
...
...
@@ -92,4 +92,7 @@ class Profile {
@DatabaseField
val
date
:
java.util.Date
=
new
java
.
util
.
Date
()
@DatabaseField
var
userOrder
:
Long
=
_
}
src/main/scala/com/github/shadowsocks/database/ProfileManager.scala
View file @
0282975e
...
...
@@ -64,6 +64,9 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
profile
.
udpdns
=
oldProfile
.
udpdns
case
_
=>
}
val
last
=
dbHelper
.
profileDao
.
queryRaw
(
dbHelper
.
profileDao
.
queryBuilder
.
selectRaw
(
"MAX(userOrder)"
)
.
prepareStatementString
).
getFirstResult
if
(
last
!=
null
&&
last
.
length
==
1
&&
last
(
0
)
!=
null
)
profile
.
userOrder
=
last
(
0
).
toInt
+
1
dbHelper
.
profileDao
.
createOrUpdate
(
profile
)
if
(
profileAddedListener
!=
null
)
profileAddedListener
(
profile
)
profile
...
...
@@ -109,10 +112,21 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
}
}
def
getFirstProfile
=
{
try
{
val
result
=
dbHelper
.
profileDao
.
query
(
dbHelper
.
profileDao
.
queryBuilder
.
limit
(
1L
).
prepare
)
if
(
result
.
size
==
1
)
Option
(
result
.
get
(
0
))
else
None
}
catch
{
case
ex
:
Exception
=>
Log
.
e
(
Shadowsocks
.
TAG
,
"getAllProfiles"
,
ex
)
None
}
}
def
getAllProfiles
:
Option
[
List
[
Profile
]]
=
{
try
{
import
scala.collection.JavaConversions._
Option
(
dbHelper
.
profileDao
.
query
ForAll
(
).
toList
)
Option
(
dbHelper
.
profileDao
.
query
(
dbHelper
.
profileDao
.
queryBuilder
.
orderBy
(
"userOrder"
,
true
).
prepare
).
toList
)
}
catch
{
case
ex
:
Exception
=>
Log
.
e
(
Shadowsocks
.
TAG
,
"getAllProfiles"
,
ex
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment