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
Empty file.
6 changes: 3 additions & 3 deletions app/src/main/java/com/songlib/core/utils/AppConstants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ object PrefConstants {
const val INITIAL_BOOKS = "initialBooks"
const val SELECTED_BOOKS = "selectedBooks"

const val DATA_SELECTED = "dataSelected"
const val DATA_LOADED = "dataLoaded"
const val SELECT_AFRESH = "selectAfresh"
const val IS_DATA_SELECTED = "dataSelected"
const val IS_DATA_LOADED = "dataLoaded"
const val SELECT_A_FRESH = "selectAfresh"
const val IS_PRO_USER = "isProUser"
const val INSTALL_DATE = "install_date"
const val REVIEW_REQUESTED = "review_requested"
Expand Down
10 changes: 5 additions & 5 deletions app/src/main/java/com/songlib/data/sources/local/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import com.songlib.data.sources.local.daos.*
version = 2, exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {
abstract fun bookDao(): BookDao
abstract fun historyDao(): HistoryDao
abstract fun listingDao(): ListingDao
abstract fun searchDao(): SearchDao
abstract fun songDao(): SongDao
abstract fun booksDao(): BookDao
abstract fun historiesDao(): HistoryDao
abstract fun listingsDao(): ListingDao
abstract fun searchesDao(): SearchDao
abstract fun songsDao(): SongDao

companion object {
@Volatile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ interface BookDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(book: Book)

@Insert(onConflict = OnConflictStrategy.Companion.REPLACE)
suspend fun insertAll(books: List<Book>)

@Update()
fun update(book: Book)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ interface SongDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(song: Song)

@Insert(onConflict = OnConflictStrategy.Companion.REPLACE)
suspend fun insertAll(songs: List<Song>)

@Update()
fun update(song: Song)

Expand Down
20 changes: 10 additions & 10 deletions app/src/main/java/com/songlib/domain/repos/ListingRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import javax.inject.*

@Singleton
class ListingRepo @Inject constructor(context: Context) {
private var listingDao: ListingDao?
private var listingsDao: ListingDao?

init {
val db = AppDatabase.getDatabase(context)
listingDao = db?.listingDao()
listingsDao = db?.listingsDao()
}

suspend fun fetchListings(parent: Int): List<ListingUi> {
return withContext(Dispatchers.IO) {
val allListings = listingDao?.getAll(parent) ?: emptyList()
val allListings = listingsDao?.getAll(parent) ?: emptyList()

allListings.map { listing ->
ListingUi(
Expand All @@ -29,7 +29,7 @@ class ListingRepo @Inject constructor(context: Context) {
song = listing.song,
created = listing.created,
modified = listing.modified,
songCount = listingDao?.countSongs(listing.id) ?: 0,
songCount = listingsDao?.countSongs(listing.id) ?: 0,
updatedAgo = listing.modified.toLongOrNull()?.toTimeAgo() ?: ""
)
}
Expand All @@ -46,21 +46,21 @@ class ListingRepo @Inject constructor(context: Context) {
created = currentTime,
modified = currentTime
)
listingDao?.insert(newListing)
listingsDao?.insert(newListing)
}
}

suspend fun saveListItem(parent: ListingUi, song: Int) {
withContext(Dispatchers.IO) {
val currentTime = System.currentTimeMillis().toString()
listingDao?.insert(Listing(
listingsDao?.insert(Listing(
parent = parent.id,
title = "",
song = song,
created = currentTime,
modified = currentTime
))
listingDao?.update(Listing(
listingsDao?.update(Listing(
parent = parent.id,
title = parent.title,
song = song,
Expand All @@ -73,7 +73,7 @@ class ListingRepo @Inject constructor(context: Context) {
suspend fun updateListing(listing: ListingUi) {
val currentTime = System.currentTimeMillis().toString()
withContext(Dispatchers.IO) {
listingDao?.update(Listing(
listingsDao?.update(Listing(
parent = listing.id,
title = listing.title,
song = listing.song,
Expand All @@ -85,13 +85,13 @@ class ListingRepo @Inject constructor(context: Context) {

suspend fun deleteById(listId: Int) {
withContext(Dispatchers.IO) {
listingDao?.deleteById(listId)
listingsDao?.deleteById(listId)
}
}

suspend fun deleteAllListings() {
withContext(Dispatchers.IO) {
listingDao?.deleteAll()
listingsDao?.deleteAll()
}
}

Expand Down
55 changes: 45 additions & 10 deletions app/src/main/java/com/songlib/domain/repos/PrefsRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,48 @@ class PrefsRepo @Inject constructor(
set(value) = prefs.edit { putString(PrefConstants.SELECTED_BOOKS, value) }

var isDataSelected: Boolean
get() = prefs.getBoolean(PrefConstants.DATA_SELECTED, false)
set(value) = prefs.edit { putBoolean(PrefConstants.DATA_SELECTED, value) }
get() = {
val value = prefs.getBoolean(PrefConstants.IS_DATA_SELECTED, false)
value
}()
set(value) = {
prefs.edit {
putBoolean(PrefConstants.IS_DATA_SELECTED, value)
}
}()

var selectAfresh: Boolean
get() = prefs.getBoolean(PrefConstants.SELECT_AFRESH, false)
set(value) = prefs.edit { putBoolean(PrefConstants.SELECT_AFRESH, value) }
get() = {
val value = prefs.getBoolean(PrefConstants.SELECT_A_FRESH, false)
value
}()
set(value) = {
prefs.edit {
putBoolean(PrefConstants.SELECT_A_FRESH, value)
}
}()

var isProUser: Boolean
get() = prefs.getBoolean(PrefConstants.IS_PRO_USER, false)
set(value) = prefs.edit { putBoolean(PrefConstants.IS_PRO_USER, value) }
get() = {
val value = prefs.getBoolean(PrefConstants.IS_PRO_USER, false)
value
}()
set(value) = {
prefs.edit {
putBoolean(PrefConstants.IS_PRO_USER, value)
}
}()

var isDataLoaded: Boolean
get() = prefs.getBoolean(PrefConstants.DATA_LOADED, false)
set(value) = prefs.edit { putBoolean(PrefConstants.DATA_LOADED, value) }
get() = {
val value = prefs.getBoolean(PrefConstants.IS_DATA_LOADED, false)
value
}()
set(value) = {
prefs.edit {
putBoolean(PrefConstants.IS_DATA_LOADED, value)
}
}()

var appThemeMode: ThemeMode
get() = ThemeMode.valueOf(
Expand All @@ -45,8 +73,15 @@ class PrefsRepo @Inject constructor(
set(value) = prefs.edit { putString(PrefConstants.THEME_MODE, value.name) }

var horizontalSlides: Boolean
get() = prefs.getBoolean(PrefConstants.HORIZONTAL_SLIDES, false)
set(value) = prefs.edit { putBoolean(PrefConstants.HORIZONTAL_SLIDES, value) }
get() = {
val value = prefs.getBoolean(PrefConstants.HORIZONTAL_SLIDES, false)
value
}()
set(value) = {
prefs.edit {
putBoolean(PrefConstants.HORIZONTAL_SLIDES, value)
}
}()

var lastAppOpenTime: Long
get() = prefs.getLong(PrefConstants.LAST_APP_OPEN_TIME, 0L)
Expand Down
90 changes: 69 additions & 21 deletions app/src/main/java/com/songlib/domain/repos/SongBookRepo.kt
Original file line number Diff line number Diff line change
@@ -1,96 +1,144 @@
package com.songlib.domain.repos

import android.content.*
import android.util.Log
import com.songlib.data.models.*
import com.songlib.data.sources.local.*
import com.songlib.data.sources.local.daos.*
import com.songlib.data.sources.remote.ApiService
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import javax.inject.*
import kotlin.collections.isNotEmpty
import kotlin.collections.map

@Singleton
class SongBookRepo @Inject constructor(
context: Context,
private val apiService: ApiService,
) {
private var bookDao: BookDao?
private var songDao: SongDao?
private var booksDao: BookDao?
private var songsDao: SongDao?

init {
val db = AppDatabase.getDatabase(context)
bookDao = db?.bookDao()
songDao = db?.songDao()
booksDao = db?.booksDao()
songsDao = db?.songsDao()
}

fun fetchRemoteBooks(): Flow<List<Book>> = flow {
val books = apiService.getBooks()
emit(books)
try {
val books = apiService.getBooks()
if (books.isNotEmpty()) {
emit(books)
} else {
Log.d("TAG", "⚠️ No books fetched from remote")
emit(emptyList())
}
} catch (e: Exception) {
Log.e("TAG", "❌ Error fetching books: ${e.message}", e)
throw e
}
}

fun fetchRemoteSongs(books: String): Flow<List<Song>> = flow {
val songs = apiService.getSongs(books)
emit(songs)
suspend fun fetchAndSaveSongs(bookIds: List<Int>) {
try {
val booksParam = bookIds.joinToString(",")
val songs = apiService.getSongs(booksParam)
Log.d("TAG", "✅ ${songs.size} songs fetched for books: $booksParam")

if (songs.isNotEmpty()) {
saveSongs(songs)
} else {
Log.d("TAG", "⚠️ No songs fetched from remote")
}
} catch (e: Exception) {
Log.e("TAG", "❌ Error fetching songs: ${e.message}", e)
}
}

suspend fun saveBook(book: Book) {
withContext(Dispatchers.IO) {
bookDao?.insert(book)
booksDao?.insert(book)
}
}

suspend fun saveSong(song: Song) {
withContext(Dispatchers.IO) {
songDao?.insert(song)
suspend fun saveBooks(books: List<Book>) {
if (books.isEmpty()) {
Log.d("TAG", "⚠️ No books to save")
return
}

try {
booksDao?.insertAll(books)
Log.d("TAG", "✅ ${books.size} books saved successfully")
} catch (e: Exception) {
Log.e("TAG", "❌ Error saving books: ${e.message}", e)
throw e
}
}

suspend fun saveSongs(songs: List<Song>) {
if (songs.isEmpty()) {
Log.d("TAG", "⚠️ No songs to save")
return
}

try {
songsDao?.insertAll(songs)
Log.d("TAG", "✅ ${songs.size} songs saved successfully")
} catch (e: Exception) {
Log.e("TAG", "❌ Error saving songs: ${e.message}", e)
throw e
}
}

suspend fun fetchLocalBooks(): List<Book> {
var allBooks: List<Book>
withContext(Dispatchers.IO) {
allBooks = bookDao?.getAll() ?: emptyList()
allBooks = booksDao?.getAll() ?: emptyList()
}
return allBooks
}

suspend fun fetchLocalSongs(): List<Song> {
var allSongs: List<Song>
withContext(Dispatchers.IO) {
allSongs = songDao?.getAll() ?: emptyList()
allSongs = songsDao?.getAll() ?: emptyList()
}
return allSongs
}

suspend fun fetchSong(songId: Int): Song {
var song: Song
withContext(Dispatchers.IO) {
song = songDao?.getSong(songId)!!
song = songsDao?.getSong(songId)!!
}
return song
}

suspend fun updateSong(song: Song) {
withContext(Dispatchers.IO) {
songDao?.update(song)
songsDao?.update(song)
}
}

suspend fun deleteById(bookId: Int) {
withContext(Dispatchers.IO) {
bookDao?.deleteById(bookId)
booksDao?.deleteById(bookId)
}
}

suspend fun deleteAllData() {
withContext(Dispatchers.IO) {
bookDao?.deleteAll()
songDao?.deleteAll()
booksDao?.deleteAll()
songsDao?.deleteAll()
}
}

suspend fun deleteByBookId(bookId: Int) {
withContext(Dispatchers.IO) {
songDao?.deleteById(bookId)
songsDao?.deleteById(bookId)
}
}

Expand Down
Loading