Skip to main content
Glama

Smart Code Search MCP Server

media-ui.html25.7 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Voice Assistant with Media History - SCS-MCP</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } :root { --primary: #6366f1; --primary-dark: #4f46e5; --secondary: #8b5cf6; --success: #10b981; --danger: #ef4444; --warning: #f59e0b; --dark: #1f2937; --light: #f3f4f6; --border: #e5e7eb; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; flex-direction: column; } /* Header */ .header { background: rgba(255, 255, 255, 0.98); backdrop-filter: blur(20px); box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1); position: sticky; top: 0; z-index: 100; } .header-content { max-width: 1400px; margin: 0 auto; padding: 1rem 2rem; display: flex; justify-content: space-between; align-items: center; } .logo { display: flex; align-items: center; gap: 1rem; font-size: 1.5rem; font-weight: 600; background: linear-gradient(135deg, #667eea, #764ba2); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .status-bar { display: flex; gap: 1rem; } .status-indicator { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 1rem; background: var(--light); border-radius: 20px; font-size: 0.875rem; } .status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--danger); } .status-dot.connected { background: var(--success); animation: pulse 2s infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } /* Main Layout */ .main-container { flex: 1; display: flex; max-width: 1400px; width: 100%; margin: 2rem auto; padding: 0 2rem; gap: 2rem; } /* Voice Panel */ .voice-panel { flex: 0 0 400px; background: rgba(255, 255, 255, 0.98); border-radius: 20px; padding: 2rem; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1); max-height: calc(100vh - 200px); overflow-y: auto; } .mic-button { width: 120px; height: 120px; margin: 2rem auto; display: block; border-radius: 50%; background: linear-gradient(135deg, var(--primary), var(--secondary)); border: none; color: white; font-size: 48px; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 5px 20px rgba(99, 102, 241, 0.4); } .mic-button:hover { transform: scale(1.05); } .mic-button.listening { animation: listening 1.5s ease-in-out infinite; background: linear-gradient(135deg, #f093fb, #f5576c); } @keyframes listening { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.1); } } .voice-controls { display: flex; justify-content: center; gap: 1rem; margin: 2rem 0; } .control-btn { padding: 0.5rem 1rem; border: 2px solid var(--primary); background: white; border-radius: 20px; cursor: pointer; transition: all 0.3s ease; } .control-btn.active { background: var(--primary); color: white; } .transcript { background: var(--light); border-radius: 10px; padding: 1rem; min-height: 100px; font-family: 'Courier New', monospace; font-size: 0.9rem; } /* Media Panel */ .media-panel { flex: 1; background: rgba(255, 255, 255, 0.98); border-radius: 20px; padding: 2rem; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; } .media-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem; } .media-tabs { display: flex; gap: 1rem; } .tab-btn { padding: 0.5rem 1.5rem; border: none; background: var(--light); border-radius: 10px; cursor: pointer; transition: all 0.3s ease; } .tab-btn.active { background: var(--primary); color: white; } .media-actions { display: flex; gap: 1rem; } .action-btn { padding: 0.5rem 1rem; border: none; background: var(--primary); color: white; border-radius: 10px; cursor: pointer; display: flex; align-items: center; gap: 0.5rem; transition: all 0.3s ease; } .action-btn:hover { background: var(--primary-dark); } .action-btn.recording { background: var(--danger); animation: recording-pulse 1s infinite; } @keyframes recording-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } } /* Filters */ .media-filters { display: flex; gap: 1rem; margin-bottom: 2rem; flex-wrap: wrap; } .filter-group { display: flex; flex-direction: column; gap: 0.25rem; } .filter-label { font-size: 0.75rem; color: #6b7280; text-transform: uppercase; } .filter-input { padding: 0.5rem; border: 1px solid var(--border); border-radius: 5px; background: white; } /* Media Grid */ .media-content { flex: 1; overflow-y: auto; } .view-toggle { display: flex; gap: 0.5rem; margin-bottom: 1rem; } .view-btn { padding: 0.25rem 0.5rem; border: 1px solid var(--border); background: white; cursor: pointer; border-radius: 5px; } .view-btn.active { background: var(--primary); color: white; border-color: var(--primary); } .media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1.5rem; } .media-item { background: white; border-radius: 10px; overflow: hidden; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; cursor: pointer; } .media-item:hover { transform: translateY(-5px); box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15); } .media-thumbnail { width: 100%; height: 150px; object-fit: cover; background: var(--light); } .media-info { padding: 1rem; } .media-title { font-weight: 600; margin-bottom: 0.5rem; } .media-meta { display: flex; justify-content: space-between; font-size: 0.875rem; color: #6b7280; } .media-type { display: inline-block; padding: 0.25rem 0.5rem; background: var(--light); border-radius: 5px; font-size: 0.75rem; text-transform: uppercase; } .media-type.screenshot { background: #dbeafe; color: #1e40af; } .media-type.recording { background: #fce7f3; color: #be185d; } .media-type.browser { background: #f0fdf4; color: #166534; } /* Timeline View */ .media-timeline { position: relative; padding-left: 2rem; } .timeline-line { position: absolute; left: 10px; top: 0; bottom: 0; width: 2px; background: var(--border); } .timeline-item { position: relative; margin-bottom: 2rem; padding-left: 2rem; } .timeline-dot { position: absolute; left: -6px; top: 0; width: 14px; height: 14px; border-radius: 50%; background: var(--primary); border: 2px solid white; box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.1); } .timeline-content { background: white; border-radius: 10px; padding: 1rem; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .timeline-time { font-size: 0.875rem; color: #6b7280; margin-bottom: 0.5rem; } /* Session Groups */ .session-group { margin-bottom: 2rem; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; } .session-header { background: var(--light); padding: 1rem; display: flex; justify-content: space-between; align-items: center; cursor: pointer; } .session-title { font-weight: 600; } .session-stats { display: flex; gap: 1rem; font-size: 0.875rem; color: #6b7280; } .session-content { padding: 1rem; } /* Analytics */ .analytics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem; } .stat-card { background: white; border-radius: 10px; padding: 1.5rem; text-align: center; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); } .stat-value { font-size: 2rem; font-weight: 600; color: var(--primary); } .stat-label { font-size: 0.875rem; color: #6b7280; margin-top: 0.5rem; } /* Modal */ .modal { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 1000; align-items: center; justify-content: center; } .modal.active { display: flex; } .modal-content { background: white; border-radius: 20px; padding: 2rem; max-width: 90%; max-height: 90%; overflow: auto; position: relative; } .modal-close { position: absolute; top: 1rem; right: 1rem; background: none; border: none; font-size: 1.5rem; cursor: pointer; color: #6b7280; } /* Annotation Tools */ .annotation-toolbar { display: flex; gap: 0.5rem; padding: 1rem; background: var(--light); border-radius: 10px; margin-bottom: 1rem; } .annotation-tool { padding: 0.5rem; border: none; background: white; border-radius: 5px; cursor: pointer; transition: all 0.3s ease; } .annotation-tool.active { background: var(--primary); color: white; } .annotation-canvas { position: relative; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; } /* Quick Actions */ .quick-actions { position: fixed; bottom: 2rem; right: 2rem; display: flex; flex-direction: column; gap: 1rem; } .fab { width: 56px; height: 56px; border-radius: 50%; background: var(--primary); color: white; border: none; font-size: 24px; cursor: pointer; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); transition: all 0.3s ease; } .fab:hover { transform: scale(1.1); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2); } .fab.secondary { width: 48px; height: 48px; font-size: 20px; background: white; color: var(--primary); border: 2px solid var(--primary); } /* Loading Spinner */ .spinner { border: 3px solid var(--light); border-top: 3px solid var(--primary); border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite; margin: 2rem auto; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Responsive */ @media (max-width: 1024px) { .main-container { flex-direction: column; } .voice-panel { flex: none; width: 100%; } } @media (max-width: 768px) { .media-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); } .analytics-grid { grid-template-columns: 1fr; } } </style> </head> <body> <!-- Header --> <header class="header"> <div class="header-content"> <div class="logo"> <span>🎙️</span> <span>Voice Assistant + Media History</span> </div> <div class="status-bar"> <div class="status-indicator"> <div class="status-dot" id="scsStatus"></div> <span>SCS-MCP</span> </div> <div class="status-indicator"> <div class="status-dot" id="browserStatus"></div> <span>Browser</span> </div> <div class="status-indicator"> <div class="status-dot" id="voiceStatus"></div> <span>Voice</span> </div> <div class="status-indicator"> <span id="storageStatus">0 MB / 5 GB</span> </div> </div> </div> </header> <!-- Main Container --> <div class="main-container"> <!-- Voice Panel --> <aside class="voice-panel"> <h2 style="margin-bottom: 1rem;">Voice Assistant</h2> <button class="mic-button" id="micButton" onclick="toggleVoice()"> 🎤 </button> <div class="voice-controls"> <button class="control-btn active" onclick="setMode('push')">Push</button> <button class="control-btn" onclick="setMode('continuous')">Continuous</button> <button class="control-btn" onclick="setMode('wake')">Wake Word</button> </div> <div class="transcript" id="transcript"> Ready to listen... </div> <h3 style="margin: 2rem 0 1rem;">Quick Commands</h3> <div style="display: grid; gap: 0.5rem;"> <button class="action-btn" onclick="voiceCommand('take screenshot')"> 📸 Screenshot </button> <button class="action-btn" onclick="voiceCommand('start recording')"> 🎬 Start Recording </button> <button class="action-btn" onclick="voiceCommand('capture browser')"> 🌐 Browser Capture </button> <button class="action-btn" onclick="voiceCommand('show media history')"> 📁 Media History </button> </div> <h3 style="margin: 2rem 0 1rem;">Context</h3> <div style="font-size: 0.875rem; color: #6b7280;"> <div>File: <span id="currentFile">Not connected</span></div> <div>Line: <span id="currentLine">-</span></div> <div>Symbol: <span id="currentSymbol">-</span></div> </div> </aside> <!-- Media Panel --> <main class="media-panel"> <!-- Media Header --> <div class="media-header"> <div class="media-tabs"> <button class="tab-btn active" onclick="switchTab('gallery')">Gallery</button> <button class="tab-btn" onclick="switchTab('timeline')">Timeline</button> <button class="tab-btn" onclick="switchTab('sessions')">Sessions</button> <button class="tab-btn" onclick="switchTab('analytics')">Analytics</button> </div> <div class="media-actions"> <button class="action-btn" id="screenshotBtn" onclick="takeScreenshot()"> 📸 Screenshot </button> <button class="action-btn" id="recordBtn" onclick="toggleRecording()"> 🔴 Record </button> <button class="action-btn" onclick="exportMedia()"> 📥 Export </button> </div> </div> <!-- Filters --> <div class="media-filters"> <div class="filter-group"> <label class="filter-label">Type</label> <select class="filter-input" id="filterType" onchange="applyFilters()"> <option value="all">All</option> <option value="screenshot">Screenshots</option> <option value="recording">Recordings</option> <option value="browser">Browser</option> </select> </div> <div class="filter-group"> <label class="filter-label">Project</label> <select class="filter-input" id="filterProject" onchange="applyFilters()"> <option value="all">All Projects</option> </select> </div> <div class="filter-group"> <label class="filter-label">Date</label> <input type="date" class="filter-input" id="filterDate" onchange="applyFilters()"> </div> <div class="filter-group"> <label class="filter-label">Search</label> <input type="text" class="filter-input" id="filterSearch" placeholder="Search..." onkeyup="applyFilters()"> </div> </div> <!-- Media Content --> <div class="media-content"> <!-- Gallery View --> <div id="galleryView" class="view-content"> <div class="view-toggle"> <button class="view-btn active" onclick="setViewMode('grid')">⊞ Grid</button> <button class="view-btn" onclick="setViewMode('list')">☰ List</button> </div> <div class="media-grid" id="mediaGrid"> <!-- Media items will be populated here --> </div> </div> <!-- Timeline View --> <div id="timelineView" class="view-content" style="display: none;"> <div class="media-timeline" id="mediaTimeline"> <div class="timeline-line"></div> <!-- Timeline items will be populated here --> </div> </div> <!-- Sessions View --> <div id="sessionsView" class="view-content" style="display: none;"> <div id="sessionsList"> <!-- Session groups will be populated here --> </div> </div> <!-- Analytics View --> <div id="analyticsView" class="view-content" style="display: none;"> <div class="analytics-grid"> <div class="stat-card"> <div class="stat-value" id="totalMedia">0</div> <div class="stat-label">Total Media</div> </div> <div class="stat-card"> <div class="stat-value" id="todayCaptures">0</div> <div class="stat-label">Today's Captures</div> </div> <div class="stat-card"> <div class="stat-value" id="storageUsed">0 MB</div> <div class="stat-label">Storage Used</div> </div> <div class="stat-card"> <div class="stat-value" id="avgDuration">0s</div> <div class="stat-label">Avg Recording</div> </div> </div> <canvas id="analyticsChart" width="400" height="200"></canvas> </div> </div> </main> </div> <!-- Quick Actions --> <div class="quick-actions"> <button class="fab secondary" onclick="scrollToTop()" title="Scroll to top"> ↑ </button> <button class="fab" onclick="openAnnotationModal()" title="Annotate last capture"> ✏️ </button> </div> <!-- Media Viewer Modal --> <div class="modal" id="mediaModal"> <div class="modal-content"> <button class="modal-close" onclick="closeModal('mediaModal')">×</button> <div id="modalContent"> <!-- Dynamic content --> </div> </div> </div> <!-- Annotation Modal --> <div class="modal" id="annotationModal"> <div class="modal-content"> <button class="modal-close" onclick="closeModal('annotationModal')">×</button> <h2>Annotate Media</h2> <div class="annotation-toolbar"> <button class="annotation-tool active" onclick="setAnnotationTool('pen')">✏️ Pen</button> <button class="annotation-tool" onclick="setAnnotationTool('highlight')">🖍️ Highlight</button> <button class="annotation-tool" onclick="setAnnotationTool('text')">📝 Text</button> <button class="annotation-tool" onclick="setAnnotationTool('arrow')">➡️ Arrow</button> <button class="annotation-tool" onclick="clearAnnotations()">🗑️ Clear</button> </div> <div class="annotation-canvas" id="annotationCanvas"> <!-- Canvas for annotations --> </div> <button class="action-btn" onclick="saveAnnotations()" style="margin-top: 1rem;"> 💾 Save Annotations </button> </div> </div> <script src="/media-app.js"></script> </body> </html>

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stevenjjobson/scs-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server