Add location reordering support and improve page transitions
- Add DAO and repository methods for reordering locations by display order - Make PageIndicator clickable with ripple effect for future reorder UI - Replace SunCard alpha fade with dark scrim overlay for smoother transitions - Add Claude Code custom commands
This commit is contained in:
parent
ecd734582c
commit
0512ee674d
7 changed files with 106 additions and 26 deletions
15
.claude/commands/commit-push-pr.md
Normal file
15
.claude/commands/commit-push-pr.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)
|
||||
description: Create a git commit
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
- Current git status: !`git status`
|
||||
- Current git diff (staged and unstaged changes): !`git diff HEAD`
|
||||
- Current branch: !`git branch --show-current`
|
||||
- Recent commits: !`git log --oneline -10`
|
||||
|
||||
## Your task
|
||||
|
||||
Based on the above changes, create a single git commit. Then push it.
|
||||
15
.claude/commands/new-version.md
Normal file
15
.claude/commands/new-version.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)
|
||||
description: Do migration tests first. Then: update changelog, update readme, update version in gradle files, create a git commit and push it
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
- Current git status: !`git status`
|
||||
- Current git diff (staged and unstaged changes): !`git diff HEAD`
|
||||
- Current branch: !`git branch --show-current`
|
||||
- Recent commits: !`git log --oneline -10`
|
||||
|
||||
## Your task
|
||||
|
||||
Do migration tests first. Then: update changelog, update readme, update version in gradle files, create a git commit and push it
|
||||
|
|
@ -4,6 +4,7 @@ import androidx.room.Dao
|
|||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
|
|
@ -23,4 +24,10 @@ interface LocationDao {
|
|||
|
||||
@Query("DELETE FROM locations WHERE isCurrentLocation = 1")
|
||||
suspend fun deleteCurrentLocation()
|
||||
|
||||
@Update
|
||||
suspend fun updateLocations(locations: List<LocationEntity>)
|
||||
|
||||
@Query("SELECT * FROM locations ORDER BY displayOrder ASC, id ASC")
|
||||
suspend fun getAllLocationsOnce(): List<LocationEntity>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,4 +23,16 @@ class LocationRepository @Inject constructor(
|
|||
locationDao.deleteCurrentLocation()
|
||||
locationDao.insertLocation(location)
|
||||
}
|
||||
|
||||
suspend fun reorderLocations(fromIndex: Int, toIndex: Int) {
|
||||
val locations = locationDao.getAllLocationsOnce().toMutableList()
|
||||
if (fromIndex !in locations.indices || toIndex !in locations.indices) return
|
||||
val item = locations.removeAt(fromIndex)
|
||||
locations.add(toIndex, item)
|
||||
val updated = locations.mapIndexed { i, e -> e.copy(displayOrder = i) }
|
||||
locationDao.updateLocations(updated)
|
||||
}
|
||||
|
||||
suspend fun getAllLocationsOnce(): List<LocationEntity> =
|
||||
locationDao.getAllLocationsOnce()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,4 +97,10 @@ class MainViewModel @Inject constructor(
|
|||
repository.deleteLocation(id)
|
||||
}
|
||||
}
|
||||
|
||||
fun reorderLocations(fromIndex: Int, toIndex: Int) {
|
||||
viewModelScope.launch {
|
||||
repository.reorderLocations(fromIndex, toIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,20 @@ import androidx.compose.animation.animateColorAsState
|
|||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
|
|
@ -22,12 +28,22 @@ import androidx.compose.ui.unit.dp
|
|||
fun PageIndicator(
|
||||
pageCount: Int,
|
||||
currentPage: Int,
|
||||
modifier: Modifier = Modifier
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit = {}
|
||||
) {
|
||||
if (pageCount <= 1) return
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(color = Color.White.copy(alpha = 0.3f)),
|
||||
onClick = onClick
|
||||
)
|
||||
.padding(horizontal = 12.dp, vertical = 8.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
|
|
@ -55,3 +71,4 @@ fun PageIndicator(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,9 +129,9 @@ fun SunCard(
|
|||
val isSunsetWindow = location.isDaytime && location.sunProgress > 0.92f
|
||||
val particleActive = isSunriseWindow || isSunsetWindow
|
||||
|
||||
// Page transition: scale + fade (replaces parallax translationX)
|
||||
// Page transition: scale + dark scrim (no alpha fade to avoid "lightening" effect)
|
||||
val scale = lerp(0.92f, 1f, 1f - pageOffset.absoluteValue.coerceAtMost(1f))
|
||||
val pageFade = lerp(0.6f, 1f, 1f - pageOffset.absoluteValue.coerceAtMost(1f))
|
||||
val scrimAlpha = lerp(0f, 0.2f, pageOffset.absoluteValue.coerceAtMost(1f))
|
||||
|
||||
BoxWithConstraints(
|
||||
modifier = modifier
|
||||
|
|
@ -139,7 +139,6 @@ fun SunCard(
|
|||
.graphicsLayer {
|
||||
scaleX = scale
|
||||
scaleY = scale
|
||||
alpha = pageFade
|
||||
}
|
||||
.background(brush = Brush.verticalGradient(displayGradient))
|
||||
) {
|
||||
|
|
@ -419,6 +418,15 @@ fun SunCard(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Dark scrim overlay for page transition depth effect
|
||||
if (scrimAlpha > 0.01f) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black.copy(alpha = scrimAlpha))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showDeleteDialog) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue