mirror of
https://git.mihon.tech/mihonapp/mihon
synced 2024-12-18 03:01:55 +03:00
Move Glance Widget to seperate module (#8989)
Move Widget to seperate module - Create a core module for presentation. Widget and App will share some resources and hopefully composables
This commit is contained in:
parent
c892c793a8
commit
12e41b6e6f
38 changed files with 154 additions and 35 deletions
|
@ -143,6 +143,8 @@ dependencies {
|
||||||
implementation(project(":source-api"))
|
implementation(project(":source-api"))
|
||||||
implementation(project(":data"))
|
implementation(project(":data"))
|
||||||
implementation(project(":domain"))
|
implementation(project(":domain"))
|
||||||
|
implementation(project(":presentation-core"))
|
||||||
|
implementation(project(":presentation-widget"))
|
||||||
|
|
||||||
// Compose
|
// Compose
|
||||||
implementation(platform(compose.bom))
|
implementation(platform(compose.bom))
|
||||||
|
@ -181,7 +183,6 @@ dependencies {
|
||||||
implementation(androidx.splashscreen)
|
implementation(androidx.splashscreen)
|
||||||
implementation(androidx.recyclerview)
|
implementation(androidx.recyclerview)
|
||||||
implementation(androidx.viewpager)
|
implementation(androidx.viewpager)
|
||||||
implementation(androidx.glance)
|
|
||||||
implementation(androidx.profileinstaller)
|
implementation(androidx.profileinstaller)
|
||||||
|
|
||||||
implementation(androidx.bundles.lifecycle)
|
implementation(androidx.bundles.lifecycle)
|
||||||
|
|
|
@ -188,7 +188,7 @@
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".glance.UpdatesGridGlanceReceiver"
|
android:name="tachiyomi.presentation.widget.UpdatesGridGlanceReceiver"
|
||||||
android:enabled="@bool/glance_appwidget_available"
|
android:enabled="@bool/glance_appwidget_available"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/label_recent_updates">
|
android:label="@string/label_recent_updates">
|
||||||
|
|
|
@ -13,7 +13,6 @@ import android.os.Looper
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.glance.appwidget.GlanceAppWidgetManager
|
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
|
@ -36,7 +35,6 @@ import eu.kanade.tachiyomi.data.coil.MangaCoverKeyer
|
||||||
import eu.kanade.tachiyomi.data.coil.MangaKeyer
|
import eu.kanade.tachiyomi.data.coil.MangaKeyer
|
||||||
import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder
|
import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.glance.UpdatesGridGlanceWidget
|
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.network.NetworkPreferences
|
import eu.kanade.tachiyomi.network.NetworkPreferences
|
||||||
import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
|
import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
|
||||||
|
@ -47,8 +45,6 @@ import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
||||||
import eu.kanade.tachiyomi.util.system.logcat
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
import eu.kanade.tachiyomi.util.system.notification
|
import eu.kanade.tachiyomi.util.system.notification
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
||||||
import kotlinx.coroutines.flow.drop
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import logcat.AndroidLogcatLogger
|
import logcat.AndroidLogcatLogger
|
||||||
|
@ -58,7 +54,7 @@ import org.acra.config.httpSender
|
||||||
import org.acra.ktx.initAcra
|
import org.acra.ktx.initAcra
|
||||||
import org.acra.sender.HttpSender
|
import org.acra.sender.HttpSender
|
||||||
import org.conscrypt.Conscrypt
|
import org.conscrypt.Conscrypt
|
||||||
import tachiyomi.data.DatabaseHandler
|
import tachiyomi.presentation.widget.TachiyomiWidgetManager
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
@ -128,17 +124,9 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
|
||||||
setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode().get())
|
setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode().get())
|
||||||
|
|
||||||
// Updates widget update
|
// Updates widget update
|
||||||
Injekt.get<DatabaseHandler>()
|
with(TachiyomiWidgetManager) {
|
||||||
.subscribeToList { updatesViewQueries.updates(after = UpdatesGridGlanceWidget.DateLimit.timeInMillis) }
|
init(ProcessLifecycleOwner.get().lifecycleScope, Injekt.get())
|
||||||
.drop(1)
|
}
|
||||||
.distinctUntilChanged()
|
|
||||||
.onEach {
|
|
||||||
val manager = GlanceAppWidgetManager(this)
|
|
||||||
if (manager.getGlanceIds(UpdatesGridGlanceWidget::class.java).isNotEmpty()) {
|
|
||||||
UpdatesGridGlanceWidget().loadData(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
|
|
||||||
|
|
||||||
if (!LogcatLogger.isInstalled && networkPreferences.verboseLogging().get()) {
|
if (!LogcatLogger.isInstalled && networkPreferences.verboseLogging().get()) {
|
||||||
LogcatLogger.install(AndroidLogcatLogger(LogPriority.VERBOSE))
|
LogcatLogger.install(AndroidLogcatLogger(LogPriority.VERBOSE))
|
||||||
|
|
|
@ -115,12 +115,6 @@ fun Context.hasPermission(permission: String) = ContextCompat.checkSelfPermissio
|
||||||
val getDisplayMaxHeightInPx: Int
|
val getDisplayMaxHeightInPx: Int
|
||||||
get() = Resources.getSystem().displayMetrics.let { max(it.heightPixels, it.widthPixels) }
|
get() = Resources.getSystem().displayMetrics.let { max(it.heightPixels, it.widthPixels) }
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts to px.
|
|
||||||
*/
|
|
||||||
val Int.dpToPx: Int
|
|
||||||
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts to px and takes into account LTR/RTL layout.
|
* Converts to px and takes into account LTR/RTL layout.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package eu.kanade.tachiyomi.util.system
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts to px.
|
||||||
|
*/
|
||||||
|
val Int.dpToPx: Int
|
||||||
|
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
|
1
presentation-core/.gitignore
vendored
Normal file
1
presentation-core/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
17
presentation-core/build.gradle.kts
Normal file
17
presentation-core/build.gradle.kts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
plugins {
|
||||||
|
id("com.android.library")
|
||||||
|
id("org.jetbrains.kotlin.android")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "tachiyomi.presentation.core"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
consumerProguardFiles("consumer-rules.pro")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
}
|
0
presentation-core/consumer-rules.pro
Normal file
0
presentation-core/consumer-rules.pro
Normal file
21
presentation-core/proguard-rules.pro
vendored
Normal file
21
presentation-core/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
2
presentation-core/src/main/AndroidManifest.xml
Normal file
2
presentation-core/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest />
|
1
presentation-widget/.gitignore
vendored
Normal file
1
presentation-widget/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
33
presentation-widget/build.gradle.kts
Normal file
33
presentation-widget/build.gradle.kts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
plugins {
|
||||||
|
id("com.android.library")
|
||||||
|
id("org.jetbrains.kotlin.android")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "tachiyomi.presentation.widget"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
consumerProguardFiles("consumer-rules.pro")
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
}
|
||||||
|
|
||||||
|
composeOptions {
|
||||||
|
kotlinCompilerExtensionVersion = compose.versions.compiler.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":core"))
|
||||||
|
implementation(project(":data"))
|
||||||
|
implementation(project(":domain"))
|
||||||
|
implementation(project(":presentation-core"))
|
||||||
|
|
||||||
|
implementation(androidx.glance)
|
||||||
|
|
||||||
|
implementation(libs.coil.core)
|
||||||
|
|
||||||
|
}
|
0
presentation-widget/consumer-rules.pro
Normal file
0
presentation-widget/consumer-rules.pro
Normal file
21
presentation-widget/proguard-rules.pro
vendored
Normal file
21
presentation-widget/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
2
presentation-widget/src/main/AndroidManifest.xml
Normal file
2
presentation-widget/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest />
|
|
@ -1,11 +1,10 @@
|
||||||
package eu.kanade.tachiyomi.glance
|
package tachiyomi.presentation.widget
|
||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.glance.GlanceModifier
|
import androidx.glance.GlanceModifier
|
||||||
import androidx.glance.LocalContext
|
import androidx.glance.LocalContext
|
||||||
import androidx.glance.appwidget.cornerRadius
|
import androidx.glance.appwidget.cornerRadius
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
|
|
||||||
fun GlanceModifier.appWidgetBackgroundRadius(): GlanceModifier {
|
fun GlanceModifier.appWidgetBackgroundRadius(): GlanceModifier {
|
||||||
return this.cornerRadius(R.dimen.appwidget_background_radius)
|
return this.cornerRadius(R.dimen.appwidget_background_radius)
|
|
@ -0,0 +1,26 @@
|
||||||
|
package tachiyomi.presentation.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.glance.appwidget.GlanceAppWidgetManager
|
||||||
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.drop
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import tachiyomi.data.DatabaseHandler
|
||||||
|
|
||||||
|
object TachiyomiWidgetManager {
|
||||||
|
|
||||||
|
fun Context.init(scope: LifecycleCoroutineScope, database: DatabaseHandler) {
|
||||||
|
database.subscribeToList { updatesViewQueries.updates(after = UpdatesGridGlanceWidget.DateLimit.timeInMillis) }
|
||||||
|
.drop(1)
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.onEach {
|
||||||
|
val manager = GlanceAppWidgetManager(this)
|
||||||
|
if (manager.getGlanceIds(UpdatesGridGlanceWidget::class.java).isNotEmpty()) {
|
||||||
|
UpdatesGridGlanceWidget().loadData(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchIn(scope)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.kanade.tachiyomi.glance
|
package tachiyomi.presentation.widget
|
||||||
|
|
||||||
import androidx.glance.appwidget.GlanceAppWidget
|
import androidx.glance.appwidget.GlanceAppWidget
|
||||||
import androidx.glance.appwidget.GlanceAppWidgetReceiver
|
import androidx.glance.appwidget.GlanceAppWidgetReceiver
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.kanade.tachiyomi.glance
|
package tachiyomi.presentation.widget
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
@ -43,10 +43,7 @@ import coil.request.ImageRequest
|
||||||
import coil.size.Precision
|
import coil.size.Precision
|
||||||
import coil.size.Scale
|
import coil.size.Scale
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
|
||||||
import eu.kanade.tachiyomi.util.Constants
|
|
||||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
|
@ -81,7 +78,8 @@ class UpdatesGridGlanceWidget : GlanceAppWidget() {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun WidgetNotAvailable() {
|
private fun WidgetNotAvailable() {
|
||||||
val intent = Intent(LocalContext.current, MainActivity::class.java).apply {
|
val clazz = Class.forName("eu.kanade.tachiyomi.ui.main.MainActivity")
|
||||||
|
val intent = Intent(LocalContext.current, clazz).apply {
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
|
@ -134,9 +132,9 @@ class UpdatesGridGlanceWidget : GlanceAppWidget() {
|
||||||
.padding(horizontal = 3.dp),
|
.padding(horizontal = 3.dp),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
val intent = Intent(LocalContext.current, MainActivity::class.java).apply {
|
val intent = Intent(LocalContext.current, Class.forName("eu.kanade.tachiyomi.ui.main.MainActivity")).apply {
|
||||||
action = MainActivity.SHORTCUT_MANGA
|
action = "eu.kanade.tachiyomi.SHOW_MANGA"
|
||||||
putExtra(Constants.MANGA_EXTRA, mangaId)
|
putExtra("manga", mangaId)
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
|
4
presentation-widget/src/main/res/values/dimens.xml
Normal file
4
presentation-widget/src/main/res/values/dimens.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<resources>
|
||||||
|
<dimen name="appwidget_background_radius">16dp</dimen>
|
||||||
|
<dimen name="appwidget_inner_radius">12dp</dimen>
|
||||||
|
</resources>
|
|
@ -43,3 +43,5 @@ include(":core")
|
||||||
include(":macrobenchmark")
|
include(":macrobenchmark")
|
||||||
include(":data")
|
include(":data")
|
||||||
include(":domain")
|
include(":domain")
|
||||||
|
include(":presentation-widget")
|
||||||
|
include(":presentation-core")
|
||||||
|
|
Loading…
Reference in a new issue