Skip to content

Commit

Permalink
Adding a settings page. (#253)
Browse files Browse the repository at this point in the history
* Adding a settings page.

- Add changing font size. Fixes #144
- Add a few themes, including system.
- Fixes #88

* Fix migration.

* Fix migration again.
  • Loading branch information
dessalines authored Dec 20, 2022
1 parent 526d06e commit 49cc394
Show file tree
Hide file tree
Showing 30 changed files with 425 additions and 238 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
.externalNativeBuild
.cxx
local.properties
app/release
.project
.settings
.classpath
4 changes: 3 additions & 1 deletion app/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/build
/build
/release
/schemas
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ android {
dependencies {
def accompanist_version = '0.28.0'

implementation 'com.github.alorma:compose-settings-ui:0.15.0'

implementation 'com.github.jeziellago:compose-markdown:0.3.1'

implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.6'
Expand Down
72 changes: 0 additions & 72 deletions app/schemas/com.jerboa.db.AppDB/2.json

This file was deleted.

52 changes: 42 additions & 10 deletions app/src/main/java/com/jerboa/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.sp
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
Expand All @@ -22,6 +25,9 @@ import com.jerboa.db.AccountRepository
import com.jerboa.db.AccountViewModel
import com.jerboa.db.AccountViewModelFactory
import com.jerboa.db.AppDB
import com.jerboa.db.AppSettingsRepository
import com.jerboa.db.AppSettingsViewModel
import com.jerboa.db.AppSettingsViewModelFactory
import com.jerboa.ui.components.comment.edit.CommentEditActivity
import com.jerboa.ui.components.comment.edit.CommentEditViewModel
import com.jerboa.ui.components.comment.reply.CommentReplyActivity
Expand Down Expand Up @@ -51,12 +57,15 @@ import com.jerboa.ui.components.report.CreateReportViewModel
import com.jerboa.ui.components.report.comment.CreateCommentReportActivity
import com.jerboa.ui.components.report.post.CreatePostReportActivity
import com.jerboa.ui.components.settings.SettingsActivity
import com.jerboa.ui.components.settings.SettingsViewModel
import com.jerboa.ui.components.settings.account.AccountSettingsActivity
import com.jerboa.ui.components.settings.account.AccountSettingsViewModel
import com.jerboa.ui.components.settings.lookandfeel.LookAndFeelActivity
import com.jerboa.ui.theme.JerboaTheme

class JerboaApplication : Application() {
private val database by lazy { AppDB.getDatabase(this) }
val repository by lazy { AccountRepository(database.accountDao()) }
val accountRepository by lazy { AccountRepository(database.accountDao()) }
val appSettingsRepository by lazy { AppSettingsRepository(database.appSettingsDao()) }
}

class MainActivity : ComponentActivity() {
Expand All @@ -74,10 +83,12 @@ class MainActivity : ComponentActivity() {
private val commentEditViewModel by viewModels<CommentEditViewModel>()
private val postEditViewModel by viewModels<PostEditViewModel>()
private val createReportViewModel by viewModels<CreateReportViewModel>()
private val settingsViewModel by viewModels<SettingsViewModel>()

private val accountSettingsViewModel by viewModels<AccountSettingsViewModel>()
private val accountViewModel: AccountViewModel by viewModels {
AccountViewModelFactory((application as JerboaApplication).repository)
AccountViewModelFactory((application as JerboaApplication).accountRepository)
}
private val appSettingsViewModel: AppSettingsViewModel by viewModels {
AppSettingsViewModelFactory((application as JerboaApplication).appSettingsRepository)
}

override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -87,10 +98,15 @@ class MainActivity : ComponentActivity() {
fetchInitialData(accountSync, siteViewModel, homeViewModel)

setContent {
JerboaTheme {
val account = getCurrentAccount(accountViewModel)
val appSettings by appSettingsViewModel.appSettings.observeAsState()

JerboaTheme(
themeMode = ThemeMode.values()[appSettings?.theme ?: 0],
fontSize = (appSettings?.fontSize ?: 13).sp
) {
val navController = rememberNavController()
val ctx = LocalContext.current
val account = getCurrentAccount(accountViewModel)

NavHost(
navController = navController,
Expand Down Expand Up @@ -486,16 +502,32 @@ class MainActivity : ComponentActivity() {
)
}
composable(
route = "settings",
route = "settings"
) {
SettingsActivity(
navController = navController,
accountViewModel = accountViewModel
)
}
composable(
route = "lookAndFeel"
) {
LookAndFeelActivity(
navController = navController,
appSettingsViewModel = appSettingsViewModel
)
}
composable(
route = "accountSettings",
deepLinks = DEFAULT_LEMMY_INSTANCES.map { instance ->
navDeepLink { uriPattern = "$instance/settings" }
}
) {
SettingsActivity(
AccountSettingsActivity(
navController = navController,
accountViewModel = accountViewModel,
siteViewModel = siteViewModel,
settingsViewModel = settingsViewModel
accountSettingsViewModel = accountSettingsViewModel
)
}
}
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/jerboa/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -580,3 +580,11 @@ fun Context.findActivity(): Activity? = when (this) {
is ContextWrapper -> baseContext.findActivity()
else -> null
}

enum class ThemeMode {
System,
Light,
Dark,
DarkBlue,
Black
}
98 changes: 94 additions & 4 deletions app/src/main/java/com/jerboa/db/AppDB.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.jerboa.db

import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase.CONFLICT_IGNORE
import androidx.annotation.WorkerThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
Expand All @@ -10,6 +12,7 @@ import androidx.room.*
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import kotlinx.coroutines.launch
import java.util.concurrent.Executors

@Entity
data class Account(
Expand All @@ -30,6 +33,21 @@ data class Account(
val defaultSortType: Int
)

@Entity
data class AppSettings(
@PrimaryKey(autoGenerate = true) val id: Int,
@ColumnInfo(
name = "font_size",
defaultValue = "13"
)
val fontSize: Int,
@ColumnInfo(
name = "theme",
defaultValue = "0"
)
val theme: Int
)

@Dao
interface AccountDao {
@Query("SELECT * FROM account")
Expand All @@ -51,6 +69,15 @@ interface AccountDao {
suspend fun delete(account: Account)
}

@Dao
interface AppSettingsDao {
@Query("SELECT * FROM AppSettings limit 1")
fun getSettings(): LiveData<AppSettings>

@Update
suspend fun updateAppSettings(appSettings: AppSettings)
}

// Declares the DAO as a private property in the constructor. Pass in the DAO
// instead of the whole database, because you only need access to the DAO
class AccountRepository(private val accountDao: AccountDao) {
Expand Down Expand Up @@ -87,6 +114,20 @@ class AccountRepository(private val accountDao: AccountDao) {
}
}

// Declares the DAO as a private property in the constructor. Pass in the DAO
// instead of the whole database, because you only need access to the DAO
class AppSettingsRepository(private val appSettingsDao: AppSettingsDao) {

// Room executes all queries on a separate thread.
// Observed Flow will notify the observer when the data has changed.
val appSettings = appSettingsDao.getSettings()

@WorkerThread
suspend fun update(appSettings: AppSettings) {
appSettingsDao.updateAppSettings(appSettings)
}
}

val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
Expand All @@ -100,13 +141,26 @@ val MIGRATION_1_2 = object : Migration(1, 2) {
}
}

val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
"""
CREATE TABLE IF NOT EXISTS AppSettings (id INTEGER PRIMARY KEY
AUTOINCREMENT NOT NULL, font_size INTEGER NOT NULL DEFAULT 13, theme INTEGER
NOT NULL DEFAULT 0)
"""
)
}
}

@Database(
version = 2,
entities = [Account::class],
version = 3,
entities = [Account::class, AppSettings::class],
exportSchema = true
)
abstract class AppDB : RoomDatabase() {
abstract fun accountDao(): AccountDao
abstract fun appSettingsDao(): AppSettingsDao

companion object {
@Volatile
Expand All @@ -124,8 +178,24 @@ abstract class AppDB : RoomDatabase() {
"jerboa"
)
.allowMainThreadQueries()
.addMigrations(MIGRATION_1_2)
.build()
.addMigrations(MIGRATION_1_2, MIGRATION_2_3)
// Necessary because it can't insert data on creation
.addCallback(object : Callback() {
override fun onOpen(db: SupportSQLiteDatabase) {
super.onCreate(db)
Executors.newSingleThreadExecutor().execute {
db.insert(
"AppSettings",
CONFLICT_IGNORE, // Ensures it won't overwrite the existing data
ContentValues(2).apply {
put("id", 1)
put("font_size", 13)
put("theme", 0)
}
)
}
}
}).build()
INSTANCE = instance
// return instance
instance
Expand Down Expand Up @@ -167,3 +237,23 @@ class AccountViewModelFactory(private val repository: AccountRepository) :
throw IllegalArgumentException("Unknown ViewModel class")
}
}

class AppSettingsViewModel(private val repository: AppSettingsRepository) : ViewModel() {

val appSettings = repository.appSettings

fun update(appSettings: AppSettings) = viewModelScope.launch {
repository.update(appSettings)
}
}

class AppSettingsViewModelFactory(private val repository: AppSettingsRepository) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(AppSettingsViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return AppSettingsViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ fun PostAndCommunityContextHeader(
) {
Text(
text = commentView.post.name,
style = MaterialTheme.typography.subtitle1,
style = MaterialTheme.typography.h6,
modifier = Modifier.clickable { onPostClick(commentView.post.id) }
)
Row(
Expand Down
Loading

0 comments on commit 49cc394

Please sign in to comment.