mirror of
https://github.com/jamesstringer90/appsandbox.git
synced 2026-10-23 19:43:36 -05:00
Linux guest provisioning now mirrors the host's regional settings instead
of hardcoding en_US / us / America/New_York / "ubuntu":
- detect_host_locale_settings() reads the current Windows user's locale
(GetUserDefaultLocaleName), keyboard (GetKeyboardLayoutList) and
timezone (GetDynamicTimeZoneInformation), translating each to the
Linux equivalent. Language is gated to the 8 ISO-preinstalled
languages (de/en/es/fr/it/pt/ru/zh) and falls back to en_US.UTF-8
otherwise; keyboard + timezone always match the host (every XKB
layout and IANA zone ships in the squashfs offline).
- VM name flows through as the guest hostname (mirrors Windows
ComputerName), staged as /etc/appsandbox-hostname.
- All four values staged as marker files; firstboot STEP 2/3/4 read
them with safe fallbacks and STEP 17 echoes the applied values.
Create-VM UI validation is now per-guest-OS, keyed consistently off
osType across validateVmName / validateUsername / validatePassword:
- Linux hostname: lowercase, RFC-1123 charset
- Linux username: ^[a-z_][a-z0-9_-]*$, <=32 chars
- Linux password: all chars allowed (host $6$ hash path), <=255 bytes
- default name lowercases to "myappsandbox" when Linux is selected
- OS Type moved above VM Name in the modal; .field-warn now wraps so
long messages don't break the modal layout; added admin-pass-warn span
IDD audio: drop the unused GetMixFormat call that returned
AUDCLNT_E_UNSUPPORTED_FORMAT on some AMD endpoints and needlessly killed
the audio path. renderfmt is built from the guest header and Initialize
runs with AUTOCONVERTPCM, so the host mix format was never used.
192 lines
8.3 KiB
HTML
192 lines
8.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>App Sandbox</title>
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Virtual Machines -->
|
|
<section id="vm-section">
|
|
<div class="section-header">
|
|
<h2>Sandboxes</h2>
|
|
<button id="btn-new-sandbox" class="primary" onclick="openCreateModal()">+ New Sandbox</button>
|
|
</div>
|
|
<div class="vm-table-wrap">
|
|
<table id="vm-table">
|
|
<thead><tr>
|
|
<th>Name</th>
|
|
<th>OS</th>
|
|
<th>Status</th>
|
|
<th>Agent</th>
|
|
<th>CPU</th>
|
|
<th>RAM (MB)</th>
|
|
<th>HDD (GB)</th>
|
|
<th>GPU</th>
|
|
<th>Network</th>
|
|
<th class="win-only">Snapshot</th>
|
|
<th class="icon-col">▶️</th>
|
|
<th class="icon-col" title="IDD Display">📺</th>
|
|
<th class="icon-col" title="SSH">>_</th>
|
|
<th class="icon-col">⏻</th>
|
|
<th class="icon-col">✕️</th>
|
|
<th class="icon-col">🗑️</th>
|
|
<th class="icon-col">✏️</th>
|
|
</tr></thead>
|
|
<tbody id="vm-tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Log -->
|
|
<section id="log-section">
|
|
<h2 class="collapsible" onclick="toggleSection('log-section')"><span class="collapse-arrow" id="log-section-arrow">▼</span> Log</h2>
|
|
<div id="log-panel"></div>
|
|
</section>
|
|
|
|
<!-- Prerequisite modal -->
|
|
<div class="modal-overlay" id="prereq-overlay">
|
|
<div class="modal">
|
|
<h3>Virtual Machine Platform Required</h3>
|
|
<p id="prereq-message">App Sandbox requires the <strong>Virtual Machine Platform</strong> Windows feature to create and run VMs. This feature is not currently enabled.</p>
|
|
<div class="modal-buttons" id="prereq-buttons">
|
|
<button onclick="document.getElementById('prereq-overlay').classList.remove('active')">Cancel</button>
|
|
<button class="primary" onclick="enableFeature()">Enable</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create Sandbox modal -->
|
|
<div class="modal-overlay" id="create-vm-overlay">
|
|
<div class="modal wide">
|
|
<h3>New Sandbox</h3>
|
|
<div class="form-grid">
|
|
<label for="os-type">OS Type:</label>
|
|
<div class="form-row">
|
|
<select id="os-type" onchange="applyOsTypeUI()">
|
|
<option value="Windows" selected>Windows</option>
|
|
<option value="Linux">Linux</option>
|
|
<option value="macOS">macOS</option>
|
|
</select>
|
|
</div>
|
|
|
|
<label for="vm-name">VM Name:</label>
|
|
<div class="form-row">
|
|
<input type="text" id="vm-name" value="MyAppSandbox" class="input-md">
|
|
<span class="field-warn" id="vm-name-warn"></span>
|
|
</div>
|
|
|
|
<label class="needs-iso">OS Image:</label>
|
|
<div class="image-row needs-iso">
|
|
<input type="text" id="image-path" placeholder="Path to ISO or VHDX...">
|
|
<button id="btn-browse" onclick="sendCmd('browseImage')">Browse...</button>
|
|
<span class="or-separator win-only">OR</span>
|
|
<label class="win-only" style="text-align:left">Template:</label>
|
|
<div class="template-dropdown win-only" id="template-dropdown">
|
|
<div class="template-dropdown-selected" id="template-dropdown-selected">(None)</div>
|
|
<div class="template-dropdown-list" id="template-dropdown-list"></div>
|
|
<input type="hidden" id="template-select" value="">
|
|
</div>
|
|
</div>
|
|
|
|
<label class="needs-linux-version">Distribution:</label>
|
|
<div class="form-row needs-linux-version">
|
|
<select id="linux-version">
|
|
<option value="ubuntu-26.04" selected>Ubuntu 26.04 LTS</option>
|
|
</select>
|
|
<span class="host-info">Downloaded on first create (~600 MB), cached on the host</span>
|
|
</div>
|
|
|
|
<label for="hdd-size">HDD Size:</label>
|
|
<div class="form-row">
|
|
<input type="number" id="hdd-size" value="64" min="1" class="input-sm"> GB
|
|
<span class="host-info" id="host-hdd"></span>
|
|
</div>
|
|
|
|
<label for="ram-size">RAM Size:</label>
|
|
<div class="form-row">
|
|
<input type="number" id="ram-size" value="16384" min="512" class="input-sm"> MB
|
|
<span class="host-info" id="host-ram"></span>
|
|
</div>
|
|
|
|
<label for="cpu-cores">CPU Cores:</label>
|
|
<div class="form-row">
|
|
<input type="number" id="cpu-cores" value="8" min="1" class="input-sm">
|
|
<span class="host-info" id="host-cpu"></span>
|
|
</div>
|
|
|
|
<label for="gpu-mode">GPU:</label>
|
|
<div class="form-row">
|
|
<select id="gpu-mode">
|
|
<option value="0">None</option>
|
|
<option value="1" selected>Default GPU</option>
|
|
<option value="2">Try all</option>
|
|
</select>
|
|
</div>
|
|
|
|
<label for="net-mode">Network:</label>
|
|
<div class="form-row">
|
|
<select id="net-mode" onchange="onNetModeChange()">
|
|
<option value="0">None</option>
|
|
<option value="1" selected>NAT</option>
|
|
<option value="2">External</option>
|
|
<option value="3">Internal</option>
|
|
</select>
|
|
<label id="net-adapter-label" style="text-align:left">Adapter:</label>
|
|
<select id="net-adapter"></select>
|
|
</div>
|
|
|
|
<label>Username:</label>
|
|
<div class="cred-row">
|
|
<input type="text" id="admin-user" value="user" class="input-md" autocomplete="off">
|
|
<span class="field-warn" id="admin-user-warn"></span>
|
|
</div>
|
|
|
|
<label>Password:</label>
|
|
<div class="cred-row">
|
|
<input type="password" id="admin-pass" value="test123">
|
|
<label>Confirm:</label>
|
|
<input type="password" id="admin-confirm" value="test123">
|
|
<span class="toggle-pass" onmousedown="showPassword()" onmouseup="hidePassword()" onmouseleave="hidePassword()">👁</span>
|
|
<span class="field-warn" id="admin-pass-warn"></span>
|
|
</div>
|
|
|
|
<label>Options:</label>
|
|
<div class="form-row">
|
|
<label class="win-only" title="Disables Secure Boot — required for test-signed VDD driver"><input type="checkbox" id="test-mode" checked> Test Mode</label>
|
|
<label title="Exposes the VM's sshd on a host-loopback port, tunnelled over vsock"><input type="checkbox" id="ssh-enabled"> SSH Server</label>
|
|
</div>
|
|
</div>
|
|
<div class="modal-buttons">
|
|
<button onclick="closeCreateModal()">Cancel</button>
|
|
<button id="btn-create-template" class="win-only" disabled onclick="onCreateTemplate()">Build Template</button>
|
|
<button id="btn-create" class="primary" disabled onclick="onCreateVm()">Create Sandbox</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Confirm modal -->
|
|
<div class="modal-overlay" id="modal-overlay">
|
|
<div class="modal">
|
|
<h3 id="modal-title">Confirm</h3>
|
|
<p id="modal-message"></p>
|
|
<label style="display:none; font-size:12px; color:var(--text-dim); cursor:pointer; margin-bottom:8px;">
|
|
<input type="checkbox" id="modal-dont-show"> Don't show this again
|
|
</label>
|
|
<div id="modal-input-row" style="display:none; margin-bottom:12px;">
|
|
<label style="font-size:12px; color:var(--text-dim);" id="modal-input-label">Name:</label>
|
|
<input type="text" id="modal-input" style="width:100%; margin-top:4px;">
|
|
</div>
|
|
<div class="modal-buttons">
|
|
<button onclick="modalResolve(false)">Cancel</button>
|
|
<button class="danger" onclick="modalResolve(true)" id="modal-confirm-btn">Delete</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|