Skip to content

Commit

Permalink
Refactored album view and album logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Anthonyy232 committed Nov 15, 2024
1 parent 47fa756 commit 26f1e17
Show file tree
Hide file tree
Showing 31 changed files with 1,105 additions and 1,234 deletions.
101 changes: 64 additions & 37 deletions app/src/main/java/com/anthonyla/paperize/core/WallpaperUtil.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
package com.anthonyla.paperize.core
import android.R.attr.order
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
Expand All @@ -18,6 +17,7 @@ import android.graphics.Shader
import android.net.Uri
import android.os.Build
import android.provider.DocumentsContract
import android.util.Base64
import android.util.DisplayMetrics
import android.util.Log
import android.util.Size
Expand All @@ -36,6 +36,11 @@ import com.google.android.renderscript.Toolkit
import com.lazygeniouz.dfc.file.DocumentFileCompat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.nio.charset.Charset
import java.util.zip.DeflaterOutputStream
import java.util.zip.InflaterInputStream


enum class Type { HOME, LOCK, SINGLE, REFRESH }
Expand Down Expand Up @@ -395,7 +400,7 @@ suspend fun getWallpaperFromFolder(folderUri: String, context: Context): List<Wa
wallpapers.add(
Wallpaper(
initialAlbumName = "",
wallpaperUri = documentUri.toString(),
wallpaperUri = documentUri.toString().compress("content://com.android.externalstorage.documents/"),
fileName = displayName.substringBeforeLast('.', displayName),
dateModified = dateModified,
order = wallpapers.size + 1,
Expand Down Expand Up @@ -457,46 +462,31 @@ suspend fun getImageMetadata(context: Context, uriString: String): Metadata = wi
}

/**
* Helper function to find the first valid URI from a list of wallpapers
* It will search through all wallpapers of an album first, and then all wallpapers of every folder of an album
* Helper function to find the first valid URI from a list of wallpapers and folders
*/
fun findFirstValidUri(context: Context, wallpapers: List<Wallpaper>, folders: List<Folder>): String? {
wallpapers.forEach { wallpaper ->
try {
val file = DocumentFileCompat.fromSingleUri(context, wallpaper.wallpaperUri.toUri())
if (file?.exists() == true) {
return wallpaper.wallpaperUri
}
} catch (_: Exception) {
val file = DocumentFile.fromSingleUri(context, wallpaper.wallpaperUri.toUri())
if (file?.exists() == true) {
return wallpaper.wallpaperUri
}
}
}
suspend fun findFirstValidUri(
context: Context,
folders: List<Folder>,
wallpapers: List<Wallpaper>
): String? = withContext(Dispatchers.IO) {
// Check folder wallpapers first
folders.forEach { folder ->
folder.wallpapers.forEach { wallpaper ->
try {
val file = DocumentFileCompat.fromSingleUri(context, wallpaper.wallpaperUri.toUri())
if (file?.exists() == true) {
return wallpaper.wallpaperUri
}
} catch (_: Exception) {
val file = DocumentFile.fromSingleUri(context, wallpaper.wallpaperUri.toUri())
if (file?.exists() == true) {
return wallpaper.wallpaperUri
}
}
isValidUri(context, wallpaper.wallpaperUri).let { return@withContext wallpaper.wallpaperUri }
}
}
return null
// Then check individual wallpapers
wallpapers.forEach { wallpaper ->
isValidUri(context, wallpaper.wallpaperUri).let { return@withContext wallpaper.wallpaperUri }
}
return@withContext null
}

/**
* Get the folder name from the folder URI
*/
fun getFolderNameFromUri(folderUri: String, context: Context): String? {
return try {
suspend fun getFolderNameFromUri(folderUri: String, context: Context): String? = withContext(Dispatchers.IO) {
return@withContext try {
DocumentFileCompat.fromTreeUri(context, folderUri.toUri())?.name
} catch (_: Exception) {
DocumentFile.fromTreeUri(context, folderUri.toUri())?.name
Expand All @@ -507,14 +497,51 @@ fun getFolderNameFromUri(folderUri: String, context: Context): String? {
* Check if a URI is valid
*/
fun isValidUri(context: Context, uriString: String?): Boolean {
val uri = uriString?.decompress("content://com.android.externalstorage.documents/")?.toUri()
if (uri == null) { return false }
return try {
DocumentFileCompat.fromSingleUri(context, uri)?.exists() ?: false
} catch (_: Exception) {
DocumentFile.fromSingleUri(context, uri)?.exists() ?: false
}
}

fun isDirectory(context: Context, uriString: String?): Boolean {
val uri = uriString?.toUri()
if (uri == null) { return false }
return try {
uri?.let {
val inputStream = context.contentResolver.openInputStream(it)
inputStream?.close()
DocumentFileCompat.fromSingleUri(context, uri)?.isDirectory() ?: false
} catch (_: Exception) {
DocumentFile.fromSingleUri(context, uri)?.isDirectory ?: false
}
}

/**
* Compress a string
*/
fun String.compress(prefixToRemove: String, charset: Charset = Charsets.UTF_8): String {
val modifiedInput = if (this.startsWith(prefixToRemove)) {
this.removePrefix(prefixToRemove)
} else { this }
ByteArrayOutputStream().use { byteStream ->
DeflaterOutputStream(byteStream).use { deflaterStream ->
deflaterStream.write(modifiedInput.toByteArray(charset))
}
return Base64.encodeToString(byteStream.toByteArray(), Base64.DEFAULT)
}
}

/**
* Decompress a string
*/
fun String.decompress(prefixToAdd: String, charset: Charset = Charsets.UTF_8): String {
val compressedData = Base64.decode(this, Base64.DEFAULT)
ByteArrayInputStream(compressedData).use { byteStream ->
InflaterInputStream(byteStream).use { inflaterStream ->
val decompressedBytes = inflaterStream.readBytes()
return prefixToAdd + String(decompressedBytes, charset)
}
true
} catch (_: Exception) { false }
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.anthonyla.paperize.feature.wallpaper.domain.model.Wallpaper
*/
@Database(
entities = [Album::class, Wallpaper::class, Folder::class],
version = 9
version = 10
)
@TypeConverters(Converters::class)
abstract class AlbumDatabase: RoomDatabase() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,6 @@ class AlbumRepositoryImpl(
}
}

override suspend fun upsertAlbumWithWallpaperAndFolder(albumWithWallpaperAndFolder: AlbumWithWallpaperAndFolder) {
withContext(dispatcher) {
dao.upsertAlbum(albumWithWallpaperAndFolder.album)
dao.upsertWallpaperList(albumWithWallpaperAndFolder.wallpapers)
dao.upsertFolderList(albumWithWallpaperAndFolder.folders)
}
}

override fun getSelectedAlbums(): Flow<List<AlbumWithWallpaperAndFolder>> {
return dao.getSelectedAlbums().map { albumWithWallpaperAndFolderList ->
albumWithWallpaperAndFolderList.map {
Expand All @@ -48,6 +40,14 @@ class AlbumRepositoryImpl(
}
}

override suspend fun upsertAlbumWithWallpaperAndFolder(albumWithWallpaperAndFolder: AlbumWithWallpaperAndFolder) {
withContext(dispatcher) {
dao.upsertAlbum(albumWithWallpaperAndFolder.album)
dao.upsertWallpaperList(albumWithWallpaperAndFolder.wallpapers)
dao.upsertFolderList(albumWithWallpaperAndFolder.folders)
}
}

override suspend fun updateAlbumSelection(albumName: String, selected: Boolean) {
withContext(dispatcher) {
dao.updateAlbumSelection(albumName, selected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import androidx.room.PrimaryKey
* @param initialAlbumName The initial album name -- should not be changed as it is used as the key for database queries
* @param displayedAlbumName The displayed album name
* @param coverUri The cover uri of the album
* @param initialized Whether the album has been initialized
* @param homeWallpapersInQueue The list of home wallpapers in the queue
* @param lockWallpapersInQueue The list of lock wallpapers in the queue
* @param selected Whether the album is selected
Expand All @@ -19,7 +18,6 @@ data class Album(
@PrimaryKey(autoGenerate = false) val initialAlbumName: String,
val displayedAlbumName: String,
val coverUri: String?,
val initialized: Boolean = false,
val homeWallpapersInQueue: List<String> = emptyList(),
val lockWallpapersInQueue: List<String> = emptyList(),
val selected : Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,10 @@ import androidx.lifecycle.lifecycleScope
import com.anthonyla.paperize.core.SettingsConstants
import com.anthonyla.paperize.core.Type
import com.anthonyla.paperize.data.settings.SettingsDataStore
import com.anthonyla.paperize.feature.wallpaper.presentation.album.AlbumsEvent
import com.anthonyla.paperize.feature.wallpaper.presentation.album.AlbumsViewModel
import com.anthonyla.paperize.feature.wallpaper.presentation.settings_screen.SettingsEvent
import com.anthonyla.paperize.feature.wallpaper.presentation.settings_screen.SettingsState
import com.anthonyla.paperize.feature.wallpaper.presentation.settings_screen.SettingsViewModel
import com.anthonyla.paperize.feature.wallpaper.presentation.themes.PaperizeTheme
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.WallpaperEvent
import com.anthonyla.paperize.feature.wallpaper.presentation.wallpaper_screen.WallpaperScreenViewModel
import com.anthonyla.paperize.feature.wallpaper.wallpaper_alarmmanager.WallpaperAlarmItem
import com.anthonyla.paperize.feature.wallpaper.wallpaper_alarmmanager.WallpaperAlarmSchedulerImpl
import com.anthonyla.paperize.feature.wallpaper.wallpaper_alarmmanager.WallpaperReceiver
Expand All @@ -53,11 +49,9 @@ import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val albumsViewModel: AlbumsViewModel by viewModels()
@Inject lateinit var settingsDataStoreImpl: SettingsDataStore
private val settingsViewModel: SettingsViewModel by viewModels()
private val wallpaperScreenViewModel: WallpaperScreenViewModel by viewModels()
private val context = this
@Inject lateinit var settingsDataStoreImpl: SettingsDataStore
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge(
statusBarStyle = SystemBarStyle.light(Color.TRANSPARENT, Color.TRANSPARENT),
Expand All @@ -84,9 +78,6 @@ class MainActivity : ComponentActivity() {
val settingsState = settingsViewModel.state.collectAsStateWithLifecycle()
val isFirstLaunch = runBlocking { settingsDataStoreImpl.getBoolean(SettingsConstants.FIRST_LAUNCH) } ?: true
val scheduler = WallpaperAlarmSchedulerImpl(context)
if (isFirstLaunch) {
handleFirstLaunch(scheduler)
}

LifecycleEventEffect(Lifecycle.Event.ON_CREATE) {
lifecycleScope.launch {
Expand All @@ -109,44 +100,22 @@ class MainActivity : ComponentActivity() {
}
}

private fun handleFirstLaunch(scheduler: WallpaperAlarmSchedulerImpl) {
scheduler.cancelWallpaperAlarm()
wallpaperScreenViewModel.onEvent(WallpaperEvent.Reset)
settingsViewModel.onEvent(SettingsEvent.Reset)
albumsViewModel.onEvent(AlbumsEvent.Reset)
clearPersistedUriPermissions()
}

private fun clearPersistedUriPermissions() {
val contentResolver = context.contentResolver
val persistedUris = contentResolver.persistedUriPermissions
for (permission in persistedUris) {
contentResolver.releasePersistableUriPermission(
permission.uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
}
}

private fun handleWallpaperScheduling(
settings: SettingsState,
scheduler: WallpaperAlarmSchedulerImpl
) {
val wallpaperSettings = settings.wallpaperSettings
val scheduleSettings = settings.scheduleSettings

if (!wallpaperSettings.enableChanger) return
if (wallpaperSettings.homeAlbumName.isNullOrEmpty() || wallpaperSettings.lockAlbumName.isNullOrEmpty()) {
settingsViewModel.onEvent(SettingsEvent.SetChangerToggle(false))
return
}

val shouldScheduleAlarm = if (scheduleSettings.scheduleSeparately) {
!(isPendingIntentSet(Type.HOME.ordinal) && isPendingIntentSet(Type.LOCK.ordinal))
} else {
!isPendingIntentSet(Type.SINGLE.ordinal)
}

if (shouldScheduleAlarm) {
scheduleWallpaperAlarm(settings, scheduler)
}
Expand All @@ -158,7 +127,6 @@ class MainActivity : ComponentActivity() {
) {
val scheduleSettings = settings.scheduleSettings
val wallpaperSettings = settings.wallpaperSettings

scheduler.scheduleWallpaperAlarm(
WallpaperAlarmItem(
homeInterval = scheduleSettings.homeInterval,
Expand Down
Loading

0 comments on commit 26f1e17

Please sign in to comment.