diff --git a/src/lib/components/Navigation.svelte b/src/lib/components/Navigation.svelte
index aea097fa..32f408f3 100644
--- a/src/lib/components/Navigation.svelte
+++ b/src/lib/components/Navigation.svelte
@@ -1,5 +1,5 @@
diff --git a/src/lib/components/RingInput.svelte b/src/lib/components/RingInput.svelte
index dfecea3a..be6b63e5 100644
--- a/src/lib/components/RingInput.svelte
+++ b/src/lib/components/RingInput.svelte
@@ -1,43 +1,32 @@
-
diff --git a/src/lib/components/Terminal.svelte b/src/lib/components/Terminal.svelte
index 7b0f4ddd..a52847d4 100644
--- a/src/lib/components/Terminal.svelte
+++ b/src/lib/components/Terminal.svelte
@@ -1,22 +1,16 @@
-
diff --git a/src/lib/icons.js b/src/lib/icons.js
deleted file mode 100644
index 5a42d295..00000000
--- a/src/lib/icons.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export const Icon = {
- close: 0xe5cd,
-}
diff --git a/src/lib/serial/connection.js b/src/lib/serial/connection.ts
similarity index 52%
rename from src/lib/serial/connection.js
rename to src/lib/serial/connection.ts
index 09720113..327546c7 100644
--- a/src/lib/serial/connection.js
+++ b/src/lib/serial/connection.ts
@@ -1,19 +1,26 @@
import {writable} from "svelte/store"
-import {CharaDevice} from "$lib/serial/device.js"
+import {CharaDevice} from "$lib/serial/device"
-/** @type {import('svelte/store').Writable} */
-export const serialPort = writable()
+export const serialPort = writable()
-/** @type {import('svelte/store').Writable>} */
-export const serialLog = writable([])
+export interface SerialLogEntry {
+ type: "input" | "output" | "system"
+ value: string
+}
-/** @type {import('svelte/store').Writable>} */
-export const chords = writable([])
+export const serialLog = writable([])
-/** @type {import('svelte/store').Writable<[number[], number[], number[]]>} */
-export const layout = writable([[], [], []])
+export interface Chord {
+ actions: number[]
+ phrase: string
+}
+
+export const chords = writable([])
+
+export type CharaLayout = [number[], number[], number[]]
+
+export const layout = writable([[], [], []])
-/** @type {import('svelte/store').Writable} */
export const syncing = writable(false)
/** @type {CharaDevice} */
@@ -24,7 +31,7 @@ export async function initSerial() {
device ??= new CharaDevice()
serialPort.set(device)
- const parsedLayout = [[], [], []]
+ const parsedLayout: CharaLayout = [[], [], []]
for (let layer = 1; layer <= 3; layer++) {
for (let i = 0; i < 90; i++) {
parsedLayout[layer - 1][i] = await device.getLayoutKey(layer, i)
diff --git a/src/lib/serial/device.js b/src/lib/serial/device.ts
similarity index 53%
rename from src/lib/serial/device.js
rename to src/lib/serial/device.ts
index 5cbfc1a4..4eca5c8e 100644
--- a/src/lib/serial/device.js
+++ b/src/lib/serial/device.ts
@@ -1,5 +1,6 @@
-import {LineBreakTransformer} from "$lib/serial/line-break-transformer.js"
-import {serialLog} from "$lib/serial/connection.js"
+import {LineBreakTransformer} from "$lib/serial/line-break-transformer"
+import {serialLog} from "$lib/serial/connection"
+import type {Chord} from "$lib/serial/connection"
export const VENDOR_ID = 0x239a
@@ -11,29 +12,22 @@ export async function hasSerialPermission() {
}
export class CharaDevice {
- /** @type {Promise} */
- #port
- /** @type {Promise>} */
- #reader
+ private readonly port: Promise
+ private readonly reader: Promise>
- #encoder = new TextEncoder()
+ private readonly abortController1 = new AbortController()
+ private readonly abortController2 = new AbortController()
- #abortController1 = new AbortController()
- #abortController2 = new AbortController()
+ private lock?: Promise
- /** @type {Promise | undefined} */
- #lock
-
- /** @type {Promise} */
- version
- /** @type {Promise} */
- deviceId
+ version: Promise
+ deviceId: Promise
/**
* @param baudRate
*/
constructor(baudRate = 115200) {
- this.#port = navigator.serial.getPorts().then(async ports => {
+ this.port = navigator.serial.getPorts().then(async ports => {
const port =
ports.find(it => it.getInfo().usbVendorId === VENDOR_ID) ??
(await navigator.serial.requestPort({filters: [{usbVendorId: VENDOR_ID}]}))
@@ -42,7 +36,7 @@ export class CharaDevice {
serialLog.update(it => {
it.push({
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,
)}`,
})
@@ -50,29 +44,27 @@ export class CharaDevice {
})
return port
})
- this.#reader = this.#port.then(async port => {
+ this.reader = this.port.then(async port => {
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
- .pipeThrough(new TransformStream(new LineBreakTransformer()), {signal: this.#abortController2.signal})
+ return decoderStream
+ .readable!.pipeThrough(new TransformStream(new LineBreakTransformer()), {
+ signal: this.abortController2.signal,
+ })
.getReader()
})
- this.#lock = this.#reader.then(() => {
- this.#lock = undefined
+ this.lock = this.reader.then(() => {
+ delete this.lock
return true
})
this.version = this.send("VERSION")
this.deviceId = this.send("ID")
}
- /**
- * @returns {Promise}
- */
- async #read() {
- return this.#reader.then(async it => {
- /** @type {string} */
- const result = await it.read().then(({value}) => value)
+ private async internalRead() {
+ return this.reader.then(async it => {
+ const result: string = await it.read().then(({value}) => value!)
serialLog.update(it => {
it.push({
type: "output",
@@ -86,12 +78,10 @@ export class CharaDevice {
/**
* Send a command to the device
- * @param command {string}
- * @returns {Promise}
*/
- async #send(...command) {
- const port = await this.#port
- const writer = port.writable.getWriter()
+ private async internalSend(...command: string[]) {
+ const port = await this.port
+ const writer = port.writable!.getWriter()
try {
serialLog.update(it => {
it.push({
@@ -108,35 +98,32 @@ export class CharaDevice {
/**
* Read/write to serial port
- * @template T
- * @param callback {(send: (...commands: string) => Promise, read: () => Promise) => T | Promise}
- * @returns Promise
*/
- async runWith(callback) {
- while (this.#lock) {
- await this.#lock
+ async runWith(
+ callback: (send: typeof this.internalSend, read: typeof this.internalRead) => T | Promise,
+ ): Promise {
+ while (this.lock) {
+ await this.lock
}
- const send = this.#send.bind(this)
- const read = this.#read.bind(this)
- const exec = new Promise(async resolve => {
- let result
+ const send = this.internalSend.bind(this)
+ const read = this.internalRead.bind(this)
+ const exec = new Promise(async resolve => {
+ let result!: T
try {
result = await callback(send, read)
} finally {
- this.#lock = undefined
+ this.lock = undefined
resolve(result)
}
})
- this.#lock = exec.then(() => true)
+ this.lock = exec.then(() => true)
return exec
}
/**
* Send to serial port
- * @param command {string}
- * @returns Promise
*/
- async send(...command) {
+ async send(...command: string[]) {
return this.runWith(async (send, read) => {
await send(...command)
const commandString = command.join(" ").replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
@@ -144,20 +131,13 @@ export class CharaDevice {
})
}
- /**
- * @returns {Promise}
- */
- async getChordCount() {
+ async getChordCount(): Promise {
return Number.parseInt(await this.send("CML C0"))
}
- /**
- * @param index {number}
- * @returns {Promise<{actions: number[]; phrase: string, unk: number}>}
- */
- async getChord(index) {
+ async getChord(index: number): Promise {
const chord = await this.send(`CML C1 ${index}`)
- const [keys, rawPhrase, b] = chord.split(" ")
+ const [keys, rawPhrase] = chord.split(" ")
let phrase = []
for (let i = 0; i < rawPhrase.length; i += 2) {
phrase.push(Number.parseInt(rawPhrase.substring(i, i + 2), 16))
@@ -175,16 +155,10 @@ export class CharaDevice {
return {
actions,
phrase: String.fromCodePoint(...phrase),
- unk: Number(b),
}
}
- /**
- * @param layer {number}
- * @param id {number}
- * @returns {Promise}
- */
- async getLayoutKey(layer, id) {
+ async getLayoutKey(layer: number, id: number) {
const layout = await this.send(`VAR B3 A${layer} ${id}`)
const [position] = layout.split(" ").map(Number)
return position
diff --git a/src/lib/serial/keymap-codes.js b/src/lib/serial/keymap-codes.js
deleted file mode 100644
index 2bee31a4..00000000
--- a/src/lib/serial/keymap-codes.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import keymapCodes from "$lib/assets/keymap_codes.json"
-import keySymbols from "$lib/assets/key-symbols.json"
-
-/** @type {Record} */
-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,
- },
- ]),
-)
diff --git a/src/lib/serial/keymap.d.ts b/src/lib/serial/keymap-codes.ts
similarity index 59%
rename from src/lib/serial/keymap.d.ts
rename to src/lib/serial/keymap-codes.ts
index be09db9e..5475d0fb 100644
--- a/src/lib/serial/keymap.d.ts
+++ b/src/lib/serial/keymap-codes.ts
@@ -1,3 +1,6 @@
+import keymapCodes from "$lib/assets/keymap_codes.json"
+import keySymbols from "$lib/assets/key-symbols.json"
+
export interface KeyInfo {
/**
* Numeric action code
@@ -45,3 +48,17 @@ export type CharsetCategory =
| "Keybard"
| "CharaChorder"
| "CharaChorder One"
+
+export const KEYMAP_CODES: Record = 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,
+ },
+ ]),
+)
diff --git a/src/lib/serial/line-break-transformer.js b/src/lib/serial/line-break-transformer.ts
similarity index 62%
rename from src/lib/serial/line-break-transformer.js
rename to src/lib/serial/line-break-transformer.ts
index 36c6bad7..473d447d 100644
--- a/src/lib/serial/line-break-transformer.js
+++ b/src/lib/serial/line-break-transformer.ts
@@ -1,21 +1,18 @@
-// @ts-check
export class LineBreakTransformer {
- constructor() {
- this.chunks = ""
- }
+ private chunks = ""
// noinspection JSUnusedGlobalSymbols
- transform(chunk, controller) {
+ transform(chunk: string, controller: TransformStreamDefaultController) {
this.chunks += chunk
const lines = this.chunks.split("\r\n")
- this.chunks = lines.pop()
+ this.chunks = lines.pop()!
for (const line of lines) {
controller.enqueue(line)
}
}
// noinspection JSUnusedGlobalSymbols
- flush(controller) {
+ flush(controller: TransformStreamDefaultController) {
controller.enqueue(this.chunks)
}
}
diff --git a/src/routes/+layout.server.js b/src/routes/+layout.server.js
deleted file mode 100644
index 3cf134e9..00000000
--- a/src/routes/+layout.server.js
+++ /dev/null
@@ -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,
- }
-}
diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts
new file mode 100644
index 00000000..b4fef69b
--- /dev/null
+++ b/src/routes/+layout.server.ts
@@ -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
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index ca55c790..5b52648c 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,15 +1,17 @@
-
diff --git a/jsconfig.json b/tsconfig.json
similarity index 100%
rename from jsconfig.json
rename to tsconfig.json