227 lines
9.4 KiB
Markdown
227 lines
9.4 KiB
Markdown
# Gitea TUI (fjtui) System Architecture
|
|
|
|
This document provides a comprehensive overview of the Gitea/Forgejo TUI Dashboard's system architecture, component layout, and user flows. It uses **Mermaid.js** diagrams to detail the application structure and page lifecycle transitions.
|
|
|
|
---
|
|
|
|
## 1. High-Level Architecture
|
|
|
|
The Gitea TUI client is a modular CLI application written in TypeScript and Node.js. It operates as a local state machine that communicates with a Gitea or Forgejo instance REST API over HTTPS.
|
|
|
|
```mermaid
|
|
graph TD
|
|
subgraph Client ["Gitea TUI Application Context"]
|
|
EP["index.ts (CLI Entry Point)"]
|
|
ConfigManager["config.ts (Configuration Manager)"]
|
|
TuiEngine["tui.ts (TuiEngine Controller)"]
|
|
APILayer["api.ts (API Service Layer)"]
|
|
Types["types.ts (State & Entity Types)"]
|
|
end
|
|
|
|
subgraph External ["External Resources"]
|
|
LocalConfig["Local Config (./fjtui.json)"]
|
|
GlobalConfig["Global Config (~/.config/fjtui/fjtui.json)"]
|
|
GiteaAPI["Gitea/Forgejo Instance REST API"]
|
|
end
|
|
|
|
subgraph IO ["Terminal User Interface"]
|
|
Stdin["stdin (Raw Keypress Listeners)"]
|
|
Stdout["stdout (Chalk Styled Rendering)"]
|
|
end
|
|
|
|
%% Key Relationships
|
|
EP -->|Reads Config / Parses Args| ConfigManager
|
|
EP -->|Direct Connect Check| APILayer
|
|
EP -->|Initializes & Starts| TuiEngine
|
|
|
|
ConfigManager <-->|Read / Write| LocalConfig
|
|
ConfigManager <-->|Read / Write| GlobalConfig
|
|
|
|
TuiEngine -->|Subscribes to Events| Stdin
|
|
TuiEngine -->|Paints Screens| Stdout
|
|
TuiEngine -->|Fetches & Mutates Data| APILayer
|
|
TuiEngine -->|Saves Config| ConfigManager
|
|
|
|
APILayer -->|HTTP / REST Requests (Axios)| GiteaAPI
|
|
|
|
TuiEngine -.->|Operates on AppState| Types
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Screen & Page Transition Flow
|
|
|
|
The terminal application operates as a single-page terminal application (SPTA) with a central screen router state. Below is the transition flow (state machine) representing how keypress actions route the user between screens.
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> Launch : Run gitea-tui (Bootstrap or Direct Connect)
|
|
Launch --> Setup : No config / finished or skipped
|
|
Launch --> List : Config exists / direct connect (finished or skipped)
|
|
|
|
state Setup {
|
|
[*] --> EnteringCredentials
|
|
EnteringCredentials --> Validating : Enter/Submit Form
|
|
Validating --> EnteringCredentials : Connection Error
|
|
}
|
|
|
|
Setup --> RepoPicker : Validated & Repositories Loaded
|
|
|
|
state RepoPicker {
|
|
[*] --> BrowsingRepos
|
|
BrowsingRepos --> BrowsingRepos : Filter / Search
|
|
}
|
|
|
|
RepoPicker --> Setup : Escape (Go Back)
|
|
RepoPicker --> List : Select Repo (Enter) & Load Issues
|
|
|
|
state List {
|
|
[*] --> DisplayingIssues
|
|
DisplayingIssues --> DisplayingIssues : Toggle Filters / Sort / Paginate / Search
|
|
}
|
|
|
|
List --> Setup : Change Connection ('o' key)
|
|
List --> CreateIssue : Create Issue ('c' key)
|
|
List --> Details : View Issue Details (Enter)
|
|
|
|
state CreateIssue {
|
|
[*] --> FillingIssueForm
|
|
FillingIssueForm --> SavingIssue : Ctrl+S (Submit)
|
|
SavingIssue --> DisplayingIssues : Success (List reloads)
|
|
SavingIssue --> FillingIssueForm : Failure (Shows error)
|
|
}
|
|
CreateIssue --> List : Escape (Cancel)
|
|
|
|
state Details {
|
|
[*] --> ViewingDetails
|
|
ViewingDetails --> ViewingDetails : Scroll description & comments
|
|
}
|
|
|
|
Details --> List : Escape / Backspace / Q (Go Back)
|
|
Details --> Setup : Change Connection ('o' key)
|
|
Details --> AddComment : Add Comment ('c' key)
|
|
Details --> EditIssue : Edit Issue ('e' key)
|
|
Details --> AddTime : Add Tracked Time ('t' key)
|
|
Details --> SetAssignees : Set Assignees ('a' key)
|
|
Details --> ConfirmStateChange : Toggle Issue State ('x' key)
|
|
|
|
state AddComment {
|
|
[*] --> EnteringComment
|
|
EnteringComment --> SubmittingComment : Ctrl+S (Submit)
|
|
SubmittingComment --> ViewingDetails : Success (Comments reload)
|
|
SubmittingComment --> EnteringComment : Failure (Shows error)
|
|
}
|
|
AddComment --> Details : Escape (Cancel)
|
|
|
|
state EditIssue {
|
|
[*] --> EditingIssueForm
|
|
EditingIssueForm --> SubmittingEdit : Ctrl+S (Submit)
|
|
SubmittingEdit --> ViewingDetails : Success (Details reload)
|
|
SubmittingEdit --> EditingIssueForm : Failure (Shows error)
|
|
}
|
|
EditIssue --> Details : Escape (Cancel)
|
|
|
|
state AddTime {
|
|
[*] --> EnteringTime
|
|
EnteringTime --> SubmittingTime : Ctrl+S (Submit)
|
|
SubmittingTime --> ViewingDetails : Success (Time reloads)
|
|
SubmittingTime --> EnteringTime : Failure (Shows error)
|
|
}
|
|
AddTime --> Details : Escape (Cancel)
|
|
|
|
state SetAssignees {
|
|
[*] --> EnteringAssignees
|
|
EnteringAssignees --> SubmittingAssignees : Enter (Submit)
|
|
SubmittingAssignees --> ViewingDetails : Success (Assignees reload)
|
|
SubmittingAssignees --> EnteringAssignees : Failure (Shows error)
|
|
}
|
|
SetAssignees --> Details : Escape (Cancel)
|
|
|
|
state ConfirmStateChange {
|
|
[*] --> AwaitingConfirmation
|
|
AwaitingConfirmation --> Details : No / Escape (Cancel)
|
|
AwaitingConfirmation --> AnimatingChange : Yes ('y' key)
|
|
|
|
state AnimatingChange {
|
|
[*] --> AnimatingClose : If Closing (Gravestones)
|
|
[*] --> AnimatingReopen : If Reopening (Zombies)
|
|
AnimatingClose --> ExecutingStateChangeAPI : Finish Frames (1.5s)
|
|
AnimatingReopen --> ExecutingStateChangeAPI : Finish Frames (1.8s)
|
|
}
|
|
ExecutingStateChangeAPI --> ViewingDetails : Done & Reloaded
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Data Interaction & Rerender Lifecycle
|
|
|
|
When the user interacts with the interface, keyboard events are processed by the active screen key handler, state variables are updated, API calls are made if necessary, and a full screen redraw is triggered on the terminal buffer.
|
|
|
|
The following sequence diagram details the lifecyle of adding a comment to an issue:
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
autonumber
|
|
actor User as User Terminal
|
|
participant TUI as TuiEngine (tui.ts)
|
|
participant API as API Layer (api.ts)
|
|
participant Gitea as Gitea REST API
|
|
|
|
User->>TUI: Keypress (e.g. 'c' on Details screen)
|
|
TUI->>TUI: Update screen state to 'add-comment'
|
|
TUI->>TUI: Render text input area (addCommentForm)
|
|
TUI-->>User: Display empty comment field
|
|
|
|
User->>TUI: Type comment text + Ctrl+S
|
|
TUI->>TUI: Set state.loading = true & render spinner
|
|
TUI->>API: createIssueComment(config, issueNumber, commentBody)
|
|
API->>Gitea: POST /repos/{owner}/{repo}/issues/{index}/comments
|
|
Gitea-->>API: 201 Created (Comment entity JSON)
|
|
API-->>TUI: Comment Object
|
|
|
|
TUI->>TUI: Set screen state to 'details'
|
|
TUI->>TUI: Trigger loadComments(issue) (Async)
|
|
TUI->>API: fetchIssueComments(config, issueNumber)
|
|
API->>Gitea: GET /repos/{owner}/{repo}/issues/{index}/comments
|
|
Gitea-->>API: 200 OK (Comments list JSON)
|
|
API-->>TUI: Comment[] Array
|
|
TUI->>TUI: Set state.loading = false
|
|
TUI->>TUI: Render details screen + updated comments
|
|
TUI-->>User: Display issue details and new comment
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Module Directories & Code Structure
|
|
|
|
The project code is organized into a clean multi-file architecture located under [src](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src):
|
|
|
|
1. **[index.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/index.ts)**:
|
|
- Sets up Command-line parsing with the `commander` package.
|
|
- Automatically bootstraps the configuration and constructs the default `AppState`.
|
|
- Checks CLI credentials. If valid, validates them directly, bypassing the setup page and going straight to the issue dashboard.
|
|
- Instantiates the `TuiEngine` and starts the app loop.
|
|
|
|
2. **[tui.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/tui.ts)**:
|
|
- Contains the core `TuiEngine` class which manages key listeners on `process.stdin` (in raw mode).
|
|
- Manages loading spinners and UI animations (Gravestones for closed issues and Zombies for reopened issues).
|
|
- Performs terminal buffer manipulation (e.g. entering alternate screen buffer `\x1B[?1049h`, hiding cursor `\x1B[?25l`).
|
|
- Delegates the rendering of specific screens using modular helper functions (e.g., `renderSetupScreen`, `renderListScreen`, `renderDetailsScreen`).
|
|
|
|
3. **[api.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/api.ts)**:
|
|
- Hosts the REST API layer built on top of `axios`.
|
|
- Interacts with Forgejo/Gitea endpoints such as `/repos`, `/issues`, `/comments`, and `/times`.
|
|
- Handles network errors and formats them into user-friendly diagnostic messages.
|
|
|
|
4. **[config.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/config.ts)**:
|
|
- Manages persistence of credentials.
|
|
- Reads configuration locally from `fjtui.json` and globally from `~/.config/fjtui/fjtui.json`. Local configurations take priority.
|
|
- Writes updated credentials back to the user's home configuration safely.
|
|
|
|
5. **[types.ts](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/src/types.ts)**:
|
|
- Declares the TypeScript contracts and interfaces representing the application state (`AppState`), target forms (`SetupForm`, `CreateIssueForm`, etc.), and returned entities (`User`, `Issue`, `Label`, `Comment`, `RepoItem`).
|
|
|
|
6. **ASCII Art Assets**:
|
|
- [ascii-art.txt](file:///wsl.localhost/Ubuntu/home/builder/Workspaces/fjtui/ascii-art.txt): ASCII art loaded at startup to perform the color-shifting launch animation.
|