Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import zed.rainxch.core.data.services.UpdateScheduler
import zed.rainxch.core.domain.model.InstallSource
import zed.rainxch.core.domain.model.InstalledApp
import zed.rainxch.core.domain.repository.InstalledAppsRepository
import zed.rainxch.core.domain.repository.ThemesRepository
import zed.rainxch.core.domain.repository.TweaksRepository
import zed.rainxch.core.domain.system.PackageMonitor
import zed.rainxch.githubstore.app.di.initKoin

Expand Down Expand Up @@ -83,7 +83,7 @@ class GithubStoreApp : Application() {
private fun scheduleBackgroundUpdateChecks() {
appScope.launch {
try {
val intervalHours = get<ThemesRepository>().getUpdateCheckInterval().first()
val intervalHours = get<TweaksRepository>().getUpdateCheckInterval().first()
UpdateScheduler.schedule(
context = this@GithubStoreApp,
intervalHours = intervalHours,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ fun App(deepLinkUri: String? = null) {

AppNavigation(
navController = navController,
isLiquidGlassEnabled = state.isLiquidGlassEnabled,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ data class MainState(
val isAmoledTheme: Boolean = false,
val isDarkTheme: Boolean? = null,
val currentFontTheme: FontTheme = FontTheme.CUSTOM,
val isLiquidGlassEnabled: Boolean = true,
)
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import kotlinx.coroutines.launch
import zed.rainxch.core.domain.repository.AuthenticationState
import zed.rainxch.core.domain.repository.InstalledAppsRepository
import zed.rainxch.core.domain.repository.RateLimitRepository
import zed.rainxch.core.domain.repository.ThemesRepository
import zed.rainxch.core.domain.repository.TweaksRepository
import zed.rainxch.core.domain.use_cases.SyncInstalledAppsUseCase

class MainViewModel(
private val themesRepository: ThemesRepository,
private val tweaksRepository: TweaksRepository,
private val installedAppsRepository: InstalledAppsRepository,
private val authenticationState: AuthenticationState,
private val rateLimitRepository: RateLimitRepository,
Expand All @@ -37,7 +37,7 @@ class MainViewModel(
}

viewModelScope.launch {
themesRepository
tweaksRepository
.getThemeColor()
.collect { theme ->
_state.update {
Expand All @@ -46,7 +46,7 @@ class MainViewModel(
}
}
viewModelScope.launch {
themesRepository
tweaksRepository
.getAmoledTheme()
.collect { isAmoled ->
_state.update {
Expand All @@ -55,7 +55,7 @@ class MainViewModel(
}
}
viewModelScope.launch {
themesRepository
tweaksRepository
.getIsDarkTheme()
.collect { isDarkTheme ->
_state.update {
Expand All @@ -65,7 +65,7 @@ class MainViewModel(
}

viewModelScope.launch {
themesRepository
tweaksRepository
.getFontTheme()
.collect { fontTheme ->
_state.update {
Expand All @@ -74,6 +74,12 @@ class MainViewModel(
}
}

viewModelScope.launch {
tweaksRepository.getLiquidGlassEnabled().collect { enabled ->
_state.update { it.copy(isLiquidGlassEnabled = enabled) }
}
}

viewModelScope.launch {
rateLimitRepository.rateLimitState.collect { rateLimitInfo ->
_state.update { currentState ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ val mainModule: Module =
module {
viewModel {
MainViewModel(
themesRepository = get(),
tweaksRepository = get(),
installedAppsRepository = get(),
rateLimitRepository = get(),
syncUseCase = get(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ import zed.rainxch.search.presentation.SearchRoot
import zed.rainxch.starred.presentation.StarredReposRoot

@Composable
fun AppNavigation(navController: NavHostController) {
fun AppNavigation(
navController: NavHostController,
isLiquidGlassEnabled: Boolean = true,
) {
val liquidState = rememberLiquidState()
var bottomNavigationHeight by remember { mutableStateOf(0.dp) }
val density = LocalDensity.current
Expand Down Expand Up @@ -294,6 +297,7 @@ fun AppNavigation(navController: NavHostController) {
}
},
isUpdateAvailable = appsState.apps.any { it.installedApp.isUpdateAvailable },
isLiquidGlassEnabled = isLiquidGlassEnabled,
modifier =
Modifier
.align(Alignment.BottomCenter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
Expand Down Expand Up @@ -65,6 +66,7 @@ fun BottomNavigation(
currentScreen: GithubStoreGraph,
onNavigate: (GithubStoreGraph) -> Unit,
isUpdateAvailable: Boolean,
isLiquidGlassEnabled: Boolean = true,
modifier: Modifier = Modifier,
) {
val liquidState = LocalBottomNavigationLiquid.current
Expand Down Expand Up @@ -129,31 +131,36 @@ fun BottomNavigation(
modifier = modifier,
contentAlignment = Alignment.Center,
) {
val useLiquid = isLiquidGlassEnabled && isLiquidFrostAvailable()

Box(
modifier =
Modifier
.clip(CircleShape)
.background(
if (isLiquidFrostAvailable()) {
MaterialTheme.colorScheme.surfaceContainerHighest.copy(
alpha = if (isDarkTheme) .25f else .15f,
)
} else {
MaterialTheme.colorScheme.surfaceContainerHighest
},
).then(
if (isLiquidFrostAvailable()) {
Modifier.liquid(liquidState) {
this.shape = CircleShape
this.frost = if (isDarkTheme) 12.dp else 10.dp
this.curve = if (isDarkTheme) .35f else .45f
this.refraction = if (isDarkTheme) .08f else .12f
this.dispersion = if (isDarkTheme) .18f else .25f
this.saturation = if (isDarkTheme) .40f else .55f
this.contrast = if (isDarkTheme) 1.8f else 1.6f
}
.then(
if (useLiquid) {
Modifier
.background(
MaterialTheme.colorScheme.surfaceContainerHighest.copy(
alpha = if (isDarkTheme) .25f else .15f,
),
).liquid(liquidState) {
this.shape = CircleShape
this.frost = if (isDarkTheme) 12.dp else 10.dp
this.curve = if (isDarkTheme) .35f else .45f
this.refraction = if (isDarkTheme) .08f else .12f
this.dispersion = if (isDarkTheme) .18f else .25f
this.saturation = if (isDarkTheme) .40f else .55f
this.contrast = if (isDarkTheme) 1.8f else 1.6f
}
} else {
Modifier
.background(MaterialTheme.colorScheme.surfaceContainer)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.outlineVariant,
shape = CircleShape,
)
},
).pointerInput(Unit) { },
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import org.koin.dsl.module
import zed.rainxch.core.data.local.data_store.createDataStore
import zed.rainxch.core.data.local.db.AppDatabase
import zed.rainxch.core.data.local.db.initDatabase
import zed.rainxch.core.data.services.AndroidInstallerInfoExtractor
import zed.rainxch.core.data.services.AndroidDownloader
import zed.rainxch.core.data.services.AndroidFileLocationsProvider
import zed.rainxch.core.data.services.AndroidInstaller
import zed.rainxch.core.data.services.AndroidInstallerInfoExtractor
import zed.rainxch.core.data.services.AndroidLocalizationManager
import zed.rainxch.core.data.services.AndroidPackageMonitor
import zed.rainxch.core.data.services.AndroidUpdateScheduleManager
import zed.rainxch.core.data.services.FileLocationsProvider
import zed.rainxch.core.data.services.LocalizationManager
import zed.rainxch.core.data.services.shizuku.AndroidInstallerStatusProvider
Expand All @@ -24,7 +25,6 @@ import zed.rainxch.core.data.utils.AndroidBrowserHelper
import zed.rainxch.core.data.utils.AndroidClipboardHelper
import zed.rainxch.core.data.utils.AndroidShareManager
import zed.rainxch.core.domain.network.Downloader
import zed.rainxch.core.data.services.AndroidUpdateScheduleManager
import zed.rainxch.core.domain.system.Installer
import zed.rainxch.core.domain.system.InstallerStatusProvider
import zed.rainxch.core.domain.system.PackageMonitor
Expand All @@ -34,100 +34,99 @@ import zed.rainxch.core.domain.utils.BrowserHelper
import zed.rainxch.core.domain.utils.ClipboardHelper
import zed.rainxch.core.domain.utils.ShareManager

actual val corePlatformModule = module {
// Core
actual val corePlatformModule =
module {
// Core

single<Downloader> {
AndroidDownloader(
files = get(),
)
}

// AndroidInstaller — registered by class so the wrapper can inject it
single {
AndroidInstaller(
context = get(),
installerInfoExtractor = AndroidInstallerInfoExtractor(androidContext())
)
}
single<Downloader> {
AndroidDownloader(
files = get(),
)
}

// ShizukuServiceManager — manages Shizuku lifecycle, permissions, service binding
single {
ShizukuServiceManager(
context = androidContext()
).also { it.initialize() }
}
// AndroidInstaller — registered by class so the wrapper can inject it
single {
AndroidInstaller(
context = get(),
installerInfoExtractor = AndroidInstallerInfoExtractor(androidContext()),
)
}

// Installer — the ShizukuInstallerWrapper is the public Installer singleton.
// It delegates to AndroidInstaller by default, intercepting with Shizuku when enabled.
single<Installer> {
ShizukuInstallerWrapper(
androidInstaller = get<AndroidInstaller>(),
shizukuServiceManager = get(),
themesRepository = get()
).also { wrapper ->
wrapper.observeInstallerPreference(get<CoroutineScope>())
// ShizukuServiceManager — manages Shizuku lifecycle, permissions, service binding
single {
ShizukuServiceManager(
context = androidContext(),
).also { it.initialize() }
}
}

// InstallerStatusProvider — exposes Shizuku availability to the UI layer
single<InstallerStatusProvider> {
AndroidInstallerStatusProvider(
shizukuServiceManager = get(),
scope = get()
)
}
// Installer — the ShizukuInstallerWrapper is the public Installer singleton.
// It delegates to AndroidInstaller by default, intercepting with Shizuku when enabled.
single<Installer> {
ShizukuInstallerWrapper(
androidInstaller = get<AndroidInstaller>(),
shizukuServiceManager = get(),
tweaksRepository = get(),
).also { wrapper ->
wrapper.observeInstallerPreference(get<CoroutineScope>())
}
}

single<FileLocationsProvider> {
AndroidFileLocationsProvider(context = get())
}
// InstallerStatusProvider — exposes Shizuku availability to the UI layer
single<InstallerStatusProvider> {
AndroidInstallerStatusProvider(
shizukuServiceManager = get(),
scope = get(),
)
}

single<PackageMonitor> {
AndroidPackageMonitor(androidContext())
}
single<FileLocationsProvider> {
AndroidFileLocationsProvider(context = get())
}

single<LocalizationManager> {
AndroidLocalizationManager()
}
single<PackageMonitor> {
AndroidPackageMonitor(androidContext())
}

// Locals
single<LocalizationManager> {
AndroidLocalizationManager()
}

single<AppDatabase> {
initDatabase(androidContext())
}
// Locals

single<DataStore<Preferences>> {
createDataStore(androidContext())
}
single<AppDatabase> {
initDatabase(androidContext())
}

single<DataStore<Preferences>> {
createDataStore(androidContext())
}

// Utils
// Utils

single<BrowserHelper> {
AndroidBrowserHelper(androidContext())
}
single<BrowserHelper> {
AndroidBrowserHelper(androidContext())
}

single<ClipboardHelper> {
AndroidClipboardHelper(androidContext())
}
single<ClipboardHelper> {
AndroidClipboardHelper(androidContext())
}

single<AppLauncher> {
AndroidAppLauncher(
context = androidContext(),
logger = get()
)
}
single<AppLauncher> {
AndroidAppLauncher(
context = androidContext(),
logger = get(),
)
}

single<ShareManager> {
AndroidShareManager(
context = androidContext()
)
}
single<ShareManager> {
AndroidShareManager(
context = androidContext(),
)
}

single<UpdateScheduleManager> {
AndroidUpdateScheduleManager(
context = androidContext()
)
single<UpdateScheduleManager> {
AndroidUpdateScheduleManager(
context = androidContext(),
)
}
}

}
Loading