Skip to content

Commit

Permalink
feat: patch bundle sources system (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
Axelen123 authored May 26, 2023
1 parent a4842c0 commit c22371e
Show file tree
Hide file tree
Showing 40 changed files with 1,064 additions and 170 deletions.
13 changes: 13 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.devtools.ksp")
id("kotlin-parcelize")
kotlin("plugin.serialization") version "1.8.21"
}
Expand Down Expand Up @@ -37,6 +38,10 @@ android {
}
}

ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}

kotlinOptions {
jvmTarget = "11"
}
Expand Down Expand Up @@ -78,6 +83,14 @@ dependencies {
// KotlinX
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")

// Room
val roomVersion = "2.5.1"
implementation("androidx.room:room-runtime:$roomVersion")
implementation("androidx.room:room-ktx:$roomVersion")
annotationProcessor("androidx.room:room-compiler:$roomVersion")
ksp("androidx.room:room-compiler:$roomVersion")


// ReVanced
implementation("app.revanced:revanced-patcher:7.1.0")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "b40f3b048880f3f3c9361f6d1c4aaea5",
"entities": [
{
"tableName": "sources",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER NOT NULL, `name` TEXT NOT NULL, `location` TEXT NOT NULL, `version` TEXT NOT NULL, `integrations_version` TEXT NOT NULL, PRIMARY KEY(`uid`))",
"fields": [
{
"fieldPath": "uid",
"columnName": "uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "location",
"columnName": "location",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "versionInfo.patches",
"columnName": "version",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "versionInfo.integrations",
"columnName": "integrations_version",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"uid"
]
},
"indices": [
{
"name": "index_sources_name",
"unique": true,
"columnNames": [
"name"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_sources_name` ON `${TABLE_NAME}` (`name`)"
}
],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b40f3b048880f3f3c9361f6d1c4aaea5')"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import app.revanced.manager.compose.domain.manager.PreferencesManager
import app.revanced.manager.compose.domain.repository.BundleRepository
import app.revanced.manager.compose.ui.destination.Destination
import app.revanced.manager.compose.ui.screen.*
import app.revanced.manager.compose.ui.theme.ReVancedManagerTheme
Expand All @@ -22,6 +23,7 @@ import org.koin.core.parameter.parametersOf

class MainActivity : ComponentActivity() {
private val prefs: PreferencesManager by inject()
private val bundleRepository: BundleRepository by inject()
private val mainScope = MainScope()

@ExperimentalAnimationApi
Expand All @@ -30,6 +32,8 @@ class MainActivity : ComponentActivity() {

installSplashScreen()

bundleRepository.onAppStart(this@MainActivity)

val context = this
mainScope.launch(Dispatchers.IO) {
PM.loadApps(context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ class ManagerApplication : Application() {
preferencesModule,
repositoryModule,
serviceModule,
managerModule,
workerModule,
viewModelModule,
databaseModule,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package app.revanced.manager.compose.data.room

import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import app.revanced.manager.compose.data.room.sources.SourceEntity
import app.revanced.manager.compose.data.room.sources.SourceDao

@Database(entities = [SourceEntity::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun sourceDao(): SourceDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package app.revanced.manager.compose.data.room

import androidx.room.TypeConverter
import app.revanced.manager.compose.data.room.sources.SourceLocation
import io.ktor.http.*

class Converters {
@TypeConverter
fun locationFromString(value: String) = when(value) {
SourceLocation.Local.SENTINEL -> SourceLocation.Local
else -> SourceLocation.Remote(Url(value))
}

@TypeConverter
fun locationToString(location: SourceLocation) = location.toString()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package app.revanced.manager.compose.data.room.sources

import androidx.room.*

@Dao
interface SourceDao {
@Query("SELECT * FROM $sourcesTableName")
suspend fun all(): List<SourceEntity>

@Query("SELECT version, integrations_version FROM $sourcesTableName WHERE uid = :uid")
suspend fun getVersionById(uid: Int): VersionInfo

@Query("UPDATE $sourcesTableName SET version=:patches, integrations_version=:integrations WHERE uid=:uid")
suspend fun updateVersion(uid: Int, patches: String, integrations: String)

@Query("DELETE FROM $sourcesTableName")
suspend fun purge()

@Query("DELETE FROM $sourcesTableName WHERE uid=:uid")
suspend fun remove(uid: Int)

@Insert
suspend fun add(source: SourceEntity)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package app.revanced.manager.compose.data.room.sources

import androidx.room.*
import io.ktor.http.*

const val sourcesTableName = "sources"

sealed class SourceLocation {
object Local : SourceLocation() {
const val SENTINEL = "local"

override fun toString() = SENTINEL
}

data class Remote(val url: Url) : SourceLocation() {
override fun toString() = url.toString()
}
}

data class VersionInfo(
@ColumnInfo(name = "version") val patches: String,
@ColumnInfo(name = "integrations_version") val integrations: String,
)

@Entity(tableName = sourcesTableName, indices = [Index(value = ["name"], unique = true)])
data class SourceEntity(
@PrimaryKey val uid: Int,
@ColumnInfo(name = "name") val name: String,
@Embedded val versionInfo: VersionInfo,
@ColumnInfo(name = "location") val location: SourceLocation,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package app.revanced.manager.compose.di

import android.content.Context
import androidx.room.Room
import app.revanced.manager.compose.data.room.AppDatabase
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module

val databaseModule = module {
fun provideAppDatabase(context: Context) = Room.databaseBuilder(context, AppDatabase::class.java, "manager").build()

single {
provideAppDatabase(androidContext())
}
}
10 changes: 10 additions & 0 deletions app/src/main/java/app/revanced/manager/compose/di/ManagerModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package app.revanced.manager.compose.di

import app.revanced.manager.compose.domain.repository.SourceRepository
import app.revanced.manager.compose.patcher.SignerService
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module

val managerModule = module {
singleOf(::SignerService)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ package app.revanced.manager.compose.di

import app.revanced.manager.compose.domain.repository.ReVancedRepository
import app.revanced.manager.compose.network.api.ManagerAPI
import app.revanced.manager.compose.patcher.data.repository.PatchesRepository
import app.revanced.manager.compose.domain.repository.BundleRepository
import app.revanced.manager.compose.domain.repository.SourcePersistenceRepository
import app.revanced.manager.compose.domain.repository.SourceRepository
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module

val repositoryModule = module {
singleOf(::ReVancedRepository)
singleOf(::ManagerAPI)
singleOf(::PatchesRepository)
singleOf(::BundleRepository)
singleOf(::SourcePersistenceRepository)
singleOf(::SourceRepository)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package app.revanced.manager.compose.di

import app.revanced.manager.compose.network.service.HttpService
import app.revanced.manager.compose.network.service.ReVancedService
import app.revanced.manager.compose.patcher.SignerService
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module

Expand All @@ -17,5 +16,4 @@ val serviceModule = module {

single { provideReVancedService(get()) }
singleOf(::HttpService)
singleOf(::SignerService)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package app.revanced.manager.compose.di

import app.revanced.manager.compose.ui.viewmodel.AppSelectorViewModel
import app.revanced.manager.compose.ui.viewmodel.InstallerScreenViewModel
import app.revanced.manager.compose.ui.viewmodel.PatchesSelectorViewModel
import app.revanced.manager.compose.ui.viewmodel.SettingsViewModel
import app.revanced.manager.compose.ui.viewmodel.UpdateSettingsViewModel
import app.revanced.manager.compose.ui.viewmodel.*
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.dsl.module
Expand All @@ -13,11 +9,12 @@ val viewModelModule = module {
viewModel {
PatchesSelectorViewModel(
packageInfo = it.get(),
patchesRepository = get()
bundleRepository = get()
)
}
viewModelOf(::SettingsViewModel)
viewModelOf(::AppSelectorViewModel)
viewModelOf(::SourcesScreenViewModel)
viewModel {
InstallerScreenViewModel(
input = it.get(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package app.revanced.manager.compose.domain.repository

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import app.revanced.manager.compose.patcher.patch.PatchBundle
import app.revanced.manager.compose.util.launchAndRepeatWithViewLifecycle
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch

class BundleRepository(private val sourceRepository: SourceRepository) {
/**
* A [Flow] that emits whenever the sources change.
*
* The outer flow emits whenever the sources configuration changes.
* The inner flow emits whenever one of the bundles update.
*/
private val sourceUpdates = sourceRepository.sources.map { sources ->
sources.map { (name, source) ->
source.bundle.map { bundle ->
name to bundle
}
}.merge().buffer()
}

private val _bundles = MutableStateFlow<Map<String, PatchBundle>>(emptyMap())

/**
* A [Flow] that gives you all loaded [PatchBundle]s.
* This is only synced when the app is in the foreground.
*/
val bundles = _bundles.asStateFlow()

fun onAppStart(lifecycleOwner: LifecycleOwner) {
lifecycleOwner.lifecycleScope.launch {
sourceRepository.loadSources()
}

lifecycleOwner.launchAndRepeatWithViewLifecycle {
sourceUpdates.collect { events ->
val map = HashMap<String, PatchBundle>()
_bundles.emit(map)

events.collect { (name, new) ->
map[name] = new
_bundles.emit(map)
}
}
}
}
}
Loading

0 comments on commit c22371e

Please sign in to comment.