Start fixing MDI

This commit is contained in:
2025-04-22 13:54:57 +02:00
parent 792272a478
commit f3b508c9f7
8 changed files with 461 additions and 228 deletions

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { onMount, onDestroy, createEventDispatcher } from 'svelte';
import { outputHistory, addToOutputHistory, addToInputHistory, navigateInputHistory, inputHistoryIndex, activeConnection, uiSettings, accessibilitySettings, inputHistory } from '$lib/stores/mudStore';
import { activeOutputHistory, addToOutputHistory, addToInputHistory, navigateInputHistory, activeInputHistoryIndex, activeConnection, uiSettings, accessibilitySettings, activeInputHistory } from '$lib/stores/mudStore';
import { tick } from 'svelte';
import AnsiToHtml from 'ansi-to-html';
import { AccessibilityManager } from '$lib/accessibility/AccessibilityManager';
@@ -106,7 +106,7 @@
addToInputHistory(currentInput);
// Show the command in the output (only if not password - for privacy)
const isPassword = currentInput.startsWith('password') || currentInput.toLowerCase() === $inputHistory[$inputHistory.length - 2]?.toLowerCase().replace('username', 'password');
const isPassword = currentInput.startsWith('password') || currentInput.toLowerCase() === $activeInputHistory[$activeInputHistory.length - 2]?.toLowerCase().replace('username', 'password');
if (!isPassword) {
addToOutputHistory(`> ${currentInput}`, true);
} else {
@@ -146,7 +146,8 @@
} else if (event.key === 'Escape') {
event.preventDefault();
currentInput = '';
inputHistoryIndex.set(-1);
// No need to directly set inputHistoryIndex since we have per-profile indexes now
// This is handled in navigateInputHistory
}
}
@@ -267,7 +268,7 @@
// Watch output history changes to scroll to bottom
$: {
if ($outputHistory) {
if ($activeOutputHistory) {
scrollToBottom();
// Update message elements when output history changes
setTimeout(updateMessageElements, 0);
@@ -317,7 +318,7 @@
tabindex="0"
on:keydown={handleOutputKeyDown}
style="font-family: {$uiSettings.font}; font-size: {$accessibilitySettings.fontSize}px; line-height: {$accessibilitySettings.lineSpacing};">
{#each $outputHistory as item (item.id)}
{#each $activeOutputHistory as item (item.id)}
<!-- For input lines, keep them as a single block -->
{#if item.isInput}
<div class="mud-terminal-line mud-input-line" tabindex="-1">

View File

@@ -8,17 +8,48 @@
export let profile: MudProfile;
export let isNewProfile = false;
// Local state
let localProfile = { ...profile };
let autoLogin = { ...localProfile.autoLogin || { enabled: false, username: '', password: '', commands: [] } };
// Initialize with defaults first, then merge with provided profile
let defaultProfile = {
id: isNewProfile ? `profile-${Date.now()}-${Math.random().toString(36).substring(2, 9)}` : (profile?.id || ''),
name: 'New Profile',
host: 'mud.example.com',
port: 23,
useSSL: false,
ansiColor: true,
autoLogin: {
enabled: false,
username: '',
password: '',
commands: []
},
accessibilityOptions: {
textToSpeech: false,
highContrast: false,
speechRate: 1,
speechPitch: 1,
speechVolume: 1
},
font: 'monospace',
fontSize: 14,
theme: 'dark'
};
// Local state - merge default with provided profile
let localProfile = { ...defaultProfile, ...profile };
console.log('Initialized profile editor with:', localProfile);
// Extract nested objects for easier binding
let autoLogin = {
...defaultProfile.autoLogin,
...(localProfile.autoLogin || {})
};
let newCommand = '';
let accessibilityOptions = { ...localProfile.accessibilityOptions || {
textToSpeech: false,
highContrast: false,
speechRate: 1,
speechPitch: 1,
speechVolume: 1
}};
let accessibilityOptions = {
...defaultProfile.accessibilityOptions,
...(localProfile.accessibilityOptions || {})
};
// Handle form submission
function handleSubmit() {

View File

@@ -60,11 +60,17 @@
input.click();
}
// Helper function to explicitly save settings
function saveSettings() {
console.log('Explicitly saving settings');
settingsManager.saveSettings();
}
onMount(() => {
// Ensure settings are loaded from localStorage on component mount
// This ensures the UI displays the values stored in localStorage
// No need to explicitly set the uiSettings and accessibilitySettings store values
// as settingsManager already does this during initialization
console.log('SettingsPanel mounted');
// Log current settings for debugging
console.log('Current accessibility settings:', $accessibilitySettings);
console.log('Current UI settings:', $uiSettings);
});
</script>
@@ -73,7 +79,12 @@
<div class="setting-item">
<span class="setting-name">Dark Mode</span>
<label class="switch">
<input type="checkbox" bind:checked={$uiSettings.isDarkMode}>
<input type="checkbox"
bind:checked={$uiSettings.isDarkMode}
on:change={() => {
console.log('Dark mode changed to:', $uiSettings.isDarkMode);
settingsManager.saveSettings();
}}>
<span class="slider round"></span>
</label>
</div>
@@ -153,7 +164,12 @@
<div class="setting-item">
<span class="setting-name">Text-to-Speech</span>
<label class="switch">
<input type="checkbox" bind:checked={$accessibilitySettings.textToSpeech}>
<input type="checkbox"
bind:checked={$accessibilitySettings.textToSpeech}
on:change={() => {
console.log('Text-to-speech changed to:', $accessibilitySettings.textToSpeech);
settingsManager.saveSettings();
}}>
<span class="slider round"></span>
</label>
</div>

View File

@@ -53,26 +53,52 @@ export class ProfileManager extends EventEmitter {
try {
const storedProfiles = localStorage.getItem(this.storageKey);
console.log('Retrieved from localStorage:', storedProfiles);
if (storedProfiles) {
this.profiles = JSON.parse(storedProfiles);
console.log('Loaded profiles from localStorage:', this.profiles);
this.emit('profilesLoaded', this.profiles);
const parsed = JSON.parse(storedProfiles);
console.log('Parsed profiles:', parsed);
// Validate profiles before assigning
if (Array.isArray(parsed)) {
// Filter out invalid profiles
this.profiles = parsed.filter(profile => this.isValidProfile(profile));
console.log('Loaded profiles from localStorage:', this.profiles);
if (this.profiles.length > 0) {
this.emit('profilesLoaded', this.profiles);
return; // Success, exit early
} else {
console.warn('No valid profiles found in stored data, creating default');
}
} else {
console.warn('Stored profiles data is not an array, creating default');
}
} else {
console.log('No profiles found in localStorage, creating default profile');
// Add a default profile if none exist
const defaultProfile = this.createDefaultProfile();
defaultProfile.name = 'Aardwolf MUD';
defaultProfile.host = 'aardmud.org';
defaultProfile.port = 23;
this.addProfile(defaultProfile);
}
// If we got here, we need to create a default profile
const defaultProfile = this.createDefaultProfile();
defaultProfile.name = 'Aardwolf MUD';
defaultProfile.host = 'aardmud.org';
defaultProfile.port = 23;
// Clear profiles array and add the default
this.profiles = [];
this.addProfile(defaultProfile);
} catch (error) {
console.error('Failed to load profiles from local storage:', error);
console.error('Error details:', error.message, error.stack);
// Add a default profile if there was an error
const defaultProfile = this.createDefaultProfile();
defaultProfile.name = 'Aardwolf MUD';
defaultProfile.host = 'aardmud.org';
defaultProfile.port = 23;
// Clear profiles array and add the default
this.profiles = [];
this.addProfile(defaultProfile);
}
}
@@ -86,9 +112,21 @@ export class ProfileManager extends EventEmitter {
}
try {
localStorage.setItem(this.storageKey, JSON.stringify(this.profiles));
// Add logging to help debug
console.log('Saving profiles to localStorage:', this.profiles);
const profilesJson = JSON.stringify(this.profiles);
console.log('Profiles JSON:', profilesJson);
localStorage.setItem(this.storageKey, profilesJson);
console.log('Profiles saved successfully');
// Validate by reading back
const readBack = localStorage.getItem(this.storageKey);
console.log('Read back from localStorage:', readBack);
} catch (error) {
console.error('Failed to save profiles to local storage:', error);
console.error('Error details:', error.message, error.stack);
}
}

View File

@@ -1,6 +1,5 @@
import { EventEmitter } from '$lib/utils/EventEmitter';
import { get } from 'svelte/store';
import { accessibilitySettings, uiSettings } from '$lib/stores/mudStore';
import { get, writable, type Writable } from 'svelte/store';
export interface Settings {
accessibility: {
@@ -30,6 +29,11 @@ export interface Settings {
export class SettingsManager extends EventEmitter {
private settings: Settings;
private readonly STORAGE_KEY = 'svelte-mud-settings';
private initialized = false;
// Create our own stores rather than depending on the ones from mudStore
public accessibilitySettings: Writable<Settings['accessibility']>;
public uiSettings: Writable<Settings['ui']>;
constructor() {
super();
@@ -60,6 +64,31 @@ export class SettingsManager extends EventEmitter {
}
};
// Create the stores with default values
this.accessibilitySettings = writable(this.settings.accessibility);
this.uiSettings = writable(this.settings.ui);
// Set up subscriptions to save settings when they change
this.accessibilitySettings.subscribe(value => {
// Skip during initialization
if (!this.initialized) return;
if (typeof window !== 'undefined') {
// Use a small timeout to batch multiple rapid changes
setTimeout(() => this.saveSettings(), 100);
}
});
this.uiSettings.subscribe(value => {
// Skip during initialization
if (!this.initialized) return;
if (typeof window !== 'undefined') {
// Use a small timeout to batch multiple rapid changes
setTimeout(() => this.saveSettings(), 100);
}
});
// Load settings from storage
this.loadSettings();
}
@@ -68,102 +97,87 @@ export class SettingsManager extends EventEmitter {
* Load settings from localStorage
*/
private loadSettings(): void {
if (typeof window === 'undefined') {
return; // Skip during SSR
// Skip during SSR
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
console.log('SSR environment detected, skipping settings load');
return;
}
try {
const storedSettings = localStorage.getItem(this.STORAGE_KEY);
if (storedSettings) {
console.log('Retrieved settings from localStorage');
const parsedSettings = JSON.parse(storedSettings);
// Merge with defaults to ensure all properties exist
this.settings = {
accessibility: {
...this.settings.accessibility,
...parsedSettings.accessibility
},
ui: {
...this.settings.ui,
...parsedSettings.ui
}
};
console.log('Loaded settings from localStorage:', this.settings);
// Update Svelte stores with loaded settings
accessibilitySettings.set(this.settings.accessibility);
uiSettings.set(this.settings.ui);
this.emit('settingsLoaded', this.settings);
if (parsedSettings && typeof parsedSettings === 'object') {
// Update internal settings
this.settings = {
accessibility: {
...this.settings.accessibility,
...(parsedSettings.accessibility || {})
},
ui: {
...this.settings.ui,
...(parsedSettings.ui || {})
}
};
console.log('Loaded settings from localStorage:', this.settings);
// Set the stores without triggering the save callback
this.accessibilitySettings.set(this.settings.accessibility);
this.uiSettings.set(this.settings.ui);
} else {
console.warn('Invalid settings format found in localStorage');
}
} else {
console.log('No settings found in localStorage, using defaults');
// Update Svelte stores with default settings
accessibilitySettings.set(this.settings.accessibility);
uiSettings.set(this.settings.ui);
}
// Now that settings are loaded, mark as initialized
this.initialized = true;
// Notify listeners
this.emit('settingsLoaded', this.settings);
} catch (error) {
console.error('Failed to load settings from localStorage:', error);
// Mark as initialized even on error
this.initialized = true;
}
}
/**
* Save settings to localStorage
*/
// Save settings to localStorage
public saveSettings(): void {
if (typeof window === 'undefined') {
return; // Skip during SSR
}
if (typeof window === 'undefined' || !this.initialized) return;
try {
// Get current values from stores
this.settings.accessibility = get(accessibilitySettings);
this.settings.ui = get(uiSettings);
this.settings.accessibility = get(this.accessibilitySettings);
this.settings.ui = get(this.uiSettings);
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.settings));
console.log('Saved settings to localStorage:', this.settings);
console.log('Saved settings to localStorage');
this.emit('settingsSaved', this.settings);
} catch (error) {
console.error('Failed to save settings to localStorage:', error);
console.error('Failed to save settings:', error);
}
}
/**
* Update accessibility settings
*/
// Update methods
public updateAccessibilitySettings(newSettings: Partial<Settings['accessibility']>): void {
accessibilitySettings.update(current => {
const updated = { ...current, ...newSettings };
this.settings.accessibility = updated;
this.saveSettings();
return updated;
});
this.emit('accessibilitySettingsUpdated', get(accessibilitySettings));
this.accessibilitySettings.update(current => ({...current, ...newSettings}));
}
/**
* Update UI settings
*/
public updateUiSettings(newSettings: Partial<Settings['ui']>): void {
uiSettings.update(current => {
const updated = { ...current, ...newSettings };
this.settings.ui = updated;
this.saveSettings();
return updated;
});
this.emit('uiSettingsUpdated', get(uiSettings));
this.uiSettings.update(current => ({...current, ...newSettings}));
}
/**
* Reset settings to defaults
*/
// Reset settings to defaults
public resetSettings(): void {
// Create default settings
const defaultSettings: Settings = {
const defaults = {
accessibility: {
textToSpeech: false,
highContrast: false,
@@ -188,27 +202,19 @@ export class SettingsManager extends EventEmitter {
}
};
// Update stores
accessibilitySettings.set(defaultSettings.accessibility);
uiSettings.set(defaultSettings.ui);
// Update internal settings and save
this.settings = defaultSettings;
this.saveSettings();
this.emit('settingsReset', defaultSettings);
this.accessibilitySettings.set(defaults.accessibility);
this.uiSettings.set(defaults.ui);
this.emit('settingsReset', defaults);
}
/**
* Import settings from a JSON string
*/
// Import/export
public importSettings(json: string): void {
try {
const imported = JSON.parse(json);
if (typeof imported === 'object' && imported !== null) {
// Create a valid settings object with defaults for missing properties
const newSettings: Settings = {
const newSettings = {
accessibility: {
...this.settings.accessibility,
...(imported.accessibility || {})
@@ -220,12 +226,11 @@ export class SettingsManager extends EventEmitter {
};
// Update stores
accessibilitySettings.set(newSettings.accessibility);
uiSettings.set(newSettings.ui);
this.accessibilitySettings.set(newSettings.accessibility);
this.uiSettings.set(newSettings.ui);
// Update internal settings and save
// Update internal settings
this.settings = newSettings;
this.saveSettings();
this.emit('settingsImported', newSettings);
}
@@ -235,13 +240,10 @@ export class SettingsManager extends EventEmitter {
}
}
/**
* Export settings to a JSON string
*/
public exportSettings(): string {
// Get current values from stores
this.settings.accessibility = get(accessibilitySettings);
this.settings.ui = get(uiSettings);
this.settings.accessibility = get(this.accessibilitySettings);
this.settings.ui = get(this.uiSettings);
return JSON.stringify(this.settings, null, 2);
}

View File

@@ -16,64 +16,27 @@ export const activeProfileId = writable<string | null>(null);
// Store for triggers
export const triggers = writable<Trigger[]>([]);
// Store for MUD output history
// Store for MUD output history - keyed by profile ID
export const outputHistory = writable<{
id: string;
text: string;
timestamp: number;
isInput?: boolean;
highlights?: { pattern: string; color: string; isRegex: boolean }[]
}[]>([]);
[profileId: string]: {
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
});
// Use the stores from SettingsManager
export const accessibilitySettings = settingsManager.accessibilitySettings;
export const uiSettings = settingsManager.uiSettings;
// 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)
});
// Subscribe to settings changes to save to localStorage
accessibilitySettings.subscribe(value => {
// Skip during SSR
if (typeof window !== 'undefined') {
// Use a small timeout to batch multiple rapid changes
setTimeout(() => settingsManager.saveSettings(), 100);
}
});
uiSettings.subscribe(value => {
// Skip during SSR
if (typeof window !== 'undefined') {
// Use a small timeout to batch multiple rapid changes
setTimeout(() => settingsManager.saveSettings(), 100);
}
});
// Store for input history
export const inputHistory = writable<string[]>([]);
export const inputHistoryIndex = writable<number>(-1);
// Store for input history - keyed by profile ID
export const inputHistory = writable<{ [profileId: string]: string[] }>({});
export const inputHistoryIndex = writable<{ [profileId: string]: number }>({});
// Derived store for active profile
export const activeProfile = derived(
@@ -93,6 +56,44 @@ export const activeConnection = derived(
}
);
// Derived store for active output history
export const activeOutputHistory = derived(
[outputHistory, activeProfileId],
([$outputHistory, $activeProfileId]) => {
// If we have an active profile, use its history
if ($activeProfileId && $outputHistory[$activeProfileId]) {
return $outputHistory[$activeProfileId];
}
// Otherwise fall back to the default profile's history or an empty array
return $outputHistory['default'] || [];
}
);
// Derived store for active input history
export const activeInputHistory = derived(
[inputHistory, activeProfileId],
([$inputHistory, $activeProfileId]) => {
// If we have an active profile, use its history
if ($activeProfileId && $inputHistory[$activeProfileId]) {
return $inputHistory[$activeProfileId];
}
// Otherwise fall back to the default profile's history or an empty array
return $inputHistory['default'] || [];
}
);
// Derived store for active input history index
export const activeInputHistoryIndex = derived(
[inputHistoryIndex, activeProfileId],
([$inputHistoryIndex, $activeProfileId]) => {
const targetProfileId = $activeProfileId || 'default';
return $inputHistoryIndex[targetProfileId] !== undefined ?
$inputHistoryIndex[targetProfileId] : -1;
}
);
// Store for GMCP data
export const gmcpData = writable<{ [module: string]: any }>({});
@@ -101,7 +102,17 @@ export const gmcpDebugLog = writable<{ id: string; module: string; data: any; ti
// Helper functions
export function addToOutputHistory(text: string, isInput = false, highlights: { pattern: string; color: string; isRegex: boolean }[] = []) {
outputHistory.update(history => {
const profileId = get(activeProfileId);
outputHistory.update(allHistory => {
// Default profile ID for cases where there's no active profile
const targetProfileId = profileId || 'default';
// Initialize history for this profile if it doesn't exist
if (!allHistory[targetProfileId]) {
allHistory[targetProfileId] = [];
}
const maxSize = get(uiSettings).outputBufferSize;
const newItem = {
id: `output-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
@@ -111,12 +122,15 @@ export function addToOutputHistory(text: string, isInput = false, highlights: {
highlights
};
// Limit history size
const updatedHistory = [...history, newItem];
// Limit history size for this profile
const updatedHistory = [...allHistory[targetProfileId], newItem];
if (updatedHistory.length > maxSize) {
return updatedHistory.slice(updatedHistory.length - maxSize);
allHistory[targetProfileId] = updatedHistory.slice(updatedHistory.length - maxSize);
} else {
allHistory[targetProfileId] = updatedHistory;
}
return updatedHistory;
return allHistory;
});
}
@@ -163,30 +177,56 @@ export function logGmcpMessage(module: string, data: any) {
}
export function addToInputHistory(text: string) {
inputHistory.update(history => {
const profileId = get(activeProfileId);
inputHistory.update(allHistory => {
// Default profile ID for cases where there's no active profile
const targetProfileId = profileId || 'default';
// Initialize history for this profile if it doesn't exist
if (!allHistory[targetProfileId]) {
allHistory[targetProfileId] = [];
}
// Don't add empty strings or duplicates of the last command
if (!text || (history.length > 0 && history[history.length - 1] === text)) {
return history;
if (!text || (allHistory[targetProfileId].length > 0 && allHistory[targetProfileId][allHistory[targetProfileId].length - 1] === text)) {
return allHistory;
}
const maxSize = get(uiSettings).inputHistorySize;
const updatedHistory = [...history, text];
const updatedHistory = [...allHistory[targetProfileId], text];
// Limit history size
if (updatedHistory.length > maxSize) {
return updatedHistory.slice(updatedHistory.length - maxSize);
allHistory[targetProfileId] = updatedHistory.slice(updatedHistory.length - maxSize);
} else {
allHistory[targetProfileId] = updatedHistory;
}
return updatedHistory;
return allHistory;
});
// Reset history index to point to the end
inputHistoryIndex.set(-1);
setInputHistoryIndex(profileId || 'default', -1);
}
// Helper to set input history index for a specific profile
function setInputHistoryIndex(profileId: string, index: number) {
inputHistoryIndex.update(indices => ({
...indices,
[profileId]: index
}));
}
export function navigateInputHistory(direction: 'up' | 'down', currentInput: string) {
const history = get(inputHistory);
let index = get(inputHistoryIndex);
const profileId = get(activeProfileId);
const targetProfileId = profileId || 'default';
const allHistory = get(inputHistory);
const history = allHistory[targetProfileId] || [];
const allIndices = get(inputHistoryIndex);
let index = allIndices[targetProfileId] !== undefined ? allIndices[targetProfileId] : -1;
if (history.length === 0) return currentInput;
@@ -194,8 +234,13 @@ export function navigateInputHistory(direction: 'up' | 'down', currentInput: str
// 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];
// Initialize if needed
if (!h[targetProfileId]) {
h[targetProfileId] = [];
}
if (currentInput && h[targetProfileId].length > 0 && h[targetProfileId][h[targetProfileId].length - 1] !== currentInput) {
h[targetProfileId] = [...h[targetProfileId], currentInput];
}
return h;
});
@@ -208,7 +253,8 @@ export function navigateInputHistory(direction: 'up' | 'down', currentInput: str
index = Math.max(-1, index - 1);
}
inputHistoryIndex.set(index);
// Update the index for this profile
setInputHistoryIndex(targetProfileId, index);
// Return appropriate value from history or empty string
if (index === -1) {
@@ -219,7 +265,14 @@ export function navigateInputHistory(direction: 'up' | 'down', currentInput: str
}
export function clearOutputHistory() {
outputHistory.set([]);
const profileId = get(activeProfileId);
const targetProfileId = profileId || 'default';
outputHistory.update(allHistory => {
// Clear only the current profile's history
allHistory[targetProfileId] = [];
return allHistory;
});
}
export function updateGmcpData(module: string, data: any) {

View File

@@ -1,4 +1,4 @@
import { ProfileManager } from '$lib/profiles/ProfileManager';
// No need to import ProfileManager here
import { get } from 'svelte/store';
import { activeProfile } from '$lib/stores/mudStore';
import type { MudProfile } from '$lib/profiles/ProfileManager';
@@ -12,7 +12,6 @@ import TriggerEditor from '$lib/components/TriggerEditor.svelte';
*/
export class ModalHelper {
private static modal: Modal | null = null;
private static profileManager = new ProfileManager();
/**
* Show the full-featured profile editor modal
@@ -57,8 +56,31 @@ export class ModalHelper {
throw new Error('Failed to create modal instance');
}
// Get profile to edit or create new one
const profile = existingProfile || this.profileManager.createDefaultProfile();
// Get profile to edit or use the default empty profile
const profile = existingProfile || {
id: `profile-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
name: 'New Profile',
host: 'mud.example.com',
port: 23,
useSSL: false,
ansiColor: true,
autoLogin: {
enabled: false,
username: '',
password: '',
commands: []
},
aliases: {},
macros: {},
gmcpPackages: [],
accessibilityOptions: {
textToSpeech: false,
highContrast: false,
speechRate: 1,
speechPitch: 1,
speechVolume: 1
}
};
const isNewProfile = !existingProfile;
console.log('Setting up modal with profile:', profile);

View File

@@ -68,38 +68,58 @@
onMount(() => {
console.log('Page mounted');
// Initialize profile manager
profileManager = new ProfileManager();
console.log('Profile manager initialized');
// Initialize trigger system
triggerSystem = new TriggerSystem();
console.log('Trigger system initialized');
// Load profiles
loadProfiles();
// Load triggers
loadTriggers();
// Check URL parameters for debug mode
checkUrlParams();
// Subscribe to profile manager events for real-time updates
profileManager.on('profileAdded', () => {
console.log('Profile added event detected');
try {
console.log('Starting initialization');
// Initialize profile manager
profileManager = new ProfileManager();
console.log('Profile manager initialized');
// Initialize trigger system
triggerSystem = new TriggerSystem();
console.log('Trigger system initialized');
// Load profiles first to ensure we have them
console.log('Loading profiles...');
loadProfiles();
});
profileManager.on('profileUpdated', () => {
console.log('Profile updated event detected');
loadProfiles();
});
profileManager.on('profileRemoved', () => {
console.log('Profile removed event detected');
loadProfiles();
});
console.log('Profiles loaded, count:', $profiles.length);
// Then load triggers
loadTriggers();
// Check URL parameters for debug mode
checkUrlParams();
// Subscribe to profile manager events for real-time updates
profileManager.on('profileAdded', () => {
console.log('Profile added event detected');
loadProfiles();
});
profileManager.on('profileUpdated', () => {
console.log('Profile updated event detected');
loadProfiles();
});
profileManager.on('profileRemoved', () => {
console.log('Profile removed event detected');
loadProfiles();
});
// Ensure settings are properly loaded and initialized
console.log('Initial profiles state:', $profiles);
console.log('Active profile ID:', $activeProfileId);
// Make sure we have an active profile selected if any profiles exist
if ($profiles.length > 0 && !$activeProfileId) {
console.log('No active profile selected, setting first profile as active');
activeProfileId.set($profiles[0].id);
}
} catch (error) {
console.error('Error during page initialization:', error);
console.error('Error details:', error.message, error.stack);
// Provide user feedback about the error
addToOutputHistory(`Error initializing client: ${error.message}. Please reload the page.`);
}
});
// Check URL for debug parameters
@@ -128,13 +148,63 @@
// Load profiles from manager
function loadProfiles() {
const allProfiles = profileManager.getProfiles();
console.log('Loaded profiles:', allProfiles); // Debug
profiles.set(allProfiles);
// Set active profile if available and not already set
if (!$activeProfileId && allProfiles.length > 0) {
activeProfileId.set(allProfiles[0].id);
try {
if (!profileManager) {
console.error('Profile manager not initialized');
return;
}
// Get all profiles from the manager
const allProfiles = profileManager.getProfiles();
console.log('Loaded profiles from manager:', allProfiles);
// Create a default profile if none exist
if (allProfiles.length === 0) {
console.log('No profiles found, creating default profile');
const defaultProfile = profileManager.createDefaultProfile();
defaultProfile.name = 'Aardwolf MUD';
defaultProfile.host = 'aardmud.org';
defaultProfile.port = 23;
profileManager.addProfile(defaultProfile);
// Get profiles again after adding the default one
const updatedProfiles = profileManager.getProfiles();
console.log('Profiles after adding default:', updatedProfiles);
profiles.set(updatedProfiles);
// Set this as the active profile
if (updatedProfiles.length > 0) {
activeProfileId.set(updatedProfiles[0].id);
}
} else {
// Update the profiles store
profiles.set(allProfiles);
// Set active profile if available and not already set
if (!$activeProfileId && allProfiles.length > 0) {
console.log('Setting active profile to:', allProfiles[0].id);
activeProfileId.set(allProfiles[0].id);
}
}
// If active profile ID is set but no longer exists in profiles, reset it
if ($activeProfileId && !allProfiles.some(p => p.id === $activeProfileId)) {
console.log('Active profile no longer exists, resetting');
if (allProfiles.length > 0) {
activeProfileId.set(allProfiles[0].id);
} else {
activeProfileId.set(null);
}
}
// Add a default message to the output history so users see something
if (allProfiles.length > 0) {
addToOutputHistory('\nWelcome to SvelteMUD Client!\n\nSelect a profile from the Profiles tab and click Connect to begin.\n\n');
}
} catch (error) {
console.error('Error loading profiles:', error);
console.error('Error details:', error.message, error.stack);
addToOutputHistory(`Error loading profiles: ${error.message}`);
}
}