mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2025-12-11 13:26:16 +00:00
@@ -1,497 +0,0 @@
|
||||
s + Dup,say
|
||||
y + b,by
|
||||
y + Dup,why
|
||||
n + Dup,no
|
||||
n + f,find
|
||||
l + f,life
|
||||
l + p,people
|
||||
l + s + p,spell
|
||||
l + n,line
|
||||
l + n + p,plant
|
||||
t + h,that
|
||||
t + n + h,than
|
||||
t + n + p,plant
|
||||
t + l + f,left
|
||||
a + f,after
|
||||
a + d,add
|
||||
a + d + f,had
|
||||
a + h,has
|
||||
a + s,as
|
||||
a + s + h,has
|
||||
a + y + d,day
|
||||
a + y + s,say
|
||||
a + n,an
|
||||
a + n + d,and
|
||||
a + n + d + f,hand
|
||||
a + n + h,hand
|
||||
a + n + y,any
|
||||
a + l,all
|
||||
a + l + d,land
|
||||
a + l + p,plant
|
||||
a + l + s,last
|
||||
a + l + y + p,play
|
||||
a + l + n + d,land
|
||||
a + t,at
|
||||
a + t + h,that
|
||||
a + t + n + h,than
|
||||
a + t + l + s,last
|
||||
a + t + l + n + p,plant
|
||||
- + ?,question
|
||||
w + h,who
|
||||
w + s,saw
|
||||
w + y + h,why
|
||||
w + t,without
|
||||
w + t + h,watch
|
||||
w + t + n,went
|
||||
w + a,was
|
||||
w + a + h,what
|
||||
w + a + s,saw
|
||||
w + a + y,way
|
||||
w + a + y + Dup,away
|
||||
w + a + n,want
|
||||
w + a + l + f,walk
|
||||
w + a + l + y,always
|
||||
w + a + l + y + s,always
|
||||
w + a + t,watch
|
||||
w + a + t + h,watch
|
||||
w + a + t + n,want
|
||||
g + b,begin
|
||||
g + Dup,question
|
||||
g + h,here
|
||||
g + p,page
|
||||
g + l + n,long
|
||||
g + t,get
|
||||
k + q,quick
|
||||
k + f,and
|
||||
k + l + y + q,quickly
|
||||
k + t + l,talk
|
||||
k + a + b,back
|
||||
k + a + s,ask
|
||||
k + a + t + l,talk
|
||||
k + w + a + l,walk
|
||||
m + f,form
|
||||
m + y,my
|
||||
m + t + Dup,mountain
|
||||
m + a + f,family
|
||||
m + a + s,small
|
||||
m + a + y,may
|
||||
m + a + n,man
|
||||
m + a + n + y,many
|
||||
m + a + l,almost
|
||||
m + a + l + s,small
|
||||
m + a + l + s + Dup,small
|
||||
c + b,because
|
||||
c + Dup,sea
|
||||
c + h,head
|
||||
c + a + n,can
|
||||
c + a + n + h,change
|
||||
c + a + l,call
|
||||
c + a + l + p,place
|
||||
c + k + a + b,back
|
||||
u + p,us
|
||||
u + y,you
|
||||
u + j,just
|
||||
u + j + s,just
|
||||
u + t + b,but
|
||||
u + t + p,put
|
||||
u + t + s + d,study
|
||||
u + t + n,until
|
||||
u + t + j + s,just
|
||||
u + a + l,last
|
||||
u + k + q,quick
|
||||
u + k + l + y + q,quickly
|
||||
u + m + h,much
|
||||
u + m + n,number
|
||||
u + m + t + s,must
|
||||
u + m + c + h,much
|
||||
u + c + s + h,such
|
||||
u + c + t,cut
|
||||
u + c + t + n,country
|
||||
' + a + s,say
|
||||
' + a + n,any
|
||||
' + m + a + n,many
|
||||
o + Dup,off
|
||||
o + f,of
|
||||
o + f + f,food
|
||||
o + d,do
|
||||
o + s,so
|
||||
o + y + b,boy
|
||||
o + n,on
|
||||
o + n + s + Dup,soon
|
||||
o + l,line
|
||||
o + l + Dup,oil
|
||||
o + l + d,old
|
||||
o + l + y,only
|
||||
o + l + n + y,only
|
||||
o + t,to
|
||||
o + t + b,both
|
||||
o + t + Dup,too
|
||||
o + t + s,stop
|
||||
o + t + s + p,stop
|
||||
o + t + n,not
|
||||
o + t + n + f,often
|
||||
o + t + n + d,don't
|
||||
o + t + n + p,point
|
||||
o + a + n + h,another
|
||||
o + a + l,also
|
||||
o + a + l + s,also
|
||||
o + w,own
|
||||
o + w + h,how
|
||||
o + w + s + h,show
|
||||
o + w + n,now
|
||||
o + w + n + d,down
|
||||
o + w + l + f,follow
|
||||
o + w + t,two
|
||||
o + g,go
|
||||
o + g + Dup,good
|
||||
o + g + n + s,song
|
||||
o + g + l + n,long
|
||||
o + g + t,got
|
||||
o + g + a + l,along
|
||||
o + g + a + l + n,along
|
||||
o + k + b,book
|
||||
o + k + n,know
|
||||
o + k + l,look
|
||||
o + k + t,took
|
||||
o + k + t + Dup,took
|
||||
o + k + w + n,know
|
||||
o + v + a + b,above
|
||||
o + v + k,move
|
||||
o + m + s,some
|
||||
o + m + t + s,most
|
||||
o + m + a + l,almost
|
||||
o + m + a + l + s,almost
|
||||
o + m + a + t + l + s,almost
|
||||
o + c + f,food
|
||||
o + c + l + s + h,school
|
||||
o + u,our
|
||||
o + u + f,four
|
||||
o + u + s + h,should
|
||||
o + u + y,you
|
||||
o + u + n + f,found
|
||||
o + u + n + f + f,found
|
||||
o + u + n + s,sound
|
||||
o + u + n + s + d,sound
|
||||
o + u + l + s + d + f,should
|
||||
o + u + l + s + h,should
|
||||
o + u + t,out
|
||||
o + u + a + b,about
|
||||
o + u + a + t + b,about
|
||||
o + u + w + l + d,would
|
||||
o + u + g + n + y,young
|
||||
o + u + g + t + h,thought
|
||||
o + u + m + t + n,mountain
|
||||
o + u + m + t + n + Dup,mountain
|
||||
o + u + c + l + d,could
|
||||
o + ' + t + n + d,don't
|
||||
o + o + l,oil
|
||||
o + o + t + n,into
|
||||
o + o + t + n + p,point
|
||||
o + o + u + w + t + h,without
|
||||
o + o + u + m + a + t + n,mountain
|
||||
i + f,if
|
||||
i + f + f,different
|
||||
i + d,did
|
||||
i + RH_Thumb_1_Center,different
|
||||
i + s,is
|
||||
i + s + d,side
|
||||
i + s + h,his
|
||||
i + n,in
|
||||
i + n + f + f,find
|
||||
i + l,list
|
||||
i + l + n,line
|
||||
i + t,it
|
||||
i + t + s + Dup,still
|
||||
i + t + s + h,this
|
||||
i + t + n,into
|
||||
i + t + l + s,list
|
||||
i + t + l + s + Dup,still
|
||||
i + a + s,said
|
||||
i + a + s + d,said
|
||||
i + a + n,animal
|
||||
i + w + h,which
|
||||
i + w + h + Dup,which
|
||||
i + w + l,will
|
||||
i + w + l + Dup,will
|
||||
i + w + l + h,while
|
||||
i + w + t + h,with
|
||||
i + g,give
|
||||
i + g + b,big
|
||||
i + g + h,high
|
||||
i + g + n + h,night
|
||||
i + g + l + h,light
|
||||
i + g + t + n + h,thing
|
||||
i + g + t + l + h,light
|
||||
i + g + a + n,again
|
||||
i + g + a + n + Dup,again
|
||||
i + k + n + d,kind
|
||||
i + k + l,like
|
||||
i + k + t + n + h,think
|
||||
i + v + l,live
|
||||
i + m + h,him
|
||||
i + m + p,important
|
||||
i + m + s,miss
|
||||
i + m + s + Dup,miss
|
||||
i + m + l,mile
|
||||
i + m + t,time
|
||||
i + m + t + h,might
|
||||
i + m + a + n,animal
|
||||
i + m + a + n + Dup,animal
|
||||
i + m + a + l + n,another
|
||||
i + m + g + t + h,might
|
||||
i + c + p,picture
|
||||
i + c + t + y,city
|
||||
i + u + t + l + n,until
|
||||
i + u + w + t + h,without
|
||||
i + u + k + q,quick
|
||||
i + u + k + l + y + q,quickly
|
||||
i + u + c + k + q,quick
|
||||
i + u + c + k + l + y + q,quickly
|
||||
i + ' + t,it's
|
||||
i + ' + t + s,it's
|
||||
e + b,be
|
||||
e + Dup,earth
|
||||
e + x,example
|
||||
e + f + b,before
|
||||
e + h,he
|
||||
e + h + Dup,here
|
||||
e + s,state
|
||||
e + s + Dup,see
|
||||
e + s + h,she
|
||||
e + y + Dup,eye
|
||||
e + n,name
|
||||
e + n + b,been
|
||||
e + n + Dup,need
|
||||
e + n + d,end
|
||||
e + l + h,help
|
||||
e + l + h + f,help
|
||||
e + l + s + p,spell
|
||||
e + t,the
|
||||
e + t + Dup,eat
|
||||
e + t + f,feet
|
||||
e + t + h,there
|
||||
e + t + s,set
|
||||
e + t + s + h,these
|
||||
e + t + y + h,they
|
||||
e + t + n + x,next
|
||||
e + t + n + h,then
|
||||
e + t + l,let
|
||||
e + t + l + Dup,tell
|
||||
e + t + l + f,left
|
||||
e + a,at
|
||||
e + a + f,father
|
||||
e + a + d + f,head
|
||||
e + a + h,hear
|
||||
e + a + p,paper
|
||||
e + a + s,sea
|
||||
e + a + y,year
|
||||
e + a + n,name
|
||||
e + a + t,eat
|
||||
e + a + t + s + Dup,state
|
||||
e + w,we
|
||||
e + w + f,few
|
||||
e + w + n,new
|
||||
e + w + n + h,when
|
||||
e + w + l,well
|
||||
e + w + l + Dup,well
|
||||
e + w + t + b,between
|
||||
e + w + t + n,went
|
||||
e + w + t + n + b,between
|
||||
e + g + h,here
|
||||
e + g + t,get
|
||||
e + g + a + p,page
|
||||
e + g + a + n + b,began
|
||||
e + k,keep
|
||||
e + k + p,keep
|
||||
e + k + t,take
|
||||
e + k + a + t,take
|
||||
e + v + y,every
|
||||
e + v + n,even
|
||||
e + v + a + h,have
|
||||
e + v + a + l,leave
|
||||
e + v + a + l + Dup,leave
|
||||
e + m,me
|
||||
e + m + s,seem
|
||||
e + m + s + Dup,seem
|
||||
e + m + n,men
|
||||
e + m + t + h,them
|
||||
e + m + a,make
|
||||
e + m + a + d,made
|
||||
e + m + a + s,same
|
||||
e + m + a + n,mean
|
||||
e + m + a + l + p + x,example
|
||||
e + m + c + a,came
|
||||
e + c + s,second
|
||||
e + c + t + n + s,sentence
|
||||
e + c + a,came
|
||||
e + c + a + f,face
|
||||
e + c + a + h,each
|
||||
e + c + a + l + p,place
|
||||
e + LH_Thumb_1_Center + a,make
|
||||
e + u + s,use
|
||||
e + u + s + q,question
|
||||
e + u + n + d,under
|
||||
e + u + t + q,quite
|
||||
e + u + c + a + s + b,because
|
||||
e + o + p,open
|
||||
e + o + s + d,does
|
||||
e + o + n,one
|
||||
e + o + n + p,open
|
||||
e + o + l + b,below
|
||||
e + o + l + h,hello
|
||||
e + o + l + h + Dup,hello
|
||||
e + o + l + p,people
|
||||
e + o + t + f,often
|
||||
e + o + t + h,other
|
||||
e + o + t + s + h,those
|
||||
e + o + t + n + f,often
|
||||
e + o + w + l + b,below
|
||||
e + o + g + t + h,together
|
||||
e + o + v,over
|
||||
e + o + v + a + b,above
|
||||
e + o + v + k,move
|
||||
e + o + m,move
|
||||
e + o + m + h,home
|
||||
e + o + m + s,some
|
||||
e + o + m + t + s,sometime
|
||||
e + o + m + t + s + h,something
|
||||
e + o + m + g + t + n + s + h,something
|
||||
e + o + m + c,come
|
||||
e + o + c,come
|
||||
e + o + c + n,once
|
||||
e + o + c + n + s + d,second
|
||||
e + o + c + l + s,close
|
||||
e + o + u + s + h,house
|
||||
e + o + u + n,enough
|
||||
e + o + u + g + n + h,enough
|
||||
e + i + s + d,side
|
||||
e + i + l + f,life
|
||||
e + i + l + n,line
|
||||
e + i + t + q,quite
|
||||
e + i + t + l,little
|
||||
e + i + t + l + Dup,little
|
||||
e + i + a + d,idea
|
||||
e + i + w + l + h,while
|
||||
e + i + w + t + h,white
|
||||
e + i + g,give
|
||||
e + i + g + p,give
|
||||
e + i + g + n + b,begin
|
||||
e + i + k + l,like
|
||||
e + i + v + l,live
|
||||
e + i + m + l,mile
|
||||
e + i + m + t,time
|
||||
e + i + u + t + q,quite
|
||||
e + i + u + u + t + n + s + q,question
|
||||
r + e + h,her
|
||||
r + e + t + Dup,tree
|
||||
r + e + t + h,there
|
||||
r + e + t + h + Dup,three
|
||||
r + e + t + l,letter
|
||||
r + e + a,are
|
||||
r + e + a + d,read
|
||||
r + e + a + h,hear
|
||||
r + e + a + p,paper
|
||||
r + e + a + n,near
|
||||
r + e + a + l + y,really
|
||||
r + e + a + l + y + Dup,really
|
||||
r + e + a + t + f,after
|
||||
r + e + a + t + h,earth
|
||||
r + e + a + t + RH_Thumb_1_Center,father
|
||||
r + e + a + t + l,learn
|
||||
r + e + w,were
|
||||
r + e + w + Dup,were
|
||||
r + e + w + h,where
|
||||
r + e + w + a + n + s,answer
|
||||
r + e + w + a + t,water
|
||||
r + e + g + h,here
|
||||
r + e + g + a + l,large
|
||||
r + e + g + a + t,great
|
||||
r + e + v + y,very
|
||||
r + e + v + y + Dup,every
|
||||
r + e + v + n,never
|
||||
r + e + u + n + d,under
|
||||
r + e + u + m + n + b,number
|
||||
r + e + o + f + b,before
|
||||
r + e + o + t + h,other
|
||||
r + e + o + g + t + h,together
|
||||
r + e + o + v,over
|
||||
r + e + o + m,more
|
||||
r + e + o + m + t + h,mother
|
||||
r + e + i + t + h,their
|
||||
r + e + i + t + n + f + f,different
|
||||
r + e + i + v,river
|
||||
r + e + i + c + l + d + f,children
|
||||
r + e + i + u + c + t + p,picture
|
||||
r + f,for
|
||||
r + h,her
|
||||
r + y,your
|
||||
r + n,near
|
||||
r + l,learn
|
||||
r + t + Dup,tree
|
||||
r + t + f,father
|
||||
r + t + s + Dup,start
|
||||
r + t + y,try
|
||||
r + t + l,letter
|
||||
r + t + l + Dup,letter
|
||||
r + a,are
|
||||
r + a + f,far
|
||||
r + a + d,read
|
||||
r + a + d + f,hard
|
||||
r + a + h,hard
|
||||
r + a + p,part
|
||||
r + a + l + y,really
|
||||
r + a + l + y + Dup,really
|
||||
r + a + t + p,part
|
||||
r + a + t + s + Dup,start
|
||||
r + w,were
|
||||
r + w + h,where
|
||||
r + w + t,water
|
||||
r + w + a + n + s,answer
|
||||
r + g + t,great
|
||||
r + g + a + l,large
|
||||
r + v + y,very
|
||||
r + v + n,never
|
||||
r + v + l,later
|
||||
r + m + f,form
|
||||
r + c + a,car
|
||||
r + c + a + y,carry
|
||||
r + c + a + y + Dup,carry
|
||||
r + u + n,run
|
||||
r + u + t + h,through
|
||||
r + u + t + n,turn
|
||||
r + ' + t + s,story
|
||||
r + o,or
|
||||
r + o + f,for
|
||||
r + o + t + y + s,story
|
||||
r + o + a + n + h,another
|
||||
r + o + w,work
|
||||
r + o + w + d,word
|
||||
r + o + w + l + d,world
|
||||
r + o + g,grow
|
||||
r + o + LeftDoubleClick,grow
|
||||
r + o + k + w,work
|
||||
r + o + m,more
|
||||
r + o + m + f,from
|
||||
r + o + m + t + h,mother
|
||||
r + o + u,our
|
||||
r + o + u + f,four
|
||||
r + o + u + y,your
|
||||
r + o + u + a,around
|
||||
r + o + u + a + n,around
|
||||
r + o + u + a + n + d,around
|
||||
r + o + u + g,group
|
||||
r + o + u + g + p,group
|
||||
r + o + u + g + t + h,through
|
||||
r + o + u + c + t + n,country
|
||||
r + o + u + c + t + n + y,country
|
||||
r + i + t + h,their
|
||||
r + i + t + s + f,first
|
||||
r + i + a,air
|
||||
r + i + w + t,write
|
||||
r + i + g + h,right
|
||||
r + i + g + l,girl
|
||||
r + i + g + t + h,right
|
||||
r + i + v,river
|
||||
r + i + v + Dup,river
|
||||
r + i + m + t + n + p,important
|
||||
r + i + c + l + h,children
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
let info = $derived(
|
||||
typeof action === "number"
|
||||
? (KEYMAP_CODES.get(action) ?? { code: action })
|
||||
? ($KEYMAP_CODES.get(action) ?? { code: action })
|
||||
: action,
|
||||
);
|
||||
let dynamicMapping = $derived(info.keyCode && $osLayout.get(info.keyCode));
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
$props();
|
||||
|
||||
let key = $derived(
|
||||
(typeof id === "number" ? KEYMAP_CODES.get(id) ?? id : id) as
|
||||
(typeof id === "number" ? ($KEYMAP_CODES.get(id) ?? id) : id) as
|
||||
| number
|
||||
| KeyInfo,
|
||||
);
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
KEYMAP_CATEGORIES,
|
||||
KEYMAP_CODES,
|
||||
KEYMAP_IDS,
|
||||
type KeyInfo,
|
||||
} from "$lib/serial/keymap-codes";
|
||||
import FlexSearch from "flexsearch";
|
||||
import { onMount } from "svelte";
|
||||
import ActionListItem from "$lib/components/ActionListItem.svelte";
|
||||
import LL from "$i18n/i18n-svelte";
|
||||
import { action } from "$lib/title";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
let {
|
||||
currentAction = undefined,
|
||||
@@ -27,10 +29,13 @@
|
||||
});
|
||||
|
||||
const index = new FlexSearch.Index({ tokenize: "full" });
|
||||
createIndex();
|
||||
|
||||
async function createIndex() {
|
||||
for (const [, action] of KEYMAP_CODES) {
|
||||
$effect(() => {
|
||||
createIndex($KEYMAP_CODES);
|
||||
});
|
||||
|
||||
async function createIndex(codes: Map<number, KeyInfo>) {
|
||||
for (const [, action] of codes) {
|
||||
await index?.addAsync(
|
||||
action.code,
|
||||
`${action.title || ""} ${action.variant || ""} ${action.category} ${action.id || ""} ${
|
||||
@@ -42,7 +47,7 @@
|
||||
|
||||
async function search() {
|
||||
results = (await index!.searchAsync(searchBox.value)) as number[];
|
||||
exact = KEYMAP_IDS.get(searchBox.value)?.code;
|
||||
exact = get(KEYMAP_IDS).get(searchBox.value)?.code;
|
||||
code = Number(searchBox.value);
|
||||
}
|
||||
|
||||
@@ -127,7 +132,7 @@
|
||||
bind:group={filter}
|
||||
/></label
|
||||
>
|
||||
{#each KEYMAP_CATEGORIES as category}
|
||||
{#each $KEYMAP_CATEGORIES as category}
|
||||
<label
|
||||
>{category.name}<input
|
||||
name="category"
|
||||
@@ -167,7 +172,7 @@
|
||||
{#if filter !== undefined || results.length > 0}
|
||||
{@const resultValue =
|
||||
results.length === 0
|
||||
? Array.from(KEYMAP_CODES, ([it]) => it)
|
||||
? Array.from($KEYMAP_CODES, ([it]) => it)
|
||||
: results}
|
||||
{#each filter ? resultValue.filter( (it) => filter.has(it), ) : resultValue as id (id)}
|
||||
<li><ActionListItem {id} onclick={() => select(id)} /></li>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
isApplied: true,
|
||||
}}
|
||||
{@const { code, icon, id, display, title, keyCode, variant } =
|
||||
KEYMAP_CODES.get(actionId) ?? { code: actionId }}
|
||||
$KEYMAP_CODES.get(actionId) ?? { code: actionId }}
|
||||
{@const dynamicMapping = keyCode && $osLayout.get(keyCode)}
|
||||
{@const tooltip =
|
||||
(title ?? id ?? `0x${code.toString(16)}`) +
|
||||
|
||||
132
src/lib/meta/meta-storage.ts
Normal file
132
src/lib/meta/meta-storage.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import type { RawVersionMeta, VersionMeta } from "./types/meta";
|
||||
import type { Listing } from "./types/listing";
|
||||
import type { KeymapCategory } from "./types/actions";
|
||||
import { browser } from "$app/environment";
|
||||
|
||||
let lock: Promise<void> | undefined = undefined;
|
||||
|
||||
export async function getMeta(
|
||||
device: string,
|
||||
version: string,
|
||||
fetch: typeof window.fetch = window.fetch,
|
||||
): Promise<VersionMeta | undefined> {
|
||||
while (lock) await lock;
|
||||
let resolveLock!: () => void;
|
||||
lock = new Promise((resolve) => (resolveLock = resolve));
|
||||
|
||||
try {
|
||||
if (!browser) return fetchMeta(device, version, fetch);
|
||||
|
||||
const dbRequest = indexedDB.open("version-meta", 1);
|
||||
const db = await new Promise<IDBDatabase>((resolve, reject) => {
|
||||
dbRequest.onsuccess = () => resolve(dbRequest.result);
|
||||
dbRequest.onerror = () => reject(dbRequest.error);
|
||||
dbRequest.onupgradeneeded = () => {
|
||||
const db = dbRequest.result;
|
||||
db.createObjectStore("meta", { keyPath: ["device", "version"] });
|
||||
};
|
||||
});
|
||||
|
||||
try {
|
||||
const readTransaction = db.transaction(["meta"], "readonly");
|
||||
const store = readTransaction.objectStore("meta");
|
||||
const itemRequest = store.get([device, version]);
|
||||
const item = await new Promise<VersionMeta | undefined>((resolve) => {
|
||||
itemRequest.onsuccess = () => resolve(itemRequest.result);
|
||||
itemRequest.onerror = () => resolve(undefined);
|
||||
});
|
||||
|
||||
if (item) return item;
|
||||
|
||||
const meta = await fetchMeta(device, version);
|
||||
if (!meta) return undefined;
|
||||
|
||||
const putTransaction = db.transaction(["meta"], "readwrite");
|
||||
const putStore = putTransaction.objectStore("meta");
|
||||
const putRequest = putStore.put(meta);
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
putRequest.onsuccess = () => resolve();
|
||||
putRequest.onerror = () => reject(putRequest.error);
|
||||
});
|
||||
putTransaction.commit();
|
||||
|
||||
return meta;
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
resolveLock();
|
||||
lock = undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async function fetchMeta(
|
||||
device: string,
|
||||
version: string,
|
||||
fetch: typeof window.fetch = window.fetch,
|
||||
): Promise<VersionMeta> {
|
||||
const path = `${import.meta.env.VITE_FIRMWARE_URL}/${device}/${version}`;
|
||||
const files: Listing[] = await fetch(`${path}/`).then((res) => res.json());
|
||||
const meta: Partial<RawVersionMeta> | undefined = files.some(
|
||||
(entry) => entry.type === "file" && entry.name === "meta.json",
|
||||
)
|
||||
? await fetch(`${path}/meta.json`).then((res) => res.json())
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
version: meta?.version ?? version,
|
||||
device: meta?.target ?? device,
|
||||
date: new Date(meta?.git_date ?? files[0]?.mtime ?? ""),
|
||||
path,
|
||||
commit: meta?.git_commit ?? undefined,
|
||||
dirty: meta?.git_is_dirty ?? false,
|
||||
public: meta?.public_build ?? !version.includes("+"),
|
||||
developmentBuild: (meta?.development_mode ?? 0) === 1,
|
||||
factoryDefaults: meta?.factory_defaults
|
||||
? {
|
||||
layout: await fetch(`${path}/${meta.factory_defaults.layout}`).then(
|
||||
(it) => it.json(),
|
||||
),
|
||||
settings: await fetch(
|
||||
`${path}/${meta.factory_defaults.settings}`,
|
||||
).then((it) => it.json()),
|
||||
chords: Object.fromEntries(
|
||||
await Promise.all(
|
||||
Object.entries(meta.factory_defaults.chords).map(
|
||||
async ([name, file]) => [
|
||||
name,
|
||||
await fetch(`${path}/${file}`).then((it) => it.json()),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
}
|
||||
: undefined,
|
||||
actions: await (meta?.actions
|
||||
? fetch(`${path}/${meta.actions}`).then((it) => it.json())
|
||||
: Promise.all<KeymapCategory[]>(
|
||||
Object.values(import.meta.glob("$lib/assets/keymaps/*.yml")).map(
|
||||
async (load) => load().then((it) => (it as any).default),
|
||||
),
|
||||
)),
|
||||
update: {
|
||||
uf2:
|
||||
meta?.update?.uf2 ??
|
||||
files.find(
|
||||
(entry) => entry.type === "file" && entry.name === "CURRENT.UF2",
|
||||
)?.name ??
|
||||
undefined,
|
||||
ota:
|
||||
meta?.update?.ota ??
|
||||
files.find(
|
||||
(entry) => entry.type === "file" && entry.name === "firmware.bin",
|
||||
)?.name ??
|
||||
undefined,
|
||||
esptool: meta?.update?.esptool ?? undefined,
|
||||
},
|
||||
spiFlash: meta?.spi_flash ?? undefined,
|
||||
};
|
||||
}
|
||||
19
src/lib/meta/types/actions.ts
Normal file
19
src/lib/meta/types/actions.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export interface KeymapCategory {
|
||||
name: string;
|
||||
description: string;
|
||||
icon?: string;
|
||||
display?: string;
|
||||
type?: "unassigned";
|
||||
actions: Record<number, Partial<ActionInfo>>;
|
||||
}
|
||||
|
||||
export interface ActionInfo {
|
||||
id: string;
|
||||
title: string;
|
||||
icon: string;
|
||||
display: string;
|
||||
description: string;
|
||||
variant: "left" | "right";
|
||||
variantOf: number;
|
||||
keyCode: string;
|
||||
}
|
||||
@@ -1,4 +1,11 @@
|
||||
export interface VersionMeta {
|
||||
import type {
|
||||
CharaChordFile,
|
||||
CharaLayoutFile,
|
||||
CharaSettingsFile,
|
||||
} from "$lib/share/chara-file";
|
||||
import type { KeymapCategory } from "./actions";
|
||||
|
||||
export interface RawVersionMeta {
|
||||
version: string;
|
||||
target: string;
|
||||
git_commit: string;
|
||||
@@ -6,6 +13,12 @@ export interface VersionMeta {
|
||||
git_date: string;
|
||||
public_build: boolean;
|
||||
development_mode: number;
|
||||
actions: string;
|
||||
factory_defaults: {
|
||||
layout: string;
|
||||
settings: string;
|
||||
chords: Record<string, string>;
|
||||
};
|
||||
update: {
|
||||
ota: string | null;
|
||||
uf2: string | null;
|
||||
@@ -15,6 +28,29 @@ export interface VersionMeta {
|
||||
spi_flash: SPIFlashInfo | null;
|
||||
}
|
||||
|
||||
export interface VersionMeta {
|
||||
version: string;
|
||||
device: string;
|
||||
path: string;
|
||||
date: Date;
|
||||
public: boolean;
|
||||
commit?: string;
|
||||
dirty: boolean;
|
||||
developmentBuild: boolean;
|
||||
actions: KeymapCategory[];
|
||||
factoryDefaults?: {
|
||||
layout: CharaLayoutFile;
|
||||
settings: CharaSettingsFile;
|
||||
chords: Record<string, CharaChordFile>;
|
||||
};
|
||||
update: {
|
||||
ota?: string;
|
||||
uf2?: string;
|
||||
esptool?: EspToolData;
|
||||
};
|
||||
spiFlash?: SPIFlashInfo;
|
||||
}
|
||||
|
||||
export interface SPIFlashInfo {
|
||||
type: string;
|
||||
size: string;
|
||||
@@ -6,6 +6,8 @@ import type { CharaLayout } from "$lib/serialization/layout";
|
||||
import { persistentWritable } from "$lib/storage";
|
||||
import { userPreferences } from "$lib/preferences";
|
||||
import settingInfo from "$lib/assets/settings.yml";
|
||||
import { getMeta } from "$lib/meta/meta-storage";
|
||||
import type { VersionMeta } from "$lib/meta/types/meta";
|
||||
|
||||
export const serialPort = writable<CharaDevice | undefined>();
|
||||
|
||||
@@ -47,6 +49,8 @@ export const syncStatus: Writable<
|
||||
"done" | "error" | "downloading" | "uploading"
|
||||
> = writable("done");
|
||||
|
||||
export const deviceMeta = writable<VersionMeta | undefined>(undefined);
|
||||
|
||||
export interface ProgressInfo {
|
||||
max: number;
|
||||
current: number;
|
||||
@@ -65,6 +69,12 @@ export async function initSerial(manual = false, withSync = true) {
|
||||
export async function sync() {
|
||||
const device = get(serialPort);
|
||||
if (!device) return;
|
||||
getMeta(
|
||||
`${device.device}_${device.chipset}`.toLowerCase(),
|
||||
device.version.toString(),
|
||||
).then((meta) => {
|
||||
deviceMeta.set(meta);
|
||||
});
|
||||
const chordCount = await device.getChordCount();
|
||||
syncStatus.set("downloading");
|
||||
|
||||
|
||||
@@ -1,38 +1,64 @@
|
||||
import type { ActionInfo, KeymapCategory } from "$lib/assets/keymaps/keymap";
|
||||
import { derived, type Readable } from "svelte/store";
|
||||
import { deviceMeta } from "./connection";
|
||||
|
||||
export interface KeyInfo extends Partial<ActionInfo> {
|
||||
code: number;
|
||||
category?: KeymapCategory;
|
||||
}
|
||||
|
||||
export const KEYMAP_CATEGORIES = (await Promise.all(
|
||||
const fallbackActions = await Promise.all<KeymapCategory>(
|
||||
Object.values(import.meta.glob("$lib/assets/keymaps/*.yml")).map(
|
||||
async (load) => load().then((it) => (it as any).default),
|
||||
),
|
||||
)) as KeymapCategory[];
|
||||
|
||||
export const KEYMAP_CODES = new Map<number, KeyInfo>(
|
||||
KEYMAP_CATEGORIES.flatMap((category) =>
|
||||
Object.entries(category.actions).map(([code, action]) => [
|
||||
Number(code),
|
||||
{ ...action, code: Number(code), category },
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
||||
export const KEYMAP_KEYCODES = new Map<string, number>(
|
||||
KEYMAP_CATEGORIES.flatMap((category) =>
|
||||
Object.entries(category.actions).map(
|
||||
([code, action]) => [action.keyCode!, Number(code)] as const,
|
||||
export let KEYMAP_CATEGORIES: Readable<KeymapCategory[]> = derived(
|
||||
deviceMeta,
|
||||
(deviceMeta) => deviceMeta?.actions ?? fallbackActions,
|
||||
);
|
||||
|
||||
export const KEYMAP_CODES: Readable<Map<number, KeyInfo>> = derived(
|
||||
KEYMAP_CATEGORIES,
|
||||
(categories) =>
|
||||
new Map<number, KeyInfo>(
|
||||
categories.flatMap((category) =>
|
||||
Object.entries(category.actions).map(([code, action]) => [
|
||||
Number(code),
|
||||
{ ...action, code: Number(code), category },
|
||||
]),
|
||||
),
|
||||
),
|
||||
).filter(([keyCode]) => keyCode !== undefined),
|
||||
);
|
||||
|
||||
export const KEYMAP_IDS = new Map<string, KeyInfo>(
|
||||
KEYMAP_CATEGORIES.flatMap((category) =>
|
||||
Object.entries(category.actions).map(
|
||||
([code, action]) =>
|
||||
[action.id!, { ...action, code: Number(code), category }] as const,
|
||||
export const KEYMAP_KEYCODES: Readable<Map<string, number>> = derived(
|
||||
KEYMAP_CATEGORIES,
|
||||
(categories) =>
|
||||
new Map<string, number>(
|
||||
categories
|
||||
.flatMap((category) =>
|
||||
Object.entries(category.actions).map(
|
||||
([code, action]) => [action.keyCode!, Number(code)] as const,
|
||||
),
|
||||
)
|
||||
.filter(([keyCode]) => keyCode !== undefined),
|
||||
),
|
||||
);
|
||||
|
||||
export const KEYMAP_IDS: Readable<Map<string, KeyInfo>> = derived(
|
||||
KEYMAP_CATEGORIES,
|
||||
(categories) =>
|
||||
new Map<string, KeyInfo>(
|
||||
categories
|
||||
.flatMap((category) =>
|
||||
Object.entries(category.actions).map(
|
||||
([code, action]) =>
|
||||
[
|
||||
action.id!,
|
||||
{ ...action, code: Number(code), category },
|
||||
] as const,
|
||||
),
|
||||
)
|
||||
.filter(([id]) => id !== undefined),
|
||||
),
|
||||
).filter(([id]) => id !== undefined),
|
||||
);
|
||||
|
||||
@@ -107,57 +107,61 @@ export type ChordInfo = Chord &
|
||||
id: number[];
|
||||
deleted: boolean;
|
||||
};
|
||||
export const chords = derived([overlay, deviceChords], ([overlay, chords]) => {
|
||||
const newChords = new Set(overlay.chords.keys());
|
||||
export const chords = derived(
|
||||
[overlay, deviceChords, KEYMAP_CODES],
|
||||
([overlay, chords, codes]) => {
|
||||
const newChords = new Set(overlay.chords.keys());
|
||||
|
||||
const changedChords = chords.map<ChordInfo>((chord) => {
|
||||
const id = JSON.stringify(chord.actions);
|
||||
if (overlay.chords.has(id)) {
|
||||
newChords.delete(id);
|
||||
const changedChord = overlay.chords.get(id)!;
|
||||
return {
|
||||
id: chord.actions,
|
||||
// use the old phrase for stable editing
|
||||
sortBy: chord.phrase.map((it) => KEYMAP_CODES.get(it)?.id ?? it).join(),
|
||||
actions: changedChord.actions,
|
||||
phrase: changedChord.phrase,
|
||||
actionsChanged: id !== JSON.stringify(changedChord.actions),
|
||||
phraseChanged:
|
||||
JSON.stringify(chord.phrase) !== JSON.stringify(changedChord.phrase),
|
||||
isApplied: false,
|
||||
deleted: changedChord.deleted,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
id: chord.actions,
|
||||
sortBy: chord.phrase.map((it) => KEYMAP_CODES.get(it)?.id ?? it).join(),
|
||||
actions: chord.actions,
|
||||
phrase: chord.phrase,
|
||||
phraseChanged: false,
|
||||
actionsChanged: false,
|
||||
isApplied: true,
|
||||
deleted: false,
|
||||
};
|
||||
}
|
||||
});
|
||||
for (const id of newChords) {
|
||||
const chord = overlay.chords.get(id)!;
|
||||
changedChords.push({
|
||||
sortBy: "",
|
||||
isApplied: false,
|
||||
actionsChanged: true,
|
||||
phraseChanged: false,
|
||||
deleted: chord.deleted,
|
||||
id: JSON.parse(id),
|
||||
phrase: chord.phrase,
|
||||
actions: chord.actions,
|
||||
const changedChords = chords.map<ChordInfo>((chord) => {
|
||||
const id = JSON.stringify(chord.actions);
|
||||
if (overlay.chords.has(id)) {
|
||||
newChords.delete(id);
|
||||
const changedChord = overlay.chords.get(id)!;
|
||||
return {
|
||||
id: chord.actions,
|
||||
// use the old phrase for stable editing
|
||||
sortBy: chord.phrase.map((it) => codes.get(it)?.id ?? it).join(),
|
||||
actions: changedChord.actions,
|
||||
phrase: changedChord.phrase,
|
||||
actionsChanged: id !== JSON.stringify(changedChord.actions),
|
||||
phraseChanged:
|
||||
JSON.stringify(chord.phrase) !==
|
||||
JSON.stringify(changedChord.phrase),
|
||||
isApplied: false,
|
||||
deleted: changedChord.deleted,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
id: chord.actions,
|
||||
sortBy: chord.phrase.map((it) => codes.get(it)?.id ?? it).join(),
|
||||
actions: chord.actions,
|
||||
phrase: chord.phrase,
|
||||
phraseChanged: false,
|
||||
actionsChanged: false,
|
||||
isApplied: true,
|
||||
deleted: false,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
for (const id of newChords) {
|
||||
const chord = overlay.chords.get(id)!;
|
||||
changedChords.push({
|
||||
sortBy: "",
|
||||
isApplied: false,
|
||||
actionsChanged: true,
|
||||
phraseChanged: false,
|
||||
deleted: chord.deleted,
|
||||
id: JSON.parse(id),
|
||||
phrase: chord.phrase,
|
||||
actions: chord.actions,
|
||||
});
|
||||
}
|
||||
|
||||
return changedChords.sort(({ sortBy: a }, { sortBy: b }) =>
|
||||
a.localeCompare(b),
|
||||
);
|
||||
});
|
||||
return changedChords.sort(({ sortBy: a }, { sortBy: b }) =>
|
||||
a.localeCompare(b),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export const chordHashes = derived(
|
||||
chords,
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"CHARACHORDER ONE M0": {
|
||||
"latest": "1.1.3",
|
||||
"next": null
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { PageLoad } from "./$types";
|
||||
import type { DirectoryListing } from "./listing";
|
||||
import type { DirectoryListing } from "$lib/meta/types/listing";
|
||||
|
||||
export const load = (async ({ fetch }) => {
|
||||
const result = await fetch(import.meta.env.VITE_FIRMWARE_URL);
|
||||
const result = await fetch(`${import.meta.env.VITE_FIRMWARE_URL}/`);
|
||||
const data = await result.json();
|
||||
|
||||
return { devices: data as DirectoryListing[] };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { PageLoad } from "./$types";
|
||||
import type { DirectoryListing } from "../listing";
|
||||
import type { DirectoryListing } from "$lib/meta/types/listing";
|
||||
|
||||
export const load = (async ({ fetch, params }) => {
|
||||
const result = await fetch(
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
$serialPort = undefined;
|
||||
try {
|
||||
const file = await fetch(
|
||||
`${data.meta.path}/${data.meta.update.ota?.name}`,
|
||||
`${data.meta.path}/${data.meta.update.ota}`,
|
||||
).then((it) => it.blob());
|
||||
|
||||
await port.updateFirmware(file);
|
||||
@@ -46,7 +46,7 @@
|
||||
: undefined,
|
||||
);
|
||||
let isCorrectDevice = $derived(
|
||||
currentDevice ? currentDevice === data.meta.target : undefined,
|
||||
currentDevice ? currentDevice === data.meta.device : undefined,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -84,11 +84,11 @@
|
||||
|
||||
async function getFileSystem() {
|
||||
if (!data.meta.update.uf2) return;
|
||||
const uf2Promise = fetch(
|
||||
`${data.meta.path}/${data.meta.update.uf2.name}`,
|
||||
).then((it) => it.blob());
|
||||
const uf2Promise = fetch(`${data.meta.path}/${data.meta.update.uf2}`).then(
|
||||
(it) => it.blob(),
|
||||
);
|
||||
const handle = await window.showSaveFilePicker({
|
||||
id: `${data.meta.target}-update`,
|
||||
id: `${data.meta.device}-update`,
|
||||
suggestedName: "CURRENT.UF2",
|
||||
excludeAcceptAllOption: true,
|
||||
types: [
|
||||
@@ -172,7 +172,7 @@
|
||||
const port = await navigator.serial.requestPort();
|
||||
try {
|
||||
console.log(data.meta);
|
||||
const spiFlash = data.meta.spi_flash!;
|
||||
const spiFlash = data.meta.spiFlash!;
|
||||
espLoader = await connectEsp(port);
|
||||
|
||||
/*espLoader.flashSpiAttach(
|
||||
@@ -189,7 +189,7 @@
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
{#if data.meta.update.ota && !data.meta.target.endsWith("m0")}
|
||||
{#if data.meta.update.ota && !data.meta.device.endsWith("m0")}
|
||||
{@const buttonError = error || (!success && isCorrectDevice === false)}
|
||||
<section>
|
||||
<button
|
||||
|
||||
@@ -1,50 +1,14 @@
|
||||
import type { PageLoad } from "./$types";
|
||||
import type { FileListing, Listing } from "../../listing";
|
||||
import type { VersionMeta } from "$lib/meta";
|
||||
import { getMeta } from "$lib/meta/meta-storage";
|
||||
import { error } from "@sveltejs/kit";
|
||||
|
||||
export const load = (async ({ fetch, params }) => {
|
||||
const result = await fetch(
|
||||
`${import.meta.env.VITE_FIRMWARE_URL}/${params.device}/${params.version}/`,
|
||||
);
|
||||
const data: Listing[] = await result.json();
|
||||
const meta: VersionMeta | undefined = data.some(
|
||||
(entry) => entry.type === "file" && entry.name === "meta.json",
|
||||
)
|
||||
? await fetch(
|
||||
`${import.meta.env.VITE_FIRMWARE_URL}/${params.device}/${params.version}/meta.json`,
|
||||
).then((res) => res.json())
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
meta: {
|
||||
version: meta?.version ?? params.version,
|
||||
target: meta?.target ?? params.device,
|
||||
path: `${import.meta.env.VITE_FIRMWARE_URL}${params.device}/${params.version}`,
|
||||
git_commit: meta?.git_commit ?? "",
|
||||
git_is_dirty: meta?.git_is_dirty ?? false,
|
||||
git_date: meta?.git_date ?? data[0]?.mtime ?? "",
|
||||
public_build: meta?.public_build ?? !params.version.includes("+"),
|
||||
development_mode: meta?.development_mode ?? 0,
|
||||
update: {
|
||||
uf2:
|
||||
(data.find(
|
||||
(entry) =>
|
||||
entry.type === "file" &&
|
||||
entry.name === (meta?.update?.uf2 ?? "CURRENT.UF2"),
|
||||
) as FileListing) ?? undefined,
|
||||
ota:
|
||||
data.find(
|
||||
(entry) =>
|
||||
entry.type === "file" &&
|
||||
entry.name === (meta?.update?.ota ?? "firmware.bin"),
|
||||
) ?? undefined,
|
||||
esptool: meta?.update?.esptool ?? undefined,
|
||||
},
|
||||
files: data.filter(
|
||||
(entry) =>
|
||||
entry.type === "file" && (!meta?.files || entry.name in meta.files),
|
||||
) as FileListing[],
|
||||
spi_flash: meta?.spi_flash ?? undefined,
|
||||
},
|
||||
};
|
||||
const meta = await getMeta(params.device, params.version, fetch);
|
||||
if (meta === undefined) {
|
||||
error(
|
||||
404,
|
||||
`The version ${params.version} for device ${params.device} does not exist.`,
|
||||
);
|
||||
}
|
||||
return { meta };
|
||||
}) satisfies PageLoad;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { initMatrixClient, isLoggedIn, matrix } from "$lib/chat/chat";
|
||||
import { initMatrixClient, isLoggedIn, matrix } from "$lib/chat/chat-rx";
|
||||
import { flip } from "svelte/animate";
|
||||
import { slide } from "svelte/transition";
|
||||
import Login from "./Login.svelte";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { KEYMAP_CODES } from "$lib/serial/keymap-codes";
|
||||
import { KEYMAP_CODES, type KeyInfo } from "$lib/serial/keymap-codes";
|
||||
import FlexSearch from "flexsearch";
|
||||
import LL from "$i18n/i18n-svelte";
|
||||
import { action } from "$lib/title";
|
||||
@@ -40,16 +40,21 @@
|
||||
$effect(() => {
|
||||
abortIndexing?.();
|
||||
progress = 0;
|
||||
buildIndex($chords, $osLayout).then(searchIndex.set);
|
||||
buildIndex($chords, $osLayout, $KEYMAP_CODES).then(searchIndex.set);
|
||||
});
|
||||
|
||||
function encodeChord(chord: ChordInfo, osLayout: Map<string, string>, onlyPhrase: boolean = false) {
|
||||
function encodeChord(
|
||||
chord: ChordInfo,
|
||||
osLayout: Map<string, string>,
|
||||
codes: Map<number, KeyInfo>,
|
||||
onlyPhrase: boolean = false,
|
||||
) {
|
||||
const plainPhrase: string[] = [""];
|
||||
const extraActions: string[] = [];
|
||||
const extraCodes: string[] = [];
|
||||
|
||||
for (const actionCode of chord.phrase ?? []) {
|
||||
const action = KEYMAP_CODES.get(actionCode);
|
||||
const action = codes.get(actionCode);
|
||||
if (!action) {
|
||||
extraCodes.push(`0x${actionCode.toString(16)}`);
|
||||
continue;
|
||||
@@ -96,7 +101,7 @@
|
||||
const input = chord.actions
|
||||
.slice(chord.actions.lastIndexOf(0) + 1)
|
||||
.map((it) => {
|
||||
const info = KEYMAP_CODES.get(it);
|
||||
const info = codes.get(it);
|
||||
if (!info) return `0x${it.toString(16)}`;
|
||||
const osCode = info.keyCode && osLayout.get(info.keyCode);
|
||||
const result = osCode?.length === 1 ? osCode : info.id;
|
||||
@@ -118,6 +123,7 @@
|
||||
async function buildIndex(
|
||||
chords: ChordInfo[],
|
||||
osLayout: Map<string, string>,
|
||||
codes: Map<number, KeyInfo>,
|
||||
): Promise<FlexSearch.Index> {
|
||||
if (chords.length === 0 || !browser) return index;
|
||||
index = new FlexSearch.Index({
|
||||
@@ -148,7 +154,7 @@
|
||||
progress = i;
|
||||
|
||||
if ("phrase" in chord) {
|
||||
await index.addAsync(i, encodeChord(chord, osLayout));
|
||||
await index.addAsync(i, encodeChord(chord, osLayout, codes));
|
||||
}
|
||||
}
|
||||
return index;
|
||||
@@ -186,7 +192,9 @@
|
||||
function downloadVocabulary() {
|
||||
const vocabulary = new Set(
|
||||
$chords.map((it) =>
|
||||
"phrase" in it ? encodeChord(it, $osLayout, true).trim() : "",
|
||||
"phrase" in it
|
||||
? encodeChord(it, $osLayout, $KEYMAP_CODES, true).trim()
|
||||
: "",
|
||||
),
|
||||
);
|
||||
vocabulary.delete("");
|
||||
|
||||
@@ -23,7 +23,7 @@ process.env["VITE_LEARN_URL"] = "https://www.iq-eq.io/";
|
||||
process.env["VITE_LATEST_FIRMWARE"] = "1.1.4";
|
||||
process.env["VITE_STORE_URL"] = "https://www.charachorder.com/";
|
||||
process.env["VITE_MATRIX_URL"] = "https://charachorder.io/";
|
||||
process.env["VITE_FIRMWARE_URL"] = "https://charachorder.io/firmware/";
|
||||
process.env["VITE_FIRMWARE_URL"] = "https://charachorder.io/firmware";
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
|
||||
Reference in New Issue
Block a user