refactor: split app.js into focused frontend modules (phase 5)

Extract 8 modules from the 15K-line app.js monolith:
- constants.js: shared constants, timing, escapeHtml(), extractSyncSegments()
- mobile-handlers.js: MobileDetection, KeyboardHandler, SwipeHandler
- voice-input.js: DeepgramProvider, VoiceInput
- notification-manager.js: NotificationManager class
- keyboard-accessory.js: KeyboardAccessoryBar, FocusTrap
- api-client.js: _api(), _apiJson(), _apiPost(), _apiDelete() helpers
- subagent-windows.js: 13 subagent window methods (open, close, drag, lines)
- vendor/xterm-zerolag-input.js: IIFE build replacing inlined copy

app.js reduced from ~15,200 to ~11,500 lines. All modules use global
scope with <script defer> ordering. Prototype extensions use
Object.assign(CodemanApp.prototype, {...}) pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-03-01 04:57:37 +01:00
co-authored by Claude Opus 4.6
parent e7a9cbe442
commit f44f0a912f
14 changed files with 4660 additions and 3800 deletions
+3 -3
View File
@@ -361,7 +361,7 @@ Object.assign(CodemanApp.prototype, {
prompt += 'Output `<promise>BLOCKED</promise>` with explanation';
// Show preview with highlighting (escape first, then apply formatting)
const escapedPrompt = this.escapeHtml(prompt);
const escapedPrompt = escapeHtml(prompt);
const highlightedPrompt = escapedPrompt
.replace(/&lt;promise&gt;/g, '<span class="preview-highlight">&lt;promise&gt;')
.replace(/&lt;\/promise&gt;/g, '&lt;/promise&gt;</span>')
@@ -724,7 +724,7 @@ Object.assign(CodemanApp.prototype, {
<input type="checkbox" class="plan-item-checkbox" ${item.enabled ? 'checked' : ''}
onchange="app.togglePlanItem(${index})">
${item.priority ? `<span class="plan-item-priority-badge">${item.priority}</span>` : ''}
<span class="plan-item-text">${this.escapeHtml(item.content)}</span>
<span class="plan-item-text">${escapeHtml(item.content)}</span>
`;
fragment.appendChild(row);
});
@@ -847,7 +847,7 @@ Object.assign(CodemanApp.prototype, {
<div class="plan-subagent-header">
<span>
<span class="plan-subagent-icon">${typeIcons[agentType] || '🤖'}</span>
<span class="plan-subagent-title">${typeLabels[agentType] || this.escapeHtml(agentType)}</span>
<span class="plan-subagent-title">${typeLabels[agentType] || escapeHtml(agentType)}</span>
</span>
<span class="plan-subagent-model">${model}</span>
</div>