mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-09-10 17:45:42 +00:00
dd0889e3d6
Introduce a SessionManager for relay-based remote sessions in the Tauri MGMT client: new SessionCommand API, start/stop/session input routing, clipboard/recording/quality controls, and notification read/dismiss state. Wire AppState with new mutexes and show main window on startup. CI: add SBOM generation (anchore) and Trivy vulnerability scan steps. Misc: change console Docker DB path, large README/CHANGELOG updates (chat E2E, unattended access/WOL, i18n expansion, CDAP/SDK docs), and many web-nodejs assets/locales/routes/views/services and server-side changes.
188 lines
9.6 KiB
HTML
188 lines
9.6 KiB
HTML
<%- include('layouts/main', {
|
|
title: typeof title !== 'undefined' ? title : _('nav.chat'),
|
|
pageStyles: typeof pageStyles !== 'undefined' ? pageStyles : ['chat'],
|
|
pageScripts: typeof pageScripts !== 'undefined' ? pageScripts : ['chatCrypto', 'chat'],
|
|
currentPage: typeof currentPage !== 'undefined' ? currentPage : 'chat',
|
|
breadcrumb: typeof breadcrumb !== 'undefined' ? breadcrumb : [{ label: _('nav.chat') }],
|
|
body: `
|
|
<div class="chat-page" id="chat-page">
|
|
<!-- Sidebar: contacts & groups -->
|
|
<aside class="chat-sidebar" id="chat-sidebar">
|
|
<div class="chat-sidebar-header">
|
|
<h2 class="chat-sidebar-title">${_('nav.chat')}</h2>
|
|
<div class="chat-sidebar-actions">
|
|
<button class="chat-icon-btn" id="chat-new-group-btn" title="${_('chat.create_group')}">
|
|
<span class="material-icons">group_add</span>
|
|
</button>
|
|
<button class="chat-icon-btn" id="chat-search-toggle" title="${_('chat.search_messages')}">
|
|
<span class="material-icons">search</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Search bar (hidden by default) -->
|
|
<div class="chat-search-bar" id="chat-search-bar" style="display:none">
|
|
<input type="text" class="chat-search-input" id="chat-search-input"
|
|
placeholder="${_('chat.search_placeholder')}">
|
|
<button class="chat-icon-btn chat-search-close" id="chat-search-close">
|
|
<span class="material-icons">close</span>
|
|
</button>
|
|
</div>
|
|
<div class="chat-search-results" id="chat-search-results" style="display:none"></div>
|
|
|
|
<!-- Tabs: Contacts / Groups -->
|
|
<div class="chat-tabs">
|
|
<button class="chat-tab active" data-tab="contacts">
|
|
<span class="material-icons">people</span>
|
|
${_('chat.contacts')}
|
|
</button>
|
|
<button class="chat-tab" data-tab="groups">
|
|
<span class="material-icons">groups</span>
|
|
${_('chat.groups')}
|
|
</button>
|
|
</div>
|
|
|
|
<div class="chat-list-wrap">
|
|
<!-- Contact list -->
|
|
<div class="chat-list" id="chat-contacts-list" data-tab-content="contacts">
|
|
<div class="chat-list-empty">
|
|
<span class="material-icons">forum</span>
|
|
<p>${_('chat.no_contacts')}</p>
|
|
</div>
|
|
</div>
|
|
<!-- Group list -->
|
|
<div class="chat-list" id="chat-groups-list" data-tab-content="groups" style="display:none">
|
|
<div class="chat-list-empty">
|
|
<span class="material-icons">group</span>
|
|
<p>${_('chat.no_groups')}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Presence selector -->
|
|
<div class="chat-presence-bar" id="chat-presence-bar">
|
|
<select class="chat-presence-select" id="chat-presence-select">
|
|
<option value="online">${_('chat.presence_online')}</option>
|
|
<option value="away">${_('chat.presence_away')}</option>
|
|
<option value="busy">${_('chat.presence_busy')}</option>
|
|
</select>
|
|
<span class="chat-presence-dot" id="chat-my-presence-dot"></span>
|
|
<span class="chat-username">${typeof user !== 'undefined' && user ? user.username : 'Operator'}</span>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Main chat area -->
|
|
<section class="chat-main" id="chat-main">
|
|
<!-- Empty state -->
|
|
<div class="chat-empty-state" id="chat-empty-state">
|
|
<span class="material-icons chat-empty-icon">chat</span>
|
|
<h3>${_('chat.select_conversation')}</h3>
|
|
<p>${_('chat.select_conversation_hint')}</p>
|
|
</div>
|
|
|
|
<!-- Conversation view (hidden initially) -->
|
|
<div class="chat-conversation" id="chat-conversation" style="display:none">
|
|
<!-- Conversation header -->
|
|
<div class="chat-conv-header" id="chat-conv-header">
|
|
<button class="chat-icon-btn chat-back-btn" id="chat-back-btn" title="${_('actions.back')}">
|
|
<span class="material-icons">arrow_back</span>
|
|
</button>
|
|
<div class="chat-conv-info">
|
|
<div class="chat-conv-avatar" id="chat-conv-avatar"></div>
|
|
<div class="chat-conv-details">
|
|
<span class="chat-conv-name" id="chat-conv-name"></span>
|
|
<span class="chat-conv-status" id="chat-conv-status"></span>
|
|
</div>
|
|
</div>
|
|
<div class="chat-conv-actions">
|
|
<button class="chat-icon-btn" id="chat-encrypt-btn" title="${_('chat.e2e_enabled')}">
|
|
<span class="material-icons">lock</span>
|
|
</button>
|
|
<button class="chat-icon-btn" id="chat-conv-search-btn" title="${_('chat.search_messages')}">
|
|
<span class="material-icons">search</span>
|
|
</button>
|
|
<button class="chat-icon-btn" id="chat-conv-info-btn" title="${_('chat.info')}">
|
|
<span class="material-icons">info</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- E2E encryption banner -->
|
|
<div class="chat-e2e-banner" id="chat-e2e-banner" style="display:none">
|
|
<span class="material-icons">enhanced_encryption</span>
|
|
<span id="chat-e2e-text">${_('chat.e2e_establishing')}</span>
|
|
</div>
|
|
|
|
<!-- Messages area -->
|
|
<div class="chat-messages" id="chat-messages">
|
|
<div class="chat-messages-inner" id="chat-messages-inner"></div>
|
|
</div>
|
|
|
|
<!-- Typing indicator -->
|
|
<div class="chat-typing" id="chat-typing" style="display:none">
|
|
<span class="chat-typing-dots">
|
|
<span></span><span></span><span></span>
|
|
</span>
|
|
<span class="chat-typing-text" id="chat-typing-text">${_('chat.typing_indicator')}</span>
|
|
</div>
|
|
|
|
<!-- Input area -->
|
|
<div class="chat-input-area" id="chat-input-area">
|
|
<div class="chat-input-row">
|
|
<button class="chat-icon-btn" id="chat-attach-btn" title="${_('chat.attach_file')}">
|
|
<span class="material-icons">attach_file</span>
|
|
</button>
|
|
<button class="chat-icon-btn" id="chat-emoji-btn" title="${_('chat.emoji')}">
|
|
<span class="material-icons">sentiment_satisfied_alt</span>
|
|
</button>
|
|
<div class="chat-input-wrap">
|
|
<textarea class="chat-input" id="chat-input" rows="1"
|
|
placeholder="${_('chat.type_message')}" maxlength="4096"></textarea>
|
|
</div>
|
|
<button class="chat-send-btn" id="chat-send-btn" title="${_('chat.send')}">
|
|
<span class="material-icons">send</span>
|
|
</button>
|
|
</div>
|
|
<!-- File preview (hidden) -->
|
|
<div class="chat-file-preview" id="chat-file-preview" style="display:none">
|
|
<span class="chat-file-name" id="chat-file-name"></span>
|
|
<span class="chat-file-size" id="chat-file-size"></span>
|
|
<button class="chat-icon-btn chat-file-remove" id="chat-file-remove">
|
|
<span class="material-icons">close</span>
|
|
</button>
|
|
</div>
|
|
<input type="file" id="chat-file-input" style="display:none">
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<!-- Create Group Modal -->
|
|
<div class="modal-overlay" id="chat-group-modal" style="display:none">
|
|
<div class="modal-dialog">
|
|
<div class="modal-header">
|
|
<h3>${_('chat.create_group')}</h3>
|
|
<button class="modal-close" id="chat-group-modal-close">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="form-group">
|
|
<label>${_('chat.group_name')}</label>
|
|
<input type="text" class="form-input" id="chat-group-name-input"
|
|
placeholder="${_('chat.group_name_placeholder')}" maxlength="64">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>${_('chat.group_members')}</label>
|
|
<div class="chat-member-select" id="chat-member-select"></div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-secondary" id="chat-group-cancel">${_('actions.cancel')}</button>
|
|
<button class="btn btn-primary" id="chat-group-create">${_('actions.create')}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Emoji Picker (lightweight) -->
|
|
<div class="chat-emoji-picker" id="chat-emoji-picker" style="display:none"></div>
|
|
` }) %>
|