Skip to content

Commit

Permalink
GH-14 Add settings view with a possibility to change avatar url (Resolve
Browse files Browse the repository at this point in the history
 #14)
  • Loading branch information
dzikoysk committed Feb 26, 2023
1 parent e7fdf5c commit a2dfd5c
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 35 deletions.
2 changes: 1 addition & 1 deletion pom-application/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ android {
applicationId "net.dzikoysk.presenceofmind"
minSdk 29
targetSdk 33
versionCode 10
versionCode 11
versionName "1.0.0-RC.11"
archivesBaseName = "presence-of-mind-$versionName"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ import android.content.SharedPreferences
import androidx.core.content.edit
import net.dzikoysk.presenceofmind.BuildConfig

private const val DEFAULT_AVATAR = "https://avatars.githubusercontent.com/u/75123628?s=200&v=4"

sealed interface PresenceRepository {

fun setColorMode(isLightMode: Boolean)

fun isLightMode(): Boolean

fun setLatestVersionCode(code: Int)

fun getLatestVersionCode(): Int

fun setAvatarUrl(url: String)
fun getAvatarUrl(): String

}

class SharedPreferencesPresenceRepository(
Expand All @@ -23,44 +26,36 @@ class SharedPreferencesPresenceRepository(

private val lightModeId = "light-mode-$version"
private val latestVersionCodeId = "latest-version-code-$version"
private val avatarUrlId = "avatar-url-$version"

private fun setProperty(modifier: SharedPreferences.Editor.() -> Unit): Unit =
sharedPreferences.edit(commit = true) { modifier(this) }

override fun setColorMode(isLightMode: Boolean) = setProperty {
putBoolean(lightModeId, isLightMode)
}

override fun isLightMode(): Boolean =
sharedPreferences.getBoolean(lightModeId, true)
override fun setColorMode(isLightMode: Boolean) = setProperty { putBoolean(lightModeId, isLightMode) }
override fun isLightMode(): Boolean = sharedPreferences.getBoolean(lightModeId, true)

override fun setLatestVersionCode(code: Int) = setProperty {
putInt(latestVersionCodeId, code)
}
override fun setLatestVersionCode(code: Int) = setProperty { putInt(latestVersionCodeId, code) }
override fun getLatestVersionCode(): Int = sharedPreferences.getInt(latestVersionCodeId, BuildConfig.VERSION_CODE)

override fun getLatestVersionCode(): Int =
sharedPreferences.getInt(latestVersionCodeId, BuildConfig.VERSION_CODE)
override fun setAvatarUrl(url: String) = setProperty { putString(avatarUrlId, url) }
override fun getAvatarUrl(): String = sharedPreferences.getString(avatarUrlId, DEFAULT_AVATAR).takeUnless { it.isNullOrEmpty() }?: DEFAULT_AVATAR

}

class InMemoryPresenceRepository : PresenceRepository {

private var lightMode = true
private var latestVersionCode = BuildConfig.VERSION_CODE
private var avatarUrl = DEFAULT_AVATAR

override fun setColorMode(isLightMode: Boolean) {
this.lightMode = isLightMode
}

override fun isLightMode(): Boolean =
lightMode
override fun setColorMode(isLightMode: Boolean) { this.lightMode = isLightMode }
override fun isLightMode(): Boolean = lightMode

override fun setLatestVersionCode(code: Int) {
latestVersionCode = code
}
override fun setLatestVersionCode(code: Int) { this.latestVersionCode = code }
override fun getLatestVersionCode(): Int = latestVersionCode

override fun getLatestVersionCode(): Int =
latestVersionCode
override fun setAvatarUrl(url: String) { this.avatarUrl = url }
override fun getAvatarUrl(): String = avatarUrl

}

Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package net.dzikoysk.presenceofmind.pages

import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.tooling.preview.Preview
import net.dzikoysk.presenceofmind.createDefaultTasks
import net.dzikoysk.presenceofmind.model.presence.InMemoryPresenceRepository
import net.dzikoysk.presenceofmind.model.presence.PresenceOfMindTheme
import net.dzikoysk.presenceofmind.model.presence.PresenceRepository
import net.dzikoysk.presenceofmind.model.task.TaskService
import net.dzikoysk.presenceofmind.pages.settings.Settings

/** Redirects to other pages */

enum class Page {
DASHBOARD
DASHBOARD,
SETTINGS
}

@Composable
Expand All @@ -33,12 +37,20 @@ fun Router(
page: Page
) {
PresenceOfMindTheme(lightTheme = presenceRepository.isLightMode()) {
when (page) {
val currentPage = remember { mutableStateOf(page) }

when (currentPage.value) {
Page.DASHBOARD ->
Dashboard(
presenceRepository = presenceRepository,
taskService = taskService,
restartActivity = restartActivity
restartActivity = restartActivity,
changePage = { currentPage.value = it }
)
Page.SETTINGS ->
Settings(
presenceRepository = presenceRepository,
changePage = { currentPage.value = it }
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import net.dzikoysk.presenceofmind.R

@Composable
fun AvatarImage(
avatarUrl: String,
openMenu: () -> Unit = {}
) {
GlideImage(
Expand All @@ -28,7 +29,7 @@ fun AvatarImage(
.height(32.dp)
.clip(CircleShape)
.clickable(onClick = { openMenu() }),
imageModel = { "https://avatars.githubusercontent.com/u/75123628?s=200&v=4" },
imageModel = { avatarUrl },
imageOptions = ImageOptions(
contentScale = ContentScale.Crop
),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package net.dzikoysk.presenceofmind.pages

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
Expand All @@ -14,7 +20,12 @@ import net.dzikoysk.presenceofmind.model.presence.InMemoryPresenceRepository
import net.dzikoysk.presenceofmind.model.presence.PresenceRepository
import net.dzikoysk.presenceofmind.model.task.MarkedAs
import net.dzikoysk.presenceofmind.model.task.TaskService
import net.dzikoysk.presenceofmind.pages.dashboard.*
import net.dzikoysk.presenceofmind.pages.dashboard.AnimatedMenuDrawer
import net.dzikoysk.presenceofmind.pages.dashboard.AvatarImage
import net.dzikoysk.presenceofmind.pages.dashboard.ChangeThemeButton
import net.dzikoysk.presenceofmind.pages.dashboard.CreateTaskButton
import net.dzikoysk.presenceofmind.pages.dashboard.SwapTasksButton
import net.dzikoysk.presenceofmind.pages.dashboard.TodayLabel
import net.dzikoysk.presenceofmind.pages.dashboard.editor.AnimatedEditorDrawer
import net.dzikoysk.presenceofmind.pages.dashboard.editor.TaskToEdit
import net.dzikoysk.presenceofmind.pages.dashboard.list.TaskList
Expand All @@ -27,15 +38,15 @@ fun DashboardPreview() {
Dashboard(
presenceRepository = InMemoryPresenceRepository(),
taskService = TaskService().also { it.createDefaultTasks() },
restartActivity = {}
)
}

@Composable
fun Dashboard(
presenceRepository: PresenceRepository,
taskService: TaskService,
restartActivity: () -> Unit
restartActivity: () -> Unit = {},
changePage: (Page) -> Unit = {}
) {
val selectedTasks = remember { mutableStateOf(MarkedAs.UNFINISHED) }
val openMenu = remember { mutableStateOf(false) }
Expand All @@ -58,6 +69,7 @@ fun Dashboard(
.fillMaxWidth()
) {
AvatarImage(
avatarUrl = presenceRepository.getAvatarUrl(),
openMenu = { openMenu.value = true }
)
TodayLabel(
Expand Down Expand Up @@ -85,6 +97,7 @@ fun Dashboard(
}
AnimatedMenuDrawer(
open = openMenu.value,
openSettings = { changePage(Page.SETTINGS) },
close = { openMenu.value = false }
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
Expand Down Expand Up @@ -34,13 +42,15 @@ import net.dzikoysk.presenceofmind.components.scaledSp
@Composable
fun MenuDrawerPreview() {
MenuDrawer(
openSettings = {},
closeMenu = {}
)
}

@Composable
fun AnimatedMenuDrawer(
open: Boolean,
openSettings: () -> Unit,
close: () -> Unit
) {
val density = LocalDensity.current
Expand All @@ -52,13 +62,15 @@ fun AnimatedMenuDrawer(
}
) {
MenuDrawer(
closeMenu = { close() }
openSettings = openSettings,
closeMenu = close
)
}
}

@Composable
fun MenuDrawer(
openSettings: () -> Unit,
closeMenu: () -> Unit,
) {
val interactionSource = remember { MutableInteractionSource() }
Expand Down Expand Up @@ -91,6 +103,14 @@ fun MenuDrawer(
)
}
Column(Modifier.padding(vertical = 16.dp)) {
Text(
text = "Settings",
fontWeight = FontWeight.SemiBold,
fontSize = 15.scaledSp(),
modifier = Modifier
.clickable { openSettings() }
.padding(vertical = 8.dp)
)
Text(
text = "Sources",
fontWeight = FontWeight.SemiBold,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package net.dzikoysk.presenceofmind.pages.settings

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import net.dzikoysk.presenceofmind.R
import net.dzikoysk.presenceofmind.components.scaledSp
import net.dzikoysk.presenceofmind.model.presence.InMemoryPresenceRepository
import net.dzikoysk.presenceofmind.model.presence.PresenceRepository
import net.dzikoysk.presenceofmind.pages.Page

@Preview(showBackground = false)
@Composable
fun SettingsPreview() {
Settings()
}

@Composable
fun Settings(
presenceRepository: PresenceRepository = InMemoryPresenceRepository(),
changePage: (Page) -> Unit = {}
) {
val avatarUrl = remember { mutableStateOf(presenceRepository.getAvatarUrl()) }

Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(vertical = 24.dp)
.clickable {
presenceRepository.setAvatarUrl(avatarUrl.value)
changePage(Page.DASHBOARD)
}
) {
Icon(
contentDescription = "Back to dashboard",
painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24),
modifier = Modifier.padding(end = 8.dp)
)
Text(
text = "Go back",
fontSize = 15.scaledSp(),
fontWeight = FontWeight.Bold
)
}

Row {
Column {
Text(
fontSize = 15.scaledSp(),
text = "Avatar URL",
modifier = Modifier.padding(bottom = 10.dp)
)

TextField(
value = avatarUrl.value,
onValueChange = { avatarUrl.value = it }
)
}
}
}
}

0 comments on commit a2dfd5c

Please sign in to comment.