mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-22 01:42:47 +00:00
migrate to typescript
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import {serialPort, syncing} from "$lib/serial/connection.js"
|
import {serialPort, syncing} from "$lib/serial/connection"
|
||||||
import {browser} from "$app/environment"
|
import {browser} from "$app/environment"
|
||||||
import {page} from "$app/stores"
|
import {page} from "$app/stores"
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,43 +1,32 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
import {layout} from "$lib/serial/connection.js"
|
import {layout} from "$lib/serial/connection"
|
||||||
import {KEYMAP_CODES} from "$lib/serial/keymap-codes.js"
|
import type {CharaLayout} from "$lib/serial/connection"
|
||||||
|
import {KEYMAP_CODES} from "$lib/serial/keymap-codes"
|
||||||
|
import type {KeyInfo} from "$lib/serial/keymap-codes"
|
||||||
|
|
||||||
export let activeLayer = 0
|
export let activeLayer = 0
|
||||||
|
export let keys: Record<"d" | "n" | "w" | "e", number>
|
||||||
/** @type {{d: number, n: number, w: number, e: number, s: number}} */
|
export let type: "primary" | "secondary" | "tertiary" = "primary"
|
||||||
export let keys
|
|
||||||
|
|
||||||
/** @type {'primary' | 'secondary' | 'tertiary'} */
|
|
||||||
export let type = "primary"
|
|
||||||
|
|
||||||
const layerNames = ["Primary Layer", "Number Layer", "Function Layer"]
|
const layerNames = ["Primary Layer", "Number Layer", "Function Layer"]
|
||||||
|
|
||||||
const virtualLayerMap = [1, 0, 2]
|
const virtualLayerMap = [1, 0, 2]
|
||||||
const characterOffset = 8
|
const characterOffset = 8
|
||||||
|
|
||||||
function offsetDistance(quadrant, layer, activeLayer) {
|
function offsetDistance(quadrant: number, layer: number, activeLayer: number): number {
|
||||||
const layerOffsetIndex = virtualLayerMap[layer] - virtualLayerMap[activeLayer]
|
const layerOffsetIndex = virtualLayerMap[layer] - virtualLayerMap[activeLayer]
|
||||||
const layerOffset = quadrant > 2 ? -characterOffset : characterOffset
|
const layerOffset = quadrant > 2 ? -characterOffset : characterOffset
|
||||||
return 25 * quadrant + layerOffsetIndex * layerOffset
|
return 25 * quadrant + layerOffsetIndex * layerOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function getKeyDescriptions(keys: KeyInfo[]): string {
|
||||||
* @param keys {import('$lib/serial/keymap.js').KeyInfo[]}
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
function getKeyDescriptions(keys) {
|
|
||||||
return keys.map(({title, id, code}, i) => `${title || id || code} (${layerNames[i]})`).join("\n")
|
return keys.map(({title, id, code}, i) => `${title || id || code} (${layerNames[i]})`).join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function getActions(id: number, layout: CharaLayout): KeyInfo[] {
|
||||||
* @param id {number}
|
|
||||||
* @param layout {[number[], number[], number[]]}
|
|
||||||
* @returns import('$lib/serial/keymap.js').KeyInfo[]
|
|
||||||
*/
|
|
||||||
function getActions(id, layout) {
|
|
||||||
return Array.from({length: 3}).map((_, i) => {
|
return Array.from({length: 3}).map((_, i) => {
|
||||||
const actionId = layout?.[i][id]
|
const actionId = layout?.[i][id]
|
||||||
return actionId !== undefined ? KEYMAP_CODES[actionId] : {code: actionId}
|
return KEYMAP_CODES[actionId]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
import {serialLog, serialPort} from "$lib/serial/connection.js"
|
import {serialLog, serialPort} from "$lib/serial/connection"
|
||||||
import {slide} from "svelte/transition"
|
import {slide} from "svelte/transition"
|
||||||
|
|
||||||
/**
|
function submit(event: InputEvent) {
|
||||||
* @param event {InputEvent}
|
|
||||||
*/
|
|
||||||
function submit(event) {
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
$serialPort.send(value.trim())
|
$serialPort.send(value.trim())
|
||||||
value = ""
|
value = ""
|
||||||
io.scrollTo({top: io.scrollHeight})
|
io.scrollTo({top: io.scrollHeight})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {string} */
|
let value: string
|
||||||
let value
|
let io: HTMLDivElement
|
||||||
|
|
||||||
/** @type {HTMLDivElement} */
|
|
||||||
let io
|
|
||||||
|
|
||||||
export let resizable = false
|
export let resizable = false
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export const Icon = {
|
|
||||||
close: 0xe5cd,
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,26 @@
|
|||||||
import {writable} from "svelte/store"
|
import {writable} from "svelte/store"
|
||||||
import {CharaDevice} from "$lib/serial/device.js"
|
import {CharaDevice} from "$lib/serial/device"
|
||||||
|
|
||||||
/** @type {import('svelte/store').Writable<import('./device.js').CharaDevice>} */
|
export const serialPort = writable<CharaDevice>()
|
||||||
export const serialPort = writable()
|
|
||||||
|
|
||||||
/** @type {import('svelte/store').Writable<Array<{type: 'input' | 'output' | 'system'; value: string}>>} */
|
export interface SerialLogEntry {
|
||||||
export const serialLog = writable([])
|
type: "input" | "output" | "system"
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {import('svelte/store').Writable<Array<{actions: number[]; phrase: string}>>} */
|
export const serialLog = writable<SerialLogEntry[]>([])
|
||||||
export const chords = writable([])
|
|
||||||
|
|
||||||
/** @type {import('svelte/store').Writable<[number[], number[], number[]]>} */
|
export interface Chord {
|
||||||
export const layout = writable([[], [], []])
|
actions: number[]
|
||||||
|
phrase: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const chords = writable<Chord[]>([])
|
||||||
|
|
||||||
|
export type CharaLayout = [number[], number[], number[]]
|
||||||
|
|
||||||
|
export const layout = writable<CharaLayout>([[], [], []])
|
||||||
|
|
||||||
/** @type {import('svelte/store').Writable<boolean>} */
|
|
||||||
export const syncing = writable(false)
|
export const syncing = writable(false)
|
||||||
|
|
||||||
/** @type {CharaDevice} */
|
/** @type {CharaDevice} */
|
||||||
@@ -24,7 +31,7 @@ export async function initSerial() {
|
|||||||
device ??= new CharaDevice()
|
device ??= new CharaDevice()
|
||||||
serialPort.set(device)
|
serialPort.set(device)
|
||||||
|
|
||||||
const parsedLayout = [[], [], []]
|
const parsedLayout: CharaLayout = [[], [], []]
|
||||||
for (let layer = 1; layer <= 3; layer++) {
|
for (let layer = 1; layer <= 3; layer++) {
|
||||||
for (let i = 0; i < 90; i++) {
|
for (let i = 0; i < 90; i++) {
|
||||||
parsedLayout[layer - 1][i] = await device.getLayoutKey(layer, i)
|
parsedLayout[layer - 1][i] = await device.getLayoutKey(layer, i)
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import {LineBreakTransformer} from "$lib/serial/line-break-transformer.js"
|
import {LineBreakTransformer} from "$lib/serial/line-break-transformer"
|
||||||
import {serialLog} from "$lib/serial/connection.js"
|
import {serialLog} from "$lib/serial/connection"
|
||||||
|
import type {Chord} from "$lib/serial/connection"
|
||||||
|
|
||||||
export const VENDOR_ID = 0x239a
|
export const VENDOR_ID = 0x239a
|
||||||
|
|
||||||
@@ -11,29 +12,22 @@ export async function hasSerialPermission() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class CharaDevice {
|
export class CharaDevice {
|
||||||
/** @type {Promise<SerialPort>} */
|
private readonly port: Promise<SerialPort>
|
||||||
#port
|
private readonly reader: Promise<ReadableStreamDefaultReader<string>>
|
||||||
/** @type {Promise<ReadableStreamDefaultReader<string>>} */
|
|
||||||
#reader
|
|
||||||
|
|
||||||
#encoder = new TextEncoder()
|
private readonly abortController1 = new AbortController()
|
||||||
|
private readonly abortController2 = new AbortController()
|
||||||
|
|
||||||
#abortController1 = new AbortController()
|
private lock?: Promise<true>
|
||||||
#abortController2 = new AbortController()
|
|
||||||
|
|
||||||
/** @type {Promise<true> | undefined} */
|
version: Promise<string>
|
||||||
#lock
|
deviceId: Promise<string>
|
||||||
|
|
||||||
/** @type {Promise<string>} */
|
|
||||||
version
|
|
||||||
/** @type {Promise<string>} */
|
|
||||||
deviceId
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param baudRate
|
* @param baudRate
|
||||||
*/
|
*/
|
||||||
constructor(baudRate = 115200) {
|
constructor(baudRate = 115200) {
|
||||||
this.#port = navigator.serial.getPorts().then(async ports => {
|
this.port = navigator.serial.getPorts().then(async ports => {
|
||||||
const port =
|
const port =
|
||||||
ports.find(it => it.getInfo().usbVendorId === VENDOR_ID) ??
|
ports.find(it => it.getInfo().usbVendorId === VENDOR_ID) ??
|
||||||
(await navigator.serial.requestPort({filters: [{usbVendorId: VENDOR_ID}]}))
|
(await navigator.serial.requestPort({filters: [{usbVendorId: VENDOR_ID}]}))
|
||||||
@@ -42,7 +36,7 @@ export class CharaDevice {
|
|||||||
serialLog.update(it => {
|
serialLog.update(it => {
|
||||||
it.push({
|
it.push({
|
||||||
type: "system",
|
type: "system",
|
||||||
value: `Connected; ID: 0x${info.usbProductId.toString(16)}; Vendor: 0x${info.usbVendorId.toString(
|
value: `Connected; ID: 0x${info.usbProductId?.toString(16)}; Vendor: 0x${info.usbVendorId?.toString(
|
||||||
16,
|
16,
|
||||||
)}`,
|
)}`,
|
||||||
})
|
})
|
||||||
@@ -50,29 +44,27 @@ export class CharaDevice {
|
|||||||
})
|
})
|
||||||
return port
|
return port
|
||||||
})
|
})
|
||||||
this.#reader = this.#port.then(async port => {
|
this.reader = this.port.then(async port => {
|
||||||
const decoderStream = new TextDecoderStream()
|
const decoderStream = new TextDecoderStream()
|
||||||
void port.readable.pipeTo(decoderStream.writable, {signal: this.#abortController1.signal})
|
void port.readable!.pipeTo(decoderStream.writable, {signal: this.abortController1.signal})
|
||||||
|
|
||||||
return decoderStream.readable
|
return decoderStream
|
||||||
.pipeThrough(new TransformStream(new LineBreakTransformer()), {signal: this.#abortController2.signal})
|
.readable!.pipeThrough(new TransformStream(new LineBreakTransformer()), {
|
||||||
|
signal: this.abortController2.signal,
|
||||||
|
})
|
||||||
.getReader()
|
.getReader()
|
||||||
})
|
})
|
||||||
this.#lock = this.#reader.then(() => {
|
this.lock = this.reader.then(() => {
|
||||||
this.#lock = undefined
|
delete this.lock
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
this.version = this.send("VERSION")
|
this.version = this.send("VERSION")
|
||||||
this.deviceId = this.send("ID")
|
this.deviceId = this.send("ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private async internalRead() {
|
||||||
* @returns {Promise<string>}
|
return this.reader.then(async it => {
|
||||||
*/
|
const result: string = await it.read().then(({value}) => value!)
|
||||||
async #read() {
|
|
||||||
return this.#reader.then(async it => {
|
|
||||||
/** @type {string} */
|
|
||||||
const result = await it.read().then(({value}) => value)
|
|
||||||
serialLog.update(it => {
|
serialLog.update(it => {
|
||||||
it.push({
|
it.push({
|
||||||
type: "output",
|
type: "output",
|
||||||
@@ -86,12 +78,10 @@ export class CharaDevice {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a command to the device
|
* Send a command to the device
|
||||||
* @param command {string}
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
*/
|
||||||
async #send(...command) {
|
private async internalSend(...command: string[]) {
|
||||||
const port = await this.#port
|
const port = await this.port
|
||||||
const writer = port.writable.getWriter()
|
const writer = port.writable!.getWriter()
|
||||||
try {
|
try {
|
||||||
serialLog.update(it => {
|
serialLog.update(it => {
|
||||||
it.push({
|
it.push({
|
||||||
@@ -108,35 +98,32 @@ export class CharaDevice {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Read/write to serial port
|
* Read/write to serial port
|
||||||
* @template T
|
|
||||||
* @param callback {(send: (...commands: string) => Promise<void>, read: () => Promise<string>) => T | Promise<T>}
|
|
||||||
* @returns Promise<T>
|
|
||||||
*/
|
*/
|
||||||
async runWith(callback) {
|
async runWith<T>(
|
||||||
while (this.#lock) {
|
callback: (send: typeof this.internalSend, read: typeof this.internalRead) => T | Promise<T>,
|
||||||
await this.#lock
|
): Promise<T> {
|
||||||
|
while (this.lock) {
|
||||||
|
await this.lock
|
||||||
}
|
}
|
||||||
const send = this.#send.bind(this)
|
const send = this.internalSend.bind(this)
|
||||||
const read = this.#read.bind(this)
|
const read = this.internalRead.bind(this)
|
||||||
const exec = new Promise(async resolve => {
|
const exec = new Promise<T>(async resolve => {
|
||||||
let result
|
let result!: T
|
||||||
try {
|
try {
|
||||||
result = await callback(send, read)
|
result = await callback(send, read)
|
||||||
} finally {
|
} finally {
|
||||||
this.#lock = undefined
|
this.lock = undefined
|
||||||
resolve(result)
|
resolve(result)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.#lock = exec.then(() => true)
|
this.lock = exec.then(() => true)
|
||||||
return exec
|
return exec
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send to serial port
|
* Send to serial port
|
||||||
* @param command {string}
|
|
||||||
* @returns Promise<string>
|
|
||||||
*/
|
*/
|
||||||
async send(...command) {
|
async send(...command: string[]) {
|
||||||
return this.runWith(async (send, read) => {
|
return this.runWith(async (send, read) => {
|
||||||
await send(...command)
|
await send(...command)
|
||||||
const commandString = command.join(" ").replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
|
const commandString = command.join(" ").replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
|
||||||
@@ -144,20 +131,13 @@ export class CharaDevice {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async getChordCount(): Promise<number> {
|
||||||
* @returns {Promise<number>}
|
|
||||||
*/
|
|
||||||
async getChordCount() {
|
|
||||||
return Number.parseInt(await this.send("CML C0"))
|
return Number.parseInt(await this.send("CML C0"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async getChord(index: number): Promise<Chord> {
|
||||||
* @param index {number}
|
|
||||||
* @returns {Promise<{actions: number[]; phrase: string, unk: number}>}
|
|
||||||
*/
|
|
||||||
async getChord(index) {
|
|
||||||
const chord = await this.send(`CML C1 ${index}`)
|
const chord = await this.send(`CML C1 ${index}`)
|
||||||
const [keys, rawPhrase, b] = chord.split(" ")
|
const [keys, rawPhrase] = chord.split(" ")
|
||||||
let phrase = []
|
let phrase = []
|
||||||
for (let i = 0; i < rawPhrase.length; i += 2) {
|
for (let i = 0; i < rawPhrase.length; i += 2) {
|
||||||
phrase.push(Number.parseInt(rawPhrase.substring(i, i + 2), 16))
|
phrase.push(Number.parseInt(rawPhrase.substring(i, i + 2), 16))
|
||||||
@@ -175,16 +155,10 @@ export class CharaDevice {
|
|||||||
return {
|
return {
|
||||||
actions,
|
actions,
|
||||||
phrase: String.fromCodePoint(...phrase),
|
phrase: String.fromCodePoint(...phrase),
|
||||||
unk: Number(b),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async getLayoutKey(layer: number, id: number) {
|
||||||
* @param layer {number}
|
|
||||||
* @param id {number}
|
|
||||||
* @returns {Promise<number>}
|
|
||||||
*/
|
|
||||||
async getLayoutKey(layer, id) {
|
|
||||||
const layout = await this.send(`VAR B3 A${layer} ${id}`)
|
const layout = await this.send(`VAR B3 A${layer} ${id}`)
|
||||||
const [position] = layout.split(" ").map(Number)
|
const [position] = layout.split(" ").map(Number)
|
||||||
return position
|
return position
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import keymapCodes from "$lib/assets/keymap_codes.json"
|
|
||||||
import keySymbols from "$lib/assets/key-symbols.json"
|
|
||||||
|
|
||||||
/** @type {Record<number, import('./keymap.js').KeyInfo>} */
|
|
||||||
export const KEYMAP_CODES = Object.fromEntries(
|
|
||||||
keymapCodes.map(([code, charset, id, title, description]) => [
|
|
||||||
code,
|
|
||||||
{
|
|
||||||
code: Number(code),
|
|
||||||
title: title || undefined,
|
|
||||||
charset: charset || undefined,
|
|
||||||
id: id || undefined,
|
|
||||||
symbol: id ? keySymbols[id] || undefined : undefined,
|
|
||||||
description: description || undefined,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import keymapCodes from "$lib/assets/keymap_codes.json"
|
||||||
|
import keySymbols from "$lib/assets/key-symbols.json"
|
||||||
|
|
||||||
export interface KeyInfo {
|
export interface KeyInfo {
|
||||||
/**
|
/**
|
||||||
* Numeric action code
|
* Numeric action code
|
||||||
@@ -45,3 +48,17 @@ export type CharsetCategory =
|
|||||||
| "Keybard"
|
| "Keybard"
|
||||||
| "CharaChorder"
|
| "CharaChorder"
|
||||||
| "CharaChorder One"
|
| "CharaChorder One"
|
||||||
|
|
||||||
|
export const KEYMAP_CODES: Record<number, KeyInfo> = Object.fromEntries(
|
||||||
|
keymapCodes.map(([code, charset, id, title, description]) => [
|
||||||
|
code,
|
||||||
|
{
|
||||||
|
code: Number(code),
|
||||||
|
title: title || undefined,
|
||||||
|
charset: (charset || undefined) as CharsetCategory,
|
||||||
|
id: id || undefined,
|
||||||
|
symbol: id ? keySymbols[id as keyof typeof keySymbols] || undefined : undefined,
|
||||||
|
description: description || undefined,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
)
|
||||||
@@ -1,21 +1,18 @@
|
|||||||
// @ts-check
|
|
||||||
export class LineBreakTransformer {
|
export class LineBreakTransformer {
|
||||||
constructor() {
|
private chunks = ""
|
||||||
this.chunks = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
transform(chunk, controller) {
|
transform(chunk: string, controller: TransformStreamDefaultController) {
|
||||||
this.chunks += chunk
|
this.chunks += chunk
|
||||||
const lines = this.chunks.split("\r\n")
|
const lines = this.chunks.split("\r\n")
|
||||||
this.chunks = lines.pop()
|
this.chunks = lines.pop()!
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
controller.enqueue(line)
|
controller.enqueue(line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// noinspection JSUnusedGlobalSymbols
|
// noinspection JSUnusedGlobalSymbols
|
||||||
flush(controller) {
|
flush(controller: TransformStreamDefaultController) {
|
||||||
controller.enqueue(this.chunks)
|
controller.enqueue(this.chunks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import {themeBase, themeColor, themeSuccessBase} from "$lib/style/theme.server.js"
|
|
||||||
|
|
||||||
/** @type {import("./$types").LayoutServerLoad} */
|
|
||||||
export async function load() {
|
|
||||||
return {
|
|
||||||
themeSuccessBase,
|
|
||||||
themeBase,
|
|
||||||
themeColor,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8
src/routes/+layout.server.ts
Normal file
8
src/routes/+layout.server.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import {themeBase, themeColor, themeSuccessBase} from "$lib/style/theme.server"
|
||||||
|
import type {LayoutServerLoad} from "./$types"
|
||||||
|
|
||||||
|
export const load = (async () => ({
|
||||||
|
themeSuccessBase,
|
||||||
|
themeBase,
|
||||||
|
themeColor,
|
||||||
|
})) satisfies LayoutServerLoad
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
import "$lib/fonts/noto-sans-mono.scss"
|
import "$lib/fonts/noto-sans-mono.scss"
|
||||||
import "$lib/fonts/material-symbols-rounded.scss"
|
import "$lib/fonts/material-symbols-rounded.scss"
|
||||||
import {onMount} from "svelte"
|
import {onMount} from "svelte"
|
||||||
import {applyTheme, argbFromHex, themeFromSourceColor} from "@material/material-color-utilities"
|
import {applyTheme, argbFromHex, themeFromSourceColor} from "@material/material-color-utilities"
|
||||||
import Navigation from "$lib/components/Navigation.svelte"
|
import Navigation from "$lib/components/Navigation.svelte"
|
||||||
import {hasSerialPermission} from "$lib/serial/device.js"
|
import {hasSerialPermission} from "$lib/serial/device"
|
||||||
import {initSerial} from "$lib/serial/connection.js"
|
import {initSerial} from "$lib/serial/connection"
|
||||||
|
// noinspection TypeScriptCheckImport
|
||||||
import {pwaInfo} from "virtual:pwa-info"
|
import {pwaInfo} from "virtual:pwa-info"
|
||||||
|
import type {LayoutServerData} from "./$types"
|
||||||
|
import type {RegisterSWOptions} from "vite-plugin-pwa/types"
|
||||||
|
|
||||||
/** @type {import('./$types').LayoutServerData} */
|
export let data: LayoutServerData
|
||||||
export let data
|
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const theme = themeFromSourceColor(argbFromHex("#6D81C7"), [
|
const theme = themeFromSourceColor(argbFromHex("#6D81C7"), [
|
||||||
@@ -19,15 +21,14 @@
|
|||||||
applyTheme(theme, {target: document.body, dark})
|
applyTheme(theme, {target: document.body, dark})
|
||||||
|
|
||||||
if (pwaInfo) {
|
if (pwaInfo) {
|
||||||
/** @type {import('vite-plugin-pwa/types').RegisterSWOptions} */
|
// noinspection TypeScriptCheckImport
|
||||||
const swOptions = {
|
const {registerSW} = await import("virtual:pwa-register")
|
||||||
|
registerSW({
|
||||||
immediate: true,
|
immediate: true,
|
||||||
onRegisterError(error) {
|
onRegisterError(error) {
|
||||||
console.log("ServiceWorker Registration Error", error)
|
console.log("ServiceWorker Registration Error", error)
|
||||||
},
|
},
|
||||||
}
|
} satisfies RegisterSWOptions)
|
||||||
const {registerSW} = await import("virtual:pwa-register")
|
|
||||||
registerSW(swOptions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await hasSerialPermission()) await initSerial()
|
if (await hasSerialPermission()) await initSerial()
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
export const prerender = true
|
export const prerender = true
|
||||||
|
|
||||||
export const trailingSlash = "always"
|
export const trailingSlash = "always"
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import {redirect} from "@sveltejs/kit"
|
|
||||||
|
|
||||||
/** @type {import("./$types").PageLoad} */
|
|
||||||
export function load() {
|
|
||||||
throw redirect(302, "/config/")
|
|
||||||
}
|
|
||||||
6
src/routes/+page.ts
Normal file
6
src/routes/+page.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import {redirect} from "@sveltejs/kit"
|
||||||
|
import type {PageLoad} from "./$types"
|
||||||
|
|
||||||
|
export const load = (() => {
|
||||||
|
throw redirect(302, "/config/")
|
||||||
|
}) satisfies PageLoad
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import {redirect} from "@sveltejs/kit"
|
|
||||||
|
|
||||||
/** @type {import("./$types").PageLoad} */
|
|
||||||
export function load() {
|
|
||||||
throw redirect(302, "/config/chords/")
|
|
||||||
}
|
|
||||||
6
src/routes/config/+page.ts
Normal file
6
src/routes/config/+page.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import {redirect} from "@sveltejs/kit"
|
||||||
|
import type {PageLoad} from "./$types"
|
||||||
|
|
||||||
|
export const load = (() => {
|
||||||
|
throw redirect(302, "/config/chords/")
|
||||||
|
}) satisfies PageLoad
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
import {chords} from "$lib/serial/connection.js"
|
import {chords} from "$lib/serial/connection"
|
||||||
import {KEYMAP_CODES} from "$lib/serial/keymap-codes.js"
|
import {KEYMAP_CODES} from "$lib/serial/keymap-codes"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
|||||||
Reference in New Issue
Block a user