Skip to content

Commit

Permalink
Fixed crash when no handler is set,
Browse files Browse the repository at this point in the history
Fixed bug when no extension could be installed via app,
Always create experiments shortcuts,
Mark some classes as stable for compose,
Unified a lot of "FileUtils" classes into a single one (per platform) FileExtensions.kt,
Fully rewritten IntentHandlerActivity to use Compose,
Use navigation on desktop,
Added "experiment_compose_ui" to "old" settings

Signed-off-by: MrBoom <[email protected]>
  • Loading branch information
MrBoomDeveloper committed Jan 23, 2025
1 parent 16bd531 commit d34cdc7
Show file tree
Hide file tree
Showing 42 changed files with 461 additions and 458 deletions.
6 changes: 6 additions & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ dependencies {
debugImplementation(libs.leakcanary)
}

composeCompiler {
stabilityConfigurationFiles.add(
rootProject.layout.projectDirectory.file(
"compose-stability.txt"))
}

tasks.register<GenerateSettingsTask>("generateSettings") {
packageName = "com.mrboomdev.awery.generated"
className = "AwerySettings"
Expand Down
6 changes: 6 additions & 0 deletions androidApp/mobile/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,10 @@ dependencies {
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.compose.material3)
debugImplementation(libs.androidx.compose.ui.tooling)
}

composeCompiler {
stabilityConfigurationFiles.add(
rootProject.layout.projectDirectory.file(
"compose-stability.txt"))
}
10 changes: 10 additions & 0 deletions androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@
<data android:host="add-repo" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="awery" />
<data android:host="add-repo" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.VIEW" />

Expand Down
3 changes: 3 additions & 0 deletions androidApp/src/main/assets/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@
}, {
"key": "experiment_settings2", "title": "Remastered settings",
"type": "boolean", "boolean_value": false
}, {
"key": "experiment_compose_ui", "title": "Compose UI",
"type": "boolean", "boolean_value": false
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ import com.mrboomdev.awery.util.extensions.setContentViewCompat
import com.mrboomdev.awery.util.extensions.setHorizontalPadding
import com.mrboomdev.awery.util.extensions.startActivity
import com.mrboomdev.awery.util.extensions.topPadding
import com.mrboomdev.awery.util.io.FileUtil.readAssets
import com.mrboomdev.awery.util.ui.FadeTransformer
import com.mrboomdev.awery.utils.addOnBackPressedListener
import com.mrboomdev.awery.utils.buildIntent
import com.mrboomdev.awery.utils.div
import com.mrboomdev.awery.utils.dpPx
import com.mrboomdev.awery.utils.inflater
import com.mrboomdev.awery.utils.readAssets
import com.mrboomdev.awery.utils.removeOnBackPressedListener
import com.squareup.moshi.adapter
import kotlinx.coroutines.CoroutineExceptionHandler
Expand Down
63 changes: 26 additions & 37 deletions androidApp/src/main/java/com/mrboomdev/awery/app/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import android.app.Activity
import android.app.AlertDialog
import android.app.Application
import android.app.Dialog
import android.app.UiModeManager
import android.content.ClipData
import android.content.ClipboardManager
import android.content.ComponentName
Expand All @@ -24,7 +23,6 @@ import android.util.Log
import android.util.TypedValue
import android.view.Gravity
import android.view.View
import android.widget.Toast
import android.window.OnBackInvokedCallback
import androidx.activity.ComponentActivity
import androidx.activity.OnBackPressedCallback
Expand Down Expand Up @@ -106,8 +104,8 @@ class App : Application() {
super.onCreate()
setupStrictMode()

GlobalScope.launch(Dispatchers.Default) {
initSync()
GlobalScope.launch(Dispatchers.Default) {
initSync()
}
}

Expand Down Expand Up @@ -149,33 +147,22 @@ class App : Application() {
}
}

// If any experiment is enabled, then crate an shortcut
if(AwerySettings.EXPERIMENTS.items.find { it is GeneratedSetting.Boolean && it.value == true } != null) {
if(isTv) {
// Tv doesn't show up any shortcuts, so we have to show an separate app launcher.
packageManager.setComponentEnabledSetting(
ComponentName(this, TvExperimentsActivity::class.java),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
} else {
ShortcutManagerCompat.pushDynamicShortcut(applicationContext,
ShortcutInfoCompat.Builder(this, "experiments")
.setIcon(IconCompat.createWithResource(this, R.drawable.ic_experiment_outlined))
.setLongLabel("Open experimental settings")
.setShortLabel("Experiments")
.setLongLived(true)
.setIntent(Intent(this, IntentHandlerActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = Uri.parse("awery://experiments")
}).build())
}
if(isTv) {
// Tv doesn't show up any shortcuts, so we have to show an separate app launcher.
packageManager.setComponentEnabledSetting(
ComponentName(this, TvExperimentsActivity::class.java),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
} else {
if(isTv) {
packageManager.setComponentEnabledSetting(
ComponentName(this, TvExperimentsActivity::class.java),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
} else {
ShortcutManagerCompat.removeLongLivedShortcuts(applicationContext, listOf("experiments"))
}
ShortcutManagerCompat.pushDynamicShortcut(applicationContext,
ShortcutInfoCompat.Builder(this, "experiments")
.setIcon(IconCompat.createWithResource(this, R.drawable.ic_experiment_outlined))
.setLongLabel("Open experimental settings")
.setShortLabel("Experiments")
.setLongLived(true)
.setIntent(Intent(this, IntentHandlerActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = Uri.parse("awery://experiments")
}).build())
}

didInit = true
Expand All @@ -196,11 +183,13 @@ class App : Application() {
.addMigrations(AweryDB.MIGRATION_2_3, AweryDB.MIGRATION_3_4)
.build()
}


@Deprecated("Use kotlin serialization instead!")
fun getMoshi(): Moshi {
return globalMoshi
}

@Deprecated("Use kotlin serialization instead!")
fun getMoshi(vararg adapters: Any): Moshi {
if(adapters.isEmpty()) {
return globalMoshi
Expand Down Expand Up @@ -284,7 +273,7 @@ class App : Application() {
* This method tries to do it without throwing any exceptions.
*/
@JvmStatic
@Deprecated("")
@Deprecated("Old java shit")
fun setContentViewCompat(activity: Activity, view: View) {
try {
activity.setContentView(view)
Expand All @@ -306,7 +295,7 @@ class App : Application() {
* @author MrBoomDev
*/
@JvmStatic
@Deprecated("")
@Deprecated("Old java shit")
fun enableEdgeToEdge(context: ComponentActivity) {
try {
context.enableEdgeToEdge()
Expand All @@ -317,7 +306,7 @@ class App : Application() {
}

@JvmStatic
@Deprecated("")
@Deprecated("Old java shit")
fun removeOnBackPressedListener(activity: Activity, callback: Runnable) {
val onBackInvokedCallback = backPressedCallbacks.remove(callback) ?: return

Expand All @@ -332,7 +321,7 @@ class App : Application() {
}

@JvmStatic
@Deprecated("")
@Deprecated("Old java shit")
fun addOnBackPressedListener(activity: Activity, callback: Runnable) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val onBackInvokedCallback = OnBackInvokedCallback { callback.run() }
Expand All @@ -357,13 +346,13 @@ class App : Application() {
}

@JvmStatic
@Deprecated("")
@Deprecated("Old java shit")
fun resolveAttrColor(context: Context, @AttrRes res: Int): Int {
return MaterialColors.getColor(context, res, Color.BLACK)
}

@JvmStatic
@Deprecated("")
@Deprecated("Old java shit")
@SuppressLint("RestrictedApi")
fun resolveAttr(context: Context?, @AttrRes res: Int): TypedValue? {
return MaterialAttributes.resolve(context!!, res)
Expand Down
65 changes: 15 additions & 50 deletions androidApp/src/main/java/com/mrboomdev/awery/app/AweryLifecycle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,16 @@ import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.annotation.MainThread
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.RecyclerView
import com.mrboomdev.awery.platform.PlatformResources
import com.mrboomdev.awery.platform.android.AndroidGlobals
import com.mrboomdev.awery.platform.android.AndroidGlobals.toast
import com.mrboomdev.awery.utils.UniqueIdGenerator
import org.jetbrains.annotations.Contract
import java.lang.ref.WeakReference
import java.lang.reflect.InvocationTargetException
import java.util.Objects
import java.util.WeakHashMap
import kotlin.system.exitProcess
Expand Down Expand Up @@ -137,7 +131,10 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks {
companion object {
private val infos = WeakHashMap<Activity, ActivityInfo<Activity>>()
private const val TAG = "AweryLifecycle"
private var handler: Handler? = null

private val handler by lazy {
Handler(Looper.getMainLooper())
}

@JvmStatic
@Deprecated(message = "Java")
Expand Down Expand Up @@ -261,12 +258,13 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks {

@JvmStatic
fun postRunnable(runnable: Runnable): Runnable? {
return if(handler!!.post(runnable)) runnable else null
return if(handler.post(runnable)) runnable else null
}

@JvmStatic
@Deprecated("Use coroutines")
fun runOnUiThread(runnable: Runnable): Runnable {
if(!isMainThread) handler!!.post(runnable)
if(!isMainThread) handler.post(runnable)
else runnable.run()

return runnable
Expand All @@ -282,10 +280,11 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks {
* @return May be a different callback depending on the state of the RecyclerView, so that you can cancel it.
*/
@JvmStatic
@Deprecated("Use coroutines")
fun runOnUiThread(callback: Runnable, recycler: RecyclerView): Runnable {
if(!isMainThread || recycler.isComputingLayout) {
return Runnable { runOnUiThread(callback, recycler) }
.also { handler!!.post(it) }
.also { handler.post(it) }
}

return callback.also { it.run() }
Expand All @@ -304,57 +303,23 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks {
return AndroidGlobals.applicationContext
}

@get:SuppressLint("PrivateApi", "DiscouragedPrivateApi")
private val contextUsingPrivateApi: App?
get() {
var context = invokeMethod(
"android.app.ActivityThread",
"currentApplication"
) as App?

if(context != null) {
return context
}

context = invokeMethod(
"android.app.AppGlobals",
"getInitialApplication"
) as App?

return context
}

private fun invokeMethod(className: String, methodName: String): Any? {
try {
val clazz = Class.forName(className)
val method = clazz.getMethod(methodName)
method.isAccessible = true
return method.invoke(null)
} catch(e: ClassNotFoundException) {
return null
} catch(e: IllegalAccessException) {
return null
} catch(e: InvocationTargetException) {
return null
} catch(e: NoSuchMethodException) {
return null
}
}

@JvmStatic
@Deprecated("Use coroutines")
fun cancelDelayed(runnable: Runnable?) {
handler!!.removeCallbacks(runnable!!)
handler.removeCallbacks(runnable!!)
}

@JvmStatic
@Deprecated("Use coroutines")
fun runDelayed(runnable: Runnable?, delay: Long) {
handler!!.postDelayed(runnable!!, delay)
handler.postDelayed(runnable!!, delay)
}

@JvmStatic
@Deprecated("Use coroutines")
fun runDelayed(runnable: Runnable, delay: Long, recycler: RecyclerView): Runnable {
val result = Runnable { runOnUiThread(runnable, recycler) }
handler!!.postDelayed(result, delay)
handler.postDelayed(result, delay)
return result
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import android.content.Intent
import android.util.Log
import androidx.core.content.FileProvider
import com.mrboomdev.awery.BuildConfig
import com.mrboomdev.awery.R
import com.mrboomdev.awery.app.App.Companion.getMoshi
import com.mrboomdev.awery.app.App.Companion.showLoadingWindow
import com.mrboomdev.awery.app.AweryLifecycle.Companion.runOnUiThread
Expand All @@ -18,7 +17,7 @@ import com.mrboomdev.awery.generated.size
import com.mrboomdev.awery.generated.update_available
import com.mrboomdev.awery.platform.android.AndroidGlobals.toast
import com.mrboomdev.awery.platform.i18n
import com.mrboomdev.awery.util.ContentType
import com.mrboomdev.awery.data.ContentType
import com.mrboomdev.awery.util.NiceUtils
import com.mrboomdev.awery.util.extensions.formatFileSize
import com.mrboomdev.awery.util.extensions.removeIndent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.mrboomdev.awery.data.settings;

import static com.mrboomdev.awery.util.io.FileUtil.readAssets;
import static com.mrboomdev.awery.utils.FileExtensionsAndroid.readAssets;

import android.content.SharedPreferences;

Expand Down Expand Up @@ -50,11 +50,8 @@ public static SettingsItem getSettingsMap() {
}

try {
var json = readAssets("settings.json");

settingsMapInstance = Parser.fromString(SettingsItem.class, json);
settingsMapInstance = Parser.fromString(SettingsItem.class, readAssets("settings.json"));
settingsMapInstance.setAsParentForChildren();

reloadSettingsMapValues();
return settingsMapInstance;
} catch(IOException e) {
Expand Down
Loading

0 comments on commit d34cdc7

Please sign in to comment.