|
@@ -29,32 +29,18 @@ import java.util.concurrent.atomic.AtomicInteger
|
|
|
import kotlin.coroutines.resume
|
|
import kotlin.coroutines.resume
|
|
|
import kotlin.coroutines.suspendCoroutine
|
|
import kotlin.coroutines.suspendCoroutine
|
|
|
|
|
|
|
|
-abstract class BaseActivity<D : Design<*>> :
|
|
|
|
|
- AppCompatActivity(),
|
|
|
|
|
|
|
+abstract class BaseActivity<D : Design<*>> : AppCompatActivity(),
|
|
|
CoroutineScope by MainScope(),
|
|
CoroutineScope by MainScope(),
|
|
|
Broadcasts.Observer {
|
|
Broadcasts.Observer {
|
|
|
- enum class Event {
|
|
|
|
|
- ServiceRecreated,
|
|
|
|
|
- ActivityStart,
|
|
|
|
|
- ActivityStop,
|
|
|
|
|
- ClashStop,
|
|
|
|
|
- ClashStart,
|
|
|
|
|
- ProfileLoaded,
|
|
|
|
|
- ProfileChanged,
|
|
|
|
|
- ProfileUpdateCompleted,
|
|
|
|
|
- ProfileUpdateFailed
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
protected val uiStore by lazy { UiStore(this) }
|
|
protected val uiStore by lazy { UiStore(this) }
|
|
|
protected val events = Channel<Event>(Channel.UNLIMITED)
|
|
protected val events = Channel<Event>(Channel.UNLIMITED)
|
|
|
protected var activityStarted: Boolean = false
|
|
protected var activityStarted: Boolean = false
|
|
|
protected val clashRunning: Boolean
|
|
protected val clashRunning: Boolean
|
|
|
get() = Remote.broadcasts.clashRunning
|
|
get() = Remote.broadcasts.clashRunning
|
|
|
protected var design: D? = null
|
|
protected var design: D? = null
|
|
|
- private set(value) {
|
|
|
|
|
|
|
+ set(value) {
|
|
|
field = value
|
|
field = value
|
|
|
-
|
|
|
|
|
if (value != null) {
|
|
if (value != null) {
|
|
|
setContentView(value.root)
|
|
setContentView(value.root)
|
|
|
} else {
|
|
} else {
|
|
@@ -75,14 +61,14 @@ abstract class BaseActivity<D : Design<*>> :
|
|
|
|
|
|
|
|
suspend fun <I, O> startActivityForResult(
|
|
suspend fun <I, O> startActivityForResult(
|
|
|
contracts: ActivityResultContract<I, O>,
|
|
contracts: ActivityResultContract<I, O>,
|
|
|
- input: I
|
|
|
|
|
|
|
+ input: I,
|
|
|
): O = withContext(Dispatchers.Main) {
|
|
): O = withContext(Dispatchers.Main) {
|
|
|
val requestKey = nextRequestKey.getAndIncrement().toString()
|
|
val requestKey = nextRequestKey.getAndIncrement().toString()
|
|
|
|
|
|
|
|
ActivityResultLifecycle().use { lifecycle, start ->
|
|
ActivityResultLifecycle().use { lifecycle, start ->
|
|
|
suspendCoroutine { c ->
|
|
suspendCoroutine { c ->
|
|
|
activityResultRegistry.register(requestKey, lifecycle, contracts) {
|
|
activityResultRegistry.register(requestKey, lifecycle, contracts) {
|
|
|
- c.resumeWith(Result.success(it))
|
|
|
|
|
|
|
+ c.resume(it)
|
|
|
}.apply { start() }.launch(input)
|
|
}.apply { start() }.launch(input)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -92,7 +78,6 @@ abstract class BaseActivity<D : Design<*>> :
|
|
|
suspendCoroutine<Unit> {
|
|
suspendCoroutine<Unit> {
|
|
|
window.decorView.post {
|
|
window.decorView.post {
|
|
|
this.design = design
|
|
this.design = design
|
|
|
-
|
|
|
|
|
it.resume(Unit)
|
|
it.resume(Unit)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -100,49 +85,35 @@ abstract class BaseActivity<D : Design<*>> :
|
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
super.onCreate(savedInstanceState)
|
|
super.onCreate(savedInstanceState)
|
|
|
-
|
|
|
|
|
applyDayNight()
|
|
applyDayNight()
|
|
|
|
|
|
|
|
launch {
|
|
launch {
|
|
|
main()
|
|
main()
|
|
|
-
|
|
|
|
|
- finish()
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
override fun onStart() {
|
|
override fun onStart() {
|
|
|
super.onStart()
|
|
super.onStart()
|
|
|
-
|
|
|
|
|
activityStarted = true
|
|
activityStarted = true
|
|
|
-
|
|
|
|
|
Remote.broadcasts.addObserver(this)
|
|
Remote.broadcasts.addObserver(this)
|
|
|
-
|
|
|
|
|
events.trySend(Event.ActivityStart)
|
|
events.trySend(Event.ActivityStart)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
override fun onStop() {
|
|
override fun onStop() {
|
|
|
super.onStop()
|
|
super.onStop()
|
|
|
-
|
|
|
|
|
activityStarted = false
|
|
activityStarted = false
|
|
|
-
|
|
|
|
|
Remote.broadcasts.removeObserver(this)
|
|
Remote.broadcasts.removeObserver(this)
|
|
|
-
|
|
|
|
|
events.trySend(Event.ActivityStop)
|
|
events.trySend(Event.ActivityStop)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
override fun onDestroy() {
|
|
override fun onDestroy() {
|
|
|
design?.cancel()
|
|
design?.cancel()
|
|
|
-
|
|
|
|
|
cancel()
|
|
cancel()
|
|
|
-
|
|
|
|
|
super.onDestroy()
|
|
super.onDestroy()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
override fun finish() {
|
|
override fun finish() {
|
|
|
- if (deferRunning) {
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if (deferRunning) return
|
|
|
deferRunning = true
|
|
deferRunning = true
|
|
|
|
|
|
|
|
launch {
|
|
launch {
|
|
@@ -172,7 +143,6 @@ abstract class BaseActivity<D : Design<*>> :
|
|
|
|
|
|
|
|
override fun onSupportNavigateUp(): Boolean {
|
|
override fun onSupportNavigateUp(): Boolean {
|
|
|
this.onBackPressed()
|
|
this.onBackPressed()
|
|
|
-
|
|
|
|
|
return true
|
|
return true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -212,49 +182,45 @@ abstract class BaseActivity<D : Design<*>> :
|
|
|
|
|
|
|
|
private fun queryDayNight(config: Configuration = resources.configuration): DayNight {
|
|
private fun queryDayNight(config: Configuration = resources.configuration): DayNight {
|
|
|
return when (uiStore.darkMode) {
|
|
return when (uiStore.darkMode) {
|
|
|
- DarkMode.Auto -> {
|
|
|
|
|
- if (config.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES)
|
|
|
|
|
- DayNight.Night
|
|
|
|
|
- else
|
|
|
|
|
- DayNight.Day
|
|
|
|
|
- }
|
|
|
|
|
- DarkMode.ForceLight -> {
|
|
|
|
|
- DayNight.Day
|
|
|
|
|
- }
|
|
|
|
|
- DarkMode.ForceDark -> {
|
|
|
|
|
- DayNight.Night
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ DarkMode.Auto -> if (config.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES) DayNight.Night else DayNight.Day
|
|
|
|
|
+ DarkMode.ForceLight -> DayNight.Day
|
|
|
|
|
+ DarkMode.ForceDark -> DayNight.Night
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private fun applyDayNight(config: Configuration = resources.configuration) {
|
|
private fun applyDayNight(config: Configuration = resources.configuration) {
|
|
|
val dayNight = queryDayNight(config)
|
|
val dayNight = queryDayNight(config)
|
|
|
-
|
|
|
|
|
when (dayNight) {
|
|
when (dayNight) {
|
|
|
- DayNight.Night -> {
|
|
|
|
|
- theme.applyStyle(R.style.AppThemeDark, true)
|
|
|
|
|
- }
|
|
|
|
|
- DayNight.Day -> {
|
|
|
|
|
- theme.applyStyle(R.style.AppThemeLight, true)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ DayNight.Night -> theme.applyStyle(R.style.AppThemeDark, true)
|
|
|
|
|
+ DayNight.Day -> theme.applyStyle(R.style.AppThemeLight, true)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
window.isAllowForceDarkCompat = false
|
|
window.isAllowForceDarkCompat = false
|
|
|
window.isSystemBarsTranslucentCompat = true
|
|
window.isSystemBarsTranslucentCompat = true
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
window.statusBarColor = resolveThemedColor(android.R.attr.statusBarColor)
|
|
window.statusBarColor = resolveThemedColor(android.R.attr.statusBarColor)
|
|
|
window.navigationBarColor = resolveThemedColor(android.R.attr.navigationBarColor)
|
|
window.navigationBarColor = resolveThemedColor(android.R.attr.navigationBarColor)
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= 23) {
|
|
if (Build.VERSION.SDK_INT >= 23) {
|
|
|
- window.isLightStatusBarsCompat =
|
|
|
|
|
- resolveThemedBoolean(android.R.attr.windowLightStatusBar)
|
|
|
|
|
|
|
+ window.isLightStatusBarsCompat = resolveThemedBoolean(android.R.attr.windowLightStatusBar)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= 27) {
|
|
if (Build.VERSION.SDK_INT >= 27) {
|
|
|
- window.isLightNavigationBarCompat =
|
|
|
|
|
- resolveThemedBoolean(android.R.attr.windowLightNavigationBar)
|
|
|
|
|
|
|
+ window.isLightNavigationBarCompat = resolveThemedBoolean(android.R.attr.windowLightNavigationBar)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.dayNight = dayNight
|
|
this.dayNight = dayNight
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ enum class Event {
|
|
|
|
|
+ ServiceRecreated,
|
|
|
|
|
+ ActivityStart,
|
|
|
|
|
+ ActivityStop,
|
|
|
|
|
+ ClashStop,
|
|
|
|
|
+ ClashStart,
|
|
|
|
|
+ ProfileLoaded,
|
|
|
|
|
+ ProfileChanged,
|
|
|
|
|
+ ProfileUpdateCompleted,
|
|
|
|
|
+ ProfileUpdateFailed,
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|