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
fa0669df
Commit
fa0669df
authored
Jan 12, 2020
by
Mygod
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move sync to service
parent
392f2f90
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
205 additions
and
107 deletions
+205
-107
core/src/main/AndroidManifest.xml
core/src/main/AndroidManifest.xml
+5
-0
core/src/main/java/com/github/shadowsocks/Core.kt
core/src/main/java/com/github/shadowsocks/Core.kt
+6
-4
core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt
...in/java/com/github/shadowsocks/database/ProfileManager.kt
+3
-41
core/src/main/java/com/github/shadowsocks/subscription/SubscriptionService.kt
...om/github/shadowsocks/subscription/SubscriptionService.kt
+178
-0
core/src/main/res/drawable/ic_file_cloud_download.xml
core/src/main/res/drawable/ic_file_cloud_download.xml
+0
-0
core/src/main/res/values/strings.xml
core/src/main/res/values/strings.xml
+3
-0
mobile/build.gradle
mobile/build.gradle
+0
-1
mobile/src/main/java/com/github/shadowsocks/subscription/SubscriptionFragment.kt
...m/github/shadowsocks/subscription/SubscriptionFragment.kt
+7
-45
mobile/src/main/res/drawable/ic_file_cloud_queue.xml
mobile/src/main/res/drawable/ic_file_cloud_queue.xml
+0
-0
mobile/src/main/res/layout/layout_profile.xml
mobile/src/main/res/layout/layout_profile.xml
+1
-1
mobile/src/main/res/layout/layout_subscriptions.xml
mobile/src/main/res/layout/layout_subscriptions.xml
+0
-13
mobile/src/main/res/menu/navigation_main.xml
mobile/src/main/res/menu/navigation_main.xml
+1
-1
mobile/src/main/res/menu/subscription_menu.xml
mobile/src/main/res/menu/subscription_menu.xml
+1
-1
No files found.
core/src/main/AndroidManifest.xml
View file @
fa0669df
...
@@ -61,6 +61,11 @@
...
@@ -61,6 +61,11 @@
android:exported=
"false"
>
android:exported=
"false"
>
</service>
</service>
<service
android:name=
"com.github.shadowsocks.subscription.SubscriptionService"
android:exported=
"false"
>
</service>
<activity
<activity
android:name=
"com.github.shadowsocks.UrlImportActivity"
android:name=
"com.github.shadowsocks.UrlImportActivity"
android:theme=
"@style/Theme.AppCompat.Translucent"
android:theme=
"@style/Theme.AppCompat.Translucent"
...
...
core/src/main/java/com/github/shadowsocks/Core.kt
View file @
fa0669df
...
@@ -42,6 +42,7 @@ import com.github.shadowsocks.database.Profile
...
@@ -42,6 +42,7 @@ import com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.net.TcpFastOpen
import
com.github.shadowsocks.net.TcpFastOpen
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.subscription.SubscriptionService
import
com.github.shadowsocks.utils.*
import
com.github.shadowsocks.utils.*
import
com.google.firebase.FirebaseApp
import
com.google.firebase.FirebaseApp
import
com.google.firebase.analytics.FirebaseAnalytics
import
com.google.firebase.analytics.FirebaseAnalytics
...
@@ -61,6 +62,7 @@ object Core {
...
@@ -61,6 +62,7 @@ object Core {
lateinit
var
configureIntent
:
(
Context
)
->
PendingIntent
lateinit
var
configureIntent
:
(
Context
)
->
PendingIntent
val
activity
by
lazy
{
app
.
getSystemService
<
ActivityManager
>()
!!
}
val
activity
by
lazy
{
app
.
getSystemService
<
ActivityManager
>()
!!
}
val
connectivity
by
lazy
{
app
.
getSystemService
<
ConnectivityManager
>()
!!
}
val
connectivity
by
lazy
{
app
.
getSystemService
<
ConnectivityManager
>()
!!
}
val
notification
by
lazy
{
app
.
getSystemService
<
NotificationManager
>()
!!
}
val
packageInfo
:
PackageInfo
by
lazy
{
getPackageInfo
(
app
.
packageName
)
}
val
packageInfo
:
PackageInfo
by
lazy
{
getPackageInfo
(
app
.
packageName
)
}
val
deviceStorage
by
lazy
{
if
(
Build
.
VERSION
.
SDK_INT
<
24
)
app
else
DeviceStorageApp
(
app
)
}
val
deviceStorage
by
lazy
{
if
(
Build
.
VERSION
.
SDK_INT
<
24
)
app
else
DeviceStorageApp
(
app
)
}
val
analytics
:
FirebaseAnalytics
by
lazy
{
FirebaseAnalytics
.
getInstance
(
deviceStorage
)
}
val
analytics
:
FirebaseAnalytics
by
lazy
{
FirebaseAnalytics
.
getInstance
(
deviceStorage
)
}
...
@@ -128,16 +130,16 @@ object Core {
...
@@ -128,16 +130,16 @@ object Core {
fun
updateNotificationChannels
()
{
fun
updateNotificationChannels
()
{
if
(
Build
.
VERSION
.
SDK_INT
>=
26
)
@RequiresApi
(
26
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
26
)
@RequiresApi
(
26
)
{
val
nm
=
app
.
getSystemService
<
NotificationManager
>()
!!
notification
.
createNotificationChannels
(
listOf
(
nm
.
createNotificationChannels
(
listOf
(
NotificationChannel
(
"service-vpn"
,
app
.
getText
(
R
.
string
.
service_vpn
),
NotificationChannel
(
"service-vpn"
,
app
.
getText
(
R
.
string
.
service_vpn
),
if
(
Build
.
VERSION
.
SDK_INT
>=
28
)
NotificationManager
.
IMPORTANCE_MIN
if
(
Build
.
VERSION
.
SDK_INT
>=
28
)
NotificationManager
.
IMPORTANCE_MIN
else
NotificationManager
.
IMPORTANCE_LOW
),
// #1355
else
NotificationManager
.
IMPORTANCE_LOW
),
// #1355
NotificationChannel
(
"service-proxy"
,
app
.
getText
(
R
.
string
.
service_proxy
),
NotificationChannel
(
"service-proxy"
,
app
.
getText
(
R
.
string
.
service_proxy
),
NotificationManager
.
IMPORTANCE_LOW
),
NotificationManager
.
IMPORTANCE_LOW
),
NotificationChannel
(
"service-transproxy"
,
app
.
getText
(
R
.
string
.
service_transproxy
),
NotificationChannel
(
"service-transproxy"
,
app
.
getText
(
R
.
string
.
service_transproxy
),
NotificationManager
.
IMPORTANCE_LOW
)))
NotificationManager
.
IMPORTANCE_LOW
),
nm
.
deleteNotificationChannel
(
"service-nat"
)
// NAT mode is gone for good
SubscriptionService
.
notificationChannel
))
notification
.
deleteNotificationChannel
(
"service-nat"
)
// NAT mode is gone for good
}
}
}
}
...
...
core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt
View file @
fa0669df
...
@@ -24,7 +24,9 @@ import android.database.sqlite.SQLiteCantOpenDatabaseException
...
@@ -24,7 +24,9 @@ import android.database.sqlite.SQLiteCantOpenDatabaseException
import
android.util.LongSparseArray
import
android.util.LongSparseArray
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.*
import
com.github.shadowsocks.utils.DirectBoot
import
com.github.shadowsocks.utils.forEachTry
import
com.github.shadowsocks.utils.printLog
import
com.google.gson.JsonStreamParser
import
com.google.gson.JsonStreamParser
import
org.json.JSONArray
import
org.json.JSONArray
import
java.io.IOException
import
java.io.IOException
...
@@ -52,46 +54,6 @@ object ProfileManager {
...
@@ -52,46 +54,6 @@ object ProfileManager {
return
profile
return
profile
}
}
fun
createProfilesFromSubscription
(
jsons
:
Sequence
<
InputStream
>)
{
val
currentId
=
DataStore
.
profileId
val
profiles
=
getAllProfiles
()
val
subscriptions
=
mutableMapOf
<
Pair
<
String
?
,
String
>,
Profile
>()
val
toUpdate
=
mutableSetOf
<
Long
>()
var
feature
:
Profile
?
=
null
profiles
?.
forEach
{
profile
->
// preprocessing phase
if
(
currentId
==
profile
.
id
)
feature
=
profile
if
(
profile
.
subscription
==
Profile
.
SubscriptionStatus
.
UserConfigured
)
return
@forEach
if
(
subscriptions
.
putIfAbsentCompat
(
profile
.
name
to
profile
.
formattedAddress
,
profile
)
!=
null
)
{
delProfile
(
profile
.
id
)
if
(
currentId
==
profile
.
id
)
DataStore
.
profileId
=
0
}
else
if
(
profile
.
subscription
==
Profile
.
SubscriptionStatus
.
Active
)
{
toUpdate
.
add
(
profile
.
id
)
profile
.
subscription
=
Profile
.
SubscriptionStatus
.
Obsolete
}
}
jsons
.
asIterable
().
forEachTry
{
json
->
Profile
.
parseJson
(
JsonStreamParser
(
json
.
bufferedReader
()).
asSequence
().
single
(),
feature
)
{
subscriptions
.
computeCompat
(
it
.
name
to
it
.
formattedAddress
)
{
_
,
oldProfile
->
when
(
oldProfile
?.
subscription
)
{
Profile
.
SubscriptionStatus
.
Active
->
oldProfile
// skip dup subscription
Profile
.
SubscriptionStatus
.
Obsolete
->
{
oldProfile
.
password
=
it
.
password
oldProfile
.
method
=
it
.
method
oldProfile
.
plugin
=
it
.
plugin
oldProfile
.
udpFallback
=
it
.
udpFallback
oldProfile
.
subscription
=
Profile
.
SubscriptionStatus
.
Active
oldProfile
}
else
->
createProfile
(
it
.
apply
{
subscription
=
Profile
.
SubscriptionStatus
.
Active
})
}
}
}
}
profiles
?.
forEach
{
profile
->
if
(
toUpdate
.
contains
(
profile
.
id
))
updateProfile
(
profile
)
}
}
fun
createProfilesFromJson
(
jsons
:
Sequence
<
InputStream
>,
replace
:
Boolean
=
false
)
{
fun
createProfilesFromJson
(
jsons
:
Sequence
<
InputStream
>,
replace
:
Boolean
=
false
)
{
val
profiles
=
if
(
replace
)
getAllProfiles
()
?.
associateBy
{
it
.
formattedAddress
}
else
null
val
profiles
=
if
(
replace
)
getAllProfiles
()
?.
associateBy
{
it
.
formattedAddress
}
else
null
val
feature
=
if
(
replace
)
{
val
feature
=
if
(
replace
)
{
...
...
core/src/main/java/com/github/shadowsocks/subscription/SubscriptionService.kt
0 → 100644
View file @
fa0669df
/*******************************************************************************
* *
* Copyright (C) 2020 by Max Lv <max.c.lv@gmail.com> *
* Copyright (C) 2020 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
package
com.github.shadowsocks.subscription
import
android.app.NotificationChannel
import
android.app.NotificationManager
import
android.app.Service
import
android.content.Intent
import
android.os.IBinder
import
android.widget.Toast
import
androidx.annotation.RequiresApi
import
androidx.core.app.NotificationCompat
import
androidx.core.content.ContextCompat
import
androidx.lifecycle.MutableLiveData
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.Core.app
import
com.github.shadowsocks.core.R
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.*
import
com.google.gson.JsonStreamParser
import
kotlinx.coroutines.*
import
java.io.File
import
java.io.IOException
import
java.io.InputStream
import
java.net.HttpURLConnection
class
SubscriptionService
:
Service
()
{
companion
object
{
private
const
val
NOTIFICATION_CHANNEL
=
"service-subscription"
private
const
val
NOTIFICATION_ID
=
2
private
var
worker
:
Job
?
=
null
val
idle
=
MutableLiveData
<
Boolean
>(
true
)
val
notificationChannel
@RequiresApi
(
26
)
get
()
=
NotificationChannel
(
NOTIFICATION_CHANNEL
,
app
.
getText
(
R
.
string
.
service_subscription
),
NotificationManager
.
IMPORTANCE_LOW
)
}
override
fun
onBind
(
intent
:
Intent
?):
IBinder
?
=
null
override
fun
onStartCommand
(
intent
:
Intent
?,
flags
:
Int
,
startId
:
Int
):
Int
{
if
(
worker
==
null
)
{
idle
.
value
=
false
worker
=
GlobalScope
.
launch
{
val
urls
=
Subscription
.
instance
.
urls
val
notification
=
NotificationCompat
.
Builder
(
this
@SubscriptionService
,
NOTIFICATION_CHANNEL
).
apply
{
color
=
ContextCompat
.
getColor
(
this
@SubscriptionService
,
R
.
color
.
material_primary_500
)
priority
=
NotificationCompat
.
PRIORITY_LOW
setCategory
(
NotificationCompat
.
CATEGORY_PROGRESS
)
setContentTitle
(
getString
(
R
.
string
.
service_subscription_working
))
setOngoing
(
true
)
setProgress
(
urls
.
size
(),
0
,
false
)
setSmallIcon
(
R
.
drawable
.
ic_file_cloud_download
)
setWhen
(
0
)
}
Core
.
notification
.
notify
(
NOTIFICATION_ID
,
notification
.
build
())
var
counter
=
0
val
workers
=
urls
.
asIterable
().
map
{
url
->
async
(
Dispatchers
.
IO
)
{
val
tempFile
=
File
.
createTempFile
(
"subscription-"
,
".json"
,
cacheDir
)
try
{
(
url
.
openConnection
()
as
HttpURLConnection
).
useCancellable
{
tempFile
.
outputStream
().
use
{
out
->
inputStream
.
copyTo
(
out
)
}
}
tempFile
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
()
Toast
.
makeText
(
this
@SubscriptionService
,
e
.
readableMessage
,
Toast
.
LENGTH_LONG
).
show
()
if
(!
tempFile
.
delete
())
tempFile
.
deleteOnExit
()
null
}
finally
{
withContext
(
Dispatchers
.
Main
)
{
counter
+=
1
Core
.
notification
.
notify
(
NOTIFICATION_ID
,
notification
.
apply
{
setProgress
(
urls
.
size
(),
counter
,
false
)
}.
build
())
}
}
}
}
try
{
val
localJsons
=
workers
.
awaitAll
()
withContext
(
Dispatchers
.
Main
)
{
Core
.
notification
.
notify
(
NOTIFICATION_ID
,
notification
.
apply
{
setProgress
(
0
,
0
,
true
)
}.
build
())
createProfilesFromSubscription
(
localJsons
.
asSequence
().
filterNotNull
().
map
{
it
.
inputStream
()
})
}
}
finally
{
for
(
worker
in
workers
)
{
worker
.
cancel
()
try
{
worker
.
getCompleted
()
?.
apply
{
if
(!
delete
())
deleteOnExit
()
}
}
catch
(
_
:
Exception
)
{
}
}
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
Core
.
notification
.
cancel
(
NOTIFICATION_ID
)
idle
.
value
=
true
}
check
(
worker
!=
null
)
worker
=
null
stopSelf
(
startId
)
}
}
}
else
stopSelf
(
startId
)
return
START_NOT_STICKY
}
private
fun
createProfilesFromSubscription
(
jsons
:
Sequence
<
InputStream
>)
{
val
currentId
=
DataStore
.
profileId
val
profiles
=
ProfileManager
.
getAllProfiles
()
val
subscriptions
=
mutableMapOf
<
Pair
<
String
?
,
String
>,
Profile
>()
val
toUpdate
=
mutableSetOf
<
Long
>()
var
feature
:
Profile
?
=
null
profiles
?.
forEach
{
profile
->
// preprocessing phase
if
(
currentId
==
profile
.
id
)
feature
=
profile
if
(
profile
.
subscription
==
Profile
.
SubscriptionStatus
.
UserConfigured
)
return
@forEach
if
(
subscriptions
.
putIfAbsentCompat
(
profile
.
name
to
profile
.
formattedAddress
,
profile
)
!=
null
)
{
ProfileManager
.
delProfile
(
profile
.
id
)
if
(
currentId
==
profile
.
id
)
DataStore
.
profileId
=
0
}
else
if
(
profile
.
subscription
==
Profile
.
SubscriptionStatus
.
Active
)
{
toUpdate
.
add
(
profile
.
id
)
profile
.
subscription
=
Profile
.
SubscriptionStatus
.
Obsolete
}
}
for
(
json
in
jsons
.
asIterable
())
try
{
Profile
.
parseJson
(
JsonStreamParser
(
json
.
bufferedReader
()).
asSequence
().
single
(),
feature
)
{
subscriptions
.
computeCompat
(
it
.
name
to
it
.
formattedAddress
)
{
_
,
oldProfile
->
when
(
oldProfile
?.
subscription
)
{
Profile
.
SubscriptionStatus
.
Active
->
oldProfile
// skip dup subscription
Profile
.
SubscriptionStatus
.
Obsolete
->
{
oldProfile
.
password
=
it
.
password
oldProfile
.
method
=
it
.
method
oldProfile
.
plugin
=
it
.
plugin
oldProfile
.
udpFallback
=
it
.
udpFallback
oldProfile
.
subscription
=
Profile
.
SubscriptionStatus
.
Active
oldProfile
}
else
->
ProfileManager
.
createProfile
(
it
.
apply
{
subscription
=
Profile
.
SubscriptionStatus
.
Active
})
}
}
}
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
()
Toast
.
makeText
(
this
,
e
.
readableMessage
,
Toast
.
LENGTH_LONG
).
show
()
}
profiles
?.
forEach
{
profile
->
if
(
toUpdate
.
contains
(
profile
.
id
))
ProfileManager
.
updateProfile
(
profile
)
}
}
override
fun
onDestroy
()
{
worker
?.
cancel
()
super
.
onDestroy
()
}
}
mobile/src/main/res/drawable/ic_action
_cloud_download.xml
→
core/src/main/res/drawable/ic_file
_cloud_download.xml
View file @
fa0669df
File moved
core/src/main/res/values/strings.xml
View file @
fa0669df
...
@@ -140,6 +140,9 @@
...
@@ -140,6 +140,9 @@
<string
name=
"add_subscription"
>
Add a subscription
</string>
<string
name=
"add_subscription"
>
Add a subscription
</string>
<string
name=
"edit_subscription"
>
Edit subscription
</string>
<string
name=
"edit_subscription"
>
Edit subscription
</string>
<string
name=
"update_subscription"
>
Refresh servers from subscription
</string>
<string
name=
"update_subscription"
>
Refresh servers from subscription
</string>
<string
name=
"service_subscription"
>
Subscription Service
</string>
<string
name=
"service_subscription_working"
>
Syncing subscriptions… (%d of %d)
</string>
<string
name=
"service_subscription_finishing"
>
Finishing up…
</string>
<!-- acl -->
<!-- acl -->
<string
name=
"custom_rules"
>
Custom rules
</string>
<string
name=
"custom_rules"
>
Custom rules
</string>
...
...
mobile/build.gradle
View file @
fa0669df
...
@@ -70,7 +70,6 @@ dependencies {
...
@@ -70,7 +70,6 @@ dependencies {
implementation
'com.twofortyfouram:android-plugin-api-for-locale:1.0.4'
implementation
'com.twofortyfouram:android-plugin-api-for-locale:1.0.4'
implementation
'me.zhanghai.android.fastscroll:library:1.1.0'
implementation
'me.zhanghai.android.fastscroll:library:1.1.0'
implementation
'xyz.belvi.mobilevision:barcodescanner:2.0.3'
implementation
'xyz.belvi.mobilevision:barcodescanner:2.0.3'
implementation
'me.zhanghai.android.materialprogressbar:library:1.6.1'
testImplementation
"junit:junit:$junitVersion"
testImplementation
"junit:junit:$junitVersion"
androidTestImplementation
"androidx.test:runner:$androidTestVersion"
androidTestImplementation
"androidx.test:runner:$androidTestVersion"
androidTestImplementation
"androidx.test.espresso:espresso-core:$androidEspressoVersion"
androidTestImplementation
"androidx.test.espresso:espresso-core:$androidEspressoVersion"
...
...
mobile/src/main/java/com/github/shadowsocks/subscription/SubscriptionFragment.kt
View file @
fa0669df
...
@@ -33,6 +33,7 @@ import android.widget.EditText
...
@@ -33,6 +33,7 @@ import android.widget.EditText
import
android.widget.TextView
import
android.widget.TextView
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.widget.Toolbar
import
androidx.appcompat.widget.Toolbar
import
androidx.lifecycle.observe
import
androidx.recyclerview.widget.DefaultItemAnimator
import
androidx.recyclerview.widget.DefaultItemAnimator
import
androidx.recyclerview.widget.ItemTouchHelper
import
androidx.recyclerview.widget.ItemTouchHelper
import
androidx.recyclerview.widget.LinearLayoutManager
import
androidx.recyclerview.widget.LinearLayoutManager
...
@@ -41,22 +42,14 @@ import com.github.shadowsocks.MainActivity
...
@@ -41,22 +42,14 @@ import com.github.shadowsocks.MainActivity
import
com.github.shadowsocks.R
import
com.github.shadowsocks.R
import
com.github.shadowsocks.ToolbarFragment
import
com.github.shadowsocks.ToolbarFragment
import
com.github.shadowsocks.bg.BaseService
import
com.github.shadowsocks.bg.BaseService
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.plugin.AlertDialogFragment
import
com.github.shadowsocks.plugin.AlertDialogFragment
import
com.github.shadowsocks.utils.asIterable
import
com.github.shadowsocks.utils.readableMessage
import
com.github.shadowsocks.utils.readableMessage
import
com.github.shadowsocks.utils.useCancellable
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.MainListListener
import
com.github.shadowsocks.widget.MainListListener
import
com.github.shadowsocks.widget.UndoSnackbarManager
import
com.github.shadowsocks.widget.UndoSnackbarManager
import
com.google.android.material.textfield.TextInputLayout
import
com.google.android.material.textfield.TextInputLayout
import
kotlinx.android.parcel.Parcelize
import
kotlinx.android.parcel.Parcelize
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.launch
import
me.zhanghai.android.fastscroll.FastScrollerBuilder
import
me.zhanghai.android.fastscroll.FastScrollerBuilder
import
me.zhanghai.android.materialprogressbar.MaterialProgressBar
import
java.net.HttpURLConnection
import
java.net.MalformedURLException
import
java.net.MalformedURLException
import
java.net.URL
import
java.net.URL
...
@@ -218,42 +211,8 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
...
@@ -218,42 +211,8 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
private
val
adapter
by
lazy
{
SubscriptionAdapter
()
}
private
val
adapter
by
lazy
{
SubscriptionAdapter
()
}
private
lateinit
var
list
:
RecyclerView
private
lateinit
var
list
:
RecyclerView
private
lateinit
var
progress
:
MaterialProgressBar
private
var
mode
:
ActionMode
?
=
null
private
var
mode
:
ActionMode
?
=
null
private
lateinit
var
undoManager
:
UndoSnackbarManager
<
Any
>
private
lateinit
var
undoManager
:
UndoSnackbarManager
<
URL
>
private
var
fetchJob
:
Job
?
=
null
private
fun
fetchServerFromSubscriptions
()
{
if
(
fetchJob
?.
isActive
!=
true
)
{
val
activity
=
activity
as
MainActivity
progress
.
visibility
=
View
.
VISIBLE
fetchJob
=
GlobalScope
.
launch
{
val
subscription
=
Subscription
.
instance
for
(
url
in
subscription
.
urls
.
asIterable
())
{
try
{
val
connection
=
url
.
openConnection
()
as
HttpURLConnection
connection
.
useCancellable
{
ProfileManager
.
createProfilesFromSubscription
(
sequenceOf
(
connection
.
inputStream
))
}
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
()
activity
.
snackbar
(
e
.
readableMessage
).
show
()
}
}
progress
.
post
{
progress
.
visibility
=
View
.
INVISIBLE
}
}
}
}
override
fun
onPause
()
{
fetchJob
?.
cancel
()
super
.
onPause
()
}
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?):
View
?
=
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?):
View
?
=
inflater
.
inflate
(
R
.
layout
.
layout_subscriptions
,
container
,
false
)
inflater
.
inflate
(
R
.
layout
.
layout_subscriptions
,
container
,
false
)
...
@@ -264,13 +223,15 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
...
@@ -264,13 +223,15 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
toolbar
.
setTitle
(
R
.
string
.
subscriptions
)
toolbar
.
setTitle
(
R
.
string
.
subscriptions
)
toolbar
.
inflateMenu
(
R
.
menu
.
subscription_menu
)
toolbar
.
inflateMenu
(
R
.
menu
.
subscription_menu
)
toolbar
.
setOnMenuItemClickListener
(
this
)
toolbar
.
setOnMenuItemClickListener
(
this
)
SubscriptionService
.
idle
.
observe
(
this
)
{
toolbar
.
menu
.
findItem
(
R
.
id
.
action_update_subscription
).
isEnabled
=
it
}
val
activity
=
activity
as
MainActivity
val
activity
=
activity
as
MainActivity
list
=
view
.
findViewById
(
R
.
id
.
list
)
list
=
view
.
findViewById
(
R
.
id
.
list
)
list
.
setOnApplyWindowInsetsListener
(
MainListListener
)
list
.
setOnApplyWindowInsetsListener
(
MainListListener
)
list
.
layoutManager
=
LinearLayoutManager
(
activity
,
RecyclerView
.
VERTICAL
,
false
)
list
.
layoutManager
=
LinearLayoutManager
(
activity
,
RecyclerView
.
VERTICAL
,
false
)
list
.
itemAnimator
=
DefaultItemAnimator
()
list
.
itemAnimator
=
DefaultItemAnimator
()
list
.
adapter
=
adapter
list
.
adapter
=
adapter
progress
=
view
.
findViewById
(
R
.
id
.
indeterminate_horizontal_progress
)
FastScrollerBuilder
(
list
).
useMd2Style
().
build
()
FastScrollerBuilder
(
list
).
useMd2Style
().
build
()
undoManager
=
UndoSnackbarManager
(
activity
,
adapter
::
undo
)
undoManager
=
UndoSnackbarManager
(
activity
,
adapter
::
undo
)
ItemTouchHelper
(
object
:
ItemTouchHelper
.
SimpleCallback
(
0
,
ItemTouchHelper
.
START
or
ItemTouchHelper
.
END
)
{
ItemTouchHelper
(
object
:
ItemTouchHelper
.
SimpleCallback
(
0
,
ItemTouchHelper
.
START
or
ItemTouchHelper
.
END
)
{
...
@@ -299,7 +260,8 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
...
@@ -299,7 +260,8 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
true
true
}
}
R
.
id
.
action_update_subscription
->
{
R
.
id
.
action_update_subscription
->
{
fetchServerFromSubscriptions
()
val
context
=
requireContext
()
context
.
startService
(
Intent
(
context
,
SubscriptionService
::
class
.
java
))
true
true
}
}
else
->
false
else
->
false
...
...
mobile/src/main/res/drawable/ic_cloud_queue.xml
→
mobile/src/main/res/drawable/ic_
file_
cloud_queue.xml
View file @
fa0669df
File moved
mobile/src/main/res/layout/layout_profile.xml
View file @
fa0669df
...
@@ -43,7 +43,7 @@
...
@@ -43,7 +43,7 @@
android:focusable=
"true"
android:focusable=
"true"
android:padding=
"12dp"
android:padding=
"12dp"
android:visibility=
"gone"
android:visibility=
"gone"
app:srcCompat=
"@drawable/ic_cloud_queue"
/>
app:srcCompat=
"@drawable/ic_
file_
cloud_queue"
/>
<androidx.appcompat.widget.AppCompatImageView
<androidx.appcompat.widget.AppCompatImageView
android:id=
"@+id/edit"
android:id=
"@+id/edit"
...
...
mobile/src/main/res/layout/layout_subscriptions.xml
View file @
fa0669df
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
<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"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_height=
"match_parent"
...
@@ -9,18 +8,6 @@
...
@@ -9,18 +8,6 @@
<include
layout=
"@layout/toolbar_light_dark"
/>
<include
layout=
"@layout/toolbar_light_dark"
/>
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id=
"@+id/indeterminate_horizontal_progress"
style=
"@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_gravity=
"bottom"
android:indeterminate=
"true"
android:visibility=
"invisible"
app:mpb_progressStyle=
"horizontal"
app:mpb_showProgressBackground=
"false"
app:mpb_useIntrinsicPadding=
"false"
/>
<FrameLayout
<FrameLayout
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:layout_height=
"0dp"
...
...
mobile/src/main/res/menu/navigation_main.xml
View file @
fa0669df
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
android:icon=
"@drawable/ic_action_description"
/>
android:icon=
"@drawable/ic_action_description"
/>
<item
android:id=
"@+id/subscriptions"
<item
android:id=
"@+id/subscriptions"
android:title=
"@string/subscriptions"
android:title=
"@string/subscriptions"
android:icon=
"@drawable/ic_
action
_cloud_download"
/>
android:icon=
"@drawable/ic_
file
_cloud_download"
/>
<item
android:id=
"@+id/customRules"
<item
android:id=
"@+id/customRules"
android:title=
"@string/custom_rules"
android:title=
"@string/custom_rules"
android:icon=
"@drawable/ic_action_assignment"
/>
android:icon=
"@drawable/ic_action_assignment"
/>
...
...
mobile/src/main/res/menu/subscription_menu.xml
View file @
fa0669df
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
app:showAsAction=
"always"
/>
app:showAsAction=
"always"
/>
<item
android:title=
"@string/update_subscription"
<item
android:title=
"@string/update_subscription"
android:id=
"@+id/action_update_subscription"
android:id=
"@+id/action_update_subscription"
android:icon=
"@drawable/ic_
action
_cloud_download"
android:icon=
"@drawable/ic_
file
_cloud_download"
android:alphabeticShortcut=
"r"
android:alphabeticShortcut=
"r"
app:showAsAction=
"ifRoom"
/>
app:showAsAction=
"ifRoom"
/>
</menu>
</menu>
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