215 lines
6.3 KiB
TypeScript
215 lines
6.3 KiB
TypeScript
|
|
import { writable, derived, get } from 'svelte/store';
|
||
|
|
import type { MudProfile } from '$lib/profiles/ProfileManager';
|
||
|
|
import type { MudConnection } from '$lib/connection/MudConnection';
|
||
|
|
import type { Trigger } from '$lib/triggers/TriggerSystem';
|
||
|
|
|
||
|
|
// Store for active connections
|
||
|
|
export const connections = writable<{ [key: string]: MudConnection }>({});
|
||
|
|
|
||
|
|
// Store for profiles
|
||
|
|
export const profiles = writable<MudProfile[]>([]);
|
||
|
|
|
||
|
|
// Store for active profile ID
|
||
|
|
export const activeProfileId = writable<string | null>(null);
|
||
|
|
|
||
|
|
// Store for triggers
|
||
|
|
export const triggers = writable<Trigger[]>([]);
|
||
|
|
|
||
|
|
// Store for MUD output history
|
||
|
|
export const outputHistory = writable<{
|
||
|
|
id: string;
|
||
|
|
text: string;
|
||
|
|
timestamp: number;
|
||
|
|
isInput?: boolean;
|
||
|
|
highlights?: { pattern: string; color: string; isRegex: boolean }[]
|
||
|
|
}[]>([]);
|
||
|
|
|
||
|
|
// Store for connection status
|
||
|
|
export const connectionStatus = writable<{ [key: string]: 'connected' | 'disconnected' | 'connecting' | 'error' }>({});
|
||
|
|
|
||
|
|
// Store for accessibility settings
|
||
|
|
export const accessibilitySettings = writable({
|
||
|
|
textToSpeech: false,
|
||
|
|
highContrast: false,
|
||
|
|
fontSize: 16,
|
||
|
|
lineSpacing: 1.2,
|
||
|
|
speechRate: 1,
|
||
|
|
speechPitch: 1,
|
||
|
|
speechVolume: 1,
|
||
|
|
interruptSpeechOnEnter: true // New setting for interrupting speech on Enter key
|
||
|
|
});
|
||
|
|
|
||
|
|
// Store for UI settings
|
||
|
|
export const uiSettings = writable({
|
||
|
|
isDarkMode: true,
|
||
|
|
showTimestamps: true,
|
||
|
|
showSidebar: true,
|
||
|
|
splitViewDirection: 'horizontal', // or 'vertical'
|
||
|
|
inputHistorySize: 100,
|
||
|
|
outputBufferSize: 1000,
|
||
|
|
ansiColor: true,
|
||
|
|
font: 'monospace',
|
||
|
|
debugGmcp: false, // Setting for GMCP debugging
|
||
|
|
globalVolume: 0.7 // Global volume control for sounds (0-1)
|
||
|
|
});
|
||
|
|
|
||
|
|
// Store for input history
|
||
|
|
export const inputHistory = writable<string[]>([]);
|
||
|
|
export const inputHistoryIndex = writable<number>(-1);
|
||
|
|
|
||
|
|
// Derived store for active profile
|
||
|
|
export const activeProfile = derived(
|
||
|
|
[profiles, activeProfileId],
|
||
|
|
([$profiles, $activeProfileId]) => {
|
||
|
|
if (!$activeProfileId) return null;
|
||
|
|
return $profiles.find(profile => profile.id === $activeProfileId) || null;
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
// Derived store for active connection
|
||
|
|
export const activeConnection = derived(
|
||
|
|
[connections, activeProfileId],
|
||
|
|
([$connections, $activeProfileId]) => {
|
||
|
|
if (!$activeProfileId) return null;
|
||
|
|
return $connections[$activeProfileId] || null;
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
// Store for GMCP data
|
||
|
|
export const gmcpData = writable<{ [module: string]: any }>({});
|
||
|
|
|
||
|
|
// Store for GMCP debug messages
|
||
|
|
export const gmcpDebugLog = writable<{ id: string; module: string; data: any; timestamp: number }[]>([]);
|
||
|
|
|
||
|
|
// Helper functions
|
||
|
|
export function addToOutputHistory(text: string, isInput = false, highlights: { pattern: string; color: string; isRegex: boolean }[] = []) {
|
||
|
|
outputHistory.update(history => {
|
||
|
|
const maxSize = get(uiSettings).outputBufferSize;
|
||
|
|
const newItem = {
|
||
|
|
id: `output-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
|
||
|
|
text,
|
||
|
|
timestamp: Date.now(),
|
||
|
|
isInput,
|
||
|
|
highlights
|
||
|
|
};
|
||
|
|
|
||
|
|
// Limit history size
|
||
|
|
const updatedHistory = [...history, newItem];
|
||
|
|
if (updatedHistory.length > maxSize) {
|
||
|
|
return updatedHistory.slice(updatedHistory.length - maxSize);
|
||
|
|
}
|
||
|
|
return updatedHistory;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add GMCP message to debug log and possibly to output history if enabled
|
||
|
|
*/
|
||
|
|
export function logGmcpMessage(module: string, data: any) {
|
||
|
|
console.log('logGmcpMessage called for module:', module);
|
||
|
|
|
||
|
|
// Always add to debug log
|
||
|
|
gmcpDebugLog.update(log => {
|
||
|
|
const maxSize = 100; // Keep last 100 GMCP messages
|
||
|
|
const newItem = {
|
||
|
|
id: `gmcp-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
|
||
|
|
module,
|
||
|
|
data,
|
||
|
|
timestamp: Date.now()
|
||
|
|
};
|
||
|
|
|
||
|
|
const updatedLog = [...log, newItem];
|
||
|
|
if (updatedLog.length > maxSize) {
|
||
|
|
return updatedLog.slice(updatedLog.length - maxSize);
|
||
|
|
}
|
||
|
|
return updatedLog;
|
||
|
|
});
|
||
|
|
|
||
|
|
// Get the CURRENT state of the debugGmcp setting, not a snapshot
|
||
|
|
let currentSettings = get(uiSettings);
|
||
|
|
console.log('Current debugGmcp setting:', currentSettings.debugGmcp);
|
||
|
|
|
||
|
|
// If debug mode is enabled, also add to normal output
|
||
|
|
if (currentSettings.debugGmcp) {
|
||
|
|
console.log('GMCP debug is enabled, adding to output history');
|
||
|
|
const dataString = typeof data === 'object' ? JSON.stringify(data, null, 2) : String(data);
|
||
|
|
const gmcpText = `[GMCP] ${module}: ${dataString}`;
|
||
|
|
|
||
|
|
addToOutputHistory(gmcpText, false, [
|
||
|
|
{ pattern: '\\[GMCP\\]', color: '#8be9fd', isRegex: true },
|
||
|
|
{ pattern: module, color: '#ff79c6', isRegex: false }
|
||
|
|
]);
|
||
|
|
} else {
|
||
|
|
console.log('GMCP debug is disabled, not adding to output history');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function addToInputHistory(text: string) {
|
||
|
|
inputHistory.update(history => {
|
||
|
|
// Don't add empty strings or duplicates of the last command
|
||
|
|
if (!text || (history.length > 0 && history[history.length - 1] === text)) {
|
||
|
|
return history;
|
||
|
|
}
|
||
|
|
|
||
|
|
const maxSize = get(uiSettings).inputHistorySize;
|
||
|
|
const updatedHistory = [...history, text];
|
||
|
|
|
||
|
|
// Limit history size
|
||
|
|
if (updatedHistory.length > maxSize) {
|
||
|
|
return updatedHistory.slice(updatedHistory.length - maxSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
return updatedHistory;
|
||
|
|
});
|
||
|
|
|
||
|
|
// Reset history index to point to the end
|
||
|
|
inputHistoryIndex.set(-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function navigateInputHistory(direction: 'up' | 'down', currentInput: string) {
|
||
|
|
const history = get(inputHistory);
|
||
|
|
let index = get(inputHistoryIndex);
|
||
|
|
|
||
|
|
if (history.length === 0) return currentInput;
|
||
|
|
|
||
|
|
if (direction === 'up') {
|
||
|
|
// If we're at the beginning of navigation, save the current input
|
||
|
|
if (index === -1) {
|
||
|
|
inputHistory.update(h => {
|
||
|
|
if (currentInput && h[h.length - 1] !== currentInput) {
|
||
|
|
return [...h, currentInput];
|
||
|
|
}
|
||
|
|
return h;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// Move up in history
|
||
|
|
index = Math.min(history.length - 1, index + 1);
|
||
|
|
} else if (direction === 'down') {
|
||
|
|
// Move down in history
|
||
|
|
index = Math.max(-1, index - 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
inputHistoryIndex.set(index);
|
||
|
|
|
||
|
|
// Return appropriate value from history or empty string
|
||
|
|
if (index === -1) {
|
||
|
|
return '';
|
||
|
|
} else {
|
||
|
|
return history[history.length - 1 - index];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export function clearOutputHistory() {
|
||
|
|
outputHistory.set([]);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function updateGmcpData(module: string, data: any) {
|
||
|
|
gmcpData.update(currentData => {
|
||
|
|
return {
|
||
|
|
...currentData,
|
||
|
|
[module]: data
|
||
|
|
};
|
||
|
|
});
|
||
|
|
}
|