diff --git a/assets/control.html b/assets/control.html index 6ffc1d5..2043802 100644 --- a/assets/control.html +++ b/assets/control.html @@ -28,120 +28,133 @@ + + +
- -
- -
- Disconnected -
- - - -
-
- - -
- +
+ Disconnected
- -
- - -
-
- - -
-
-
- - -
-
-
+ +
+
-
-
-
- - - -
-
- + + +
+
+ +
+
+
+ +
+ +
+
+
-
-
-
- - - -
-
- + +
+
+ + +
+
+
+
+

Idle Avatar

+
+ + + +
+
+ +
+
+
+

Talking Avatar

+
+ + + +
+
+ +
+
-
+
diff --git a/assets/css/control.css b/assets/css/control.css index 3ef9cc7..4cf168f 100644 --- a/assets/css/control.css +++ b/assets/css/control.css @@ -5,10 +5,15 @@ --color-secondary: #f5f5f5; --color-secondary-dark: #e5e5e5; --color-success: #4CAF50; + --color-success-dark: #388E3C; --color-danger: #f44336; + --color-danger-dark: #e53935; --color-warning: #ff9800; + --color-warning-dark: #f57c00; --color-purple: #9C27B0; + --color-purple-dark: #7B1FA2; --color-orange: #FF5722; + --color-orange-dark: #E64A19; /* Text colors */ --text-primary: #333; @@ -64,12 +69,13 @@ body { display: flex; flex-direction: column; height: 100%; + gap: var(--spacing-lg); } /* Connection Panel */ -.connection-panel { +/* .connection-panel { margin-bottom: 10px; -} +} */ .platform-controls { display: grid; @@ -79,8 +85,8 @@ body { } .connection-controls { - display: flex; - flex-direction: column; + display: grid; + grid-template-columns: 2fr 4fr; gap: var(--spacing-md); } @@ -148,6 +154,17 @@ body { overflow: hidden; text-overflow: ellipsis; flex: 1; + display: flex; + align-items: center; + justify-content: flex-start; + /* border: 1px solid var(--border-color); */ +} +.status-indicator:before { + content: ""; + width: 10px; + height: 10px; + border-radius: 50%; + margin-right: var(--spacing-sm); } /* Button Group */ @@ -198,6 +215,16 @@ body { background-color: var(--color-secondary-dark); } +.btn-danger { + background-color: var(--color-danger); + color: var(--text-light); + border-color: var(--color-danger); +} + +.btn-danger:hover:not(:disabled) { + background-color: var(--color-danger-dark); +} + /* Button Sizes */ .btn-sm { padding: 4px 8px; @@ -217,38 +244,94 @@ body { /* Settings Panel */ .settings-panel { - margin-bottom: 10px; + flex: 1; display: flex; - gap: 8px; - align-items: center; - justify-content: space-between; + flex-direction: column; + min-height: 0; } -.setting-group { +#settings-tabs { + display: flex; + flex-direction: column; + height: 100%; + border: 0px; + padding: 0; +} + +#settings-tabs .ui-tabs-nav { + background: none; + border: none; + border-bottom: 1px solid var(--border-color); + border-radius: 0; + padding: 0; + /* margin-bottom: var(--spacing-lg); */ +} + +#settings-tabs .ui-tabs-nav li { + background: none; + border: none; + margin: 0 var(--spacing-md) -1px 0; +} + +#settings-tabs .ui-tabs-nav li a { + padding: var(--spacing-md) var(--spacing-lg); + font-size: var(--font-sm); + color: var(--text-secondary); +} + +#settings-tabs .ui-tabs-nav li.ui-tabs-active { + background: var(--text-light); + border: 0px; + border-bottom: 2px solid var(--color-primary); +} + +#settings-tabs .ui-tabs-nav li.ui-tabs-active a { + color: var(--color-primary); +} + +#settings-tabs .ui-tabs-panel { + flex: 1; display: flex; + flex-direction: column; + min-height: 0; + overflow: hidden; + padding: 0; + padding-top: var(--spacing-lg); + padding-bottom: var(--spacing-md); +} + +.setting-list { + display: grid; + grid-template-columns: 1fr 1fr; align-items: center; - gap: 8px; + justify-content: space-between; + padding: var(--spacing-xl) 0; + border-bottom: 1px solid var(--border-color); } -.setting-group label { - font-size: 13px; - color: #666; +.setting-list label { + font-size: var(--font-sm); + font-weight: 600; + color: var(--text-secondary); +} + +.setting-group { + padding: var(--spacing-xl) 0; + border-bottom: 1px solid var(--border-color); } /* Chat Panel */ .chat-panel { - flex-grow: 1; - display: flex; - flex-direction: column; + flex: 1; min-height: 0; + position: relative; } #chat-container { - flex-grow: 1; + height: 100%; overflow-y: auto; border: 1px solid var(--border-color); - padding: var(--spacing-lg); - position: relative; + border-radius: var(--border-radius-md); } /* Chat Message Styles */ @@ -258,20 +341,42 @@ body { padding: var(--spacing-sm); border-bottom: 1px solid var(--border-color-light); word-break: break-word; - font-size: var(--font-sm); + font-size: var(--font-md); line-height: 1.3; transition: var(--transition-default); + justify-content: space-between; + gap: var(--spacing-md); + align-items: center; } .chat-message:hover { background-color: rgba(0, 0, 0, 0.02); } +.message-main { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--spacing-sm); +} + +.author-name { + flex-shrink: 0; +} + +.message-content { + flex: 1; + min-width: 0; +} + .author-name { font-weight: bold; color: #666; margin-right: 6px; flex-shrink: 0; + font-size: var(--font-sm); } .author-name.moderator { @@ -286,11 +391,6 @@ body { color: var(--color-orange); } -.message-content { - flex: 1; - min-width: 0; -} - /* Emote styles */ .chat-message img.emote { height: 16px; @@ -301,11 +401,36 @@ body { /* Message Actions */ .message-actions { display: flex; - gap: var(--spacing-xs); - margin-left: var(--spacing-sm); + gap: 0px; + align-items: center; flex-shrink: 0; } +.message-actions button { + cursor: pointer; + background-color: var(--color-secondary); + border: 1px solid var(--border-color); + font-size: var(--font-sm); + padding: var(--spacing-xs) var(--spacing-sm); + transition: var(--transition-default); + border-radius: var(--border-radius-sm); +} + +.message-actions button:hover { + background-color: var(--color-secondary-dark); +} + +.message-actions button:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.message-actions button:last-child:not(:only-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: 0px; +} + .tts-button, .display-button { cursor: pointer; @@ -383,18 +508,33 @@ body { /* Status Colors */ .status-indicator.connected { + color: var(--color-success); + border-color: var(--color-success); + /* color: var(--text-light); */ +} + +.status-indicator.connected:before { background-color: var(--color-success); - color: var(--text-light); } .status-indicator.disconnected { + color: var(--color-danger); + border-color: var(--color-danger); + /* color: var(--text-light); */ +} + +.status-indicator.disconnected:before { background-color: var(--color-danger); - color: var(--text-light); } .status-indicator.error { + color: var(--color-warning); + border-color: var(--color-warning); + /* color: var(--text-light); */ +} + +.status-indicator.error:before { background-color: var(--color-warning); - color: var(--text-light); } /* Disabled States */ @@ -410,7 +550,11 @@ button:not(:disabled):hover { /* Add these styles */ .avatar-section { - padding: var(--spacing-md) 0; + margin-bottom: var(--spacing-xl); +} + +.avatar-section:last-child { + margin-bottom: 0; } .avatar-section h3 { @@ -461,6 +605,10 @@ button:not(:disabled):hover { display: flex; align-items: center; gap: 8px; + padding: var(--spacing-md); + border-radius: var(--border-radius-md); + border: 1px solid var(--border-color); + justify-content: space-between; } /* Override jQuery UI tab styles for our use case */ @@ -513,12 +661,12 @@ button:not(:disabled):hover { } /* Tabs Styling */ -#avatar-tabs.ui-tabs { +#avatar-tabs.ui-tabs, .tabs { padding: 0; border: none; } -#avatar-tabs .ui-tabs-nav { +#avatar-tabs .ui-tabs-nav, .tabs-nav { background: none; border: none; border-bottom: 1px solid var(--border-color); @@ -527,29 +675,29 @@ button:not(:disabled):hover { margin-bottom: var(--spacing-lg); } -#avatar-tabs .ui-tabs-nav li { +#avatar-tabs .ui-tabs-nav li, .tabs-nav li { background: none; border: none; margin: 0 var(--spacing-md) -1px 0; } -#avatar-tabs .ui-tabs-nav li a { +#avatar-tabs .ui-tabs-nav li a, .tabs-nav li a { padding: var(--spacing-md) var(--spacing-lg); font-size: var(--font-sm); color: var(--text-secondary); } -#avatar-tabs .ui-tabs-nav li.ui-tabs-active { +#avatar-tabs .ui-tabs-nav li.ui-tabs-active, .tabs-nav li.active { background: var(--text-light); border: 1px solid var(--border-color); border-bottom: 1px solid var(--text-light); } -#avatar-tabs .ui-tabs-nav li.ui-tabs-active a { +#avatar-tabs .ui-tabs-nav li.ui-tabs-active a, .tabs-nav li.active a { color: var(--color-primary); } -#avatar-tabs .ui-tabs-panel { +#avatar-tabs .ui-tabs-panel, .tabs-panel { padding: 0; } @@ -566,7 +714,6 @@ button:not(:disabled):hover { .control-group { display: flex; gap: 10px; - margin: 10px 0; } /* Add toggle switch styles */ @@ -613,4 +760,16 @@ button:not(:disabled):hover { .toggle-input:checked + .toggle-display:before { transform: translateX(20px); +} + +/* Update livechat tab styles */ +#livechat-tab { + display: flex; + flex-direction: column; + height: 100%; + gap: var(--spacing-lg); +} + +.w-full { + flex: 1; } \ No newline at end of file diff --git a/assets/js/control.js b/assets/js/control.js index c5c7f4c..f057b88 100644 --- a/assets/js/control.js +++ b/assets/js/control.js @@ -89,4 +89,13 @@ class Controller { document.addEventListener('DOMContentLoaded', () => { console.log('DOM loaded - initializing Controller'); new Controller(); +}); + +// Add this after initializing other components +$(document).ready(function() { + // Initialize tabs + $("#settings-tabs").tabs(); + + // Remove the avatar settings modal initialization since it's now in a tab + $("#open-avatar-settings").remove(); }); \ No newline at end of file diff --git a/assets/js/modules/AvatarManager.js b/assets/js/modules/AvatarManager.js index 2c87a48..2a098ed 100644 --- a/assets/js/modules/AvatarManager.js +++ b/assets/js/modules/AvatarManager.js @@ -54,7 +54,6 @@ export class AvatarManager { img.alt = `Avatar option`; item.appendChild(img); - item.addEventListener('click', () => this.setAvatar(type, path)); grid.appendChild(item); }); } @@ -91,13 +90,53 @@ export class AvatarManager { setupEventListeners() { console.log('Setting up avatar upload event listeners'); - document.getElementById('upload-idle').addEventListener('click', () => this.uploadAvatar('idle')); - document.getElementById('upload-talking').addEventListener('click', () => this.uploadAvatar('talking')); - document.getElementById('open-avatar-settings').addEventListener('click', () => { - $("#avatar-settings-modal").dialog('open'); + this.setupUploadHandlers(); + this.setupAvatarSelection(); + } + + setupUploadHandlers() { + const uploadButtons = { + idle: document.getElementById('upload-idle'), + talking: document.getElementById('upload-talking') + }; + + const fileInputs = { + idle: document.getElementById('idle-avatar'), + talking: document.getElementById('talking-avatar') + }; + + Object.entries(uploadButtons).forEach(([type, button]) => { + if (button) { + button.addEventListener('click', () => this.handleUpload(type, fileInputs[type])); + } + }); + } + + setupAvatarSelection() { + ['idle', 'talking'].forEach(type => { + const grid = document.getElementById(`${type}-avatar-grid`); + if (grid) { + grid.addEventListener('click', (e) => { + const item = e.target.closest('.avatar-item'); + if (item) { + const img = item.querySelector('img'); + const path = img.src.substring(img.src.indexOf('/avatars/')); + this.setAvatar(type, path); + } + }); + } }); } + handleUpload(type, fileInput) { + if (!fileInput.files.length) { + console.warn('No file selected'); + alert('Please select a file first'); + return; + } + this.uploadAvatar(type); + } + async uploadAvatar(type) { console.log(`Starting upload for ${type} avatar`); const fileInput = document.getElementById(`${type}-avatar`); diff --git a/assets/js/modules/ChatManager.js b/assets/js/modules/ChatManager.js index 0febca9..f47847d 100644 --- a/assets/js/modules/ChatManager.js +++ b/assets/js/modules/ChatManager.js @@ -144,8 +144,10 @@ export class ChatManager { const displayButton = ``; return ` - ${authorName}: - ${displayContent} +
+ ${authorName}: + ${displayContent} +
${ttsButton} ${displayButton}