Skip to content

Commit

Permalink
feat: rework wallpaper changer - allow multiple configs at the same time
Browse files Browse the repository at this point in the history
  • Loading branch information
Bnyro committed Dec 8, 2024
1 parent d0aefe6 commit 73d4ba2
Show file tree
Hide file tree
Showing 10 changed files with 363 additions and 187 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ enum class WallpaperSource {
ONLINE,
FAVORITES,
LOCAL,
NONE;
}
26 changes: 25 additions & 1 deletion app/src/main/java/com/bnyro/wallpaper/obj/WallpaperConfig.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
package com.bnyro.wallpaper.obj

import android.content.Context
import androidx.work.NetworkType
import com.bnyro.wallpaper.R
import com.bnyro.wallpaper.enums.WallpaperSource
import com.bnyro.wallpaper.enums.WallpaperTarget
import com.bnyro.wallpaper.ext.formatMinutes
import com.bnyro.wallpaper.ui.nav.DrawerScreens
import kotlinx.serialization.Serializable

@Serializable
data class WallpaperConfig(
val id: Int,
var changeIntervalMinutes: Int = 12 * 60,
var networkType: NetworkType = NetworkType.CONNECTED,
var target: WallpaperTarget = WallpaperTarget.BOTH,
var source: WallpaperSource = WallpaperSource.ONLINE,
var applyImageFilters: Boolean = true,
var selectedApiRoutes: List<String> = listOf(DrawerScreens.apiScreens[0].route),
var localFolderUris: List<String> = listOf()
)
) {
fun getSummary(context: Context): String {
val targetString = when (target) {
WallpaperTarget.HOME -> R.string.home
WallpaperTarget.LOCK -> R.string.lockscreen
WallpaperTarget.BOTH -> R.string.both
}
val sourceString = when (source) {
WallpaperSource.LOCAL -> R.string.local
WallpaperSource.ONLINE -> R.string.online
WallpaperSource.FAVORITES -> R.string.favorites
}

return "${context.getString(sourceString)} - ${context.getString(targetString)} (${
changeIntervalMinutes.toLong().formatMinutes()
})"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package com.bnyro.wallpaper.receivers
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.bnyro.wallpaper.util.Preferences
import com.bnyro.wallpaper.util.WorkerHelper

class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
WorkerHelper.enqueue(context, true)
WorkerHelper.enqueueOrCancelAll(context, Preferences.getWallpaperConfigs(), true)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.bnyro.wallpaper.ui.components

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand All @@ -10,11 +11,13 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
Expand All @@ -26,10 +29,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import androidx.documentfile.provider.DocumentFile
import androidx.work.NetworkType
import com.bnyro.wallpaper.R
import com.bnyro.wallpaper.obj.WallpaperConfig
import com.bnyro.wallpaper.enums.WallpaperSource
import com.bnyro.wallpaper.enums.WallpaperTarget
import com.bnyro.wallpaper.ext.formatMinutes
import com.bnyro.wallpaper.ui.components.prefs.CheckboxPref
import com.bnyro.wallpaper.ui.components.prefs.MultiSelectionBlockPreference
import com.bnyro.wallpaper.ui.components.prefs.ListPreference
Expand All @@ -38,119 +43,197 @@ import com.bnyro.wallpaper.ui.nav.DrawerScreens
import com.bnyro.wallpaper.util.PickFolderContract
import com.bnyro.wallpaper.util.str

private val changeIntervals = listOf(
15L,
30L,
60L,
180L,
360L,
720L,
1440L
)

private val networkTypes = listOf(
R.string.all_networks to NetworkType.CONNECTED,
R.string.unmetered to NetworkType.UNMETERED,
R.string.metered to NetworkType.METERED,
R.string.not_roaming to NetworkType.NOT_ROAMING,
)

@Composable
fun WallpaperChangerPref(config: WallpaperConfig, onChange: (WallpaperConfig) -> Unit) {
fun WallpaperChangerPrefDialog(
config: WallpaperConfig,
onConfigChange: (WallpaperConfig) -> Unit,
onDismissRequest: () -> Unit
) {
val context = LocalContext.current

var wallpaperSource by remember { mutableStateOf(config.source) }
var wallpaperTarget by remember { mutableStateOf(config.target) }
var changeInterval by remember { mutableIntStateOf(config.changeIntervalMinutes) }
var networkType by remember { mutableStateOf(config.networkType) }
val wallpaperSources =
listOf(R.string.online, R.string.favorites, R.string.local, R.string.none)
var wallpaperEnginesIndices = remember {
config.selectedApiRoutes.map { route ->
DrawerScreens.apiScreens.indexOfFirst { it.route == route }
}
}
val localFolderUris = remember {
config.localFolderUris.toMutableStateList()
}

val localWallpaperDirChooser = rememberLauncherForActivityResult(PickFolderContract()) {
val uri = it ?: return@rememberLauncherForActivityResult

config.localFolderUris += uri.toString()
localFolderUris.add(uri.toString())
onChange(config)
var applyImageFilters by remember {
mutableStateOf(config.applyImageFilters)
}

SettingsCategory(
title = stringResource(
when (config.target) {
WallpaperTarget.BOTH -> R.string.both
WallpaperTarget.HOME -> R.string.home
WallpaperTarget.LOCK -> R.string.lockscreen
AlertDialog(
onDismissRequest = onDismissRequest,
dismissButton = {
DialogButton(stringResource(android.R.string.cancel)) {
onDismissRequest()
}
)
)
val wallpaperSources = listOf(R.string.online, R.string.favorites, R.string.local, R.string.none)
var wallpaperSource by remember { mutableStateOf(config.source) }
ListPreference(
prefKey = null,
title = stringResource(R.string.wallpaper_changer_source),
entries = wallpaperSources.map { stringResource(it) },
values = List(wallpaperSources.size) { index -> index.toString() },
defaultValue = wallpaperSource.ordinal.toString()
) { newValue ->
config.source = WallpaperSource.values()[newValue.toInt()]
wallpaperSource = config.source
onChange(config)
}
},
confirmButton = {
DialogButton(stringResource(android.R.string.ok)) {
val newConfig = WallpaperConfig(
id = config.id,
changeIntervalMinutes = changeInterval,
networkType = networkType,
target = wallpaperTarget,
source = wallpaperSource,
selectedApiRoutes = wallpaperEnginesIndices.map { DrawerScreens.apiScreens[it].route },
localFolderUris = localFolderUris,
applyImageFilters = applyImageFilters
)
onConfigChange(newConfig)
onDismissRequest()
}
},
title = {
Text(stringResource(R.string.wallpaper_changer))
},
text = {
val localWallpaperDirChooser = rememberLauncherForActivityResult(PickFolderContract()) {
val uri = it ?: return@rememberLauncherForActivityResult

Crossfade(targetState = wallpaperSource, label = "wallpaper_source") { state ->
when (state) {
WallpaperSource.ONLINE -> {
var currentSelections = remember {
config.selectedApiRoutes.map { route ->
DrawerScreens.apiScreens.indexOfFirst { it.route == route }
}
}
config.localFolderUris += uri.toString()
localFolderUris.add(uri.toString())
}

Column {
MultiSelectionBlockPreference(
preferenceKey = null,
entries = DrawerScreens.apiScreens.map { it.title.str() },
values = DrawerScreens.apiScreens.map { it.route },
defaultSelections = currentSelections
entries = listOf(R.string.home, R.string.lockscreen).map { stringResource(it) },
values = listOf(WallpaperTarget.HOME, WallpaperTarget.LOCK).map { it.name },
defaultSelections = when (wallpaperTarget) {
WallpaperTarget.BOTH -> listOf(0, 1)
WallpaperTarget.HOME -> listOf(0)
else -> listOf(1)
},
requireAtLeastOne = true
) { selections ->
config.selectedApiRoutes = selections.map { DrawerScreens.apiScreens[it].route }
currentSelections = selections
onChange(config)
wallpaperTarget = when {
selections.size == 2 -> WallpaperTarget.BOTH
selections[0] == 0 -> WallpaperTarget.HOME
else -> WallpaperTarget.LOCK
}
}
}

WallpaperSource.LOCAL -> Column(
modifier = Modifier.fillMaxWidth()
) {
SettingsCategory(title = stringResource(R.string.directories))
ListPreference(
prefKey = null,
title = stringResource(R.string.change_interval),
entries = changeIntervals.map { it.formatMinutes() },
values = changeIntervals.map { it.toString() },
defaultValue = changeInterval.toString()
) {
changeInterval = it.toInt()
}

localFolderUris.forEach {
var selectedDirectoryName by remember {
mutableStateOf("")
AnimatedVisibility(visible = wallpaperSource != WallpaperSource.LOCAL) {
ListPreference(
prefKey = null,
title = stringResource(R.string.network_type),
entries = networkTypes.map { stringResource(id = it.first) },
values = networkTypes.map { it.second.name },
defaultValue = networkType.name
) {
networkType = NetworkType.valueOf(it)
}
}

ListPreference(
prefKey = null,
title = stringResource(R.string.wallpaper_changer_source),
entries = wallpaperSources.map { stringResource(it) },
values = List(wallpaperSources.size) { index -> index.toString() },
defaultValue = wallpaperSource.ordinal.toString()
) { newValue ->
wallpaperSource = WallpaperSource.values()[newValue.toInt()]
}

LaunchedEffect(it) {
DocumentFile.fromTreeUri(context, it.toUri())?.let { file ->
selectedDirectoryName = file.name ?: it
Crossfade(targetState = wallpaperSource, label = "wallpaper_source") { state ->
when (state) {
WallpaperSource.ONLINE -> {
MultiSelectionBlockPreference(
preferenceKey = null,
entries = DrawerScreens.apiScreens.map { it.title.str() },
values = DrawerScreens.apiScreens.map { it.route },
defaultSelections = wallpaperEnginesIndices
) { selections ->
wallpaperEnginesIndices = selections
}
}
}

Spacer(modifier = Modifier.width(12.dp))
Row(
modifier = Modifier.padding(start = 10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(selectedDirectoryName)
Spacer(modifier = Modifier.weight(1f))
ButtonWithIcon(icon = Icons.Default.Delete) {
config.localFolderUris -= it
localFolderUris.remove(it)
onChange(config)
WallpaperSource.LOCAL -> Column(
modifier = Modifier.fillMaxWidth()
) {
SettingsCategory(title = stringResource(R.string.directories))

localFolderUris.forEach {
var selectedDirectoryName by remember {
mutableStateOf("")
}

LaunchedEffect(it) {
DocumentFile.fromTreeUri(context, it.toUri())?.let { file ->
selectedDirectoryName = file.name ?: it
}
}

Spacer(modifier = Modifier.width(12.dp))
Row(
modifier = Modifier.padding(start = 10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(selectedDirectoryName)
Spacer(modifier = Modifier.weight(1f))
ButtonWithIcon(icon = Icons.Default.Delete) {
localFolderUris.remove(it)
}
}
}

Button(
onClick = {
localWallpaperDirChooser.launch(null)
}
) {
Text(stringResource(R.string.choose_dir))
}
}

else -> Unit
}
}

Button(
onClick = {
localWallpaperDirChooser.launch(null)
}
) {
Text(stringResource(R.string.choose_dir))
CheckboxPref(
prefKey = null,
title = stringResource(id = R.string.apply_image_filters),
defaultValue = applyImageFilters
) { newValue ->
applyImageFilters = newValue
}
}

else -> Unit
}
}

var applyImageFilters by remember {
mutableStateOf(config.applyImageFilters)
}
CheckboxPref(
prefKey = null,
title = stringResource(id = R.string.apply_image_filters),
defaultValue = applyImageFilters
) { newValue ->
config.applyImageFilters = newValue
applyImageFilters = newValue
onChange(config)
}
)
}
Loading

0 comments on commit 73d4ba2

Please sign in to comment.