mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-09-10 17:45:42 +00:00
ffe907e73a
Safe EJS bootstrap for /remote/guest; panel session wins over stale guest cookie.
442 lines
28 KiB
HTML
442 lines
28 KiB
HTML
<%- include('layouts/viewer', {
|
|
title: title || _('remote.title'),
|
|
pageScripts: ['billing-report', 'remote'],
|
|
body: `
|
|
|
|
<!-- RdClient phone gate -->
|
|
<div class="rd-phone-gate" id="rd-phone-gate" hidden>
|
|
<div class="rd-phone-gate-card">
|
|
<div class="rd-phone-gate-icon">
|
|
<span class="material-icons">tablet_mac</span>
|
|
</div>
|
|
<h1 class="rd-phone-gate-title">${_('remote.phone_unsupported_title')}</h1>
|
|
<p class="rd-phone-gate-body">${_('remote.phone_unsupported_body')}</p>
|
|
<div class="rd-phone-gate-actions">
|
|
<a href="/devices" class="rd-phone-gate-btn rd-phone-gate-btn-primary">${_('remote.phone_unsupported_back_devices')}</a>
|
|
<a href="/" class="rd-phone-gate-btn rd-phone-gate-btn-secondary">${_('mobile_nav.home')}</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- RdClient shell: tabs + viewer + toolbar (fullscreen target) -->
|
|
<div id="rd-viewer-shell" class="rd-viewer-shell">
|
|
|
|
<!-- Session Tab Bar -->
|
|
<div class="session-tab-bar session-tab-bar--slim" id="session-tab-bar">
|
|
<button type="button" class="tab-bar-back" id="btn-back-devices" title="${_('remote.back_to_devices')}">
|
|
<span class="material-icons">arrow_back</span>
|
|
</button>
|
|
<div class="session-tabs" id="session-tabs"></div>
|
|
<div class="toolbar-notch-slot toolbar-chrome-hidden" id="toolbar-notch-slot">
|
|
<div class="viewer-toolbar" id="viewer-toolbar">
|
|
<div class="toolbar-drawer" id="toolbar-drawer">
|
|
<div class="toolbar-expanded" id="toolbar-expanded">
|
|
<div class="toolbar-left">
|
|
<span class="toolbar-device-info">
|
|
<span class="toolbar-device-id" id="toolbar-device-id"></span>
|
|
<span class="toolbar-separator toolbar-status-sep">|</span>
|
|
<span class="toolbar-status" id="toolbar-status">${_('remote.connecting')}</span>
|
|
</span>
|
|
</div>
|
|
<div class="toolbar-monitor-strip" id="toolbar-monitor-strip" hidden></div>
|
|
<div class="toolbar-right">
|
|
<div class="toolbar-dropdown">
|
|
<button class="toolbar-btn" id="btn-actions" title="${_('remote.actions')}">
|
|
<span class="material-icons">flash_on</span>
|
|
</button>
|
|
<div class="toolbar-dropdown-menu" id="actions-menu">
|
|
<button class="dropdown-item" id="btn-cad">
|
|
<span class="material-icons">security</span> Ctrl+Alt+Del
|
|
</button>
|
|
<button class="dropdown-item" id="btn-lock">
|
|
<span class="material-icons">lock</span> ${_('remote.lock_screen')}
|
|
</button>
|
|
<button class="dropdown-item" id="btn-restart-remote">
|
|
<span class="material-icons">restart_alt</span> ${_('remote.restart_remote')}
|
|
</button>
|
|
<div class="dropdown-separator"></div>
|
|
<button class="dropdown-item" id="btn-refresh-screen">
|
|
<span class="material-icons">refresh</span> ${_('remote.refresh_screen')}
|
|
</button>
|
|
<button class="dropdown-item" id="btn-clipboard-paste">
|
|
<span class="material-icons">content_paste</span> ${_('remote.clipboard_paste')}
|
|
</button>
|
|
<button class="dropdown-item" id="btn-reset-keyboard">
|
|
<span class="material-icons">keyboard</span> ${_('remote.reset_keyboard')}
|
|
</button>
|
|
<div class="dropdown-separator"></div>
|
|
<button class="dropdown-item toggle-item" id="btn-block-input" data-active="false">
|
|
<span class="material-icons">block</span> ${_('remote.block_input')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="toolbar-dropdown">
|
|
<button class="toolbar-btn" id="btn-display" title="${_('remote.display_settings')}">
|
|
<span class="material-icons">tune</span>
|
|
</button>
|
|
<div class="toolbar-dropdown-menu toolbar-dropdown-wide" id="display-menu">
|
|
<div class="display-menu-grid">
|
|
<section class="display-menu-section">
|
|
<div class="dropdown-label">${_('remote.image_quality')}</div>
|
|
<button class="dropdown-item quality-item active" data-quality="Best">
|
|
<span class="material-icons">hd</span> ${_('remote.quality_best')}
|
|
</button>
|
|
<button class="dropdown-item quality-item" data-quality="Balanced">
|
|
<span class="material-icons">tune</span> ${_('remote.quality_balanced')}
|
|
</button>
|
|
<button class="dropdown-item quality-item" data-quality="Low">
|
|
<span class="material-icons">speed</span> ${_('remote.quality_low')}
|
|
</button>
|
|
</section>
|
|
<section class="display-menu-section">
|
|
<div class="dropdown-label">${_('remote.codec')}</div>
|
|
<button class="dropdown-item codec-item active" data-codec="Auto">
|
|
<span class="material-icons">auto_awesome</span> ${_('remote.codec_auto')}
|
|
</button>
|
|
<button class="dropdown-item codec-item" data-codec="VP9">
|
|
<span class="material-icons">memory</span> VP9
|
|
</button>
|
|
<button class="dropdown-item codec-item" data-codec="AV1">
|
|
<span class="material-icons">memory</span> AV1
|
|
</button>
|
|
<button class="dropdown-item codec-item" data-codec="H264">
|
|
<span class="material-icons">memory</span> H264
|
|
</button>
|
|
<button class="dropdown-item codec-item" data-codec="VP8">
|
|
<span class="material-icons">memory</span> VP8
|
|
</button>
|
|
<button class="dropdown-item codec-item" data-codec="H265">
|
|
<span class="material-icons">memory</span> H265
|
|
</button>
|
|
</section>
|
|
<section class="display-menu-section">
|
|
<div class="dropdown-label">${_('remote.keyboard_mode')}</div>
|
|
<button class="dropdown-item keyboard-mode-item active" data-keyboard-mode="Auto">
|
|
<span class="material-icons">auto_awesome</span> ${_('remote.keyboard_mode_auto')}
|
|
</button>
|
|
<button class="dropdown-item keyboard-mode-item" data-keyboard-mode="Legacy">
|
|
<span class="material-icons">translate</span> ${_('remote.keyboard_mode_legacy')}
|
|
</button>
|
|
<button class="dropdown-item keyboard-mode-item" data-keyboard-mode="Map">
|
|
<span class="material-icons">keyboard</span> ${_('remote.keyboard_mode_map')}
|
|
</button>
|
|
</section>
|
|
<section class="display-menu-section">
|
|
<div class="dropdown-label">${_('remote.scale_mode')}</div>
|
|
<button class="dropdown-item scale-item active" data-scale="fit">
|
|
<span class="material-icons">fit_screen</span> ${_('remote.scale_fit')}
|
|
</button>
|
|
<button class="dropdown-item scale-item" data-scale="fill">
|
|
<span class="material-icons">crop_free</span> ${_('remote.scale_fill')}
|
|
</button>
|
|
<button class="dropdown-item scale-item" data-scale="1:1">
|
|
<span class="material-icons">filter_1</span> ${_('remote.scale_original')}
|
|
</button>
|
|
<button class="dropdown-item scale-item" data-scale="stretch">
|
|
<span class="material-icons">open_in_full</span> ${_('remote.scale_stretch')}
|
|
</button>
|
|
</section>
|
|
<section class="display-menu-section display-menu-section--full">
|
|
<button class="dropdown-item toggle-item" id="btn-show-cursor" data-active="true">
|
|
<span class="material-icons">mouse</span> ${_('remote.show_cursor')}
|
|
</button>
|
|
<button class="dropdown-item toggle-item" id="btn-lock-session" data-active="false">
|
|
<span class="material-icons">lock_clock</span> ${_('remote.lock_after_session')}
|
|
</button>
|
|
<button class="dropdown-item toggle-item" id="btn-privacy-mode" data-active="false">
|
|
<span class="material-icons">visibility_off</span> ${_('remote.privacy_mode')}
|
|
</button>
|
|
<button class="dropdown-item toggle-item" id="btn-disable-clipboard" data-active="false">
|
|
<span class="material-icons">content_paste_off</span> ${_('remote.disable_clipboard')}
|
|
</button>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<button class="toolbar-btn" id="btn-audio" title="${_('remote.toggle_audio')}">
|
|
<span class="material-icons">volume_up</span>
|
|
</button>
|
|
<div class="toolbar-dropdown">
|
|
<button class="toolbar-btn" id="btn-monitors" title="${_('remote.monitors') || 'Monitors'}" style="display:none">
|
|
<span class="material-icons">desktop_windows</span>
|
|
</button>
|
|
<div class="toolbar-dropdown-menu" id="monitors-menu">
|
|
<div class="dropdown-label">${_('remote.select_monitor') || 'Select Monitor'}</div>
|
|
</div>
|
|
</div>
|
|
<button class="toolbar-btn" id="btn-chat" title="${_('remote.chat')}">
|
|
<span class="material-icons">chat</span>
|
|
</button>
|
|
<button class="toolbar-btn" id="btn-file-transfer" title="${_('remote.file_transfer') || 'File Transfer'}">
|
|
<span class="material-icons">folder_open</span>
|
|
</button>
|
|
<button class="toolbar-btn" id="btn-record" title="${_('remote.record')}">
|
|
<span class="material-icons">fiber_manual_record</span>
|
|
</button>
|
|
<button class="toolbar-btn" id="btn-viewonly" title="${_('remote.view_only')}">
|
|
<span class="material-icons">visibility</span>
|
|
</button>
|
|
<button class="toolbar-btn" id="btn-pin" title="${_('remote.pin_toolbar')}">
|
|
<span class="material-icons">push_pin</span>
|
|
</button>
|
|
<button class="toolbar-btn toolbar-btn-danger" id="btn-disconnect" title="${_('remote.disconnect')}">
|
|
<span class="material-icons">power_settings_new</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="toolbar-handle" id="toolbar-handle" role="button" tabindex="0" aria-expanded="false" aria-controls="toolbar-drawer" title="${_('remote.toggle_menu')}">
|
|
<button type="button" class="handle-btn" id="btn-handle-fullscreen" title="${_('remote.fullscreen')}">
|
|
<span class="material-icons">fullscreen</span>
|
|
</button>
|
|
<span class="toolbar-handle-grip" aria-hidden="true">
|
|
<span class="material-icons">expand_less</span>
|
|
</span>
|
|
<button type="button" class="handle-btn handle-expand" id="btn-toolbar-expand" title="${_('remote.toggle_menu')}">
|
|
<span class="material-icons">expand_more</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<button type="button" class="tab-bar-add" id="btn-add-session" title="${_('remote.new_connection') || 'New Connection'}">
|
|
<span class="material-icons">add</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Session picker (address book overlay) -->
|
|
<div class="session-picker-backdrop" id="session-picker-backdrop" hidden>
|
|
<div class="session-picker-panel" id="session-picker-panel" role="dialog" aria-labelledby="session-picker-title">
|
|
<div class="session-picker-header">
|
|
<h2 class="session-picker-title" id="session-picker-title">${_('remote.session_picker.title') || 'Choose device'}</h2>
|
|
<button type="button" class="session-picker-close" id="session-picker-close" title="${_('actions.close')}">
|
|
<span class="material-icons">close</span>
|
|
</button>
|
|
</div>
|
|
<div class="session-picker-quick">
|
|
<input type="text" class="session-picker-quick-input" id="session-picker-quick-id"
|
|
placeholder="${_('remote.device_id_placeholder') || 'Enter Device ID'}" autocomplete="off" spellcheck="false">
|
|
<button type="button" class="session-picker-quick-btn" id="session-picker-quick-btn">
|
|
<span class="material-icons">play_arrow</span>
|
|
${_('remote_dashboard.connect')}
|
|
</button>
|
|
</div>
|
|
<div class="session-picker-body">
|
|
<aside class="session-picker-sidebar" id="session-picker-sidebar">
|
|
<div class="session-picker-nav-heading">${_('remote_dashboard.nav_folders')}</div>
|
|
<ul class="session-picker-nav-list" id="session-picker-folders">
|
|
<li data-static="1"><button type="button" class="rd-picker-nav-item active" data-nav="folder" data-id="all">
|
|
<span class="material-icons">devices</span>
|
|
<span class="rd-picker-nav-label">${_('remote_dashboard.filter_all')}</span>
|
|
<span class="rd-picker-nav-count" id="rd-picker-count-all">0</span>
|
|
</button></li>
|
|
<li data-static="1"><button type="button" class="rd-picker-nav-item" data-nav="folder" data-id="unassigned">
|
|
<span class="material-icons">folder_off</span>
|
|
<span class="rd-picker-nav-label">${_('remote_dashboard.unassigned')}</span>
|
|
<span class="rd-picker-nav-count" id="rd-picker-count-unassigned">0</span>
|
|
</button></li>
|
|
</ul>
|
|
<ul class="session-picker-nav-list" id="session-picker-folders-custom"></ul>
|
|
<div class="session-picker-nav-heading">${_('remote_dashboard.nav_groups')}</div>
|
|
<ul class="session-picker-nav-list" id="session-picker-groups">
|
|
<li class="hidden" data-static="1" id="session-picker-groups-empty">${_('remote_dashboard.no_groups')}</li>
|
|
</ul>
|
|
<div class="session-picker-nav-heading">${_('remote_dashboard.nav_tags')}</div>
|
|
<ul class="session-picker-nav-list" id="session-picker-tags">
|
|
<li class="hidden" data-static="1" id="session-picker-tags-empty">${_('remote_dashboard.no_tags')}</li>
|
|
</ul>
|
|
</aside>
|
|
<div class="session-picker-content" id="session-picker-content">
|
|
<div class="session-picker-toolbar">
|
|
<span class="session-picker-section-title" id="session-picker-section-title">${_('remote_dashboard.nav_address_book')}</span>
|
|
<div class="session-picker-search-wrap">
|
|
<span class="material-icons session-picker-search-icon">search</span>
|
|
<input type="search" id="session-picker-search" class="session-picker-search"
|
|
placeholder="${_('remote_dashboard.search_placeholder')}" autocomplete="off">
|
|
</div>
|
|
<div class="session-picker-filters" role="tablist">
|
|
<button type="button" class="rd-picker-filter active" data-filter="all">${_('remote_dashboard.filter_all')}</button>
|
|
<button type="button" class="rd-picker-filter" data-filter="online">${_('remote_dashboard.filter_online')}</button>
|
|
<button type="button" class="rd-picker-filter" data-filter="offline">${_('remote_dashboard.filter_offline')}</button>
|
|
</div>
|
|
<div class="session-picker-view-toggle" role="group">
|
|
<button type="button" class="rd-picker-icon-btn active" id="session-picker-view-grid" title="${_('remote_dashboard.view_grid')}">
|
|
<span class="material-icons">grid_view</span>
|
|
</button>
|
|
<button type="button" class="rd-picker-icon-btn" id="session-picker-view-list" title="${_('remote_dashboard.view_list')}">
|
|
<span class="material-icons">view_list</span>
|
|
</button>
|
|
</div>
|
|
<span class="session-picker-count" id="session-picker-count"></span>
|
|
<button type="button" class="rd-picker-icon-btn" id="session-picker-refresh" title="${_('remote_dashboard.sync_now')}">
|
|
<span class="material-icons">sync</span>
|
|
</button>
|
|
</div>
|
|
<div class="session-picker-main" id="session-picker-main">
|
|
<div class="session-picker-loading hidden" id="session-picker-loading">
|
|
<span class="material-icons">sync</span>
|
|
<span>${_('remote_dashboard.loading')}</span>
|
|
</div>
|
|
<div class="session-picker-error hidden" id="session-picker-error">
|
|
<span class="material-icons">error_outline</span>
|
|
<span id="session-picker-error-text">${_('remote_dashboard.error_load')}</span>
|
|
<button type="button" class="rd-picker-btn" id="session-picker-retry">${_('remote_dashboard.retry')}</button>
|
|
</div>
|
|
<div class="session-picker-empty hidden" id="session-picker-empty">
|
|
<span class="material-icons">devices_other</span>
|
|
<p>${_('remote_dashboard.empty')}</p>
|
|
</div>
|
|
<div class="rd-picker-grid hidden" id="session-picker-grid"></div>
|
|
<div class="rd-picker-table-wrap hidden" id="session-picker-table-wrap">
|
|
<table class="rd-picker-table">
|
|
<thead>
|
|
<tr>
|
|
<th>${_('remote_dashboard.col_status')}</th>
|
|
<th>${_('remote_dashboard.col_id')}</th>
|
|
<th>${_('remote_dashboard.col_hostname')}</th>
|
|
<th>${_('remote_dashboard.col_platform')}</th>
|
|
<th>${_('remote_dashboard.col_last_seen')}</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="session-picker-tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Main Viewer Container (session panels are inserted here) -->
|
|
<div class="viewer-container" id="viewer-container"></div>
|
|
|
|
</div><!-- /#rd-viewer-shell -->
|
|
<nav class="rd-mobile-toolbar" id="rd-mobile-toolbar" aria-label="${_('remote.mobile_toolbar') || 'Remote controls'}">
|
|
<button type="button" class="rd-mobile-toolbar-btn active" id="rd-mob-input-touch" data-mode="direct" title="${_('remote.input_mode_touch')}">
|
|
<span class="material-icons">touch_app</span>
|
|
<span>${_('remote.input_mode_touch')}</span>
|
|
</button>
|
|
<button type="button" class="rd-mobile-toolbar-btn" id="rd-mob-input-touchpad" data-mode="touchpad" title="${_('remote.input_mode_touchpad')}">
|
|
<span class="material-icons">swipe</span>
|
|
<span>${_('remote.input_mode_touchpad')}</span>
|
|
</button>
|
|
<button type="button" class="rd-mobile-toolbar-btn" id="rd-mob-keyboard" title="${_('remote.show_keyboard')}">
|
|
<span class="material-icons">keyboard</span>
|
|
<span>${_('remote.show_keyboard')}</span>
|
|
</button>
|
|
<button type="button" class="rd-mobile-toolbar-btn" id="rd-mob-special" title="${_('remote.special_keys')}">
|
|
<span class="material-icons">keyboard_command_key</span>
|
|
<span>${_('remote.special_keys')}</span>
|
|
</button>
|
|
<button type="button" class="rd-mobile-toolbar-btn" id="rd-mob-cad" title="Ctrl+Alt+Del">
|
|
<span class="material-icons">security</span>
|
|
<span>CAD</span>
|
|
</button>
|
|
<button type="button" class="rd-mobile-toolbar-btn" id="rd-mob-fullscreen" title="${_('remote.fullscreen')}">
|
|
<span class="material-icons">fullscreen</span>
|
|
<span>${_('remote.fullscreen')}</span>
|
|
</button>
|
|
</nav>
|
|
<div class="rd-special-keys-panel" id="rd-special-keys-panel" role="group" aria-label="${_('remote.special_keys')}">
|
|
<button type="button" class="rd-special-key-btn" data-special="Meta">Win</button>
|
|
<button type="button" class="rd-special-key-btn" data-special="Alt+Tab">Alt+Tab</button>
|
|
<button type="button" class="rd-special-key-btn" data-special="PrintScreen">${_('remote.special_print_screen') || 'Print Screen'}</button>
|
|
<button type="button" class="rd-special-key-btn" data-special="Escape">Esc</button>
|
|
</div>
|
|
<input type="text" class="rd-keyboard-bridge" id="rd-keyboard-bridge" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" aria-hidden="true" tabindex="-1">
|
|
|
|
<!-- Session Panel Template (cloned for each session) -->
|
|
<template id="session-panel-template">
|
|
<div class="session-panel">
|
|
<div class="viewer-overlay session-connection-overlay">
|
|
<div class="overlay-card">
|
|
<div class="overlay-icon"><span class="material-icons">connected_tv</span></div>
|
|
<h2 class="overlay-title">${_('remote.title')}</h2>
|
|
<p class="overlay-device-id session-device-label"></p>
|
|
<p class="overlay-device-name session-device-name"></p>
|
|
<div class="overlay-status">
|
|
<div class="spinner"></div>
|
|
<span class="session-status-text">${_('remote.connecting')}</span>
|
|
</div>
|
|
<div class="overlay-actions session-overlay-actions" style="display:none;">
|
|
<button class="btn btn-primary session-btn-reconnect">
|
|
<span class="material-icons">refresh</span>
|
|
${_('remote.reconnect')}
|
|
</button>
|
|
<button class="btn btn-secondary session-btn-cdap-fallback" style="display:none;margin-top:8px;" title="${_('remote.cdap_fallback_hint')}">
|
|
<span class="material-icons">photo_camera</span>
|
|
${_('remote.use_cdap_fallback')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="viewer-overlay session-password-overlay" style="display:none;">
|
|
<div class="overlay-card">
|
|
<div class="overlay-icon"><span class="material-icons">lock</span></div>
|
|
<h2 class="overlay-title">${_('remote.password_required')}</h2>
|
|
<p class="overlay-device-id session-password-label"></p>
|
|
<div class="password-form">
|
|
<div class="form-group">
|
|
<input type="password" class="form-input session-password-input"
|
|
placeholder="${_('remote.password_placeholder')}" autocomplete="off">
|
|
</div>
|
|
<p class="login-error session-login-error" style="display:none;"></p>
|
|
<div class="password-form-footer">
|
|
<label class="session-remember-peer">
|
|
<input type="checkbox" class="session-remember-peer-checkbox">
|
|
<span>${_('remote.remember_peer_password') || 'Remember device password on this device'}</span>
|
|
</label>
|
|
<button class="btn btn-primary btn-full session-btn-authenticate">
|
|
<span class="material-icons">login</span>
|
|
${_('remote.connect')}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="viewer-overlay session-2fa-overlay" style="display:none;">
|
|
<div class="overlay-card">
|
|
<div class="overlay-icon"><span class="material-icons">verified_user</span></div>
|
|
<h2 class="overlay-title">${_('remote.2fa_required') || '2FA Verification'}</h2>
|
|
<p class="overlay-subtitle">${_('remote.2fa_hint') || 'Enter the 6-digit code from your authenticator app'}</p>
|
|
<div class="password-form">
|
|
<div class="form-group">
|
|
<input type="text" class="form-input session-2fa-input"
|
|
placeholder="000000" autocomplete="one-time-code"
|
|
maxlength="6" inputmode="numeric" pattern="[0-9]*"
|
|
style="text-align:center;font-size:1.5rem;letter-spacing:0.5em;">
|
|
</div>
|
|
<p class="login-error session-2fa-error" style="display:none;"></p>
|
|
<button class="btn btn-primary btn-full session-btn-verify-2fa">
|
|
<span class="material-icons">verified</span>
|
|
${_('remote.verify') || 'Verify'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<canvas class="session-canvas" tabindex="0"></canvas>
|
|
<div class="chat-panel session-chat-panel" style="display:none;">
|
|
<div class="chat-header">
|
|
<span>${_('remote.chat')}</span>
|
|
<button class="chat-close session-btn-chat-close"><span class="material-icons">close</span></button>
|
|
</div>
|
|
<div class="chat-messages session-chat-messages"></div>
|
|
<div class="chat-input-area">
|
|
<input type="text" class="chat-input session-chat-input" placeholder="${_('remote.chat_placeholder')}" />
|
|
<button class="chat-send session-btn-chat-send"><span class="material-icons">send</span></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- Initial session data (from server route) -->
|
|
<script nonce="${cspNonce}">
|
|
window.__initialDeviceId = ` + JSON.stringify(deviceId) + `;
|
|
window.__initialDeviceName = ` + JSON.stringify(device && device.hostname ? device.hostname : '') + `;
|
|
window.__capabilities = ` + JSON.stringify(capabilities || { transport: 'rd' }) + `;
|
|
window.__guestToken = ` + JSON.stringify((typeof guestToken !== 'undefined' && guestToken) ? guestToken : '') + `;
|
|
</script>
|
|
|
|
`
|
|
}) %>
|