komikku/app/src/main/java/eu/kanade/tachiyomi/di/AppModule.kt
kana-shii c41d5fb847
feat(discord): Discord RPC from Anikku (#1100)
* Add RPC [Barebone, barely works]

Co-Authored-By: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>

* refactor connections

* RPC (#223)

* Add error handling and refactor DiscordRPCService methods

* Add Discord RPC customization options and preferences

* Update Discord RPC button labels and clean up comments

* Refactor DiscordRPCService to improve readability by adding braces for null checks

* Refactor ConnectionsPreferences to improve code clarity and organization

* Refactor ConnectionsPreferences to improve code clarity and organization

(cherry picked from commit df42d196368d28c3c9dcee3692f3f9140da7f2a1)

* Feat: implement Discord account management enhancements and RPC restart functionality (#245)

* fix: correct indentation in CastManager for better readability

* feat: implement Discord account management enhancements and RPC restart functionality

(cherry picked from commit b7c50f1f0184dd717c5cc4dee0310053bfb8d613)

* Notification color & icon for DiscordRPC

Co-Authored-By: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>

* Change foss variant application id suffix to '.foss' and more (mihonapp/mihon#1831)

- Remove `BuildConfig.PREVIEW`
- Rename `BuildConfig.INCLUDE_ANALYTICS` -> `BuildConfig.ANALYTICS_INCLUDED`
- Rename `BuildConfig.INCLUDE_UPDATER` -> `BuildConfig.UPDATER_ENABLED`
- Rename build property `with-analytics` -> `include-analytics`
- Rename build property `with-updater` -> `enable-updater`
- Add build property to disable code shrink
- Add build property to include dependency info in apk/app bundle

(cherry picked from commit 0893609ad2c4791dc404d72a5e69a2e0373517ae)

* feat(discord): update App/icon & fully works with all screens

* update Discord Rich Presence application ID and icon URLs

* Fix updateDiscordRPC for all screens (also reuse code)

* integrate Discord Rich Presence for WebViewScreen

* feat: ghibli style images for Discord RPC

* optimize code

* further optimize

* supprest useless warning

* refactor: simplify setScreen calls related to lastUsedScreen

* optimize whole file

* a

Co-Authored-By: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>

* fix(discord): update download button URL to point to the official website

* feat(discord): allow stop Discord RPC from notification

also improve error handling

* fix(i18n): Torrent server "stop" multi-lang

* Start DiscordRPCService as foreground service on Android O+

This commit modifies the `DiscordRPCService` to start as a foreground service on Android O (API level 26) and above. This change ensures the service continues to run in the background, especially when the app is not in the foreground.

- Added a conditional check using `Build.VERSION.SDK_INT` to detect if the device is running Android O or later.
- If the device is running Android O or later, `startForegroundService` is called instead of `startService` to ensure it runs as foreground service.
- If the device is running a version prior to Android O, `startService` is called.

(cherry picked from commit 869617d8cac3aa8461158f1f9a34b9e29147e8f0)

* fix(discord): episode/chapter formating

* fix(discord): Fix & improve Discord login/accounts

* New webview with DiscordLoginScreen

* Add appbar

* Using Webview directly instead of AndroidView and add clearCookies, browsing navigation

* Using coroutine instead of thread

* Revert service

* use response block

* save preference in coroutine too

* no web navigator

* address comments for DiscordLoginScreen

* Refactor Settings screen & dialog

* Using serialization to parse JSON to avoid blocking API

* Don't clear all cookies and web storage aggressively

* Extract constant

* Fix login

Co-Authored-By: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>

* fix(discord): Fix screen crash & token retrievement

* Update images to my liking

* spotless

* small fixes

* Update strings.xml

* Revert "Update images to my liking"

This reverts commit 4ad3b9f84fdada45ee480ae7dc242b6e1b4bc18a.

* small fixes

* hopeful fix + chapter progress

* Update ReaderActivity.kt

* Update ReaderActivity.kt

* remove timestamps

* Remove isNSFW check

because 95% of tachi extensions are rated as +18, even when there is sfw content

* Clean up

* Fix ReaderActivity

* Cleanup Settings

* Fix login

* Fix lag when getting categories

* Fix jump to pages

* Remove old SDK check

* Fix status when back from reading

* Remove pages progress

* Only set necessary action in ReaderActivity

* Using IO coroutine instead

* Add back timestamps

* Fix strings & settings

* Fix crash

* ActivityType

* Adjust description

* refactor Discord settings menu

* Using its own scope

* Optimize the connection waiting

* remove source.isNSFW

* Using screenModelScope

* Fix state access

* add modifier

* sharing OkHttpClient instance for better resource management

* Restart RPC directly via service intent instead of toggling

* remove lint suppression

* add back showProgress

* Fix set Discord status

* Fix Discord login no avatar

* Handle API rate limits and errors in getDiscordUri

* Token-based isLogged checking

* Make Discord token sensitive data and not in backup

* Minor fix

* remove debug message

---------

Co-authored-by: Cuong-Tran <16017808+cuong-tran@users.noreply.github.com>
Co-authored-by: Cuong-Tran <cuongtran.tm@gmail.com>
Co-authored-by: Dark25 <nadiecaca2000@gmail.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
Co-authored-by: Jery <jery99961@gmail.com>
2025-09-04 12:40:32 +07:00

206 lines
7.7 KiB
Kotlin

package eu.kanade.tachiyomi.di
import android.app.Application
import android.os.Build
import androidx.core.content.ContextCompat
import androidx.sqlite.db.SupportSQLiteDatabase
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
import eu.kanade.domain.track.store.DelayedTrackingStore
import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.BackupRestoreStatus
import eu.kanade.tachiyomi.data.LibraryUpdateStatus
import eu.kanade.tachiyomi.data.SyncStatus
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.data.connections.ConnectionsManager
import eu.kanade.tachiyomi.data.download.DownloadCache
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.DownloadProvider
import eu.kanade.tachiyomi.data.saver.ImageSaver
import eu.kanade.tachiyomi.data.sync.service.GoogleDriveService
import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.network.JavaScriptEngine
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.AndroidSourceManager
import eu.kanade.tachiyomi.util.system.isDebugBuildType
import exh.eh.EHentaiUpdateHelper
import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
import kotlinx.serialization.json.Json
import kotlinx.serialization.protobuf.ProtoBuf
import mihon.core.archive.CbzCrypto
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
import nl.adaptivity.xmlutil.XmlDeclMode
import nl.adaptivity.xmlutil.core.XmlVersion
import nl.adaptivity.xmlutil.serialization.XML
import tachiyomi.core.common.storage.AndroidStorageFolderProvider
import tachiyomi.core.common.storage.UniFileTempFileManager
import tachiyomi.data.AndroidDatabaseHandler
import tachiyomi.data.Database
import tachiyomi.data.DatabaseHandler
import tachiyomi.data.DateColumnAdapter
import tachiyomi.data.History
import tachiyomi.data.Mangas
import tachiyomi.data.StringListColumnAdapter
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.domain.manga.interactor.GetCustomMangaInfo
import tachiyomi.domain.source.service.SourceManager
import tachiyomi.domain.storage.service.StorageManager
import tachiyomi.source.local.image.LocalCoverManager
import tachiyomi.source.local.io.LocalSourceFileSystem
import uy.kohesive.injekt.api.InjektModule
import uy.kohesive.injekt.api.InjektRegistrar
import uy.kohesive.injekt.api.addSingleton
import uy.kohesive.injekt.api.addSingletonFactory
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
// SY -->
private const val LEGACY_DATABASE_NAME = "tachiyomi.db"
// SY <--
class AppModule(val app: Application) : InjektModule {
// SY -->
private val securityPreferences: SecurityPreferences by injectLazy()
// SY <--
override fun InjektRegistrar.registerInjectables() {
addSingleton(app)
addSingletonFactory<SqlDriver> {
// SY -->
if (securityPreferences.encryptDatabase().get()) {
System.loadLibrary("sqlcipher")
}
// SY <--
AndroidSqliteDriver(
schema = Database.Schema,
context = app,
// SY -->
name = if (securityPreferences.encryptDatabase().get()) {
CbzCrypto.DATABASE_NAME
} else {
LEGACY_DATABASE_NAME
},
factory = if (securityPreferences.encryptDatabase().get()) {
SupportOpenHelperFactory(CbzCrypto.getDecryptedPasswordSql(), null, false, 25)
} else if (isDebugBuildType && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Support database inspector in Android Studio
FrameworkSQLiteOpenHelperFactory()
} else {
RequerySQLiteOpenHelperFactory()
},
// SY <--
callback = object : AndroidSqliteDriver.Callback(Database.Schema) {
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
setPragma(db, "foreign_keys = ON")
setPragma(db, "journal_mode = WAL")
setPragma(db, "synchronous = NORMAL")
}
private fun setPragma(db: SupportSQLiteDatabase, pragma: String) {
val cursor = db.query("PRAGMA $pragma")
cursor.moveToFirst()
cursor.close()
}
},
)
}
addSingletonFactory {
Database(
driver = get(),
historyAdapter = History.Adapter(
last_readAdapter = DateColumnAdapter,
),
mangasAdapter = Mangas.Adapter(
genreAdapter = StringListColumnAdapter,
update_strategyAdapter = UpdateStrategyColumnAdapter,
),
)
}
addSingletonFactory<DatabaseHandler> { AndroidDatabaseHandler(get(), get()) }
addSingletonFactory {
Json {
ignoreUnknownKeys = true
explicitNulls = false
}
}
addSingletonFactory {
XML {
defaultPolicy {
ignoreUnknownChildren()
}
autoPolymorphic = true
xmlDeclMode = XmlDeclMode.Charset
indent = 2
xmlVersion = XmlVersion.XML10
}
}
addSingletonFactory<ProtoBuf> {
ProtoBuf
}
addSingletonFactory { UniFileTempFileManager(app) }
addSingletonFactory { ChapterCache(app, get(), get()) }
addSingletonFactory { CoverCache(app) }
addSingletonFactory { NetworkHelper(app, get(), isDebugBuildType) }
addSingletonFactory { JavaScriptEngine(app) }
addSingletonFactory<SourceManager> { AndroidSourceManager(app, get(), get()) }
addSingletonFactory { ExtensionManager(app) }
addSingletonFactory { DownloadProvider(app) }
addSingletonFactory { DownloadManager(app) }
addSingletonFactory { DownloadCache(app) }
addSingletonFactory { TrackerManager() }
addSingletonFactory { DelayedTrackingStore(app) }
addSingletonFactory { ImageSaver(app) }
addSingletonFactory { AndroidStorageFolderProvider(app) }
addSingletonFactory { LocalSourceFileSystem(get()) }
addSingletonFactory { LocalCoverManager(app, get()) }
addSingletonFactory { StorageManager(app, get()) }
// SY -->
addSingletonFactory { EHentaiUpdateHelper(app) }
addSingletonFactory { PagePreviewCache(app) }
// SY <--
// KMK -->
addSingletonFactory { BackupRestoreStatus() }
addSingletonFactory { SyncStatus() }
addSingletonFactory { LibraryUpdateStatus() }
// KMK <--
// AM (CONNECTIONS) -->
addSingletonFactory { ConnectionsManager() }
// <-- AM (CONNECTIONS)
// Asynchronously init expensive components for a faster cold start
ContextCompat.getMainExecutor(app).execute {
get<NetworkHelper>()
get<SourceManager>()
get<Database>()
get<DownloadManager>()
// SY -->
get<GetCustomMangaInfo>()
// SY <--
}
addSingletonFactory { GoogleDriveService(app) }
}
}