# Features and Flows

## Overview

This document describes the user-facing features in the app and the main state/behavior objects behind each flow.

## Authentication

### Main files

- `presentation/auth/AuthViewModel.kt`
- `presentation/auth/AuthScreen.kt`
- `domain/auth/PasskeyAuthenticator.kt`
- `jvmMain/data/auth/BrowserPasskeyAuthenticator.jvm.kt`

### User flow

1. User enters an email address.
2. The auth ViewModel validates the email format.
3. The app tries a passkey login first.
4. If the backend reports `UserNotFound`, the app falls back to registration.
5. On success, the returned bearer token is stored in `CurrentSessionProvider`.
6. Root state reacts to the active session and moves the app into the authenticated flow.

### Notes

- The desktop implementation launches the system browser.
- A local callback server listens on `127.0.0.1`.
- Errors are surfaced through snackbar events.

## Root application state

### Main files

- `presentation/root/AppRootScreenModel.kt`
- `presentation/root/AppRootRoute.kt`
- `presentation/root/AppRootUiState.kt`

### Responsibilities

- load any persisted token
- watch the current session
- decide whether the app is loading, unauthenticated, or authenticated
- bootstrap theme mode
- load user settings needed by the shell
- load current subscription tier with retries

### Why it matters

This model is the bridge between low-level session persistence and high-level screen navigation.

## Daily feed

### Main files

- `presentation/dailyfeed/DailyFeedViewModel.kt`
- `presentation/dailyfeed/DailyFeedScreen.kt`
- `domain/usecase/GetDailyFeedUseCase.kt`
- `thulur_api/methods/daily_feed/DailyFeedMethod.kt`

### Behavior

The daily feed screen:

- loads the current day on startup
- allows back and forward navigation by day
- tracks whether the loaded feed is backend-default or explicit
- supports topic/article visibility modes
- supports jumping to another day when a thread has more articles there
- reacts to the local read-article cache

### State model

The screen alternates between:

- loading
- empty
- success
- error

The ViewModel also stores:

- selected day
- feed scroll position
- per-thread article visibility
- optional focus requests used after cross-day navigation

## Thread history

### Main files

- `presentation/dailyfeed/thread_history/ThreadHistoryViewModel.kt`
- `presentation/dailyfeed/thread_history/ThreadHistoryRoute.kt`
- `domain/usecase/GetThreadHistoryUseCase.kt`
- `thulur_api/methods/thread_history/ThreadHistoryMethod.kt`

### Behavior

Thread history loads all known days for a thread and then:

- sorts them descending by day
- resolves the initial visible day from the originating daily-feed day
- lets the user move between days inside the thread
- updates read-state markings when the in-memory read cache changes

### Subscription-gated behavior

Whether a thread can be discussed in chat is derived from the subscription tier loaded in root state, not from a dedicated thread-history service.

## Chat

### Main files

- `presentation/chat/ChatViewModel.kt`
- `presentation/chat/ChatScreen.kt`
- `presentation/router/ChatMode.kt`
- `domain/usecase/SendGeneralChatMessageUseCase.kt`
- `domain/usecase/SendThreadChatMessageUseCase.kt`

### Modes

- `General`
- `Thread(threadId)`

### Behavior

When the user sends a message:

1. The input is trimmed and validated.
2. The UI immediately appends a user message and a pending assistant message.
3. The ViewModel calls either general chat or thread chat.
4. The pending assistant bubble is replaced with the real result or an error message.

### Link handling

Assistant replies contain markdown and a list of related article IDs. Links clicked inside chat can resolve into:

- a tracked article reader launch
- a browser-fallback article reader launch

## Article reader

### Main files

- `presentation/dailyfeed/article_reader/ArticleReaderViewModel.kt`
- `presentation/dailyfeed/article_reader/ArticleReaderScreen.kt`
- `presentation/dailyfeed/article_reader/ArticleReaderLaunchMode.kt`
- `jvmMain/presentation/dailyfeed/article_reader/JcefBrowserRuntime.jvm.kt`
- `jvmMain/presentation/dailyfeed/article_reader/PlatformArticleWebView.jvm.kt`

### Launch modes

- `Tracked(articleId, isRead)`
- `BrowserFallback`

### Behavior in tracked mode

Tracked mode can:

- load paragraph metadata for the article
- track reading progress
- collect a rating
- mark the article as read in the in-memory cache after a successful rating submission

### Rate submission rules

Rate submission is skipped when:

- the launch mode is browser fallback
- the article is already marked read
- no rating has been set
- another submission is already in progress

### Desktop runtime notes

- JCEF is prewarmed at app startup.
- JCEF is disposed when the main window closes.
- JCEF runtime files are stored under the user home directory in `.thulur/jcef-runtime`.

## Settings

### Main files

- `presentation/settings/SettingsViewModel.kt`
- `presentation/settings/SettingsScreen.kt`
- `presentation/settings/SettingsUiState.kt`
- `domain/usecase/GetUserSettingsUseCase.kt`
- `domain/usecase/PatchUserSettingsUseCase.kt`
- `thulur_api/methods/settings/*`
- `thulur_api/methods/feeds/*`
- `thulur_api/methods/auth/*`

### Sections in state

- `AccountAndApp`
- `Subscription`
- `Feeds`

The current shared ViewModel actively manages account/app settings and feeds. Subscription capability is currently consumed elsewhere through the root user/subscription load.

### Account data

The account area loads:

- current user email
- active auth sessions

It also supports terminating individual auth sessions.

### App settings

The app settings area manages:

- theme
- language
- notifications enabled
- feed schedule time
- timezone
- suggestions outside the current followed feeds

Settings mutations are optimistic:

1. local state updates immediately
2. the patch request is sent
3. confirmed values replace the optimistic state on success
4. state rolls back to the last confirmed values on failure

### Feeds management

The feeds area loads:

- followed feeds
- the full feed catalog

It supports:

- searching the available catalog
- following a feed by identifier
- unfollowing a feed by feed ID
- separate pending sets for follow and unfollow actions

## Theme and shared UI primitives

### Main files

- `presentation/theme/*`
- `presentation/composables/*`

### Conventions

- prefer `ThulurTheme` and existing `Thulur*` components
- keep shared styling decisions in `presentation/theme`
- keep reusable UI primitives in `presentation/composables`

This keeps feature screens visually consistent and reduces one-off widget implementations.
