From 7368b27c65ffb28e7985d4a5002e55387cb957eb Mon Sep 17 00:00:00 2001 From: choiminyeong Date: Mon, 12 Oct 2026 14:28:44 +0900 Subject: [PATCH] TASK-069: bottom tab switches glide the whole width Agent: main (opus) Co-Authored-By: Claude Opus 5.5 --- .../java/com/ubisam/ubgitea/MainActivity.kt | 23 +++++++++++++------ docs/development-log.md | 9 ++++++++ tasks/069-in-app-motion.md | 3 ++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/ubisam/ubgitea/MainActivity.kt b/app/src/main/java/com/ubisam/ubgitea/MainActivity.kt index 89941ab..87e006f 100644 --- a/app/src/main/java/com/ubisam/ubgitea/MainActivity.kt +++ b/app/src/main/java/com/ubisam/ubgitea/MainActivity.kt @@ -17,10 +17,12 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInHorizontally +import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.togetherWith import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box @@ -41,6 +43,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.IntOffset import com.ubisam.ubgitea.core.auth.protocol.UBGiteaOAuthDefaults import com.ubisam.ubgitea.core.notifications.FavoritePushNotifier import com.ubisam.ubgitea.core.notifications.FavoritePushScheduler @@ -436,13 +439,19 @@ class MainActivity : ComponentActivity() { transitionSpec = { val fromTab = initialState.tab val toTab = targetState.tab - val direction = when { - stackDepth != shownDepth[0] -> stackDepth - shownDepth[0] - fromTab != null && toTab != null -> toTab.ordinal - fromTab.ordinal - else -> 0 - }.coerceIn(-1, 1) - (fadeIn(tween(200, delayMillis = 50)) + slideInHorizontally(tween(260)) { it / 10 * direction }) - .togetherWith(fadeOut(tween(90))) + val tabSwitch = stackDepth == shownDepth[0] && fromTab != null && toTab != null + if (tabSwitch) { + // Tabs sit side by side: the old one glides out as the new one + // glides in, the whole width, like turning to the next page. + val direction = (toTab.ordinal - fromTab.ordinal).coerceIn(-1, 1) + val glide = tween(320, easing = FastOutSlowInEasing) + slideInHorizontally(glide) { it * direction } + .togetherWith(slideOutHorizontally(glide) { -it * direction }) + } else { + val direction = (stackDepth - shownDepth[0]).coerceIn(-1, 1) + (fadeIn(tween(200, delayMillis = 50)) + slideInHorizontally(tween(260)) { it / 10 * direction }) + .togetherWith(fadeOut(tween(90))) + } }, contentKey = { it::class }, label = "route", diff --git a/docs/development-log.md b/docs/development-log.md index 287f905..13c7797 100644 --- a/docs/development-log.md +++ b/docs/development-log.md @@ -1552,3 +1552,12 @@ This is the append-only implementation and handoff record shared by Codex and Cl superseded. Publishing is the three steps in `tasks/070-update-from-gitea.md`. - Caution: the page at `choimy0204.github.io/ubgitea/` still exists (password, 0.2.0). Copies of the app older than 0.2.2 keep reading it and see "up to date". + +## 2026-10-12 (continued) — TASK-069: tab switches glide + +- Request: the product owner wanted moving between bottom tabs to glide. +- What changed: a tab switch now moves both screens the whole width, the old one out as the new + one comes in (320 ms), in place of the short nudge with a fade. Pushed and popped screens keep + the short slide. +- Checks and results: the five required checks pass. Not seen on a device; not in the published + 0.2.2. diff --git a/tasks/069-in-app-motion.md b/tasks/069-in-app-motion.md index 4439fae..7be1472 100644 --- a/tasks/069-in-app-motion.md +++ b/tasks/069-in-app-motion.md @@ -17,7 +17,8 @@ The app moves where it used to jump, and what moves is the launcher icon's tea c 6. Pull to refresh brings the cup down with the finger; the steam appears near the release point. 7. A file's diff arrives row by row the first time it is shown. 8. Added while this was in progress (product owner, 2026-10-12): switching bottom tabs slides the - screen in from the side that tab sits on, and the tab's icon springs. + whole screen sideways, the old tab gliding out as the new one glides in, and the tab's icon + springs. ## Scope