Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ dependencies {
testImplementation(libs.sqldelight.test)
testImplementation(libs.jdbc.sqlite)
testImplementation(libs.androidx.test.core)
testImplementation(libs.kotlinx.coroutines.test)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Box
Expand Down Expand Up @@ -115,6 +116,10 @@ class MainActivity : ComponentActivity() {
directive = directive,
)

BackHandler(drawerState.isOpen) {
coroutineScope.launch { drawerState.close() }
}

OpenLettersTheme(
appTheme = currentTheme.first,
colorPalette = currentTheme.second,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ SELECT id FROM reminder ORDER BY scheduledFor DESC, title ASC;

urgentReminders:
SELECT id FROM reminder WHERE
-- (scheduledFor BETWEEN (strftime('%s','now', 'utc') - 86400) AND (strftime('%s','now', 'utc')) + 86400) AND acknowledged = 0 OR
scheduledFor <= strftime('%s','now', 'utc') AND acknowledged = 0
ORDER BY scheduledFor ASC, created ASC;
(scheduledFor <= strftime('%s','now', 'utc') OR scheduledFor <= strftime('%s', 'now', '+48 hours'))
AND acknowledged = 0
ORDER BY scheduledFor ASC, created DESC;

upcomingReminders:
SELECT id FROM reminder WHERE
(scheduledFor > (strftime('%s','now', 'utc'))) AND acknowledged = 0
ORDER BY scheduledFor ASC, created ASC;
(scheduledFor > (strftime('%s', 'now', '+48 hours'))) AND acknowledged = 0
ORDER BY scheduledFor ASC, created DESC;

pastReminders:
SELECT id FROM reminder WHERE acknowledged != 0 ORDER BY scheduledFor DESC, created DESC;
SELECT id FROM reminder WHERE acknowledged = 1 ORDER BY scheduledFor DESC, created DESC;

upsert:
INSERT INTO reminder (id, title, description, scheduledFor, created, lastModified, notificationId) VALUES (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.frozendevelopment.openletters.extensions

import android.text.format.DateUtils
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

Expand All @@ -14,3 +15,9 @@ val LocalDateTime.dateString: String
val dateTimeFormatter = DateTimeFormatter.ofPattern("MMM d, yyyy")
return this.format(dateTimeFormatter)
}

val LocalDateTime.relativeDateString: String
get() {
val targetMillis = toInstant(java.time.ZoneOffset.UTC).toEpochMilli()
return DateUtils.getRelativeTimeSpanString(targetMillis).toString()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,29 @@ import androidx.compose.animation.core.tween
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale

@Composable
fun Modifier.pulse() {
fun Modifier.pulse(
initialScale: Float = 1f,
targetScale: Float = 0.95f,
durationMillis: Int = 600,
): Modifier {
val infiniteTransition = rememberInfiniteTransition(label = "pulseInfiniteTransition")
val scale by infiniteTransition.animateFloat(
label = "pulseAnimation",
initialValue = 1f,
targetValue = 0.95f,
initialValue = initialScale,
targetValue = targetScale,
animationSpec =
infiniteRepeatable(
animation =
tween(
durationMillis = 600,
durationMillis = durationMillis,
easing = FastOutLinearInEasing,
),
repeatMode = RepeatMode.Reverse,
),
)

return this.scale(scale)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewLightDark
Expand All @@ -41,6 +42,7 @@ import com.github.skydoves.colorpicker.compose.HsvColorPicker
import com.github.skydoves.colorpicker.compose.rememberColorPickerController
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
import net.frozendevelopment.openletters.R
import net.frozendevelopment.openletters.data.sqldelight.models.CategoryId
import net.frozendevelopment.openletters.extensions.Random
import net.frozendevelopment.openletters.extensions.contrastColor
Expand Down Expand Up @@ -106,6 +108,7 @@ fun CategoryFormView(

Column(
verticalArrangement = Arrangement.spacedBy(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
CenterAlignedTopAppBar(
title = { Text(text = state.title) },
Expand Down Expand Up @@ -133,10 +136,9 @@ fun CategoryFormView(
}

CategoryPill(
modifier =
Modifier
.padding(horizontal = 16.dp)
.fillMaxWidth(),
modifier = Modifier
.padding(horizontal = 16.dp)
.fillMaxWidth(),
color = state.color,
) {
BasicTextField(
Expand All @@ -155,7 +157,7 @@ fun CategoryFormView(
) { innerTextField ->
if (state.label.isBlank() && !isFocused) {
Text(
text = "Tap to type your label",
text = stringResource(R.string.tap_to_type_your_label),
color = state.color.contrastColor,
style = MaterialTheme.typography.titleLarge,
)
Expand All @@ -167,36 +169,41 @@ fun CategoryFormView(

HorizontalDivider()

HsvColorPicker(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.padding(horizontal = 16.dp),
onColorChanged = { onColorChanged(it.color) },
controller = controller,
initialColor = state.color,
)

BrightnessSlider(
modifier = Modifier
.fillMaxWidth()
.height(35.dp)
.padding(horizontal = 16.dp),
controller = controller,
borderRadius = 32.dp,
)

TextButton(
modifier = Modifier.fillMaxWidth(.95f),
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.navigationBarsPadding(),
onClick = {
val color = Color.Random
controller.selectByColor(color, true)
onColorChanged(color)
},
) {
Text(text = "Randomize Color")
Text(
text = "Randomize Color",
style = MaterialTheme.typography.titleLarge,
)
}

BrightnessSlider(
modifier =
Modifier
.fillMaxWidth(.95f)
.height(35.dp),
controller = controller,
borderRadius = 32.dp,
)

HsvColorPicker(
modifier =
Modifier
.fillMaxWidth()
.navigationBarsPadding()
.padding(horizontal = 16.dp),
onColorChanged = { onColorChanged(it.color) },
controller = controller,
initialColor = state.color,
)
}
}

Expand All @@ -219,11 +226,11 @@ private fun CategoryFormPreview(state: CategoryFormState) {
@PreviewLightDark
private fun CategoryForm() {
CategoryFormPreview(
state =
CategoryFormState(
mode = CategoryFormDestination.Mode.Create,
label = "",
color = Color(0xFF0F0FF0),
),
state = CategoryFormState(
mode = CategoryFormDestination.Mode.Create,
label = "",
color = Color(0xFF0F0FF0),
isBusy = false,
),
)
}
Loading
Loading