Pixelcat-App-Android/app/src/main/kotlin/at/connyduck/pixelcat/db/AccountManager.kt

190 lines
5.8 KiB
Kotlin

/*
* Copyright (C) 2020 Conny Duck
*
* This file is part of Pixelcat.
*
* Pixelcat is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Pixelcat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package at.connyduck.pixelcat.db
import android.util.Log
import at.connyduck.pixelcat.db.entitity.AccountAuthData
import at.connyduck.pixelcat.db.entitity.AccountEntity
import at.connyduck.pixelcat.model.Account
import javax.inject.Inject
import javax.inject.Singleton
/**
* This class caches the account database and handles all account related operations
*/
private const val TAG = "AccountManager"
@Singleton
class AccountManager @Inject constructor(db: AppDatabase) {
private var activeAccount: AccountEntity? = null
private var accounts: MutableList<AccountEntity> = mutableListOf()
private val accountDao: AccountDao = db.accountDao()
suspend fun activeAccount(): AccountEntity? {
if (activeAccount == null) {
accounts = accountDao.loadAll().toMutableList()
activeAccount = accounts.find { acc ->
acc.isActive
}
}
return activeAccount
}
/**
* Adds a new empty account and makes it the active account.
* More account information has to be added later with [updateActiveAccount]
* or the account wont be saved to the database.
* @param domain the domain of the accounts instance
* @param authData the auth data of the new account
*/
suspend fun addAccount(domain: String, authData: AccountAuthData) {
activeAccount?.let {
it.isActive = false
Log.d(TAG, "addAccount: saving account with id " + it.id)
accountDao.insertOrReplace(it)
}
val maxAccountId = accounts.maxByOrNull { it.id }?.id ?: 0
val newAccountId = maxAccountId + 1
activeAccount = AccountEntity(
id = newAccountId,
domain = domain,
auth = authData,
isActive = true
)
}
/**
* Saves an already known account to the database.
* New accounts must be created with [addAccount]
* @param account the account to save
*/
suspend fun saveAccount(account: AccountEntity) {
if (account.id != 0L) {
Log.d(TAG, "saveAccount: saving account with id " + account.id)
accountDao.insertOrReplace(account)
}
}
/**
* Logs the current account out by deleting all data of the account.
* @return the new active account, or null if no other account was found
*/
suspend fun logActiveAccountOut(): AccountEntity? {
if (activeAccount == null) {
return null
} else {
accounts.remove(activeAccount!!)
accountDao.delete(activeAccount!!)
if (accounts.size > 0) {
accounts[0].isActive = true
activeAccount = accounts[0]
Log.d(TAG, "logActiveAccountOut: saving account with id " + accounts[0].id)
accountDao.insertOrReplace(accounts[0])
} else {
activeAccount = null
}
return activeAccount
}
}
/**
* updates the current account with new information from the api and saves it in the database
* @param account the [Account] object returned from the api
*/
suspend fun updateActiveAccount(account: Account) {
activeAccount?.let {
it.accountId = account.id
it.username = account.username
it.displayName = account.name
it.profilePictureUrl = account.avatar
Log.d(TAG, "updateActiveAccount: saving account with id " + it.id)
it.id = accountDao.insertOrReplace(it)
val accountIndex = accounts.indexOf(it)
if (accountIndex != -1) {
// in case the user was already logged in with this account, remove the old information
accounts.removeAt(accountIndex)
accounts.add(accountIndex, it)
} else {
accounts.add(it)
}
}
}
/**
* changes the active account
* @param accountId the database id of the new active account
*/
suspend fun setActiveAccount(accountId: Long) {
activeAccount?.let {
Log.d(TAG, "setActiveAccount: saving account with id " + it.id)
it.isActive = false
saveAccount(it)
}
activeAccount = accounts.find { acc ->
acc.id == accountId
}
activeAccount?.let {
it.isActive = true
accountDao.insertOrReplace(it)
}
}
/**
* @return an immutable list of all accounts in the database
*/
suspend fun getAllAccounts(): List<AccountEntity> {
// TODO only load accounts on demand
accounts = accountDao.loadAll().toMutableList()
activeAccount = accounts.find { acc ->
acc.isActive
}
return accounts.toList()
}
/**
* Finds an account by its database id
* @param accountId the id of the account
* @return the requested account or null if it was not found
*/
fun getAccountById(accountId: Long): AccountEntity? {
return accounts.find { acc ->
acc.id == accountId
}
}
}