From 95c78d12e12b6c2389980d0c20894e9d220f08cf Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Thu, 17 Nov 2022 19:01:54 +0100 Subject: [PATCH] more colors --- Habitica/build.gradle | 2 + Habitica/res/drawable-mdpi/arrow_back.png | Bin 0 -> 184 bytes Habitica/res/drawable-xhdpi/arrow_back.png | Bin 0 -> 214 bytes Habitica/res/drawable-xxhdpi/arrow_back.png | Bin 0 -> 283 bytes .../android/habitica/models/tasks/Task.kt | 26 ++ .../ui/activities/TaskSummaryActivity.kt | 279 ++++++++++++------ common/src/main/res/values/colors.xml | 14 + 7 files changed, 230 insertions(+), 91 deletions(-) create mode 100644 Habitica/res/drawable-mdpi/arrow_back.png create mode 100644 Habitica/res/drawable-xhdpi/arrow_back.png create mode 100644 Habitica/res/drawable-xxhdpi/arrow_back.png diff --git a/Habitica/build.gradle b/Habitica/build.gradle index 2dbde8c1d..babbc5ce3 100644 --- a/Habitica/build.gradle +++ b/Habitica/build.gradle @@ -107,6 +107,8 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" implementation "com.google.android.material:compose-theme-adapter:1.1.21" + implementation "androidx.compose.material3:material3:1.0.1" + implementation "com.google.accompanist:accompanist-systemuicontroller:0.27.1" implementation 'androidx.activity:activity-compose:1.6.1' implementation "androidx.compose.runtime:runtime-livedata:$compose_version" diff --git a/Habitica/res/drawable-mdpi/arrow_back.png b/Habitica/res/drawable-mdpi/arrow_back.png new file mode 100644 index 0000000000000000000000000000000000000000..5a6ce17d7b9fc1d8378d22023512ff15d39c3025 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzOSc?V@L(#+sOwx85B5N_g{3#4VitVBR7SW zHCAWSYW^mN`@1=15}w(}nfO!+);;<1Xx5qoU)df`m(z+iacXv5C-`y39utK{f)W3< a-kJ)D{$Y6eINB0uFoUP7pUXO@geCxRp*SP} literal 0 HcmV?d00001 diff --git a/Habitica/res/drawable-xhdpi/arrow_back.png b/Habitica/res/drawable-xhdpi/arrow_back.png new file mode 100644 index 0000000000000000000000000000000000000000..eb2fd3b180689b7ed1ccff0e4961828ae46b1ce8 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?2=RS;(M3{v?36l5$8 za(7}_cTVOdki(Mh=_y1 zHj4zZ{BixKa=m=h9f=tS?yk2=xbS4|osRZB#Y)YMdydHbkUpt8J?7KXCz=6Ir`n2b zX!LEFF}b2!V_soPS3rxB$ij|(rJ}gajxCLj-3C4d%=5&AJ2jdbp98IB@O1TaS?83{ F1ORKtNOk}K literal 0 HcmV?d00001 diff --git a/Habitica/res/drawable-xxhdpi/arrow_back.png b/Habitica/res/drawable-xxhdpi/arrow_back.png new file mode 100644 index 0000000000000000000000000000000000000000..92e71e95dc3f9751767bf39b47eb4200b2ebd8ee GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?393lL^>oo1K-6l5$8 za(7}_cTVOdki(Mh=e=~7Y#+1w3N(xYqE6D zj!u6U!M_vd9<)?A`8+1TkyYmPj#wb|EoJpAJiExGukk5_B-$^V-Ftv-sY<0tEiKL6%VKfWAzWD<16f1yOZO1y)v z{-cJBBRa}g@)k??B|PL1LnaEBbDTTB=B}fQ!$Ch6hm%@L3o^PmVqS1}KR%p&>qLMu P(CrMKu6{1-oD!M return R.color.maroon_700 + this.value < -10 -> return R.color.red_700 + this.value < -1 -> return R.color.orange_700 + this.value < 1 -> return R.color.yellow_700 + this.value < 5 -> return R.color.green_700 + this.value < 10 -> return R.color.teal_700 + else -> R.color.blue_700 + } + } + + val extraExtraLightTaskColor: Int + get() { + return when { + this.value < -20 -> return R.color.maroon_600 + this.value < -10 -> return R.color.red_600 + this.value < -1 -> return R.color.orange_600 + this.value < 1 -> return R.color.yellow_600 + this.value < 5 -> return R.color.green_600 + this.value < 10 -> return R.color.teal_600 + else -> R.color.blue_600 + } + } + val extraLightTaskColor: Int get() { return when { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt index 363baaade..5df9960c4 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt @@ -1,14 +1,13 @@ package com.habitrpg.android.habitica.ui.activities import android.os.Bundle -import android.view.Window -import android.view.WindowManager import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.compose.foundation.Image import androidx.compose.foundation.background 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.heightIn import androidx.compose.foundation.layout.padding @@ -18,30 +17,37 @@ import androidx.compose.material.ButtonDefaults import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.asLiveData +import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.UserComponent import com.habitrpg.android.habitica.data.TaskRepository import com.habitrpg.android.habitica.helpers.MainNavigationController import com.habitrpg.android.habitica.helpers.TaskDescriptionBuilder +import com.habitrpg.android.habitica.ui.theme.HabiticaTheme import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel -import com.habitrpg.common.habitica.helpers.MarkdownParser import com.habitrpg.shared.habitica.models.tasks.TaskType import java.text.DateFormat import javax.inject.Inject @@ -56,34 +62,33 @@ class TaskSummaryViewModel(val taskId: String) : BaseViewModel() { } @Suppress("UNCHECKED_CAST") - class Factory(private val taskID: String): ViewModelProvider.Factory { + class Factory(private val taskID: String) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return TaskSummaryViewModel(taskID) as T } } } -class TaskSummaryActivity: BaseActivity() { +class TaskSummaryActivity : BaseActivity() { override fun getLayoutResId(): Int? = null - private val viewModel: TaskSummaryViewModel by viewModels { TaskSummaryViewModel.Factory(intent.extras?.getString( - TaskFormActivity.TASK_ID_KEY - ) ?: "") } + private val viewModel: TaskSummaryViewModel by viewModels { + TaskSummaryViewModel.Factory( + intent.extras?.getString( + TaskFormActivity.TASK_ID_KEY + ) ?: "" + ) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - TaskSummaryView(viewModel = viewModel) + HabiticaTheme { + TaskSummaryView(viewModel = viewModel) + } } } - override fun onStart() { - super.onStart() - val window: Window = window - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - window.statusBarColor = ContextCompat.getColor(this, viewModel.task.value?.lightTaskColor ?: R.color.brand_300) - } - override fun injectActivity(component: UserComponent?) { component?.inject(this) } @@ -95,103 +100,195 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) { val task by viewModel.task.observeAsState() val titleModifier = Modifier.padding(top = 30.dp) val textModifier = Modifier.padding(top = 4.dp) - val completedTimeFormat = DateFormat.getTimeInstance() - val darkestColor = colorResource(task?.darkestTaskColor ?: R.color.text_primary) - Column(Modifier.background(colorResource(task?.lightTaskColor ?: R.color.brand_300))) { - Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(0.dp, 4.dp)) { - Button(onClick = { - MainNavigationController.navigateBack() - }, colors = ButtonDefaults.textButtonColors(contentColor = darkestColor), elevation = ButtonDefaults.elevation(0.dp)) { - Image(painterResource(R.drawable.ic_arrow_back_white_36dp), stringResource(R.string.action_back), colorFilter = ColorFilter.tint(colorResource(task?.darkestTaskColor ?: R.color.white))) - } - Text( - stringResource(R.string.task_summary), - fontSize = 18.sp, - fontWeight = FontWeight.Medium, - color = darkestColor, - modifier = Modifier.padding(start = 6.dp) - ) + val completedTimeFormat = DateFormat.getTimeInstance(DateFormat.SHORT) + if (task != null) { + val darkestColor = colorResource(task?.darkestTaskColor ?: R.color.text_primary) + val systemUiController = rememberSystemUiController() + val statusBarColor = colorResource(task?.lightTaskColor ?: R.color.brand_400) + val lightestColor = colorResource(task?.lightestTaskColor ?: R.color.window_background) + DisposableEffect(systemUiController) { + systemUiController.setStatusBarColor(statusBarColor, darkIcons = true) + systemUiController.setNavigationBarColor(lightestColor) + onDispose {} } - Column( - Modifier - .background( - MaterialTheme.colors.background, - RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp) - ) - .padding(20.dp, 5.dp) - .fillMaxWidth()) { - Text(stringResource(R.string.title), fontSize = 16.sp, color = darkestColor, fontWeight = FontWeight.Medium, modifier = titleModifier) - Text(task?.text ?: "", fontSize = 16.sp, color = MaterialTheme.colors.onBackground, modifier = textModifier) - if (task?.notes?.isNotBlank() == true) { + Column(Modifier.background(colorResource(task?.lightTaskColor ?: R.color.brand_300))) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(vertical = 2.dp) + ) { + Button( + onClick = { + MainNavigationController.navigateBack() + }, + colors = ButtonDefaults.textButtonColors(contentColor = darkestColor), + elevation = ButtonDefaults.elevation(0.dp) + ) { + Image( + painterResource(R.drawable.arrow_back), + stringResource(R.string.action_back), + colorFilter = ColorFilter.tint( + colorResource( + task?.darkestTaskColor ?: R.color.white + ) + ) + ) + } Text( - stringResource(R.string.notes), - fontSize = 16.sp, - color = MaterialTheme.colors.onSecondary, + stringResource(R.string.task_summary), + fontSize = 18.sp, fontWeight = FontWeight.Medium, - modifier = titleModifier - ) - Text( - task?.notes ?: "", - fontSize = 16.sp, - color = MaterialTheme.colors.onBackground, - modifier = textModifier + color = darkestColor, + modifier = Modifier.padding(start = 0.dp) ) } - if (task?.type != TaskType.REWARD) { + Column( + Modifier + .shadow(16.dp) + .background( + lightestColor, + RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp) + ) + .padding(20.dp, 5.dp) + .fillMaxWidth() + .fillMaxHeight() + ) { Text( - stringResource(R.string.description), + stringResource(R.string.title), fontSize = 16.sp, color = darkestColor, fontWeight = FontWeight.Medium, modifier = titleModifier ) - Text(MarkdownParser.parseMarkdown(task?.let { taskDescriptionBuilder.describe(it) } ?: "").toString(), - fontSize = 16.sp, - color = MaterialTheme.colors.onBackground, - modifier = textModifier) - } - if (task?.checklist?.isNotEmpty() == true) { - task?.checklist?.let { checklist -> - Text(stringResource(R.string.checklist), fontSize = 16.sp, color = darkestColor, fontWeight = FontWeight.Medium, modifier = titleModifier) - for (item in checklist) { - Text(item.text ?: "", fontSize = 16.sp, fontWeight = FontWeight.Medium, modifier = Modifier - .background(colorResource(R.color.gray_700)) - .padding(15.dp) - .fillMaxWidth()) + Text( + task?.text ?: "", fontSize = 16.sp, color = darkestColor, + fontWeight = FontWeight.Normal, modifier = textModifier + ) + if (task?.notes?.isNotBlank() == true) { + Text( + stringResource(R.string.notes), + fontSize = 16.sp, + color = darkestColor, + fontWeight = FontWeight.Medium, + modifier = titleModifier + ) + Text( + task?.notes ?: "", + fontSize = 16.sp, + color = darkestColor, + fontWeight = FontWeight.Normal, + modifier = textModifier + ) + } + if (task?.type != TaskType.REWARD) { + Text( + stringResource(R.string.description), + fontSize = 16.sp, + color = darkestColor, + fontWeight = FontWeight.Medium, + modifier = titleModifier + ) + Text(task?.let { taskDescriptionBuilder.describe(it) }!!.makeBoldComposable(), + fontSize = 16.sp, + color = darkestColor, + fontWeight = FontWeight.Normal, + modifier = textModifier) + } + if (task?.checklist?.isNotEmpty() == true) { + task?.checklist?.let { checklist -> + Text( + stringResource(R.string.checklist), + fontSize = 16.sp, + color = darkestColor, + fontWeight = FontWeight.Medium, + modifier = titleModifier.padding(bottom = 4.dp) + ) + for (item in checklist) { + Text( + item.text ?: "", + fontSize = 16.sp, + fontWeight = FontWeight.Medium, + color = darkestColor, + modifier = Modifier + .padding(vertical = 4.dp) + .background( + colorResource( + task?.extraExtraLightTaskColor ?: R.color.gray_700 + ), + RoundedCornerShape(8.dp) + ) + .padding(15.dp) + .fillMaxWidth() + ) + } } } - } - if (task?.group?.assignedUsersDetail?.isNotEmpty() == true) { - Text(stringResource(R.string.assigned_to), fontSize = 16.sp, color = darkestColor, fontWeight = FontWeight.Medium, modifier = titleModifier.padding(bottom = 4.dp)) - for (item in task?.group?.assignedUsersDetail ?: emptyList()) { - UserRow(item.assignedUsername ?: "", Modifier - .padding(vertical = 4.dp) - .background(colorResource(R.color.gray_700), RoundedCornerShape(8.dp)) - .padding(15.dp, 12.dp) - .heightIn(min = 24.dp) - .fillMaxWidth(), - extraContent = if (item.completed) ({ - Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(top = 4.dp)) { - Image(painterResource(R.drawable.completed), null) - Text(stringResource(R.string.completed_at, - item.completedDate?.let { completedTimeFormat.format(it) } ?: ""), - fontSize = 14.sp, - color = colorResource(R.color.green_10), modifier = Modifier.padding(start = 4.dp)) - } - }) else null) + if (task?.group?.assignedUsersDetail?.isNotEmpty() == true) { + Text( + stringResource(R.string.assigned_to), + fontSize = 16.sp, + color = darkestColor, + fontWeight = FontWeight.Medium, + modifier = titleModifier.padding(bottom = 4.dp) + ) + for (item in task?.group?.assignedUsersDetail ?: emptyList()) { + UserRow( + item.assignedUsername ?: "", Modifier + .padding(vertical = 4.dp) + .background( + colorResource( + task?.extraExtraLightTaskColor ?: R.color.gray_700 + ), + RoundedCornerShape(8.dp) + ) + .padding(15.dp, 12.dp) + .heightIn(min = 24.dp) + .fillMaxWidth(), + color = darkestColor, + extraContent = if (item.completed) ({ + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(top = 4.dp) + ) { + Image(painterResource(R.drawable.completed), null) + Text(stringResource(R.string.completed_at, + item.completedDate?.let { completedTimeFormat.format(it) } + ?: ""), + fontSize = 14.sp, + color = colorResource(R.color.green_10), + modifier = Modifier.padding(start = 4.dp)) + } + }) else null + ) + } } } } } } +private fun String.makeBoldComposable(): AnnotatedString { + return buildAnnotatedString { + var isBold = false + for (segment in split("**")) { + withStyle(style = SpanStyle(fontWeight = if (isBold) FontWeight.SemiBold else FontWeight.Normal)) { + append(segment) + } + isBold = !isBold + } + } +} + @Composable -fun UserRow(username: String, modifier: Modifier = Modifier, extraContent: @Composable (() -> Unit)? = null) { +fun UserRow( + username: String, + modifier: Modifier = Modifier, + extraContent: @Composable (() -> Unit)? = null, + color: Color? = null +) { Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier) { Column { Text( - "@$username", fontSize = 16.sp, fontWeight = FontWeight.Medium, modifier = Modifier - .background(colorResource(R.color.gray_700)) + "@$username", fontSize = 16.sp, fontWeight = FontWeight.Medium, color = color ?: MaterialTheme.colors.primary, modifier = Modifier .fillMaxWidth() ) if (extraContent != null) { diff --git a/common/src/main/res/values/colors.xml b/common/src/main/res/values/colors.xml index 1488f6ea8..e38a8810f 100644 --- a/common/src/main/res/values/colors.xml +++ b/common/src/main/res/values/colors.xml @@ -16,6 +16,8 @@ @color/brand_100 + #FFF5F5 + #FCEDED #f19595 #DE3F3F #C92B2B @@ -23,6 +25,8 @@ #7D0C0C #4C0001 + #FFF6F7 + #FCEEEF #ffb6b8 #FF6165 #F74E52 @@ -30,30 +34,40 @@ #BF262B #6c0406 + #FFF9F5 + #FCF3ED #ffc8a7 #FF944C #FA8537 #F47825 #A85219 + #FFFCF6 + #FCF3E5 #fedead #FFBE5D #FFB445 #FFA624 #EE9109 + #F5FFFB + #EDFCF7 #77f4c7 #24CC8F #20B780 #1CA372 #168059 + #F5FEFF + #EDFBFC #8eedf6 #3BCAD7 #34B5C1 #26A0AB #1A7078 + #FAFDFF + #EEF5F9 #a9dcf6 #50B5E9 #46A7D9