Skip to content

Commit 6ba213b

Browse files
CopilotGZTimeWalker
andcommitted
Analyze Slint architecture and update data models to scope-centric design
Co-authored-by: GZTimeWalker <28180262+GZTimeWalker@users.noreply.github.com>
1 parent 66d9491 commit 6ba213b

4 files changed

Lines changed: 438 additions & 90 deletions

File tree

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# Actual Architecture Analysis from Slint Project
2+
3+
## Core Concept: Scope-Based Architecture
4+
5+
The application is **scope-centric**, not page-centric. Each "scope" represents a domain/site that can control tunnels.
6+
7+
### Scope Types
8+
1. **Default Scope** (`default-scope`): User-controlled, manual tunnel creation
9+
2. **External Scopes**: Remote domains that request control (e.g., `gzctf.example.com`)
10+
11+
### Sidebar Navigation
12+
The sidebar does NOT show pages. It shows:
13+
1. "Get Started" - Main page with tunnel creation form
14+
2. "Network Logs" - Tracing logs page
15+
3. **Separator**
16+
4. "Default Scope" - User's manual tunnels
17+
5. **Dynamic Scope List** - External domains (with status icons)
18+
6. **Separator**
19+
7. "Settings" - Configuration
20+
8. "Controller Port" - API status button
21+
22+
### Page/View Structure
23+
24+
#### 1. Get Started Page (`home`)
25+
**Purpose**: Primary tunnel creation interface
26+
27+
**Components**:
28+
- Application branding with animated cursor
29+
- Update notification button (if available)
30+
- **Network interface selector dropdown** (127.0.0.1, 0.0.0.0, LAN IPs)
31+
- **Port input field**
32+
- **Remote WebSocket address input** (ws:// or wss://)
33+
- **Send button** - Creates tunnel and navigates to default-scope
34+
35+
**NOT a modal - this IS the main page**
36+
37+
#### 2. Connections Page (Dynamic, scope-specific)
38+
**Purpose**: Display tunnels for current scope
39+
40+
**Displayed for**: Any scope page (default-scope or external domain)
41+
42+
**Header Section**:
43+
- Scope icon (globe-star for default, globe-warning if pending, lock-closed if allowed)
44+
- Scope name and host
45+
- Control type badge (Manually Controlled vs External Controlled)
46+
- Features list (e.g., "basic", "basic,pingfall")
47+
- **Accept/Decline buttons** (for pending external scopes)
48+
- **Remove button** (for allowed external scopes)
49+
50+
**Instance List** (scrollable):
51+
- Each tunnel shows:
52+
- Label (custom name)
53+
- Local address (clickable to copy)
54+
- Remote address
55+
- Latency in ms (or "--" if connecting)
56+
- Click anywhere to copy local address
57+
- Click latency area to close tunnel
58+
59+
**Behavior**:
60+
- Default scope: User creates tunnels from Get Started page
61+
- External scopes: Remote API creates tunnels, user accepts/declines scope access
62+
63+
#### 3. Network Logs Page (`logs`)
64+
**Purpose**: Real-time tracing log display
65+
66+
**Features**:
67+
- Streams from `wsrx.log` file (JSON format)
68+
- Displays logs with:
69+
- Level badge (DEBUG/INFO/WARN/ERROR) with color
70+
- Target module name
71+
- Timestamp
72+
- Message (word-wrapped)
73+
- Opacity varies by level (DEBUG=0.5, INFO=0.8, WARN/ERROR=1.0)
74+
- Separator lines between entries
75+
76+
**NOT sample data - reads actual tracing logs**
77+
78+
#### 4. Settings Page (`settings`)
79+
**Purpose**: Configuration and about info
80+
81+
**Sections**:
82+
- Theme selector
83+
- Language selector
84+
- Running in tray toggle
85+
- System information display
86+
- Version info
87+
88+
### Data Models
89+
90+
#### Instance (Tunnel)
91+
```rust
92+
pub struct Instance {
93+
label: String, // Display name
94+
remote: String, // ws:// or wss:// address
95+
local: String, // IP:port
96+
latency: i32, // -1 if not connected
97+
scope_host: String, // Which scope owns this tunnel
98+
}
99+
```
100+
101+
#### Scope
102+
```rust
103+
pub struct Scope {
104+
host: String, // Domain name (unique ID)
105+
name: String, // Display name
106+
state: String, // "pending", "allowed", "syncing"
107+
features: String, // Comma-separated: "basic", "pingfall"
108+
settings: HashMap, // Feature-specific config
109+
}
110+
```
111+
112+
#### Log Entry
113+
```rust
114+
pub struct Log {
115+
timestamp: String, // "2025-11-10 15:30:45"
116+
level: String, // "DEBUG", "INFO", "WARN", "ERROR"
117+
target: String, // Module path (e.g., "wsrx::tunnel")
118+
message: String, // Log message
119+
}
120+
```
121+
122+
### Bridges (State Management)
123+
124+
#### WindowControlBridge
125+
- Window control actions (drag, minimize, maximize, close)
126+
127+
#### SystemInfoBridge
128+
- OS type, version, has_updates
129+
- Network interfaces list
130+
- **Logs array** (for Network Logs page)
131+
- Callbacks: refresh_interfaces, open_link, open_logs
132+
133+
#### InstanceBridge
134+
- **instances**: All tunnels across all scopes
135+
- **scoped_instances**: Filtered tunnels for current scope
136+
- Callbacks:
137+
- `add(remote, local)`: Create tunnel (default-scope only)
138+
- `del(local)`: Delete tunnel
139+
140+
#### ScopeBridge
141+
- **scopes**: Array of all external scopes
142+
- Callbacks:
143+
- `allow(host)`: Accept external scope
144+
- `del(host)`: Remove/decline scope
145+
146+
#### SettingsBridge
147+
- theme, language, running_in_tray
148+
- api_port, online (daemon status)
149+
150+
#### UiState (Global State)
151+
- **page**: Current page ID (string)
152+
- "home" - Get Started
153+
- "logs" - Network Logs
154+
- "settings" - Settings
155+
- "default-scope" - User's tunnels
156+
- `<domain>` - External scope (e.g., "gzctf.example.com")
157+
- **scope**: Current scope object (for connections page)
158+
- **show_sidebar**: Boolean
159+
- Callbacks:
160+
- `change_scope(host)`: Updates scope and filters scoped_instances
161+
162+
### Navigation Flow
163+
164+
1. **App starts** → "home" page (Get Started)
165+
2. **User creates tunnel** → Navigates to "default-scope" page
166+
3. **External domain requests** → New scope appears in sidebar with "pending" status
167+
4. **User clicks pending scope** → Shows connections page with Accept/Decline buttons
168+
5. **User accepts** → Scope state becomes "allowed", shows tunnels
169+
6. **Click "Network Logs"** → Shows logs page
170+
7. **Click "Settings"** → Shows settings page
171+
172+
### Key Differences from Initial Implementation
173+
174+
#### ❌ What I Got Wrong:
175+
1. Tunnel creation via modal dialog - **WRONG**, it's the main Get Started page
176+
2. Connections page as standalone - **WRONG**, it's scope-specific
177+
3. Sample log data - **WRONG**, must stream from tracing log file
178+
4. Static page navigation - **WRONG**, sidebar shows scopes not pages
179+
5. Separate pages for each view - **PARTIALLY WRONG**, connections page is dynamic
180+
181+
#### ✅ What to Keep:
182+
- GPUI entity-based state management
183+
- Component library (buttons, inputs, etc.)
184+
- Vertical scrolling implementation
185+
- Window controls and title bar
186+
187+
### Implementation Priority
188+
189+
1. **Phase 1**: Correct data models (Scope, Instance, Log with proper fields)
190+
2. **Phase 2**: Implement UiState global state with scope management
191+
3. **Phase 3**: Rewrite Get Started page as tunnel creation form
192+
4. **Phase 4**: Make Connections page scope-aware with accept/decline
193+
5. **Phase 5**: Implement tracing log subscriber and file streaming
194+
6. **Phase 6**: Update sidebar to show scopes dynamically
195+
7. **Phase 7**: Wire up bridges for actual daemon communication

crates/wsrx-desktop-gpui/MIGRATION_PLAN.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,73 @@
11
# WebSocketReflectorX GPUI Migration Plan
22

3+
## ⚠️ CORRECTED ARCHITECTURE (2025-11-10)
4+
5+
**See `ACTUAL_ARCHITECTURE.md` for detailed analysis.**
6+
7+
### Key Corrections from Original Slint Analysis:
8+
9+
1. **Application is Scope-Centric, NOT Page-Centric**
10+
- Sidebar shows **scopes** (domains), not pages
11+
- Each scope has its own connections view
12+
- "Default Scope" for user-created tunnels
13+
- External scopes for domain-controlled tunnels
14+
15+
2. **Get Started Page IS the Tunnel Creation Form**
16+
- NOT a modal dialog
17+
- Main page with network interface selector, port input, remote address input
18+
- Creating a tunnel navigates to "default-scope"
19+
20+
3. **Connections Page is Dynamic per Scope**
21+
- Shows tunnels filtered by current scope
22+
- Header shows scope status (pending/allowed)
23+
- Accept/Decline buttons for pending scopes
24+
- Each tunnel displays: label, local (copyable), remote, latency
25+
26+
4. **Network Logs Must Stream from Tracing**
27+
- Reads `wsrx.log` JSON file
28+
- NOT sample data
29+
- Displays real-time tracing output
30+
31+
5. **Sidebar Structure**:
32+
```
33+
- Get Started (home)
34+
- Network Logs (logs)
35+
---
36+
- Default Scope (default-scope)
37+
- [External Scopes...] (dynamic)
38+
---
39+
- Settings (settings)
40+
- Controller Port (API status)
41+
```
42+
43+
### Data Models (Corrected):
44+
45+
```rust
46+
pub struct Instance { // NOT "Tunnel"
47+
label: String,
48+
remote: String,
49+
local: String,
50+
latency: i32,
51+
scope_host: String,
52+
}
53+
54+
pub struct Scope {
55+
host: String, // Unique ID
56+
name: String, // Display name
57+
state: String, // "pending" | "allowed" | "syncing"
58+
features: String, // "basic,pingfall"
59+
settings: HashMap,
60+
}
61+
62+
pub struct UiState {
63+
page: String, // "home", "logs", "settings", "default-scope", or scope.host
64+
scope: Scope, // Current scope for connections page
65+
show_sidebar: bool,
66+
}
67+
```
68+
69+
---
70+
371
## Overview
472

573
This document provides a comprehensive migration plan for transitioning the WebSocketReflectorX desktop application from the Slint-based `crates/desktop` to the GPUI-based `crates/wsrx-desktop-gpui`.

0 commit comments

Comments
 (0)