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
eeef4b55
Commit
eeef4b55
authored
Jun 27, 2020
by
Mygod
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Partially migrate to ActivityResultContracts
AlertDialogFragment will be migrated after the API goes stable.
parent
01dbcec7
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
185 additions
and
222 deletions
+185
-222
core/src/main/java/com/github/shadowsocks/VpnRequestActivity.kt
...rc/main/java/com/github/shadowsocks/VpnRequestActivity.kt
+5
-20
core/src/main/java/com/github/shadowsocks/utils/ActivityResultContracts.kt
...a/com/github/shadowsocks/utils/ActivityResultContracts.kt
+66
-0
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
+0
-2
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
+4
-23
mobile/src/main/java/com/github/shadowsocks/ProfileConfigActivity.kt
...main/java/com/github/shadowsocks/ProfileConfigActivity.kt
+6
-8
mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
...main/java/com/github/shadowsocks/ProfileConfigFragment.kt
+17
-12
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
.../src/main/java/com/github/shadowsocks/ProfilesFragment.kt
+31
-55
mobile/src/main/java/com/github/shadowsocks/ScannerActivity.kt
...e/src/main/java/com/github/shadowsocks/ScannerActivity.kt
+19
-31
mobile/src/main/java/com/github/shadowsocks/ToolbarFragment.kt
...e/src/main/java/com/github/shadowsocks/ToolbarFragment.kt
+0
-3
mobile/src/main/java/com/github/shadowsocks/preference/PluginConfigurationDialogFragment.kt
...adowsocks/preference/PluginConfigurationDialogFragment.kt
+2
-3
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
.../java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
+35
-65
No files found.
core/src/main/java/com/github/shadowsocks/VpnRequestActivity.kt
View file @
eeef4b55
...
@@ -24,7 +24,6 @@ import android.app.KeyguardManager
...
@@ -24,7 +24,6 @@ import android.app.KeyguardManager
import
android.content.BroadcastReceiver
import
android.content.BroadcastReceiver
import
android.content.Intent
import
android.content.Intent
import
android.content.IntentFilter
import
android.content.IntentFilter
import
android.net.VpnService
import
android.os.Bundle
import
android.os.Bundle
import
android.widget.Toast
import
android.widget.Toast
import
androidx.appcompat.app.AppCompatActivity
import
androidx.appcompat.app.AppCompatActivity
...
@@ -32,14 +31,10 @@ import androidx.core.content.getSystemService
...
@@ -32,14 +31,10 @@ import androidx.core.content.getSystemService
import
com.github.shadowsocks.core.R
import
com.github.shadowsocks.core.R
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.StartService
import
com.github.shadowsocks.utils.broadcastReceiver
import
com.github.shadowsocks.utils.broadcastReceiver
import
timber.log.Timber
class
VpnRequestActivity
:
AppCompatActivity
()
{
class
VpnRequestActivity
:
AppCompatActivity
()
{
companion
object
{
private
const
val
REQUEST_CONNECT
=
1
}
private
var
receiver
:
BroadcastReceiver
?
=
null
private
var
receiver
:
BroadcastReceiver
?
=
null
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
...
@@ -49,23 +44,13 @@ class VpnRequestActivity : AppCompatActivity() {
...
@@ -49,23 +44,13 @@ class VpnRequestActivity : AppCompatActivity() {
return
return
}
}
if
(
getSystemService
<
KeyguardManager
>()
!!
.
isKeyguardLocked
)
{
if
(
getSystemService
<
KeyguardManager
>()
!!
.
isKeyguardLocked
)
{
receiver
=
broadcastReceiver
{
_
,
_
->
request
(
)
}
receiver
=
broadcastReceiver
{
_
,
_
->
connect
.
launch
(
null
)
}
registerReceiver
(
receiver
,
IntentFilter
(
Intent
.
ACTION_USER_PRESENT
))
registerReceiver
(
receiver
,
IntentFilter
(
Intent
.
ACTION_USER_PRESENT
))
}
else
request
(
)
}
else
connect
.
launch
(
null
)
}
}
private
fun
request
()
{
private
val
connect
=
registerForActivityResult
(
StartService
())
{
val
intent
=
VpnService
.
prepare
(
this
)
if
(
it
)
Toast
.
makeText
(
this
,
R
.
string
.
vpn_permission_denied
,
Toast
.
LENGTH_LONG
).
show
()
if
(
intent
==
null
)
onActivityResult
(
REQUEST_CONNECT
,
RESULT_OK
,
null
)
else
startActivityForResult
(
intent
,
REQUEST_CONNECT
)
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
if
(
requestCode
!=
REQUEST_CONNECT
)
return
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
if
(
resultCode
==
RESULT_OK
)
Core
.
startService
()
else
{
Toast
.
makeText
(
this
,
R
.
string
.
vpn_permission_denied
,
Toast
.
LENGTH_LONG
).
show
()
Timber
.
e
(
"Failed to start VpnService from onActivityResult: $data"
)
}
finish
()
finish
()
}
}
...
...
core/src/main/java/com/github/shadowsocks/utils/ActivityResultContracts.kt
0 → 100644
View file @
eeef4b55
/*******************************************************************************
* *
* 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.utils
import
android.app.Activity
import
android.content.Context
import
android.content.Intent
import
android.net.VpnService
import
androidx.activity.result.contract.ActivityResultContract
import
androidx.activity.result.contract.ActivityResultContracts
import
com.github.shadowsocks.Core
import
com.github.shadowsocks.preference.DataStore
import
timber.log.Timber
private
val
jsonMimeTypes
=
arrayOf
(
"application/*"
,
"text/*"
)
class
OpenJson
:
ActivityResultContracts
.
GetMultipleContents
()
{
override
fun
createIntent
(
context
:
Context
,
input
:
String
)
=
super
.
createIntent
(
context
,
jsonMimeTypes
.
first
()).
apply
{
putExtra
(
Intent
.
EXTRA_MIME_TYPES
,
jsonMimeTypes
)
}
}
class
SaveJson
:
ActivityResultContracts
.
CreateDocument
()
{
override
fun
createIntent
(
context
:
Context
,
input
:
String
)
=
super
.
createIntent
(
context
,
"profiles.json"
).
apply
{
type
=
"application/json"
}
}
class
StartService
:
ActivityResultContract
<
Void
?
,
Boolean
>()
{
private
var
cachedIntent
:
Intent
?
=
null
override
fun
getSynchronousResult
(
context
:
Context
,
input
:
Void
?):
SynchronousResult
<
Boolean
>?
{
if
(
DataStore
.
serviceMode
==
Key
.
modeVpn
)
VpnService
.
prepare
(
context
)
?.
let
{
intent
->
cachedIntent
=
intent
return
null
}
Core
.
startService
()
return
SynchronousResult
(
false
)
}
override
fun
createIntent
(
context
:
Context
,
input
:
Void
?)
=
cachedIntent
!!
.
also
{
cachedIntent
=
null
}
override
fun
parseResult
(
resultCode
:
Int
,
intent
:
Intent
?)
=
if
(
resultCode
==
Activity
.
RESULT_OK
)
{
Core
.
startService
()
false
}
else
{
Timber
.
e
(
"Failed to start VpnService: $intent"
)
true
}
}
core/src/main/java/com/github/shadowsocks/utils/Utils.kt
View file @
eeef4b55
...
@@ -133,6 +133,4 @@ fun Resources.Theme.resolveResourceId(@AttrRes resId: Int): Int {
...
@@ -133,6 +133,4 @@ fun Resources.Theme.resolveResourceId(@AttrRes resId: Int): Int {
return
typedValue
.
resourceId
return
typedValue
.
resourceId
}
}
val
Intent
.
datas
get
()
=
listOfNotNull
(
data
)
+
(
clipData
?.
asIterable
()
?.
mapNotNull
{
it
.
uri
}
?:
emptyList
())
fun
Preference
.
remove
()
=
parent
!!
.
removePreference
(
this
)
fun
Preference
.
remove
()
=
parent
!!
.
removePreference
(
this
)
mobile/src/main/java/com/github/shadowsocks/MainActivity.kt
View file @
eeef4b55
...
@@ -20,11 +20,8 @@
...
@@ -20,11 +20,8 @@
package
com.github.shadowsocks
package
com.github.shadowsocks
import
android.app.Activity
import
android.app.backup.BackupManager
import
android.app.backup.BackupManager
import
android.content.ActivityNotFoundException
import
android.content.ActivityNotFoundException
import
android.content.Intent
import
android.net.VpnService
import
android.os.Bundle
import
android.os.Bundle
import
android.os.RemoteException
import
android.os.RemoteException
import
android.view.*
import
android.view.*
...
@@ -48,6 +45,7 @@ import com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
...
@@ -48,6 +45,7 @@ import com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
import
com.github.shadowsocks.subscription.SubscriptionFragment
import
com.github.shadowsocks.subscription.SubscriptionFragment
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.SingleInstanceActivity
import
com.github.shadowsocks.utils.SingleInstanceActivity
import
com.github.shadowsocks.utils.StartService
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.ServiceButton
import
com.github.shadowsocks.widget.ServiceButton
import
com.github.shadowsocks.widget.StatsBar
import
com.github.shadowsocks.widget.StatsBar
...
@@ -61,8 +59,6 @@ import timber.log.Timber
...
@@ -61,8 +59,6 @@ import timber.log.Timber
class
MainActivity
:
AppCompatActivity
(),
ShadowsocksConnection
.
Callback
,
OnPreferenceDataStoreChangeListener
,
class
MainActivity
:
AppCompatActivity
(),
ShadowsocksConnection
.
Callback
,
OnPreferenceDataStoreChangeListener
,
NavigationView
.
OnNavigationItemSelectedListener
{
NavigationView
.
OnNavigationItemSelectedListener
{
companion
object
{
companion
object
{
private
const
val
REQUEST_CONNECT
=
1
var
stateListener
:
((
BaseService
.
State
)
->
Unit
)?
=
null
var
stateListener
:
((
BaseService
.
State
)
->
Unit
)?
=
null
}
}
...
@@ -119,15 +115,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
...
@@ -119,15 +115,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
stateListener
?.
invoke
(
state
)
stateListener
?.
invoke
(
state
)
}
}
private
fun
toggle
()
=
when
{
private
fun
toggle
()
=
if
(
state
.
canStop
)
Core
.
stopService
()
else
connect
.
launch
(
null
)
state
.
canStop
->
Core
.
stopService
()
DataStore
.
serviceMode
==
Key
.
modeVpn
->
{
val
intent
=
VpnService
.
prepare
(
this
)
if
(
intent
!=
null
)
startActivityForResult
(
intent
,
REQUEST_CONNECT
)
else
onActivityResult
(
REQUEST_CONNECT
,
Activity
.
RESULT_OK
,
null
)
}
else
->
Core
.
startService
()
}
private
val
connection
=
ShadowsocksConnection
(
true
)
private
val
connection
=
ShadowsocksConnection
(
true
)
override
fun
onServiceConnected
(
service
:
IShadowsocksService
)
=
changeState
(
try
{
override
fun
onServiceConnected
(
service
:
IShadowsocksService
)
=
changeState
(
try
{
...
@@ -141,15 +129,8 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
...
@@ -141,15 +129,8 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
connection
.
connect
(
this
,
this
)
connection
.
connect
(
this
,
this
)
}
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
private
val
connect
=
registerForActivityResult
(
StartService
())
{
when
{
if
(
it
)
snackbar
().
setText
(
R
.
string
.
vpn_permission_denied
).
show
()
requestCode
!=
REQUEST_CONNECT
->
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
resultCode
==
Activity
.
RESULT_OK
->
Core
.
startService
()
else
->
{
snackbar
().
setText
(
R
.
string
.
vpn_permission_denied
).
show
()
Timber
.
e
(
"Failed to start VpnService from onActivityResult: $data"
)
}
}
}
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
...
...
mobile/src/main/java/com/github/shadowsocks/ProfileConfigActivity.kt
View file @
eeef4b55
...
@@ -22,10 +22,12 @@ package com.github.shadowsocks
...
@@ -22,10 +22,12 @@ package com.github.shadowsocks
import
android.app.Activity
import
android.app.Activity
import
android.content.DialogInterface
import
android.content.DialogInterface
import
android.content.Intent
import
android.os.Bundle
import
android.os.Bundle
import
android.view.Menu
import
android.view.Menu
import
android.view.MenuItem
import
android.view.MenuItem
import
androidx.activity.result.component1
import
androidx.activity.result.component2
import
androidx.activity.result.contract.ActivityResultContracts
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.app.AppCompatActivity
import
androidx.appcompat.app.AppCompatActivity
import
com.github.shadowsocks.plugin.AlertDialogFragment
import
com.github.shadowsocks.plugin.AlertDialogFragment
...
@@ -36,10 +38,6 @@ import com.github.shadowsocks.utils.SingleInstanceActivity
...
@@ -36,10 +38,6 @@ import com.github.shadowsocks.utils.SingleInstanceActivity
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.ListHolderListener
class
ProfileConfigActivity
:
AppCompatActivity
()
{
class
ProfileConfigActivity
:
AppCompatActivity
()
{
companion
object
{
const
val
REQUEST_CODE_PLUGIN_HELP
=
1
}
class
UnsavedChangesDialogFragment
:
AlertDialogFragment
<
Empty
,
Empty
>()
{
class
UnsavedChangesDialogFragment
:
AlertDialogFragment
<
Empty
,
Empty
>()
{
override
fun
AlertDialog
.
Builder
.
prepare
(
listener
:
DialogInterface
.
OnClickListener
)
{
override
fun
AlertDialog
.
Builder
.
prepare
(
listener
:
DialogInterface
.
OnClickListener
)
{
setTitle
(
R
.
string
.
unsaved_changes_prompt
)
setTitle
(
R
.
string
.
unsaved_changes_prompt
)
...
@@ -79,9 +77,9 @@ class ProfileConfigActivity : AppCompatActivity() {
...
@@ -79,9 +77,9 @@ class ProfileConfigActivity : AppCompatActivity() {
else
super
.
onBackPressed
()
else
super
.
onBackPressed
()
}
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?
)
{
val
pluginHelp
=
registerForActivityResult
(
ActivityResultContracts
.
StartActivityForResult
()
)
{
if
(
requestCode
!=
REQUEST_CODE_PLUGIN_HELP
)
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
(
resultCode
,
data
)
->
else
if
(
resultCode
==
Activity
.
RESULT_OK
)
AlertDialog
.
Builder
(
this
)
if
(
resultCode
==
Activity
.
RESULT_OK
)
AlertDialog
.
Builder
(
this
)
.
setTitle
(
"?"
)
.
setTitle
(
"?"
)
.
setMessage
(
data
?.
getCharSequenceExtra
(
PluginContract
.
EXTRA_HELP_MESSAGE
))
.
setMessage
(
data
?.
getCharSequenceExtra
(
PluginContract
.
EXTRA_HELP_MESSAGE
))
.
show
()
.
show
()
...
...
mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
View file @
eeef4b55
...
@@ -30,6 +30,9 @@ import android.os.Bundle
...
@@ -30,6 +30,9 @@ import android.os.Bundle
import
android.os.Parcelable
import
android.os.Parcelable
import
android.view.MenuItem
import
android.view.MenuItem
import
android.view.View
import
android.view.View
import
androidx.activity.result.component1
import
androidx.activity.result.component2
import
androidx.activity.result.contract.ActivityResultContracts
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.app.AlertDialog
import
androidx.lifecycle.lifecycleScope
import
androidx.lifecycle.lifecycleScope
import
androidx.lifecycle.whenCreated
import
androidx.lifecycle.whenCreated
...
@@ -50,7 +53,6 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
...
@@ -50,7 +53,6 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
companion
object
PasswordSummaryProvider
:
Preference
.
SummaryProvider
<
EditTextPreference
>
{
companion
object
PasswordSummaryProvider
:
Preference
.
SummaryProvider
<
EditTextPreference
>
{
override
fun
provideSummary
(
preference
:
EditTextPreference
?)
=
"\u2022"
.
repeat
(
preference
?.
text
?.
length
?:
0
)
override
fun
provideSummary
(
preference
:
EditTextPreference
?)
=
"\u2022"
.
repeat
(
preference
?.
text
?.
length
?:
0
)
private
const
val
REQUEST_CODE_PLUGIN_CONFIGURE
=
1
const
val
REQUEST_UNSAVED_CHANGES
=
2
const
val
REQUEST_UNSAVED_CHANGES
=
2
private
const
val
REQUEST_PICK_PLUGIN
=
3
private
const
val
REQUEST_PICK_PLUGIN
=
3
}
}
...
@@ -192,15 +194,26 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
...
@@ -192,15 +194,26 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
Key
.
pluginConfigure
->
{
Key
.
pluginConfigure
->
{
val
intent
=
PluginManager
.
buildIntent
(
plugin
.
selectedEntry
!!
.
id
,
PluginContract
.
ACTION_CONFIGURE
)
val
intent
=
PluginManager
.
buildIntent
(
plugin
.
selectedEntry
!!
.
id
,
PluginContract
.
ACTION_CONFIGURE
)
if
(
intent
.
resolveActivity
(
requireContext
().
packageManager
)
==
null
)
showPluginEditor
()
else
{
if
(
intent
.
resolveActivity
(
requireContext
().
packageManager
)
==
null
)
showPluginEditor
()
else
{
startActivityForResult
(
intent
configurePlugin
.
launch
(
intent
.
putExtra
(
PluginContract
.
EXTRA_OPTIONS
,
pluginConfiguration
.
getOptions
().
toString
()),
.
putExtra
(
PluginContract
.
EXTRA_OPTIONS
,
pluginConfiguration
.
getOptions
().
toString
()))
REQUEST_CODE_PLUGIN_CONFIGURE
)
}
}
}
}
else
->
super
.
onDisplayPreferenceDialog
(
preference
)
else
->
super
.
onDisplayPreferenceDialog
(
preference
)
}
}
}
}
private
val
configurePlugin
=
registerForActivityResult
(
ActivityResultContracts
.
StartActivityForResult
())
{
(
resultCode
,
data
)
->
when
(
resultCode
)
{
Activity
.
RESULT_OK
->
{
val
options
=
data
?.
getStringExtra
(
PluginContract
.
EXTRA_OPTIONS
)
pluginConfigure
.
text
=
options
onPreferenceChange
(
null
,
options
)
}
PluginContract
.
RESULT_FALLBACK
->
showPluginEditor
()
}
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
when
(
requestCode
)
{
when
(
requestCode
)
{
REQUEST_PICK_PLUGIN
->
if
(
resultCode
==
Activity
.
RESULT_OK
)
{
REQUEST_PICK_PLUGIN
->
if
(
resultCode
==
Activity
.
RESULT_OK
)
{
...
@@ -219,14 +232,6 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
...
@@ -219,14 +232,6 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
Snackbar
.
make
(
requireView
(),
R
.
string
.
plugin_untrusted
,
Snackbar
.
LENGTH_LONG
).
show
()
Snackbar
.
make
(
requireView
(),
R
.
string
.
plugin_untrusted
,
Snackbar
.
LENGTH_LONG
).
show
()
}
}
}
}
REQUEST_CODE_PLUGIN_CONFIGURE
->
when
(
resultCode
)
{
Activity
.
RESULT_OK
->
{
val
options
=
data
?.
getStringExtra
(
PluginContract
.
EXTRA_OPTIONS
)
pluginConfigure
.
text
=
options
onPreferenceChange
(
null
,
options
)
}
PluginContract
.
RESULT_FALLBACK
->
showPluginEditor
()
}
REQUEST_UNSAVED_CHANGES
->
when
(
resultCode
)
{
REQUEST_UNSAVED_CHANGES
->
when
(
resultCode
)
{
DialogInterface
.
BUTTON_POSITIVE
->
saveAndExit
()
DialogInterface
.
BUTTON_POSITIVE
->
saveAndExit
()
DialogInterface
.
BUTTON_NEGATIVE
->
requireActivity
().
finish
()
DialogInterface
.
BUTTON_NEGATIVE
->
requireActivity
().
finish
()
...
...
mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
View file @
eeef4b55
...
@@ -21,11 +21,11 @@
...
@@ -21,11 +21,11 @@
package
com.github.shadowsocks
package
com.github.shadowsocks
import
android.annotation.SuppressLint
import
android.annotation.SuppressLint
import
android.app.Activity
import
android.content.ActivityNotFoundException
import
android.content.ActivityNotFoundException
import
android.content.Intent
import
android.content.Intent
import
android.graphics.Bitmap
import
android.graphics.Bitmap
import
android.graphics.Color
import
android.graphics.Color
import
android.net.Uri
import
android.os.Bundle
import
android.os.Bundle
import
android.text.format.Formatter
import
android.text.format.Formatter
import
android.util.LongSparseArray
import
android.util.LongSparseArray
...
@@ -34,6 +34,7 @@ import android.view.MenuItem
...
@@ -34,6 +34,7 @@ import android.view.MenuItem
import
android.view.View
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewGroup
import
android.widget.*
import
android.widget.*
import
androidx.activity.result.ActivityResultLauncher
import
androidx.appcompat.widget.PopupMenu
import
androidx.appcompat.widget.PopupMenu
import
androidx.appcompat.widget.Toolbar
import
androidx.appcompat.widget.Toolbar
import
androidx.appcompat.widget.TooltipCompat
import
androidx.appcompat.widget.TooltipCompat
...
@@ -49,7 +50,8 @@ import com.github.shadowsocks.plugin.PluginConfiguration
...
@@ -49,7 +50,8 @@ import com.github.shadowsocks.plugin.PluginConfiguration
import
com.github.shadowsocks.plugin.showAllowingStateLoss
import
com.github.shadowsocks.plugin.showAllowingStateLoss
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.utils.Action
import
com.github.shadowsocks.utils.Action
import
com.github.shadowsocks.utils.datas
import
com.github.shadowsocks.utils.OpenJson
import
com.github.shadowsocks.utils.SaveJson
import
com.github.shadowsocks.utils.readableMessage
import
com.github.shadowsocks.utils.readableMessage
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.MainListListener
import
com.github.shadowsocks.widget.MainListListener
...
@@ -75,9 +77,6 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
...
@@ -75,9 +77,6 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
var
instance
:
ProfilesFragment
?
=
null
var
instance
:
ProfilesFragment
?
=
null
private
const
val
KEY_URL
=
"com.github.shadowsocks.QRCodeDialog.KEY_URL"
private
const
val
KEY_URL
=
"com.github.shadowsocks.QRCodeDialog.KEY_URL"
private
const
val
REQUEST_IMPORT_PROFILES
=
1
private
const
val
REQUEST_REPLACE_PROFILES
=
3
private
const
val
REQUEST_EXPORT_PROFILES
=
2
private
val
iso88591
=
StandardCharsets
.
ISO_8859_1
.
newEncoder
()
private
val
iso88591
=
StandardCharsets
.
ISO_8859_1
.
newEncoder
()
}
}
...
@@ -516,19 +515,11 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
...
@@ -516,19 +515,11 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
true
true
}
}
R
.
id
.
action_import_file
->
{
R
.
id
.
action_import_file
->
{
startFilesForResult
(
Intent
(
Intent
.
ACTION_GET_CONTENT
).
apply
{
startFilesForResult
(
importProfiles
)
type
=
"application/*"
putExtra
(
Intent
.
EXTRA_ALLOW_MULTIPLE
,
true
)
putExtra
(
Intent
.
EXTRA_MIME_TYPES
,
arrayOf
(
"application/*"
,
"text/*"
))
},
REQUEST_IMPORT_PROFILES
)
true
true
}
}
R
.
id
.
action_replace_file
->
{
R
.
id
.
action_replace_file
->
{
startFilesForResult
(
Intent
(
Intent
.
ACTION_GET_CONTENT
).
apply
{
startFilesForResult
(
replaceProfiles
)
type
=
"application/*"
putExtra
(
Intent
.
EXTRA_ALLOW_MULTIPLE
,
true
)
putExtra
(
Intent
.
EXTRA_MIME_TYPES
,
arrayOf
(
"application/*"
,
"text/*"
))
},
REQUEST_REPLACE_PROFILES
)
true
true
}
}
R
.
id
.
action_manual_settings
->
{
R
.
id
.
action_manual_settings
->
{
...
@@ -544,61 +535,46 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
...
@@ -544,61 +535,46 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
true
true
}
}
R
.
id
.
action_export_file
->
{
R
.
id
.
action_export_file
->
{
startFilesForResult
(
Intent
(
Intent
.
ACTION_CREATE_DOCUMENT
).
apply
{
startFilesForResult
(
exportProfiles
)
type
=
"application/json"
putExtra
(
Intent
.
EXTRA_TITLE
,
"profiles.json"
)
// optional title that can be edited
},
REQUEST_EXPORT_PROFILES
)
true
true
}
}
else
->
false
else
->
false
}
}
}
}
private
fun
startFilesForResult
(
intent
:
Intent
,
requestCode
:
Int
)
{
private
fun
startFilesForResult
(
launcher
:
ActivityResultLauncher
<
String
>
)
{
try
{
try
{
startActivityForResult
(
intent
.
addCategory
(
Intent
.
CATEGORY_OPENABLE
),
requestCode
)
return
launcher
.
launch
(
""
)
return
}
catch
(
_
:
ActivityNotFoundException
)
{
}
catch
(
_
:
ActivityNotFoundException
)
{
}
catch
(
_
:
SecurityException
)
{
}
catch
(
_
:
SecurityException
)
{
}
}
(
activity
as
MainActivity
).
snackbar
(
getString
(
R
.
string
.
file_manager_missing
)).
show
()
(
activity
as
MainActivity
).
snackbar
(
getString
(
R
.
string
.
file_manager_missing
)).
show
()
}
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
private
fun
importOrReplaceProfiles
(
dataUris
:
List
<
Uri
>,
replace
:
Boolean
=
false
)
{
if
(
resultCode
!=
Activity
.
RESULT_OK
)
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
if
(
dataUris
.
isEmpty
())
return
else
when
(
requestCode
)
{
val
activity
=
activity
as
MainActivity
REQUEST_IMPORT_PROFILES
->
{
try
{
val
activity
=
activity
as
MainActivity
ProfileManager
.
createProfilesFromJson
(
dataUris
.
asSequence
().
map
{
try
{
activity
.
contentResolver
.
openInputStream
(
it
)
ProfileManager
.
createProfilesFromJson
(
data
!!
.
datas
.
asSequence
().
map
{
}.
filterNotNull
(),
replace
)
activity
.
contentResolver
.
openInputStream
(
it
)
}
catch
(
e
:
Exception
)
{
}.
filterNotNull
())
activity
.
snackbar
(
e
.
readableMessage
).
show
()
}
catch
(
e
:
Exception
)
{
}
activity
.
snackbar
(
e
.
readableMessage
).
show
()
}
}
private
val
importProfiles
=
registerForActivityResult
(
OpenJson
())
{
importOrReplaceProfiles
(
it
)
}
}
private
val
replaceProfiles
=
registerForActivityResult
(
OpenJson
())
{
importOrReplaceProfiles
(
it
,
true
)
}
REQUEST_REPLACE_PROFILES
->
{
private
val
exportProfiles
=
registerForActivityResult
(
SaveJson
())
{
data
->
val
activity
=
activity
as
MainActivity
if
(
data
!=
null
)
ProfileManager
.
serializeToJson
()
?.
let
{
profiles
->
try
{
val
activity
=
activity
as
MainActivity
ProfileManager
.
createProfilesFromJson
(
data
!!
.
datas
.
asSequence
().
map
{
try
{
activity
.
contentResolver
.
openInputStream
(
it
)
activity
.
contentResolver
.
openOutputStream
(
data
)
!!
.
bufferedWriter
().
use
{
}.
filterNotNull
(),
true
)
it
.
write
(
profiles
.
toString
(
2
))
}
catch
(
e
:
Exception
)
{
activity
.
snackbar
(
e
.
readableMessage
).
show
()
}
}
REQUEST_EXPORT_PROFILES
->
{
val
profiles
=
ProfileManager
.
serializeToJson
()
if
(
profiles
!=
null
)
try
{
requireContext
().
contentResolver
.
openOutputStream
(
data
?.
data
!!
)
!!
.
bufferedWriter
().
use
{
it
.
write
(
profiles
.
toString
(
2
))
}
}
catch
(
e
:
Exception
)
{
Timber
.
w
(
e
)
(
activity
as
MainActivity
).
snackbar
(
e
.
readableMessage
).
show
()
}
}
}
catch
(
e
:
Exception
)
{
Timber
.
w
(
e
)
activity
.
snackbar
(
e
.
readableMessage
).
show
()
}
}
else
->
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
}
}
}
}
...
...
mobile/src/main/java/com/github/shadowsocks/ScannerActivity.kt
View file @
eeef4b55
...
@@ -21,11 +21,11 @@
...
@@ -21,11 +21,11 @@
package
com.github.shadowsocks
package
com.github.shadowsocks
import
android.Manifest
import
android.Manifest
import
android.app.Activity
import
android.content.Intent
import
android.content.Intent
import
android.content.pm.ShortcutManager
import
android.content.pm.ShortcutManager
import
android.hardware.camera2.CameraAccessException
import
android.hardware.camera2.CameraAccessException
import
android.hardware.camera2.CameraManager
import
android.hardware.camera2.CameraManager
import
android.net.Uri
import
android.os.Build
import
android.os.Build
import
android.os.Bundle
import
android.os.Bundle
import
android.view.Menu
import
android.view.Menu
...
@@ -42,7 +42,6 @@ import androidx.work.await
...
@@ -42,7 +42,6 @@ import androidx.work.await
import
com.github.shadowsocks.Core.app
import
com.github.shadowsocks.Core.app
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.database.ProfileManager
import
com.github.shadowsocks.utils.datas
import
com.github.shadowsocks.utils.forEachTry
import
com.github.shadowsocks.utils.forEachTry
import
com.github.shadowsocks.utils.readableMessage
import
com.github.shadowsocks.utils.readableMessage
import
com.github.shadowsocks.widget.ListHolderListener
import
com.github.shadowsocks.widget.ListHolderListener
...
@@ -55,11 +54,6 @@ import kotlinx.coroutines.tasks.await
...
@@ -55,11 +54,6 @@ import kotlinx.coroutines.tasks.await
import
timber.log.Timber
import
timber.log.Timber
class
ScannerActivity
:
AppCompatActivity
(),
ImageAnalysis
.
Analyzer
{
class
ScannerActivity
:
AppCompatActivity
(),
ImageAnalysis
.
Analyzer
{
companion
object
{
private
const
val
REQUEST_IMPORT
=
2
private
const
val
REQUEST_IMPORT_OR_FINISH
=
3
}
private
val
scanner
=
BarcodeScanning
.
getClient
(
BarcodeScannerOptions
.
Builder
().
apply
{
private
val
scanner
=
BarcodeScanning
.
getClient
(
BarcodeScannerOptions
.
Builder
().
apply
{
setBarcodeFormats
(
Barcode
.
FORMAT_QR_CODE
)
setBarcodeFormats
(
Barcode
.
FORMAT_QR_CODE
)
}.
build
())
}.
build
())
...
@@ -152,31 +146,25 @@ class ScannerActivity : AppCompatActivity(), ImageAnalysis.Analyzer {
...
@@ -152,31 +146,25 @@ class ScannerActivity : AppCompatActivity(), ImageAnalysis.Analyzer {
return
super
.
onSupportNavigateUp
()
return
super
.
onSupportNavigateUp
()
}
}
private
fun
startImport
(
manual
:
Boolean
=
false
)
=
startActivityForResult
(
Intent
(
Intent
.
ACTION_GET_CONTENT
).
apply
{
private
fun
startImport
(
manual
:
Boolean
=
false
)
=
(
if
(
manual
)
import
else
importFinish
).
launch
(
"image/*"
)
addCategory
(
Intent
.
CATEGORY_OPENABLE
)
private
val
import
=
registerForActivityResult
(
ActivityResultContracts
.
GetMultipleContents
())
{
importOrFinish
(
it
)
}
type
=
"image/*"
private
val
importFinish
=
registerForActivityResult
(
ActivityResultContracts
.
GetMultipleContents
())
{
putExtra
(
Intent
.
EXTRA_ALLOW_MULTIPLE
,
true
)
importOrFinish
(
it
,
true
)
},
if
(
manual
)
REQUEST_IMPORT
else
REQUEST_IMPORT_OR_FINISH
)
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
private
fun
importOrFinish
(
dataUris
:
List
<
Uri
>,
finish
:
Boolean
=
false
)
{
when
(
requestCode
)
{
if
(
dataUris
.
isNotEmpty
())
GlobalScope
.
launch
(
Dispatchers
.
Main
.
immediate
)
{
REQUEST_IMPORT
,
REQUEST_IMPORT_OR_FINISH
->
when
{
onSupportNavigateUp
()
resultCode
==
Activity
.
RESULT_OK
->
GlobalScope
.
launch
(
Dispatchers
.
Main
.
immediate
)
{
val
feature
=
Core
.
currentProfile
?.
main
onSupportNavigateUp
()
try
{
val
feature
=
Core
.
currentProfile
?.
main
var
success
=
false
try
{
dataUris
.
forEachTry
{
uri
->
var
success
=
false
if
(
process
(
feature
)
{
InputImage
.
fromFilePath
(
app
,
uri
)
})
success
=
true
data
!!
.
datas
.
forEachTry
{
uri
->
if
(
process
(
feature
)
{
InputImage
.
fromFilePath
(
app
,
uri
)
})
success
=
true
}
Toast
.
makeText
(
app
,
if
(
success
)
R
.
string
.
action_import_msg
else
R
.
string
.
action_import_err
,
Toast
.
LENGTH_SHORT
).
show
()
}
catch
(
e
:
Exception
)
{
Toast
.
makeText
(
app
,
e
.
readableMessage
,
Toast
.
LENGTH_LONG
).
show
()
}
}
}
requestCode
==
REQUEST_IMPORT_OR_FINISH
->
onSupportNavigateUp
()
Toast
.
makeText
(
app
,
if
(
success
)
R
.
string
.
action_import_msg
else
R
.
string
.
action_import_err
,
Toast
.
LENGTH_SHORT
).
show
()
}
catch
(
e
:
Exception
)
{
Toast
.
makeText
(
app
,
e
.
readableMessage
,
Toast
.
LENGTH_LONG
).
show
()
}
}
else
->
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
}
else
if
(
finish
)
onSupportNavigateUp
()
}
}
}
}
}
mobile/src/main/java/com/github/shadowsocks/ToolbarFragment.kt
View file @
eeef4b55
...
@@ -26,9 +26,6 @@ import androidx.appcompat.widget.Toolbar
...
@@ -26,9 +26,6 @@ import androidx.appcompat.widget.Toolbar
import
androidx.core.view.GravityCompat
import
androidx.core.view.GravityCompat
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.Fragment
/**
* @author Mygod
*/
open
class
ToolbarFragment
:
Fragment
()
{
open
class
ToolbarFragment
:
Fragment
()
{
lateinit
var
toolbar
:
Toolbar
lateinit
var
toolbar
:
Toolbar
...
...
mobile/src/main/java/com/github/shadowsocks/preference/PluginConfigurationDialogFragment.kt
View file @
eeef4b55
...
@@ -46,10 +46,9 @@ class PluginConfigurationDialogFragment : EditTextPreferenceDialogFragmentCompat
...
@@ -46,10 +46,9 @@ class PluginConfigurationDialogFragment : EditTextPreferenceDialogFragmentCompat
super
.
onPrepareDialogBuilder
(
builder
)
super
.
onPrepareDialogBuilder
(
builder
)
val
intent
=
PluginManager
.
buildIntent
(
arguments
?.
getString
(
PLUGIN_ID_FRAGMENT_TAG
)
!!
,
val
intent
=
PluginManager
.
buildIntent
(
arguments
?.
getString
(
PLUGIN_ID_FRAGMENT_TAG
)
!!
,
PluginContract
.
ACTION_HELP
)
PluginContract
.
ACTION_HELP
)
val
activity
=
requireActivity
()
val
activity
=
activity
as
ProfileConfigActivity
if
(
intent
.
resolveActivity
(
activity
.
packageManager
)
!=
null
)
builder
.
setNeutralButton
(
"?"
)
{
_
,
_
->
if
(
intent
.
resolveActivity
(
activity
.
packageManager
)
!=
null
)
builder
.
setNeutralButton
(
"?"
)
{
_
,
_
->
activity
.
startActivityForResult
(
intent
.
putExtra
(
PluginContract
.
EXTRA_OPTIONS
,
editText
.
text
.
toString
()),
activity
.
pluginHelp
.
launch
(
intent
.
putExtra
(
PluginContract
.
EXTRA_OPTIONS
,
editText
.
text
.
toString
()))
ProfileConfigActivity
.
REQUEST_CODE_PLUGIN_HELP
)
}
}
}
}
...
...
tv/src/main/java/com/github/shadowsocks/tv/MainPreferenceFragment.kt
View file @
eeef4b55
...
@@ -20,15 +20,14 @@
...
@@ -20,15 +20,14 @@
package
com.github.shadowsocks.tv
package
com.github.shadowsocks.tv
import
android.app.Activity
import
android.app.backup.BackupManager
import
android.app.backup.BackupManager
import
android.content.ActivityNotFoundException
import
android.content.ActivityNotFoundException
import
android.content.Intent
import
android.content.Intent
import
android.net.VpnService
import
android.os.Bundle
import
android.os.Bundle
import
android.os.RemoteException
import
android.os.RemoteException
import
android.text.format.Formatter
import
android.text.format.Formatter
import
android.widget.Toast
import
android.widget.Toast
import
androidx.activity.result.ActivityResultLauncher
import
androidx.fragment.app.viewModels
import
androidx.fragment.app.viewModels
import
androidx.leanback.preference.LeanbackPreferenceFragmentCompat
import
androidx.leanback.preference.LeanbackPreferenceFragmentCompat
import
androidx.lifecycle.observe
import
androidx.lifecycle.observe
...
@@ -44,20 +43,12 @@ import com.github.shadowsocks.net.HttpsTest
...
@@ -44,20 +43,12 @@ import com.github.shadowsocks.net.HttpsTest
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.preference.DataStore
import
com.github.shadowsocks.preference.EditTextPreferenceModifiers
import
com.github.shadowsocks.preference.EditTextPreferenceModifiers
import
com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
import
com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
import
com.github.shadowsocks.utils.Key
import
com.github.shadowsocks.utils.*
import
com.github.shadowsocks.utils.datas
import
com.github.shadowsocks.utils.readableMessage
import
com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import
com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import
timber.log.Timber
import
timber.log.Timber
class
MainPreferenceFragment
:
LeanbackPreferenceFragmentCompat
(),
ShadowsocksConnection
.
Callback
,
class
MainPreferenceFragment
:
LeanbackPreferenceFragmentCompat
(),
ShadowsocksConnection
.
Callback
,
OnPreferenceDataStoreChangeListener
{
OnPreferenceDataStoreChangeListener
{
companion
object
{
private
const
val
REQUEST_CONNECT
=
1
private
const
val
REQUEST_REPLACE_PROFILES
=
2
private
const
val
REQUEST_EXPORT_PROFILES
=
3
}
private
lateinit
var
fab
:
ListPreference
private
lateinit
var
fab
:
ListPreference
private
lateinit
var
stats
:
Preference
private
lateinit
var
stats
:
Preference
private
lateinit
var
controlImport
:
Preference
private
lateinit
var
controlImport
:
Preference
...
@@ -177,15 +168,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
...
@@ -177,15 +168,7 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
}
}
fun
startService
()
{
fun
startService
()
{
when
{
if
(
state
==
BaseService
.
State
.
Stopped
)
connect
.
launch
(
null
)
state
!=
BaseService
.
State
.
Stopped
->
return
DataStore
.
serviceMode
==
Key
.
modeVpn
->
{
val
intent
=
VpnService
.
prepare
(
requireContext
())
if
(
intent
!=
null
)
startActivityForResult
(
intent
,
REQUEST_CONNECT
)
else
onActivityResult
(
REQUEST_CONNECT
,
Activity
.
RESULT_OK
,
null
)
}
else
->
Core
.
startService
()
}
}
}
override
fun
onPreferenceDataStoreChanged
(
store
:
PreferenceDataStore
,
key
:
String
)
{
override
fun
onPreferenceDataStoreChanged
(
store
:
PreferenceDataStore
,
key
:
String
)
{
...
@@ -212,18 +195,11 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
...
@@ -212,18 +195,11 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
true
true
}
}
Key
.
controlImport
->
{
Key
.
controlImport
->
{
startFilesForResult
(
Intent
(
Intent
.
ACTION_GET_CONTENT
).
apply
{
startFilesForResult
(
replaceProfiles
)
type
=
"application/*"
putExtra
(
Intent
.
EXTRA_ALLOW_MULTIPLE
,
true
)
putExtra
(
Intent
.
EXTRA_MIME_TYPES
,
arrayOf
(
"application/*"
,
"text/*"
))
},
REQUEST_REPLACE_PROFILES
)
true
true
}
}
Key
.
controlExport
->
{
Key
.
controlExport
->
{
startFilesForResult
(
Intent
(
Intent
.
ACTION_CREATE_DOCUMENT
).
apply
{
startFilesForResult
(
exportProfiles
)
type
=
"application/json"
putExtra
(
Intent
.
EXTRA_TITLE
,
"profiles.json"
)
// optional title that can be edited
},
REQUEST_EXPORT_PROFILES
)
true
true
}
}
Key
.
about
->
{
Key
.
about
->
{
...
@@ -237,48 +213,42 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
...
@@ -237,48 +213,42 @@ class MainPreferenceFragment : LeanbackPreferenceFragmentCompat(), ShadowsocksCo
else
->
super
.
onPreferenceTreeClick
(
preference
)
else
->
super
.
onPreferenceTreeClick
(
preference
)
}
}
private
fun
startFilesForResult
(
intent
:
Intent
,
requestCode
:
Int
):
Boolean
{
private
fun
startFilesForResult
(
launcher
:
ActivityResultLauncher
<
String
>)
{
try
{
try
{
startActivityForResult
(
intent
.
addCategory
(
Intent
.
CATEGORY_OPENABLE
),
requestCode
)
return
launcher
.
launch
(
""
)
return
false
}
catch
(
_
:
ActivityNotFoundException
)
{
}
catch
(
_
:
ActivityNotFoundException
)
{
}
catch
(
_
:
SecurityException
)
{
}
}
catch
(
_
:
SecurityException
)
{
}
Toast
.
makeText
(
requireContext
(),
R
.
string
.
file_manager_missing
,
Toast
.
LENGTH_SHORT
).
show
()
Toast
.
makeText
(
requireContext
(),
R
.
string
.
file_manager_missing
,
Toast
.
LENGTH_SHORT
).
show
()
return
true
}
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
?)
{
private
val
connect
=
registerForActivityResult
(
StartService
())
{
when
(
requestCode
)
{
if
(
it
)
Toast
.
makeText
(
requireContext
(),
R
.
string
.
vpn_permission_denied
,
Toast
.
LENGTH_SHORT
).
show
()
REQUEST_CONNECT
->
if
(
resultCode
==
Activity
.
RESULT_OK
)
Core
.
startService
()
else
{
}
Toast
.
makeText
(
requireContext
(),
R
.
string
.
vpn_permission_denied
,
Toast
.
LENGTH_SHORT
).
show
()
private
val
replaceProfiles
=
registerForActivityResult
(
OpenJson
())
{
dataUris
->
Timber
.
e
(
"Failed to start VpnService from onActivityResult: $data"
)
if
(
dataUris
.
isEmpty
())
return
@registerForActivityResult
}
val
context
=
requireContext
()
REQUEST_REPLACE_PROFILES
->
{
try
{
if
(
resultCode
!=
Activity
.
RESULT_OK
)
return
ProfileManager
.
createProfilesFromJson
(
dataUris
.
asSequence
().
map
{
val
context
=
requireContext
()
context
.
contentResolver
.
openInputStream
(
it
)
try
{
}.
filterNotNull
(),
true
)
ProfileManager
.
createProfilesFromJson
(
data
!!
.
datas
.
asSequence
().
map
{
}
catch
(
e
:
Exception
)
{
context
.
contentResolver
.
openInputStream
(
it
)
Timber
.
w
(
e
)
}.
filterNotNull
(),
true
)
Toast
.
makeText
(
context
,
e
.
readableMessage
,
Toast
.
LENGTH_SHORT
).
show
()
}
catch
(
e
:
Exception
)
{
}
Timber
.
w
(
e
)
populateProfiles
()
Toast
.
makeText
(
context
,
e
.
readableMessage
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
private
val
exportProfiles
=
registerForActivityResult
(
SaveJson
())
{
data
->
populateProfiles
()
if
(
data
!=
null
)
ProfileManager
.
serializeToJson
()
?.
let
{
profiles
->
}
val
context
=
requireContext
()
REQUEST_EXPORT_PROFILES
->
{
try
{
if
(
resultCode
!=
Activity
.
RESULT_OK
)
return
context
.
contentResolver
.
openOutputStream
(
data
)
!!
.
bufferedWriter
().
use
{
val
profiles
=
ProfileManager
.
serializeToJson
()
it
.
write
(
profiles
.
toString
(
2
))
val
context
=
requireContext
()
if
(
profiles
!=
null
)
try
{
context
.
contentResolver
.
openOutputStream
(
data
?.
data
!!
)
!!
.
bufferedWriter
().
use
{
it
.
write
(
profiles
.
toString
(
2
))
}
}
catch
(
e
:
Exception
)
{
Timber
.
w
(
e
)
Toast
.
makeText
(
context
,
e
.
readableMessage
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
}
catch
(
e
:
Exception
)
{
Timber
.
w
(
e
)
Toast
.
makeText
(
context
,
e
.
readableMessage
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
else
->
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
)
}
}
}
}
...
...
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