mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-02-14 13:12:41 +00:00
feat: wasm zero
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
argbFromHex,
|
||||
themeFromSourceColor,
|
||||
} from "@material/material-color-utilities";
|
||||
import { canAutoConnect } from "$lib/serial/device";
|
||||
import { canAutoConnect, getViablePorts } from "$lib/serial/device";
|
||||
import { initSerial } from "$lib/serial/connection";
|
||||
import type { LayoutData } from "./$types";
|
||||
import { browser } from "$app/environment";
|
||||
@@ -63,7 +63,8 @@
|
||||
}
|
||||
|
||||
if (browser && $userPreferences.autoConnect && (await canAutoConnect())) {
|
||||
await initSerial();
|
||||
const [port] = await getViablePorts();
|
||||
await initSerial(port!, true);
|
||||
}
|
||||
|
||||
if (data.importFile) {
|
||||
|
||||
144
src/routes/(app)/ConnectPopup.svelte
Normal file
144
src/routes/(app)/ConnectPopup.svelte
Normal file
@@ -0,0 +1,144 @@
|
||||
<script lang="ts">
|
||||
import LL from "$i18n/i18n-svelte";
|
||||
import { preference } from "$lib/preferences";
|
||||
import { initSerial } from "$lib/serial/connection";
|
||||
import {
|
||||
getPortName,
|
||||
PORT_FILTERS,
|
||||
type SerialPortLike,
|
||||
} from "$lib/serial/device";
|
||||
import { showConnectionFailedDialog } from "$lib/dialogs/connection-failed-dialog";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
let ports = $state<SerialPort[]>([]);
|
||||
|
||||
onMount(() => {
|
||||
refreshPorts();
|
||||
});
|
||||
|
||||
async function refreshPorts() {
|
||||
ports = await navigator.serial.getPorts();
|
||||
}
|
||||
|
||||
async function connect(port: SerialPortLike, withSync: boolean) {
|
||||
try {
|
||||
await initSerial(port, withSync);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
await showConnectionFailedDialog(String(error));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="device-list">
|
||||
<fieldset>
|
||||
<label
|
||||
><input type="checkbox" use:preference={"autoConnect"} />
|
||||
<div class="title">{$LL.deviceManager.AUTO_CONNECT()}</div>
|
||||
</label>
|
||||
|
||||
<label
|
||||
><input type="checkbox" use:preference={"backup"} />
|
||||
<div class="title">{@html $LL.backup.AUTO_BACKUP()}</div>
|
||||
</label>
|
||||
</fieldset>
|
||||
<button
|
||||
onclick={async (event) => {
|
||||
const { fetchCCOS } = await import("$lib/ccos/ccos");
|
||||
const ccos = await fetchCCOS();
|
||||
if (ccos) {
|
||||
connect(ccos, !event.shiftKey);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span class="icon">history</span>
|
||||
CC0</button
|
||||
>
|
||||
{#each ports as port}
|
||||
<div class="device">
|
||||
<button
|
||||
onclick={(event) => {
|
||||
connect(port, !event.shiftKey);
|
||||
}}
|
||||
>
|
||||
<span class="icon">history</span>
|
||||
{getPortName(port)}</button
|
||||
>
|
||||
<button
|
||||
class="error"
|
||||
onclick={() => {
|
||||
port.forget();
|
||||
refreshPorts();
|
||||
}}><span class="icon">link_off</span></button
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="pair">
|
||||
<button
|
||||
onclick={async (event) => {
|
||||
const port = await navigator.serial.requestPort({
|
||||
filters: event.shiftKey ? [] : [...PORT_FILTERS.values()],
|
||||
});
|
||||
if (!port) return;
|
||||
refreshPorts();
|
||||
connect(port, true);
|
||||
}}
|
||||
class="primary"><span class="icon">add</span>Pair</button
|
||||
>
|
||||
<a href="/ccos/zero_wasm/"><span class="icon">add</span>Virtual Device</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
button,
|
||||
a {
|
||||
padding: 10px;
|
||||
height: 32px;
|
||||
font-size: 12px;
|
||||
|
||||
.icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.pair {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.device {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
button {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
button.error {
|
||||
color: var(--md-sys-color-error);
|
||||
}
|
||||
|
||||
label {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
|
||||
.title {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
fieldset {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -7,16 +7,14 @@
|
||||
import { detectLocale, locales } from "$i18n/i18n-util";
|
||||
import { loadLocaleAsync } from "$i18n/i18n-util.async";
|
||||
import { tick } from "svelte";
|
||||
import SyncOverlay from "./SyncOverlay.svelte";
|
||||
import {
|
||||
initSerial,
|
||||
serialPort,
|
||||
sync,
|
||||
syncProgress,
|
||||
syncStatus,
|
||||
} from "$lib/serial/connection";
|
||||
import { fade, slide } from "svelte/transition";
|
||||
import { showConnectionFailedDialog } from "$lib/dialogs/connection-failed-dialog";
|
||||
import ConnectPopup from "./ConnectPopup.svelte";
|
||||
|
||||
let locale = $state(
|
||||
(browser && (localStorage.getItem("locale") as Locales)) || detectLocale(),
|
||||
@@ -48,20 +46,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function connect() {
|
||||
try {
|
||||
await initSerial(true);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
await showConnectionFailedDialog(String(error));
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect(event: MouseEvent) {
|
||||
if (event.shiftKey) {
|
||||
sync();
|
||||
} else {
|
||||
$serialPort?.forget();
|
||||
$serialPort?.close();
|
||||
$serialPort = undefined;
|
||||
}
|
||||
}
|
||||
@@ -90,9 +79,15 @@
|
||||
</ul>
|
||||
<div class="sync-box">
|
||||
{#if !$serialPort}
|
||||
<button class="warning" onclick={connect} transition:slide={{ axis: "x" }}
|
||||
<button
|
||||
class="warning"
|
||||
popovertarget="connect-popup"
|
||||
transition:slide={{ axis: "x" }}
|
||||
><span class="icon">usb</span>{$LL.deviceManager.CONNECT()}</button
|
||||
>
|
||||
<div popover id="connect-popup">
|
||||
<ConnectPopup />
|
||||
</div>
|
||||
{:else}
|
||||
<button
|
||||
transition:slide={{ axis: "x" }}
|
||||
|
||||
@@ -72,7 +72,8 @@
|
||||
|
||||
async function connect() {
|
||||
try {
|
||||
await initSerial(true, false);
|
||||
const port = await navigator.serial.requestPort();
|
||||
await initSerial(port!, true);
|
||||
step = 1;
|
||||
} catch (e) {
|
||||
error = e as Error;
|
||||
@@ -197,6 +198,10 @@
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
{#if data.meta.update.js && data.meta.update.wasm}
|
||||
<button>Add Virtual Device</button>
|
||||
{/if}
|
||||
|
||||
{#if data.meta.update.ota && !data.meta.device.endsWith("m0")}
|
||||
{@const buttonError = error || (!success && isCorrectDevice === false)}
|
||||
<section>
|
||||
@@ -260,47 +265,49 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<section>
|
||||
<ol>
|
||||
<li>
|
||||
<button class="inline-button" onclick={connect}
|
||||
><span class="icon">usb</span>Connect</button
|
||||
>
|
||||
your device
|
||||
{#if step >= 1}
|
||||
<span class="icon ok" transition:fade>check_circle</span>
|
||||
{/if}
|
||||
</li>
|
||||
{#if data.meta.update.uf2}
|
||||
<section>
|
||||
<ol>
|
||||
<li>
|
||||
<button class="inline-button" onclick={connect}
|
||||
><span class="icon">usb</span>Connect</button
|
||||
>
|
||||
your device
|
||||
{#if step >= 1}
|
||||
<span class="icon ok" transition:fade>check_circle</span>
|
||||
{/if}
|
||||
</li>
|
||||
|
||||
<li class:faded={step < 1}>
|
||||
Make a <button class="inline-button" onclick={backup}
|
||||
><span class="icon">download</span>Backup</button
|
||||
>
|
||||
{#if step >= 2}
|
||||
<span class="icon ok" transition:fade>check_circle</span>
|
||||
{/if}
|
||||
</li>
|
||||
<li class:faded={step < 1}>
|
||||
Make a <button class="inline-button" onclick={backup}
|
||||
><span class="icon">download</span>Backup</button
|
||||
>
|
||||
{#if step >= 2}
|
||||
<span class="icon ok" transition:fade>check_circle</span>
|
||||
{/if}
|
||||
</li>
|
||||
|
||||
<li class:faded={step < 2}>
|
||||
Reboot to <button class="inline-button" onclick={bootloader}
|
||||
><span class="icon">restart_alt</span>Bootloader</button
|
||||
>
|
||||
{#if step >= 3}
|
||||
<span class="icon ok" transition:fade>check_circle</span>
|
||||
{/if}
|
||||
</li>
|
||||
<li class:faded={step < 2}>
|
||||
Reboot to <button class="inline-button" onclick={bootloader}
|
||||
><span class="icon">restart_alt</span>Bootloader</button
|
||||
>
|
||||
{#if step >= 3}
|
||||
<span class="icon ok" transition:fade>check_circle</span>
|
||||
{/if}
|
||||
</li>
|
||||
|
||||
<li class:faded={step < 3}>
|
||||
Replace <button class="inline-button" onclick={getFileSystem}
|
||||
><span class="icon">deployed_code_update</span>CURRENT.UF2</button
|
||||
>
|
||||
on the new drive
|
||||
{#if step >= 4}
|
||||
<span class="icon ok" transition:fade>check_circle</span>
|
||||
{/if}
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
<li class:faded={step < 3}>
|
||||
Replace <button class="inline-button" onclick={getFileSystem}
|
||||
><span class="icon">deployed_code_update</span>CURRENT.UF2</button
|
||||
>
|
||||
on the new drive
|
||||
{#if step >= 4}
|
||||
<span class="icon ok" transition:fade>check_circle</span>
|
||||
{/if}
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
{#if false && data.meta.update.esptool}
|
||||
<section>
|
||||
|
||||
@@ -321,7 +321,7 @@
|
||||
><td></td><td></td></tr
|
||||
>
|
||||
{/if}
|
||||
{#each $items.slice(page * $pageSize - (page === 0 ? 0 : 1), (page + 1) * $pageSize - 1) as [chord] (JSON.stringify(chord?.id))}
|
||||
{#each $items.slice(page * $pageSize - (page === 0 ? 0 : 1), (page + 1) * $pageSize - 1) as [chord]}
|
||||
{#if chord}
|
||||
<ChordEdit {chord} onduplicate={() => (page = 0)} />
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user