feat(profile): prettier account age

This commit is contained in:
Diego Beraldin 2023-08-01 08:58:42 +02:00
parent 2229883cb2
commit a58eb9b6b2
8 changed files with 161 additions and 29 deletions

View File

@ -1,5 +1,7 @@
package com.github.diegoberaldin.racconforlemmy.core_utils
import java.time.LocalDateTime
import java.time.Period
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
@ -13,6 +15,39 @@ actual object DateTime {
return date.format(formatter)
}
actual fun getPrettyDate(
iso8601Timestamp: String,
yearLabel: String,
monthLabel: String,
dayLabel: String,
): String {
val now = LocalDateTime.now().toLocalDate()
val date = getDateFromIso8601Timestamp(iso8601Timestamp).toLocalDate()
val delta = Period.between(date, now)
return when {
delta.years >= 1 -> buildString {
append("${delta.years}$yearLabel")
if (delta.months >= 1) {
append(" ${delta.months}$monthLabel")
}
if (delta.days >= 1) {
append(" ${delta.days}$dayLabel")
}
}
delta.months >= 1 -> buildString {
append("${delta.months}$monthLabel")
if (delta.days >= 1) {
append(" ${delta.days}$dayLabel")
}
}
else -> buildString {
append("${delta.days}$dayLabel")
}
}
}
private fun getDateFromIso8601Timestamp(string: String): ZonedDateTime {
return ZonedDateTime.parse(string)
}

View File

@ -5,4 +5,11 @@ expect object DateTime {
iso8601Timestamp: String,
format: String,
): String
fun getPrettyDate(
iso8601Timestamp: String,
yearLabel: String,
monthLabel: String,
dayLabel: String,
): String
}

View File

@ -1,5 +1,10 @@
package com.github.diegoberaldin.racconforlemmy.core_utils
import platform.Foundation.NSCalendar
import platform.Foundation.NSCalendarIdentifierGregorian
import platform.Foundation.NSCalendarUnitDay
import platform.Foundation.NSCalendarUnitMonth
import platform.Foundation.NSCalendarUnitYear
import platform.Foundation.NSDate
import platform.Foundation.NSDateFormatter
import platform.Foundation.NSISO8601DateFormatter
@ -23,6 +28,45 @@ actual object DateTime {
return dateFormatter.stringFromDate(date)
}
actual fun getPrettyDate(
iso8601Timestamp: String,
yearLabel: String,
monthLabel: String,
dayLabel: String,
): String {
val date = getDateFromIso8601Timestamp(iso8601Timestamp) ?: return ""
val now = NSDate()
val calendar = NSCalendar(calendarIdentifier = NSCalendarIdentifierGregorian)
val delta = calendar.components(
unitFlags = NSCalendarUnitDay.or(NSCalendarUnitMonth).or(NSCalendarUnitYear),
fromDate = date,
toDate = now,
options = 0,
)
return when {
delta.year >= 1 -> buildString {
append("${delta.year}$yearLabel")
if (delta.month >= 1) {
append(" ${delta.month}$monthLabel")
}
if (delta.day >= 1) {
append(" ${delta.day}$dayLabel")
}
}
delta.month >= 1 -> buildString {
append("${delta.month}$monthLabel")
if (delta.day >= 1) {
append(" ${delta.day}$dayLabel")
}
}
else -> buildString {
append("${delta.day}$dayLabel")
}
}
}
private fun getDateFromIso8601Timestamp(string: String): NSDate? {
return NSISO8601DateFormatter().dateFromString(string)
}

View File

@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@ -34,7 +33,6 @@ import io.kamel.image.asyncPainterResource
@Composable
internal fun ProfileLoggedContent(
user: UserModel,
onLogout: () -> Unit,
) {
Column(
modifier = Modifier.fillMaxSize().padding(horizontal = Spacing.m),
@ -44,16 +42,22 @@ internal fun ProfileLoggedContent(
val avatar = user.avatar.orEmpty()
if (avatar.isNotEmpty()) {
val painterResource = asyncPainterResource(data = avatar)
KamelImage(modifier = Modifier.size(100.dp).clip(RoundedCornerShape(CornerSize.m)),
KamelImage(
modifier = Modifier.size(100.dp).clip(RoundedCornerShape(CornerSize.m)),
resource = painterResource,
contentDescription = null,
onLoading = {
CircularProgressIndicator()
})
},
)
}
val name = user.name.orEmpty()
Text(
text = name, style = MaterialTheme.typography.headlineMedium
text = user.name,
style = MaterialTheme.typography.headlineSmall,
)
Text(
text = user.host,
style = MaterialTheme.typography.titleMedium,
)
Row(
modifier = Modifier.padding(horizontal = Spacing.m).fillMaxWidth(),
@ -104,9 +108,11 @@ internal fun ProfileLoggedContent(
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
Text(
text = DateTime.getFormattedDate(
text = DateTime.getPrettyDate(
iso8601Timestamp = user.accountAge + "Z",
format = "dd.MM.yy"
yearLabel = stringResource(MR.strings.profile_year_short),
monthLabel = stringResource(MR.strings.profile_month_short),
dayLabel = stringResource(MR.strings.profile_day_short),
),
style = MaterialTheme.typography.headlineSmall,
)
@ -117,13 +123,6 @@ internal fun ProfileLoggedContent(
}
}
Spacer(modifier = Modifier.height(Spacing.l))
Button(
onClick = {
onLogout()
},
) {
Text(stringResource(MR.strings.profile_button_logout))
}
Spacer(modifier = Modifier.height(Spacing.s))
}
}

View File

@ -21,7 +21,7 @@ internal fun ProfileNotLoggedContent(
) {
Column(
modifier = Modifier.fillMaxSize().padding(horizontal = Spacing.m),
verticalArrangement = Arrangement.spacedBy(Spacing.xs)
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
Text(
text = stringResource(MR.strings.profile_not_logged_message),

View File

@ -1,9 +1,11 @@
package com.github.diegoberaldin.raccoonforlemmy.feature_profile.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Logout
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
@ -15,11 +17,13 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.bottomSheet.LocalBottomSheetNavigator
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions
import com.github.diegoberaldin.racconforlemmy.core_utils.onClick
import com.github.diegoberaldin.raccoonforlemmy.core_appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core_architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.domain_identity.di.getApiConfigurationRepository
@ -41,7 +45,9 @@ object ProfileTab : Tab {
return remember(instance) {
TabOptions(
index = 0u, title = instance, icon = icon
index = 0u,
title = instance,
icon = icon,
)
}
}
@ -61,11 +67,26 @@ object ProfileTab : Tab {
val title by remember(lang) {
mutableStateOf(staticString(MR.strings.navigation_profile.desc()))
}
TopAppBar(title = {
TopAppBar(
title = {
Text(
text = title, style = MaterialTheme.typography.titleLarge
text = title,
style = MaterialTheme.typography.titleLarge,
)
},
actions = {
if (uiState.currentUser != null) {
Image(
modifier = Modifier.onClick {
model.reduce(ProfileScreenMviModel.Intent.Logout)
},
imageVector = Icons.Default.Logout,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary),
)
}
},
)
})
},
) {
val bottomSheetNavigator = LocalBottomSheetNavigator.current
@ -78,9 +99,9 @@ object ProfileTab : Tab {
bottomSheetNavigator.show(LoginBottomSheet())
})
} else {
ProfileLoggedContent(user = user, onLogout = {
model.reduce(ProfileScreenMviModel.Intent.Logout)
})
ProfileLoggedContent(
user = user,
)
}
}
}

View File

@ -44,6 +44,9 @@
<string name="profile_post_score">Post score</string>
<string name="profile_comment_score">Comment score</string>
<string name="profile_account_age">Account age</string>
<string name="profile_year_short">y</string>
<string name="profile_month_short">m</string>
<string name="profile_day_short">d</string>
<string name="login_field_instance_name">Instance name</string>
<string name="login_field_user_name">Username (or email)</string>

View File

@ -8,6 +8,11 @@
<string name="navigation_search">Ricerca</string>
<string name="navigation_settings">Impostazioni</string>
<string name="message_generic_error">Errore generico</string>
<string name="message_missing_field">Campo obbligatorio</string>
<string name="button_confirm">Conferma</string>
<string name="home_listing_type_all">Tutti</string>
<string name="home_listing_type_local">Locali</string>
<string name="home_listing_type_subscribed">Iscrizioni</string>
@ -28,6 +33,24 @@
<string name="home_sort_type_top_year">Top anno</string>
<string name="home_instance_via">via %1$s</string>
<string name="profile_not_logged_message">Login non effettuato.\nAggiungi un account per
continuare.
</string>
<string name="profile_button_login">Login</string>
<string name="profile_button_logout">Logout</string>
<string name="profile_post_score">Punti post</string>
<string name="profile_comment_score">Punti commento</string>
<string name="profile_account_age">Età account</string>
<string name="profile_year_short">a</string>
<string name="profile_month_short">m</string>
<string name="profile_day_short">g</string>
<string name="login_field_instance_name">Nome istanza</string>
<string name="login_field_user_name">Nome utente (o email)</string>
<string name="login_field_password">Password</string>
<string name="login_field_token">TOTP 2FA token</string>
<string name="login_field_label_optional">(opzionale)</string>
<string name="settings_ui_theme">Tema interfaccia</string>
<string name="settings_theme_dark">Scuro</string>
<string name="settings_theme_light">Chiaro</string>