Skip to main content

State Overview

WikiOnitViewer maintains the simplest state model among all wiki viewers: just one custom array plus inherited properties from the base class.
┌─────────────────────────────────────────────────┐
│  State Inventory                                │
├─────────────────────────────────────────────────┤
│                                                 │
│  Own State:                                     │
│    sessions: OnitSession[]                      │
│                                                 │
│  Inherited State (from WikiBaseViewer):         │
│    container: HTMLElement | null                │
│    projectSlug: string                          │
│    category: string                             │
│    isWip: boolean                               │
│    settings: WikiViewerSettings                 │
│    currentDocument: string                      │
│                                                 │
│  Total: 7 properties (6 inherited + 1 own)      │
│                                                 │
└─────────────────────────────────────────────────┘

Sessions Array

The only state property unique to OnIt:
private sessions: OnitSession[] = [];
Structure:
  • Array of parsed session objects
  • Sorted newest first (descending sortKey)
  • Populated during loadSessions()
  • Completely replaced on refresh()
Example:
sessions = [
  {
    path: "/full/path/2025-12-28-14-30-session.md",
    name: "2025-12-28-14-30-session.md",
    date: "2025-12-28",
    time: "14:30",
    sessionName: "session",
    pattern: 3,
    sortKey: "2025-12-28T14:30:00",
    status: "active"
  },
  // ... more sessions
]

State Lifecycle

Initialization

┌─────────────────────────────────────────────────┐
│  Initialization State Changes                   │
├─────────────────────────────────────────────────┤
│                                                 │
│  BEFORE init():                                 │
│    container: null                              │
│    sessions: []                                 │
│    isWip: true (default)                        │
│                                                 │
│       ↓ init(container, projectSlug, "onit")    │
│                                                 │
│  AFTER init():                                  │
│    container: HTMLElement (assigned)            │
│    sessions: [OnitSession, ...]                 │
│    isWip: true (unchanged)                      │
│    category: "onit"                             │
│    settings: loaded from localStorage           │
│                                                 │
└─────────────────────────────────────────────────┘

Toggle Transition

┌─────────────────────────────────────────────────┐
│  WIP/Wiki Toggle Effect                         │
├─────────────────────────────────────────────────┤
│                                                 │
│  WIP Mode:                                      │
│    isWip: true                                  │
│    sessions: [WIP sessions from wip/onit/]      │
│                                                 │
│       ↓ User clicks [Wiki] button               │
│                                                 │
│  Wiki Mode:                                     │
│    isWip: false                                 │
│    sessions: [Wiki sessions from wiki/onit/]    │
│                                                 │
│  Note: Other properties unchanged               │
│                                                 │
└─────────────────────────────────────────────────┘

Refresh Cycle

┌─────────────────────────────────────────────────┐
│  Refresh State Changes                          │
├─────────────────────────────────────────────────┤
│                                                 │
│  BEFORE refresh():                              │
│    sessions: [old data - may be stale]          │
│                                                 │
│       ↓ refresh() called                        │
│                                                 │
│  AFTER refresh():                               │
│    sessions: [new data - fresh from filesystem] │
│                                                 │
│  Note: Complete array replacement               │
│        DOM fully re-rendered                    │
│        Accordion states LOST                    │
│                                                 │
└─────────────────────────────────────────────────┘

State Dependencies

Path construction depends on three state properties: getBasePath() Calculation:
// From WikiBaseViewer
const base = "~/Library/Application Support/monolex/protocols/niia/work";
const folder = isWip ? "wip" : "wiki";
return `${base}/${projectSlug}/${folder}/${category}`;
Example:
projectSlug = "monolex-006"
isWip = true
category = "onit"

Result: ~/Library/.../work/monolex-006/wip/onit/
Changing any dependency changes the filesystem path and thus the loaded sessions.

Unidirectional Data Flow

State flows in one direction only:
┌─────────────────────────────────────────────────┐
│  Data Flow                                      │
├─────────────────────────────────────────────────┤
│                                                 │
│  User Action (click toggle/refresh)             │
│       ↓                                         │
│  Event Handler                                  │
│       ↓                                         │
│  State Update (isWip, sessions)                 │
│       ↓                                         │
│  Re-render (render() called)                    │
│       ↓                                         │
│  DOM Updated (innerHTML replaced)               │
│       ↓                                         │
│  Event Listeners Attached (to new elements)     │
│       ↓                                         │
│  (Loop back to User Action)                     │
│                                                 │
│  No reverse flow: DOM → State                   │
│                                                 │
└─────────────────────────────────────────────────┘

DOM vs JavaScript State

Clear separation between persistent state and ephemeral UI state: JavaScript State (this.*):
  • sessions: OnitSession[] (source of truth)
  • isWip: boolean
  • settings: ViewerSettings
  • Persists across renders
DOM State (in elements):
  • Accordion expanded/collapsed
  • Content loaded (data-loaded)
  • Arrow rotation
  • Scroll position
  • Lost on re-render
Relationship:
  • JS state is source of truth for data
  • DOM state is ephemeral (recreated on render)
  • Re-render regenerates DOM from JS state
  • No two-way binding

State Reset Pattern

Complete replacement on refresh:
async refresh(): Promise<void> {
  await this.loadSessions();  // REPLACES this.sessions
  this.render();              // Re-renders entire DOM
}
Effect:
  • No incremental updates
  • No diffing/patching
  • Guaranteed consistency
  • Accordion states lost
Trade-offs:
  • Simplicity (SMPC principle)
  • Easy to reason about
  • Potential performance impact on large lists
  • Loses UI state

Memory Management

Automatic cleanup via garbage collection: On refresh():
  1. this.sessions = new array → Old array becomes unreachable
  2. container.innerHTML = new HTML → Old DOM nodes removed
  3. JavaScript GC cleans up old arrays
  4. Browser GC cleans up old DOM nodes
  5. Event listeners on old nodes auto-removed
No manual cleanup needed. No memory leaks from orphaned listeners.

Settings Management

User preferences loaded from localStorage: Settings Interface:
interface WikiViewerSettings {
  fontSize: string;     // "12"
  fontWeight: string;   // "300"
  lineHeight: string;   // "1.6"
  opacity: string;      // "75"
  fontFamily: string;   // "CodexMono, CodexMono EA"
}
Loading:
// From WikiBaseViewer
this.settings = {
  fontSize: localStorage.getItem("wikiViewerFontSize") || "12",
  fontWeight: localStorage.getItem("wikiViewerFontWeight") || "300",
  // ... other settings with defaults
};
Settings apply to the entire viewer container via getViewerStyles().

State Comparison

OnIt has the simplest state model:
ViewerOwn State PropsTotal StateComplexity
OnIt17Simplest
Prepare28Low-Medium
Prove39Medium
Unified410Medium-High
Docs511Highest
Minimal state aligns with SMPC: simplicity over complexity.
THE CENTER
Simple state enables predictable behavior

Technical Credibility

Single source of truth pattern. Unidirectional data flow. TypeScript type safety via interfaces. Automatic garbage collection for memory management. No manual listener cleanup required.