Some UI tuning, add README and screenshots
This commit is contained in:
16
README.md
Normal file
16
README.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Tomato
|
||||||
|
|
||||||
|
### THIS PROJECT IS IN A VERY EARLY DEVELOPMENT STAGE. MOST FEATURES ARE NOT YET READY
|
||||||
|
|
||||||
|
### About
|
||||||
|
|
||||||
|
Tomato is a minimalist Pomodoro timer for Android based on Material 3 Expressive
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
|
||||||
|
<p align="center" width="100%">
|
||||||
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg" width="24%">
|
||||||
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg" width="24%">
|
||||||
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg" width="24%">
|
||||||
|
<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg" width="24%">
|
||||||
|
</p>
|
||||||
@@ -29,9 +29,12 @@ import androidx.compose.material3.Scaffold
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@@ -55,6 +58,8 @@ fun TimerScreen(
|
|||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val motionScheme = motionScheme
|
val motionScheme = motionScheme
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
|
||||||
val color by animateColorAsState(
|
val color by animateColorAsState(
|
||||||
if (uiState.timerMode == TimerMode.FOCUS) colorScheme.primary
|
if (uiState.timerMode == TimerMode.FOCUS) colorScheme.primary
|
||||||
else colorScheme.tertiary,
|
else colorScheme.tertiary,
|
||||||
@@ -71,6 +76,10 @@ fun TimerScreen(
|
|||||||
animationSpec = motionScheme.slowEffectsSpec()
|
animationSpec = motionScheme.slowEffectsSpec()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LaunchedEffect(uiState.timerMode) {
|
||||||
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ import kotlinx.coroutines.flow.asStateFlow
|
|||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import kotlin.math.ceil
|
||||||
|
|
||||||
class UiViewModel : ViewModel() {
|
class UiViewModel : ViewModel() {
|
||||||
val focusTime = 10000
|
val focusTime = 25 * 60 * 1000
|
||||||
val shortBreakTime = 5000
|
val shortBreakTime = 5 * 60 * 1000
|
||||||
val longBreakTime = 20000
|
val longBreakTime = 15 * 60 * 1000
|
||||||
|
|
||||||
private val _uiState = MutableStateFlow(
|
private val _uiState = MutableStateFlow(
|
||||||
UiState(
|
UiState(
|
||||||
@@ -57,7 +58,7 @@ class UiViewModel : ViewModel() {
|
|||||||
timerJob = viewModelScope.launch {
|
timerJob = viewModelScope.launch {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!uiState.value.timerRunning) break
|
if (!uiState.value.timerRunning) break
|
||||||
_time.update { it - 10 }
|
_time.update { it - 100 }
|
||||||
|
|
||||||
if (time.value < 0) {
|
if (time.value < 0) {
|
||||||
cycles++
|
cycles++
|
||||||
@@ -97,15 +98,15 @@ class UiViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(10)
|
delay(100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun millisecondsToStr(t: Int): String {
|
private fun millisecondsToStr(t: Int): String {
|
||||||
val min = (t / 1000) / 60
|
val min = (ceil(t / 1000.0).toInt() / 60)
|
||||||
val sec = (t / 1000) % 60
|
val sec = (ceil(t / 1000.0).toInt() % 60)
|
||||||
return String.format(locale = Locale.getDefault(), "%02d:%02d", min, sec)
|
return String.format(locale = Locale.getDefault(), "%02d:%02d", min, sec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 160 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 164 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 179 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 180 KiB |
Reference in New Issue
Block a user