Skip to content

Add continue watching, next-up card, API-key user selection, and scoped progress tracking#107

Merged
AbandonedCart merged 18 commits intomainfrom
copilot/add-continue-watching-section
Apr 17, 2026
Merged

Add continue watching, next-up card, API-key user selection, and scoped progress tracking#107
AbandonedCart merged 18 commits intomainfrom
copilot/add-continue-watching-section

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 16, 2026

  • Understand current state (tracking carried back via savedStateHandle from previous session)
  • PlayerScreen.kt (navigateBack) — reset tracking: write false to seriesEntry.savedStateHandle["trackProgress"] on pop path; drop trackProgress param from Screen.Series.createRoute on new-screen path
  • PlayerViewModel.kt (reportWatchProgress) — fix completion: when markPlayedIfComplete && isComplete, call markItemPlayed only (skip updateUserItemData so end-position is never saved); otherwise call updateUserItemData only
  • Build passes

Copilot AI and others added 8 commits April 16, 2026 21:02
Agent-Logs-Url: https://github.com/intro-skipper/segment-editor-mobile/sessions/cde8024f-c93d-4829-88dc-bfb1f969e5bc

Co-authored-by: AbandonedCart <1173913+AbandonedCart@users.noreply.github.com>
…selection

- Add `hasExplicitUserSelection` flag to SecurePreferences
- Set flag false during API key auth (auto-pick), true during username/password auth
- Set flag true when user explicitly selects a user in Settings
- Gate continue-watching load in LibraryViewModel on this flag
- Fix coil import (coil2 not coil3), add missing strings, fix indentation, fix line length
- Also complete prior work: user selection w/ avatar in Settings, Next Up card in player

Agent-Logs-Url: https://github.com/intro-skipper/segment-editor-mobile/sessions/cde8024f-c93d-4829-88dc-bfb1f969e5bc

Co-authored-by: AbandonedCart <1173913+AbandonedCart@users.noreply.github.com>
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 16, 2026

Reviewer's Guide

Implements Jellyfin-style continue watching and next-up playback features with scoped server-side progress tracking, plus an API-key user selector that gates which user’s data is used and whether continue watching is visible.

Sequence diagram for continue watching playback and server progress tracking

sequenceDiagram
    actor User
    participant LibraryScreen
    participant AppNavigation
    participant PlayerScreen
    participant PlayerViewModel
    participant MediaRepository
    participant SecurePreferences
    participant JellyfinApiService
    participant JellyfinServer

    User->>LibraryScreen: Tap continue watching item
    LibraryScreen->>AppNavigation: onContinueWatchingClick(itemId)
    AppNavigation->>AppNavigation: Screen.Player.createRoute(itemId, trackProgress=true)
    AppNavigation->>PlayerScreen: Navigate with itemId, trackProgressEnabled=true

    PlayerScreen->>PlayerViewModel: loadMediaItem(itemId, trackProgressToServer=true)
    PlayerViewModel->>PlayerViewModel: Reset lastProgressReportAtMs, hasMarkedPlayedForCurrentItem
    PlayerViewModel->>SecurePreferences: getUserId()
    SecurePreferences-->>PlayerViewModel: userId

    PlayerViewModel->>MediaRepository: getItemResult(userId, itemId, fields with RunTimeTicks, UserData)
    MediaRepository->>JellyfinApiService: getItem
    JellyfinApiService->>JellyfinServer: GET /Users/{userId}/Items/{itemId}
    JellyfinServer-->>JellyfinApiService: MediaItem JSON
    JellyfinApiService-->>MediaRepository: MediaItem
    MediaRepository-->>PlayerViewModel: Result(MediaItem)

    PlayerViewModel->>PlayerViewModel: Compute duration, resumePositionMs from userData when trackProgressToServer=true
    PlayerViewModel-->>PlayerScreen: uiState with trackProgressToServer=true, resumePositionMs>0

    PlayerScreen->>PlayerScreen: LaunchedEffect resumes ExoPlayer
    PlayerScreen->>PlayerScreen: player.seekTo(resumePositionMs)

    loop Periodic playback updates
        PlayerScreen->>PlayerViewModel: updatePlaybackState(isPlaying=true, currentPosition, bufferedPosition)
        PlayerViewModel->>PlayerViewModel: maybeReportWatchProgress(isPlaying, positionMs)
        alt trackProgressToServer && interval >= 15s
            PlayerViewModel->>SecurePreferences: getUserId()
            SecurePreferences-->>PlayerViewModel: userId
            PlayerViewModel->>MediaRepository: updateUserItemData(itemId, userId, UpdateUserItemDataDto)
            MediaRepository->>JellyfinApiService: updateUserItemData
            JellyfinApiService->>JellyfinServer: POST /UserItems/{itemId}/UserData
            JellyfinServer-->>JellyfinApiService: 204 No Content
        else Throttled or tracking disabled
            PlayerViewModel-->>PlayerViewModel: Skip report
        end
    end

    User->>PlayerScreen: Back or playback reaches end
    PlayerScreen->>PlayerViewModel: flushWatchProgress(positionMs or currentPosition)
    PlayerViewModel->>PlayerViewModel: reportWatchProgress(force=true, markPlayedIfComplete=true)
    PlayerViewModel->>MediaRepository: updateUserItemData(...)
    alt playedPercentage >= 95 and not hasMarkedPlayedForCurrentItem
        PlayerViewModel->>MediaRepository: markItemPlayed(itemId, userId)
        MediaRepository->>JellyfinApiService: markItemPlayed
        JellyfinApiService->>JellyfinServer: POST /UserPlayedItems/{itemId}
        JellyfinServer-->>JellyfinApiService: 204 No Content
        PlayerViewModel->>PlayerViewModel: hasMarkedPlayedForCurrentItem=true
    end

    rect rgb(235,235,255)
        PlayerViewModel->>PlayerViewModel: handlePlaybackEnded()
        PlayerViewModel->>SecurePreferences: getAutoPlayNextEpisode()
        alt autoPlayNextEpisode && nextItemId != null
            PlayerViewModel-->>PlayerScreen: PlayerEvent.NavigateToPlayer(nextItemId, trackProgressToServer=true)
            PlayerScreen->>AppNavigation: Navigate to next Player route with trackProgress=true
        end
    end
Loading

Sequence diagram for Next-Up card trigger and navigation

sequenceDiagram
    participant PlayerScreen
    participant PlayerViewModel
    participant SecurePreferences
    participant MediaRepository
    participant JellyfinApiService

    PlayerViewModel->>SecurePreferences: getUserId()
    SecurePreferences-->>PlayerViewModel: userId
    PlayerViewModel->>MediaRepository: getEpisodes(seriesId, userId, fields IndexNumber, ParentIndexNumber, ImageTags)
    MediaRepository-->>PlayerViewModel: Response(List MediaItem)

    PlayerViewModel->>PlayerViewModel: Sort episodes by season then episode
    PlayerViewModel->>PlayerViewModel: Find nextEpisode after current
    alt nextEpisode exists
        PlayerViewModel->>JellyfinApiService: getPrimaryImageUrl(nextEpisode.id, imageTag, maxWidth=320)
        JellyfinApiService-->>PlayerViewModel: imageUrl
        PlayerViewModel->>PlayerViewModel: Update uiState.nextItemId, nextItemName, nextItemImageUrl
    else no next episode
        PlayerViewModel->>PlayerViewModel: Clear nextItemId, nextItemName, nextItemImageUrl
    end

    par Segments or next episode info change
        PlayerViewModel->>PlayerViewModel: on segments loaded or next episode updated
        PlayerViewModel->>PlayerViewModel: computeNextUpTriggerMs()
    and Auto play check
        PlayerViewModel->>SecurePreferences: getAutoPlayNextEpisode()
        SecurePreferences-->>PlayerViewModel: autoPlayEnabled
    end

    PlayerViewModel->>PlayerViewModel: Determine nextUpShowAtMs based on
    PlayerViewModel->>PlayerViewModel: Outro, Preview, or 10 seconds before end
    PlayerViewModel-->>PlayerScreen: uiState.nextUpShowAtMs, showNextUpCard=false

    loop Playback position updates
        PlayerScreen->>PlayerViewModel: updatePlaybackState(isPlaying, currentPosition, bufferedPosition)
        PlayerViewModel->>PlayerViewModel: if currentPosition >= nextUpShowAtMs then showNextUpCard=true
        PlayerViewModel-->>PlayerScreen: uiState.showNextUpCard
        PlayerScreen->>PlayerScreen: Render NextUpCard overlay when visible
    end

    alt User taps NextUpCard
        PlayerScreen->>PlayerScreen: onPlayNextUp()
        PlayerScreen->>PlayerViewModel: handlePlaybackEnded()
        PlayerViewModel->>PlayerViewModel: reportWatchProgress(markPlayedIfComplete=true)
        PlayerViewModel-->>PlayerScreen: PlayerEvent.NavigateToPlayer(nextItemId, trackProgressToServer)
    else User dismisses card
        PlayerScreen->>PlayerViewModel: dismissNextUpCard()
        PlayerViewModel->>PlayerViewModel: showNextUpCard=false, nextUpShowAtMs=null
    end
Loading

Updated class diagram for playback, settings, and library models

classDiagram
    class PlayerViewModel {
        -segmentRepository: SegmentRepository
        -securePreferences: SecurePreferences
        -httpClient: OkHttpClient
        -jellyfinApiService: JellyfinApiService
        -skipMeApiService: SkipMeApiService
        -translationService: TranslationService
        -lastProgressReportAtMs: Long
        -hasMarkedPlayedForCurrentItem: Boolean
        +loadMediaItem(itemId: String, trackProgressToServer: Boolean)
        +updatePlaybackState(isPlaying: Boolean, currentPosition: Long, bufferedPosition: Long)
        +handlePlaybackEnded()
        +flushWatchProgress(positionMs: Long?)
        -maybeReportWatchProgress(isPlaying: Boolean, positionMs: Long)
        -reportWatchProgress(positionMs: Long, isPaused: Boolean, force: Boolean, markPlayedIfComplete: Boolean)
        -findNextEpisode(mediaItem: MediaItem)
        -computeNextUpTriggerMs()
        +dismissNextUpCard()
        +showNextUpCardNow()
    }

    class PlayerUiState {
        +nextItemId: String?
        +nextItemName: String?
        +nextItemImageUrl: String?
        +nextUpShowAtMs: Long?
        +showNextUpCard: Boolean
        +trackProgressToServer: Boolean
        +resumePositionMs: Long
    }

    class PlayerEvent {
    }
    class NavigateToPlayer {
        +itemId: String
        +trackProgressToServer: Boolean
    }

    class LibraryViewModel {
        -securePreferences: SecurePreferences
        -mediaRepository: MediaRepository
        +loadLibraries()
    }

    class LibraryUiState {
    }
    class Success {
        +libraries: List~Library~
        +continueWatching: List~ContinueWatchingItem~
        +isSharingLibraryId: String?
        +sharingProgress: Float?
    }

    class ContinueWatchingItem {
        +id: String
        +name: String
        +type: String?
        +seriesName: String?
        +seasonNumber: Int?
        +episodeNumber: Int?
        +primaryImageTag: String?
        +playbackPositionTicks: Long
        +runTimeTicks: Long
        +progress: Float
    }

    class SettingsViewModel {
        -securePreferences: SecurePreferences
        -jellyfinRepository: JellyfinRepository
        -authRepository: AuthRepository
        -apiService: JellyfinApiService
        -translationService: TranslationService
        +loadPreferences()
        +loadAvailableUsers()
        +selectUser(userId: String, username: String)
    }

    class SettingsUiState {
        +isApiKeyLogin: Boolean
        +availableUsers: List~UserInfo~
        +isLoadingUsers: Boolean
        +selectedUserId: String
        +selectedUsername: String
    }

    class UserInfo {
        +id: String
        +name: String
        +avatarUrl: String?
    }

    class JellyfinApiService {
        +updateUserItemData(itemId: String, data: UpdateUserItemDataDto, userId: String?): Response~Unit~
        +markItemPlayed(itemId: String, userId: String?): Response~Unit~
        +getUserImageUrl(userId: String, imageTag: String?): String?
        +getPrimaryImageUrl(itemId: String, imageTag: String, maxWidth: Int): String?
    }

    class MediaRepository {
        -apiService: JellyfinApiService
        +getContinueWatching(userId: String, limit: Int): Response~ItemsResponse~
        +updateUserItemData(itemId: String, userId: String, data: UpdateUserItemDataDto): Response~Unit~
        +markItemPlayed(itemId: String, userId: String): Response~Unit~
    }

    class SecurePreferences {
        +saveIsApiKeyLogin(isApiKey: Boolean)
        +getIsApiKeyLogin(): Boolean
        +saveHasExplicitUserSelection(hasSelection: Boolean)
        +getHasExplicitUserSelection(): Boolean
        +saveUserId(userId: String)
        +getUserId(): String?
        +saveUsername(username: String)
        +getUsername(): String?
        +setAutoPlayNextEpisode(enabled: Boolean)
        +getAutoPlayNextEpisode(): Boolean
    }

    class UpdateUserItemDataDto {
        +playbackPositionTicks: Long?
        +playedPercentage: Double?
        +played: Boolean?
    }

    PlayerViewModel --> PlayerUiState
    PlayerViewModel --> PlayerEvent
    PlayerEvent <|-- NavigateToPlayer
    LibraryViewModel --> LibraryUiState
    LibraryUiState <|-- Success
    Success --> ContinueWatchingItem
    SettingsViewModel --> SettingsUiState
    SettingsUiState --> UserInfo
    SettingsViewModel --> JellyfinApiService
    SettingsViewModel --> AuthRepository
    SettingsViewModel --> SecurePreferences
    LibraryViewModel --> SecurePreferences
    LibraryViewModel --> MediaRepository
    PlayerViewModel --> MediaRepository
    PlayerViewModel --> SecurePreferences
    MediaRepository --> JellyfinApiService
    JellyfinApiService --> UpdateUserItemDataDto
Loading

File-Level Changes

Change Details Files
Add Jellyfin-backed continue watching rail to the library screen, scoped to explicitly-selected users when in API-key mode.
  • Extend LibraryUiState with a continueWatching list and populate it from mediaRepository.getContinueWatching when API-key login has an explicit user selection or when using non-API auth.
  • Introduce ContinueWatchingItem view-model type that derives a normalized progress fraction from playback and runtime ticks.
  • Render a Continue Watching section above the library list using ContinueWatchingCard composables with poster, subtitle, and linear progress, and wire clicks to a dedicated continue-watching navigation callback.
  • Update AppNavigation to pass an onContinueWatchingClick callback that launches PlayerScreen with trackProgress enabled.
android/app/src/main/java/org/introskipper/segmenteditor/ui/screen/LibraryScreen.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/viewmodel/LibraryViewModel.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/navigation/AppNavigation.kt
Introduce server-side watch progress reporting and scoped resume behavior that only activates when playback originates from continue watching.
  • Add trackProgressToServer and resumePositionMs to PlayerUiState and thread a trackProgressEnabled flag from navigation into PlayerScreen and PlayerViewModel.loadMediaItem.
  • Populate resumePositionMs from Jellyfin UserData.playbackPositionTicks when tracking is enabled, and seek the ExoPlayer to this position once per item on load.
  • Implement throttled watch progress reporting in PlayerViewModel via updateUserItemData, flushing on pause/back/exit and at playback end, and marking items played when a 95% completion threshold is crossed.
  • Wire navigateBack and playback-end handling to call flushWatchProgress with the final playback position, and ensure auto-played episodes inherit the trackProgressToServer flag.
android/app/src/main/java/org/introskipper/segmenteditor/ui/viewmodel/PlayerViewModel.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/screen/PlayerScreen.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/navigation/AppNavigation.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/state/PlayerUiState.kt
android/app/src/main/java/org/introskipper/segmenteditor/data/repository/MediaRepository.kt
android/app/src/main/java/org/introskipper/segmenteditor/api/JellyfinApiService.kt
android/app/src/main/java/org/introskipper/segmenteditor/api/JellyfinApi.kt
android/app/src/main/java/org/introskipper/segmenteditor/data/model/PlaybackModels.kt
Add a Next-Up overlay card in the player with timing derived from segment metadata and constrained to the current series.
  • Change next-episode lookup in PlayerViewModel to fetch all episodes in a series, sort by season and episode, and resolve nextItemId, name, and thumbnail URL via Jellyfin image builders.
  • Introduce computeNextUpTriggerMs that recalculates a trigger time based on Outro and Preview segments or falls back to 10 seconds before the end, disabling when auto-play is off or there is no next episode.
  • Extend PlayerUiState with nextUpShowAtMs, showNextUpCard, nextItemName, and nextItemImageUrl, toggling visibility when updatePlaybackState crosses the trigger and providing dismiss/show helpers.
  • Implement a NextUpCard composable overlay in PlayerScreen using AnimatedVisibility and AsyncImage, and hook the play button to call handlePlaybackEnded so the existing auto-play path is reused.
android/app/src/main/java/org/introskipper/segmenteditor/ui/viewmodel/PlayerViewModel.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/screen/PlayerScreen.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/state/PlayerUiState.kt
android/app/src/main/res/values/strings.xml
Introduce API-key-mode user selection in Settings and plumb explicit-user-selection state into auth and preferences to gate continue-watching visibility.
  • Extend SettingsUiState with API-key-related fields (isApiKeyLogin, availableUsers, isLoadingUsers, selectedUserId/selectedUsername) and a UserInfo wrapper including avatar URL.
  • In SettingsViewModel, detect API-key login, fetch users via authRepository.getUsers, map them to UserInfo with JellyfinApiService.getUserImageUrl, and expose selectUser to persist userId/username and mark explicit selection.
  • Add UserSelectionSettingItem and UserAvatar composables to SettingsScreen to render an exposed dropdown of users with avatars and fallback person icons, shown only when isApiKeyLogin is true.
  • Extend SecurePreferences with isApiKeyLogin and hasExplicitUserSelection flags, set them appropriately from AuthViewModel for API-key and username/password flows, and use them in LibraryViewModel to decide when to fetch continue watching.
android/app/src/main/java/org/introskipper/segmenteditor/ui/viewmodel/SettingsViewModel.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/screen/SettingsScreen.kt
android/app/src/main/java/org/introskipper/segmenteditor/storage/SecurePreferences.kt
android/app/src/main/java/org/introskipper/segmenteditor/ui/viewmodel/AuthViewModel.kt
android/app/src/main/res/values/strings.xml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@AbandonedCart AbandonedCart marked this pull request as ready for review April 16, 2026 21:35
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

)
) {
// Pop current player from backstack to avoid loops
popUpTo("${Screen.Player.route}/{itemId}") { inclusive = true }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: popUpTo route pattern no longer matches the registered route

The composable route was changed to "${Screen.Player.route}/{itemId}?trackProgress={trackProgress}" in AppNavigation.kt, but popUpTo here still uses the old "${Screen.Player.route}/{itemId}". Compose Navigation matches routes exactly, so this popUpTo will silently fail to find any entry and player screens will stack up on each auto-play transition.

Suggested change
popUpTo("${Screen.Player.route}/{itemId}") { inclusive = true }
popUpTo("${Screen.Player.route}/{itemId}?trackProgress={trackProgress}") { inclusive = true }

viewModel: PlayerViewModel,
positionMs: Long? = null
) {
viewModel.flushWatchProgress(positionMs)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Progress flush is fire-and-forget — may not complete before navigation

flushWatchProgress launches a new coroutine inside viewModelScope. Navigation begins immediately afterward, and once the destination changes the ViewModel may be cleared before the HTTP request completes, silently dropping the final progress report.

Consider making flushWatchProgress a suspending function and awaiting it in a coroutine scope tied to the composable lifecycle (e.g. via rememberCoroutineScope) before calling navController.navigate/popBackStack, or at minimum use a NonCancellable context for the report.

@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented Apr 16, 2026

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
PlayerScreen.kt 153 popUpTo route pattern still uses old path without ?trackProgress={trackProgress} — won't pop backstack on auto-play
PlayerScreen.kt 840 flushWatchProgress fires a coroutine then navigation proceeds immediately — final progress report may be dropped
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
PlayerScreen.kt 859 Second popUpTo("${Screen.Player.route}/{itemId}") inside navigateBack has the same stale route pattern as the one at line 153 and should be updated to match the registered route.
Incremental Update (latest commits)

Changed files reviewed — no new issues found:

  • SettingsScreen.kt — fixed SwitchAccountSheet dismissal race by keeping sheet open during isSwitchingUser and auto-dismissing via LaunchedEffect on completion ✓; cleaned up inline icon references ✓
Files Reviewed (16 files)
  • JellyfinApi.kt
  • JellyfinApiService.kt
  • PlaybackModels.kt
  • MediaRepository.kt
  • SecurePreferences.kt
  • AppNavigation.kt
  • Screen.kt
  • LibraryScreen.kt
  • PlayerScreen.kt — 2 issues
  • SettingsScreen.kt
  • PlayerUiState.kt
  • AuthViewModel.kt
  • LibraryViewModel.kt
  • PlayerViewModel.kt
  • SettingsViewModel.kt
  • strings.xml

Fix these issues in Kilo Cloud


Reviewed by claude-4.6-sonnet-20260217 · 388,983 tokens

…section

Place the API-key user picker directly below the server info and above
the Change Server button, matching the requested order:
  server info → user selection (API key only) → change server

Agent-Logs-Url: https://github.com/intro-skipper/segment-editor-mobile/sessions/64cadf43-1940-40b0-ac1b-2234185b352c

Co-authored-by: AbandonedCart <1173913+AbandonedCart@users.noreply.github.com>
…itching, user-aware continue watching refresh

Agent-Logs-Url: https://github.com/intro-skipper/segment-editor-mobile/sessions/43769a49-1d6f-4738-9e4e-3dd7c6389679

Co-authored-by: AbandonedCart <1173913+AbandonedCart@users.noreply.github.com>
@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented Apr 16, 2026

Kilo Code Review could not run — your account is out of credits.

Add credits or switch to a free model to enable reviews on this change.

…ving end-position

Agent-Logs-Url: https://github.com/intro-skipper/segment-editor-mobile/sessions/a328bac4-e614-4ce9-adcf-16399506c979

Co-authored-by: AbandonedCart <1173913+AbandonedCart@users.noreply.github.com>
@AbandonedCart AbandonedCart merged commit 08e13fe into main Apr 17, 2026
2 of 3 checks passed
@AbandonedCart AbandonedCart deleted the copilot/add-continue-watching-section branch April 17, 2026 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants