Skip to content

Commit d34cdc7

Browse files
Fixed crash when no handler is set,
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]>
1 parent 16bd531 commit d34cdc7

File tree

42 files changed

+461
-458
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+461
-458
lines changed

androidApp/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ dependencies {
210210
debugImplementation(libs.leakcanary)
211211
}
212212

213+
composeCompiler {
214+
stabilityConfigurationFiles.add(
215+
rootProject.layout.projectDirectory.file(
216+
"compose-stability.txt"))
217+
}
218+
213219
tasks.register<GenerateSettingsTask>("generateSettings") {
214220
packageName = "com.mrboomdev.awery.generated"
215221
className = "AwerySettings"

androidApp/mobile/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,10 @@ dependencies {
4949
implementation(libs.androidx.ui.tooling.preview)
5050
implementation(libs.androidx.compose.material3)
5151
debugImplementation(libs.androidx.compose.ui.tooling)
52+
}
53+
54+
composeCompiler {
55+
stabilityConfigurationFiles.add(
56+
rootProject.layout.projectDirectory.file(
57+
"compose-stability.txt"))
5258
}

androidApp/src/main/AndroidManifest.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@
108108
<data android:host="add-repo" />
109109
</intent-filter>
110110

111+
<intent-filter>
112+
<action android:name="android.intent.action.VIEW" />
113+
114+
<category android:name="android.intent.category.DEFAULT" />
115+
<category android:name="android.intent.category.BROWSABLE" />
116+
117+
<data android:scheme="awery" />
118+
<data android:host="add-repo" />
119+
</intent-filter>
120+
111121
<intent-filter>
112122
<action android:name="android.intent.action.VIEW" />
113123

androidApp/src/main/assets/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@
204204
}, {
205205
"key": "experiment_settings2", "title": "Remastered settings",
206206
"type": "boolean", "boolean_value": false
207+
}, {
208+
"key": "experiment_compose_ui", "title": "Compose UI",
209+
"type": "boolean", "boolean_value": false
207210
}
208211
]
209212
},

androidApp/src/main/java/com/mrboomdev/awery/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ import com.mrboomdev.awery.util.extensions.setContentViewCompat
4949
import com.mrboomdev.awery.util.extensions.setHorizontalPadding
5050
import com.mrboomdev.awery.util.extensions.startActivity
5151
import com.mrboomdev.awery.util.extensions.topPadding
52-
import com.mrboomdev.awery.util.io.FileUtil.readAssets
5352
import com.mrboomdev.awery.util.ui.FadeTransformer
5453
import com.mrboomdev.awery.utils.addOnBackPressedListener
5554
import com.mrboomdev.awery.utils.buildIntent
5655
import com.mrboomdev.awery.utils.div
5756
import com.mrboomdev.awery.utils.dpPx
5857
import com.mrboomdev.awery.utils.inflater
58+
import com.mrboomdev.awery.utils.readAssets
5959
import com.mrboomdev.awery.utils.removeOnBackPressedListener
6060
import com.squareup.moshi.adapter
6161
import kotlinx.coroutines.CoroutineExceptionHandler

androidApp/src/main/java/com/mrboomdev/awery/app/App.kt

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import android.app.Activity
55
import android.app.AlertDialog
66
import android.app.Application
77
import android.app.Dialog
8-
import android.app.UiModeManager
98
import android.content.ClipData
109
import android.content.ClipboardManager
1110
import android.content.ComponentName
@@ -24,7 +23,6 @@ import android.util.Log
2423
import android.util.TypedValue
2524
import android.view.Gravity
2625
import android.view.View
27-
import android.widget.Toast
2826
import android.window.OnBackInvokedCallback
2927
import androidx.activity.ComponentActivity
3028
import androidx.activity.OnBackPressedCallback
@@ -106,8 +104,8 @@ class App : Application() {
106104
super.onCreate()
107105
setupStrictMode()
108106

109-
GlobalScope.launch(Dispatchers.Default) {
110-
initSync()
107+
GlobalScope.launch(Dispatchers.Default) {
108+
initSync()
111109
}
112110
}
113111

@@ -149,33 +147,22 @@ class App : Application() {
149147
}
150148
}
151149

152-
// If any experiment is enabled, then crate an shortcut
153-
if(AwerySettings.EXPERIMENTS.items.find { it is GeneratedSetting.Boolean && it.value == true } != null) {
154-
if(isTv) {
155-
// Tv doesn't show up any shortcuts, so we have to show an separate app launcher.
156-
packageManager.setComponentEnabledSetting(
157-
ComponentName(this, TvExperimentsActivity::class.java),
158-
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
159-
} else {
160-
ShortcutManagerCompat.pushDynamicShortcut(applicationContext,
161-
ShortcutInfoCompat.Builder(this, "experiments")
162-
.setIcon(IconCompat.createWithResource(this, R.drawable.ic_experiment_outlined))
163-
.setLongLabel("Open experimental settings")
164-
.setShortLabel("Experiments")
165-
.setLongLived(true)
166-
.setIntent(Intent(this, IntentHandlerActivity::class.java).apply {
167-
action = Intent.ACTION_VIEW
168-
data = Uri.parse("awery://experiments")
169-
}).build())
170-
}
150+
if(isTv) {
151+
// Tv doesn't show up any shortcuts, so we have to show an separate app launcher.
152+
packageManager.setComponentEnabledSetting(
153+
ComponentName(this, TvExperimentsActivity::class.java),
154+
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
171155
} else {
172-
if(isTv) {
173-
packageManager.setComponentEnabledSetting(
174-
ComponentName(this, TvExperimentsActivity::class.java),
175-
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
176-
} else {
177-
ShortcutManagerCompat.removeLongLivedShortcuts(applicationContext, listOf("experiments"))
178-
}
156+
ShortcutManagerCompat.pushDynamicShortcut(applicationContext,
157+
ShortcutInfoCompat.Builder(this, "experiments")
158+
.setIcon(IconCompat.createWithResource(this, R.drawable.ic_experiment_outlined))
159+
.setLongLabel("Open experimental settings")
160+
.setShortLabel("Experiments")
161+
.setLongLived(true)
162+
.setIntent(Intent(this, IntentHandlerActivity::class.java).apply {
163+
action = Intent.ACTION_VIEW
164+
data = Uri.parse("awery://experiments")
165+
}).build())
179166
}
180167

181168
didInit = true
@@ -196,11 +183,13 @@ class App : Application() {
196183
.addMigrations(AweryDB.MIGRATION_2_3, AweryDB.MIGRATION_3_4)
197184
.build()
198185
}
199-
186+
187+
@Deprecated("Use kotlin serialization instead!")
200188
fun getMoshi(): Moshi {
201189
return globalMoshi
202190
}
203191

192+
@Deprecated("Use kotlin serialization instead!")
204193
fun getMoshi(vararg adapters: Any): Moshi {
205194
if(adapters.isEmpty()) {
206195
return globalMoshi
@@ -284,7 +273,7 @@ class App : Application() {
284273
* This method tries to do it without throwing any exceptions.
285274
*/
286275
@JvmStatic
287-
@Deprecated("")
276+
@Deprecated("Old java shit")
288277
fun setContentViewCompat(activity: Activity, view: View) {
289278
try {
290279
activity.setContentView(view)
@@ -306,7 +295,7 @@ class App : Application() {
306295
* @author MrBoomDev
307296
*/
308297
@JvmStatic
309-
@Deprecated("")
298+
@Deprecated("Old java shit")
310299
fun enableEdgeToEdge(context: ComponentActivity) {
311300
try {
312301
context.enableEdgeToEdge()
@@ -317,7 +306,7 @@ class App : Application() {
317306
}
318307

319308
@JvmStatic
320-
@Deprecated("")
309+
@Deprecated("Old java shit")
321310
fun removeOnBackPressedListener(activity: Activity, callback: Runnable) {
322311
val onBackInvokedCallback = backPressedCallbacks.remove(callback) ?: return
323312

@@ -332,7 +321,7 @@ class App : Application() {
332321
}
333322

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

359348
@JvmStatic
360-
@Deprecated("")
349+
@Deprecated("Old java shit")
361350
fun resolveAttrColor(context: Context, @AttrRes res: Int): Int {
362351
return MaterialColors.getColor(context, res, Color.BLACK)
363352
}
364353

365354
@JvmStatic
366-
@Deprecated("")
355+
@Deprecated("Old java shit")
367356
@SuppressLint("RestrictedApi")
368357
fun resolveAttr(context: Context?, @AttrRes res: Int): TypedValue? {
369358
return MaterialAttributes.resolve(context!!, res)

androidApp/src/main/java/com/mrboomdev/awery/app/AweryLifecycle.kt

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,16 @@ import android.app.Activity
55
import android.app.Application.ActivityLifecycleCallbacks
66
import android.content.Context
77
import android.content.ContextWrapper
8-
import android.content.Intent
98
import android.os.Bundle
109
import android.os.Handler
1110
import android.os.Looper
1211
import android.util.Log
13-
import androidx.annotation.MainThread
14-
import androidx.fragment.app.Fragment
15-
import androidx.fragment.app.FragmentActivity
1612
import androidx.recyclerview.widget.RecyclerView
1713
import com.mrboomdev.awery.platform.PlatformResources
1814
import com.mrboomdev.awery.platform.android.AndroidGlobals
1915
import com.mrboomdev.awery.platform.android.AndroidGlobals.toast
20-
import com.mrboomdev.awery.utils.UniqueIdGenerator
2116
import org.jetbrains.annotations.Contract
2217
import java.lang.ref.WeakReference
23-
import java.lang.reflect.InvocationTargetException
2418
import java.util.Objects
2519
import java.util.WeakHashMap
2620
import kotlin.system.exitProcess
@@ -137,7 +131,10 @@ open class AweryLifecycle private constructor() : ActivityLifecycleCallbacks {
137131
companion object {
138132
private val infos = WeakHashMap<Activity, ActivityInfo<Activity>>()
139133
private const val TAG = "AweryLifecycle"
140-
private var handler: Handler? = null
134+
135+
private val handler by lazy {
136+
Handler(Looper.getMainLooper())
137+
}
141138

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

262259
@JvmStatic
263260
fun postRunnable(runnable: Runnable): Runnable? {
264-
return if(handler!!.post(runnable)) runnable else null
261+
return if(handler.post(runnable)) runnable else null
265262
}
266263

267264
@JvmStatic
265+
@Deprecated("Use coroutines")
268266
fun runOnUiThread(runnable: Runnable): Runnable {
269-
if(!isMainThread) handler!!.post(runnable)
267+
if(!isMainThread) handler.post(runnable)
270268
else runnable.run()
271269

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

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

307-
@get:SuppressLint("PrivateApi", "DiscouragedPrivateApi")
308-
private val contextUsingPrivateApi: App?
309-
get() {
310-
var context = invokeMethod(
311-
"android.app.ActivityThread",
312-
"currentApplication"
313-
) as App?
314-
315-
if(context != null) {
316-
return context
317-
}
318-
319-
context = invokeMethod(
320-
"android.app.AppGlobals",
321-
"getInitialApplication"
322-
) as App?
323-
324-
return context
325-
}
326-
327-
private fun invokeMethod(className: String, methodName: String): Any? {
328-
try {
329-
val clazz = Class.forName(className)
330-
val method = clazz.getMethod(methodName)
331-
method.isAccessible = true
332-
return method.invoke(null)
333-
} catch(e: ClassNotFoundException) {
334-
return null
335-
} catch(e: IllegalAccessException) {
336-
return null
337-
} catch(e: InvocationTargetException) {
338-
return null
339-
} catch(e: NoSuchMethodException) {
340-
return null
341-
}
342-
}
343-
344306
@JvmStatic
307+
@Deprecated("Use coroutines")
345308
fun cancelDelayed(runnable: Runnable?) {
346-
handler!!.removeCallbacks(runnable!!)
309+
handler.removeCallbacks(runnable!!)
347310
}
348311

349312
@JvmStatic
313+
@Deprecated("Use coroutines")
350314
fun runDelayed(runnable: Runnable?, delay: Long) {
351-
handler!!.postDelayed(runnable!!, delay)
315+
handler.postDelayed(runnable!!, delay)
352316
}
353317

354318
@JvmStatic
319+
@Deprecated("Use coroutines")
355320
fun runDelayed(runnable: Runnable, delay: Long, recycler: RecyclerView): Runnable {
356321
val result = Runnable { runOnUiThread(runnable, recycler) }
357-
handler!!.postDelayed(result, delay)
322+
handler.postDelayed(result, delay)
358323
return result
359324
}
360325
}

androidApp/src/main/java/com/mrboomdev/awery/app/update/UpdatesManager.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import android.content.Intent
55
import android.util.Log
66
import androidx.core.content.FileProvider
77
import com.mrboomdev.awery.BuildConfig
8-
import com.mrboomdev.awery.R
98
import com.mrboomdev.awery.app.App.Companion.getMoshi
109
import com.mrboomdev.awery.app.App.Companion.showLoadingWindow
1110
import com.mrboomdev.awery.app.AweryLifecycle.Companion.runOnUiThread
@@ -18,7 +17,7 @@ import com.mrboomdev.awery.generated.size
1817
import com.mrboomdev.awery.generated.update_available
1918
import com.mrboomdev.awery.platform.android.AndroidGlobals.toast
2019
import com.mrboomdev.awery.platform.i18n
21-
import com.mrboomdev.awery.util.ContentType
20+
import com.mrboomdev.awery.data.ContentType
2221
import com.mrboomdev.awery.util.NiceUtils
2322
import com.mrboomdev.awery.util.extensions.formatFileSize
2423
import com.mrboomdev.awery.util.extensions.removeIndent

androidApp/src/main/java/com/mrboomdev/awery/data/settings/NicePreferences.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.mrboomdev.awery.data.settings;
22

3-
import static com.mrboomdev.awery.util.io.FileUtil.readAssets;
3+
import static com.mrboomdev.awery.utils.FileExtensionsAndroid.readAssets;
44

55
import android.content.SharedPreferences;
66

@@ -50,11 +50,8 @@ public static SettingsItem getSettingsMap() {
5050
}
5151

5252
try {
53-
var json = readAssets("settings.json");
54-
55-
settingsMapInstance = Parser.fromString(SettingsItem.class, json);
53+
settingsMapInstance = Parser.fromString(SettingsItem.class, readAssets("settings.json"));
5654
settingsMapInstance.setAsParentForChildren();
57-
5855
reloadSettingsMapValues();
5956
return settingsMapInstance;
6057
} catch(IOException e) {

0 commit comments

Comments
 (0)