mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2026-01-25 19:32:41 +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(
|
let info = $derived(
|
||||||
typeof action === "number"
|
typeof action === "number"
|
||||||
? (KEYMAP_CODES.get(action) ?? { code: action })
|
? ($KEYMAP_CODES.get(action) ?? { code: action })
|
||||||
: action,
|
: action,
|
||||||
);
|
);
|
||||||
let dynamicMapping = $derived(info.keyCode && $osLayout.get(info.keyCode));
|
let dynamicMapping = $derived(info.keyCode && $osLayout.get(info.keyCode));
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
$props();
|
$props();
|
||||||
|
|
||||||
let key = $derived(
|
let key = $derived(
|
||||||
(typeof id === "number" ? KEYMAP_CODES.get(id) ?? id : id) as
|
(typeof id === "number" ? ($KEYMAP_CODES.get(id) ?? id) : id) as
|
||||||
| number
|
| number
|
||||||
| KeyInfo,
|
| KeyInfo,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,12 +3,14 @@
|
|||||||
KEYMAP_CATEGORIES,
|
KEYMAP_CATEGORIES,
|
||||||
KEYMAP_CODES,
|
KEYMAP_CODES,
|
||||||
KEYMAP_IDS,
|
KEYMAP_IDS,
|
||||||
|
type KeyInfo,
|
||||||
} from "$lib/serial/keymap-codes";
|
} from "$lib/serial/keymap-codes";
|
||||||
import FlexSearch from "flexsearch";
|
import FlexSearch from "flexsearch";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import ActionListItem from "$lib/components/ActionListItem.svelte";
|
import ActionListItem from "$lib/components/ActionListItem.svelte";
|
||||||
import LL from "$i18n/i18n-svelte";
|
import LL from "$i18n/i18n-svelte";
|
||||||
import { action } from "$lib/title";
|
import { action } from "$lib/title";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
let {
|
let {
|
||||||
currentAction = undefined,
|
currentAction = undefined,
|
||||||
@@ -27,10 +29,13 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const index = new FlexSearch.Index({ tokenize: "full" });
|
const index = new FlexSearch.Index({ tokenize: "full" });
|
||||||
createIndex();
|
|
||||||
|
|
||||||
async function createIndex() {
|
$effect(() => {
|
||||||
for (const [, action] of KEYMAP_CODES) {
|
createIndex($KEYMAP_CODES);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function createIndex(codes: Map<number, KeyInfo>) {
|
||||||
|
for (const [, action] of codes) {
|
||||||
await index?.addAsync(
|
await index?.addAsync(
|
||||||
action.code,
|
action.code,
|
||||||
`${action.title || ""} ${action.variant || ""} ${action.category} ${action.id || ""} ${
|
`${action.title || ""} ${action.variant || ""} ${action.category} ${action.id || ""} ${
|
||||||
@@ -42,7 +47,7 @@
|
|||||||
|
|
||||||
async function search() {
|
async function search() {
|
||||||
results = (await index!.searchAsync(searchBox.value)) as number[];
|
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);
|
code = Number(searchBox.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +132,7 @@
|
|||||||
bind:group={filter}
|
bind:group={filter}
|
||||||
/></label
|
/></label
|
||||||
>
|
>
|
||||||
{#each KEYMAP_CATEGORIES as category}
|
{#each $KEYMAP_CATEGORIES as category}
|
||||||
<label
|
<label
|
||||||
>{category.name}<input
|
>{category.name}<input
|
||||||
name="category"
|
name="category"
|
||||||
@@ -167,7 +172,7 @@
|
|||||||
{#if filter !== undefined || results.length > 0}
|
{#if filter !== undefined || results.length > 0}
|
||||||
{@const resultValue =
|
{@const resultValue =
|
||||||
results.length === 0
|
results.length === 0
|
||||||
? Array.from(KEYMAP_CODES, ([it]) => it)
|
? Array.from($KEYMAP_CODES, ([it]) => it)
|
||||||
: results}
|
: results}
|
||||||
{#each filter ? resultValue.filter( (it) => filter.has(it), ) : resultValue as id (id)}
|
{#each filter ? resultValue.filter( (it) => filter.has(it), ) : resultValue as id (id)}
|
||||||
<li><ActionListItem {id} onclick={() => select(id)} /></li>
|
<li><ActionListItem {id} onclick={() => select(id)} /></li>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
isApplied: true,
|
isApplied: true,
|
||||||
}}
|
}}
|
||||||
{@const { code, icon, id, display, title, keyCode, variant } =
|
{@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 dynamicMapping = keyCode && $osLayout.get(keyCode)}
|
||||||
{@const tooltip =
|
{@const tooltip =
|
||||||
(title ?? id ?? `0x${code.toString(16)}`) +
|
(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;
|
version: string;
|
||||||
target: string;
|
target: string;
|
||||||
git_commit: string;
|
git_commit: string;
|
||||||
@@ -6,6 +13,12 @@ export interface VersionMeta {
|
|||||||
git_date: string;
|
git_date: string;
|
||||||
public_build: boolean;
|
public_build: boolean;
|
||||||
development_mode: number;
|
development_mode: number;
|
||||||
|
actions: string;
|
||||||
|
factory_defaults: {
|
||||||
|
layout: string;
|
||||||
|
settings: string;
|
||||||
|
chords: Record<string, string>;
|
||||||
|
};
|
||||||
update: {
|
update: {
|
||||||
ota: string | null;
|
ota: string | null;
|
||||||
uf2: string | null;
|
uf2: string | null;
|
||||||
@@ -15,6 +28,29 @@ export interface VersionMeta {
|
|||||||
spi_flash: SPIFlashInfo | null;
|
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 {
|
export interface SPIFlashInfo {
|
||||||
type: string;
|
type: string;
|
||||||
size: string;
|
size: string;
|
||||||
@@ -6,6 +6,8 @@ import type { CharaLayout } from "$lib/serialization/layout";
|
|||||||
import { persistentWritable } from "$lib/storage";
|
import { persistentWritable } from "$lib/storage";
|
||||||
import { userPreferences } from "$lib/preferences";
|
import { userPreferences } from "$lib/preferences";
|
||||||
import settingInfo from "$lib/assets/settings.yml";
|
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>();
|
export const serialPort = writable<CharaDevice | undefined>();
|
||||||
|
|
||||||
@@ -47,6 +49,8 @@ export const syncStatus: Writable<
|
|||||||
"done" | "error" | "downloading" | "uploading"
|
"done" | "error" | "downloading" | "uploading"
|
||||||
> = writable("done");
|
> = writable("done");
|
||||||
|
|
||||||
|
export const deviceMeta = writable<VersionMeta | undefined>(undefined);
|
||||||
|
|
||||||
export interface ProgressInfo {
|
export interface ProgressInfo {
|
||||||
max: number;
|
max: number;
|
||||||
current: number;
|
current: number;
|
||||||
@@ -65,6 +69,12 @@ export async function initSerial(manual = false, withSync = true) {
|
|||||||
export async function sync() {
|
export async function sync() {
|
||||||
const device = get(serialPort);
|
const device = get(serialPort);
|
||||||
if (!device) return;
|
if (!device) return;
|
||||||
|
getMeta(
|
||||||
|
`${device.device}_${device.chipset}`.toLowerCase(),
|
||||||
|
device.version.toString(),
|
||||||
|
).then((meta) => {
|
||||||
|
deviceMeta.set(meta);
|
||||||
|
});
|
||||||
const chordCount = await device.getChordCount();
|
const chordCount = await device.getChordCount();
|
||||||
syncStatus.set("downloading");
|
syncStatus.set("downloading");
|
||||||
|
|
||||||
|
|||||||
@@ -1,38 +1,64 @@
|
|||||||
import type { ActionInfo, KeymapCategory } from "$lib/assets/keymaps/keymap";
|
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> {
|
export interface KeyInfo extends Partial<ActionInfo> {
|
||||||
code: number;
|
code: number;
|
||||||
category?: KeymapCategory;
|
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(
|
Object.values(import.meta.glob("$lib/assets/keymaps/*.yml")).map(
|
||||||
async (load) => load().then((it) => (it as any).default),
|
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>(
|
export let KEYMAP_CATEGORIES: Readable<KeymapCategory[]> = derived(
|
||||||
KEYMAP_CATEGORIES.flatMap((category) =>
|
deviceMeta,
|
||||||
Object.entries(category.actions).map(
|
(deviceMeta) => deviceMeta?.actions ?? fallbackActions,
|
||||||
([code, action]) => [action.keyCode!, Number(code)] as const,
|
);
|
||||||
|
|
||||||
|
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>(
|
export const KEYMAP_KEYCODES: Readable<Map<string, number>> = derived(
|
||||||
KEYMAP_CATEGORIES.flatMap((category) =>
|
KEYMAP_CATEGORIES,
|
||||||
Object.entries(category.actions).map(
|
(categories) =>
|
||||||
([code, action]) =>
|
new Map<string, number>(
|
||||||
[action.id!, { ...action, code: Number(code), category }] as const,
|
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[];
|
id: number[];
|
||||||
deleted: boolean;
|
deleted: boolean;
|
||||||
};
|
};
|
||||||
export const chords = derived([overlay, deviceChords], ([overlay, chords]) => {
|
export const chords = derived(
|
||||||
const newChords = new Set(overlay.chords.keys());
|
[overlay, deviceChords, KEYMAP_CODES],
|
||||||
|
([overlay, chords, codes]) => {
|
||||||
|
const newChords = new Set(overlay.chords.keys());
|
||||||
|
|
||||||
const changedChords = chords.map<ChordInfo>((chord) => {
|
const changedChords = chords.map<ChordInfo>((chord) => {
|
||||||
const id = JSON.stringify(chord.actions);
|
const id = JSON.stringify(chord.actions);
|
||||||
if (overlay.chords.has(id)) {
|
if (overlay.chords.has(id)) {
|
||||||
newChords.delete(id);
|
newChords.delete(id);
|
||||||
const changedChord = overlay.chords.get(id)!;
|
const changedChord = overlay.chords.get(id)!;
|
||||||
return {
|
return {
|
||||||
id: chord.actions,
|
id: chord.actions,
|
||||||
// use the old phrase for stable editing
|
// use the old phrase for stable editing
|
||||||
sortBy: chord.phrase.map((it) => KEYMAP_CODES.get(it)?.id ?? it).join(),
|
sortBy: chord.phrase.map((it) => codes.get(it)?.id ?? it).join(),
|
||||||
actions: changedChord.actions,
|
actions: changedChord.actions,
|
||||||
phrase: changedChord.phrase,
|
phrase: changedChord.phrase,
|
||||||
actionsChanged: id !== JSON.stringify(changedChord.actions),
|
actionsChanged: id !== JSON.stringify(changedChord.actions),
|
||||||
phraseChanged:
|
phraseChanged:
|
||||||
JSON.stringify(chord.phrase) !== JSON.stringify(changedChord.phrase),
|
JSON.stringify(chord.phrase) !==
|
||||||
isApplied: false,
|
JSON.stringify(changedChord.phrase),
|
||||||
deleted: changedChord.deleted,
|
isApplied: false,
|
||||||
};
|
deleted: changedChord.deleted,
|
||||||
} else {
|
};
|
||||||
return {
|
} else {
|
||||||
id: chord.actions,
|
return {
|
||||||
sortBy: chord.phrase.map((it) => KEYMAP_CODES.get(it)?.id ?? it).join(),
|
id: chord.actions,
|
||||||
actions: chord.actions,
|
sortBy: chord.phrase.map((it) => codes.get(it)?.id ?? it).join(),
|
||||||
phrase: chord.phrase,
|
actions: chord.actions,
|
||||||
phraseChanged: false,
|
phrase: chord.phrase,
|
||||||
actionsChanged: false,
|
phraseChanged: false,
|
||||||
isApplied: true,
|
actionsChanged: false,
|
||||||
deleted: 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,
|
|
||||||
});
|
});
|
||||||
}
|
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 }) =>
|
return changedChords.sort(({ sortBy: a }, { sortBy: b }) =>
|
||||||
a.localeCompare(b),
|
a.localeCompare(b),
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
export const chordHashes = derived(
|
export const chordHashes = derived(
|
||||||
chords,
|
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 { PageLoad } from "./$types";
|
||||||
import type { DirectoryListing } from "./listing";
|
import type { DirectoryListing } from "$lib/meta/types/listing";
|
||||||
|
|
||||||
export const load = (async ({ fetch }) => {
|
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();
|
const data = await result.json();
|
||||||
|
|
||||||
return { devices: data as DirectoryListing[] };
|
return { devices: data as DirectoryListing[] };
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { PageLoad } from "./$types";
|
import type { PageLoad } from "./$types";
|
||||||
import type { DirectoryListing } from "../listing";
|
import type { DirectoryListing } from "$lib/meta/types/listing";
|
||||||
|
|
||||||
export const load = (async ({ fetch, params }) => {
|
export const load = (async ({ fetch, params }) => {
|
||||||
const result = await fetch(
|
const result = await fetch(
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
$serialPort = undefined;
|
$serialPort = undefined;
|
||||||
try {
|
try {
|
||||||
const file = await fetch(
|
const file = await fetch(
|
||||||
`${data.meta.path}/${data.meta.update.ota?.name}`,
|
`${data.meta.path}/${data.meta.update.ota}`,
|
||||||
).then((it) => it.blob());
|
).then((it) => it.blob());
|
||||||
|
|
||||||
await port.updateFirmware(file);
|
await port.updateFirmware(file);
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
: undefined,
|
: undefined,
|
||||||
);
|
);
|
||||||
let isCorrectDevice = $derived(
|
let isCorrectDevice = $derived(
|
||||||
currentDevice ? currentDevice === data.meta.target : undefined,
|
currentDevice ? currentDevice === data.meta.device : undefined,
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,11 +84,11 @@
|
|||||||
|
|
||||||
async function getFileSystem() {
|
async function getFileSystem() {
|
||||||
if (!data.meta.update.uf2) return;
|
if (!data.meta.update.uf2) return;
|
||||||
const uf2Promise = fetch(
|
const uf2Promise = fetch(`${data.meta.path}/${data.meta.update.uf2}`).then(
|
||||||
`${data.meta.path}/${data.meta.update.uf2.name}`,
|
(it) => it.blob(),
|
||||||
).then((it) => it.blob());
|
);
|
||||||
const handle = await window.showSaveFilePicker({
|
const handle = await window.showSaveFilePicker({
|
||||||
id: `${data.meta.target}-update`,
|
id: `${data.meta.device}-update`,
|
||||||
suggestedName: "CURRENT.UF2",
|
suggestedName: "CURRENT.UF2",
|
||||||
excludeAcceptAllOption: true,
|
excludeAcceptAllOption: true,
|
||||||
types: [
|
types: [
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
const port = await navigator.serial.requestPort();
|
const port = await navigator.serial.requestPort();
|
||||||
try {
|
try {
|
||||||
console.log(data.meta);
|
console.log(data.meta);
|
||||||
const spiFlash = data.meta.spi_flash!;
|
const spiFlash = data.meta.spiFlash!;
|
||||||
espLoader = await connectEsp(port);
|
espLoader = await connectEsp(port);
|
||||||
|
|
||||||
/*espLoader.flashSpiAttach(
|
/*espLoader.flashSpiAttach(
|
||||||
@@ -189,7 +189,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container">
|
<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)}
|
{@const buttonError = error || (!success && isCorrectDevice === false)}
|
||||||
<section>
|
<section>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -1,50 +1,14 @@
|
|||||||
import type { PageLoad } from "./$types";
|
import type { PageLoad } from "./$types";
|
||||||
import type { FileListing, Listing } from "../../listing";
|
import { getMeta } from "$lib/meta/meta-storage";
|
||||||
import type { VersionMeta } from "$lib/meta";
|
import { error } from "@sveltejs/kit";
|
||||||
|
|
||||||
export const load = (async ({ fetch, params }) => {
|
export const load = (async ({ fetch, params }) => {
|
||||||
const result = await fetch(
|
const meta = await getMeta(params.device, params.version, fetch);
|
||||||
`${import.meta.env.VITE_FIRMWARE_URL}/${params.device}/${params.version}/`,
|
if (meta === undefined) {
|
||||||
);
|
error(
|
||||||
const data: Listing[] = await result.json();
|
404,
|
||||||
const meta: VersionMeta | undefined = data.some(
|
`The version ${params.version} for device ${params.device} does not exist.`,
|
||||||
(entry) => entry.type === "file" && entry.name === "meta.json",
|
);
|
||||||
)
|
}
|
||||||
? await fetch(
|
return { meta };
|
||||||
`${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,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}) satisfies PageLoad;
|
}) satisfies PageLoad;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<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 { flip } from "svelte/animate";
|
||||||
import { slide } from "svelte/transition";
|
import { slide } from "svelte/transition";
|
||||||
import Login from "./Login.svelte";
|
import Login from "./Login.svelte";
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<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 FlexSearch from "flexsearch";
|
||||||
import LL from "$i18n/i18n-svelte";
|
import LL from "$i18n/i18n-svelte";
|
||||||
import { action } from "$lib/title";
|
import { action } from "$lib/title";
|
||||||
@@ -40,16 +40,21 @@
|
|||||||
$effect(() => {
|
$effect(() => {
|
||||||
abortIndexing?.();
|
abortIndexing?.();
|
||||||
progress = 0;
|
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 plainPhrase: string[] = [""];
|
||||||
const extraActions: string[] = [];
|
const extraActions: string[] = [];
|
||||||
const extraCodes: string[] = [];
|
const extraCodes: string[] = [];
|
||||||
|
|
||||||
for (const actionCode of chord.phrase ?? []) {
|
for (const actionCode of chord.phrase ?? []) {
|
||||||
const action = KEYMAP_CODES.get(actionCode);
|
const action = codes.get(actionCode);
|
||||||
if (!action) {
|
if (!action) {
|
||||||
extraCodes.push(`0x${actionCode.toString(16)}`);
|
extraCodes.push(`0x${actionCode.toString(16)}`);
|
||||||
continue;
|
continue;
|
||||||
@@ -96,7 +101,7 @@
|
|||||||
const input = chord.actions
|
const input = chord.actions
|
||||||
.slice(chord.actions.lastIndexOf(0) + 1)
|
.slice(chord.actions.lastIndexOf(0) + 1)
|
||||||
.map((it) => {
|
.map((it) => {
|
||||||
const info = KEYMAP_CODES.get(it);
|
const info = codes.get(it);
|
||||||
if (!info) return `0x${it.toString(16)}`;
|
if (!info) return `0x${it.toString(16)}`;
|
||||||
const osCode = info.keyCode && osLayout.get(info.keyCode);
|
const osCode = info.keyCode && osLayout.get(info.keyCode);
|
||||||
const result = osCode?.length === 1 ? osCode : info.id;
|
const result = osCode?.length === 1 ? osCode : info.id;
|
||||||
@@ -118,6 +123,7 @@
|
|||||||
async function buildIndex(
|
async function buildIndex(
|
||||||
chords: ChordInfo[],
|
chords: ChordInfo[],
|
||||||
osLayout: Map<string, string>,
|
osLayout: Map<string, string>,
|
||||||
|
codes: Map<number, KeyInfo>,
|
||||||
): Promise<FlexSearch.Index> {
|
): Promise<FlexSearch.Index> {
|
||||||
if (chords.length === 0 || !browser) return index;
|
if (chords.length === 0 || !browser) return index;
|
||||||
index = new FlexSearch.Index({
|
index = new FlexSearch.Index({
|
||||||
@@ -148,7 +154,7 @@
|
|||||||
progress = i;
|
progress = i;
|
||||||
|
|
||||||
if ("phrase" in chord) {
|
if ("phrase" in chord) {
|
||||||
await index.addAsync(i, encodeChord(chord, osLayout));
|
await index.addAsync(i, encodeChord(chord, osLayout, codes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
@@ -186,7 +192,9 @@
|
|||||||
function downloadVocabulary() {
|
function downloadVocabulary() {
|
||||||
const vocabulary = new Set(
|
const vocabulary = new Set(
|
||||||
$chords.map((it) =>
|
$chords.map((it) =>
|
||||||
"phrase" in it ? encodeChord(it, $osLayout, true).trim() : "",
|
"phrase" in it
|
||||||
|
? encodeChord(it, $osLayout, $KEYMAP_CODES, true).trim()
|
||||||
|
: "",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
vocabulary.delete("");
|
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_LATEST_FIRMWARE"] = "1.1.4";
|
||||||
process.env["VITE_STORE_URL"] = "https://www.charachorder.com/";
|
process.env["VITE_STORE_URL"] = "https://www.charachorder.com/";
|
||||||
process.env["VITE_MATRIX_URL"] = "https://charachorder.io/";
|
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({
|
export default defineConfig({
|
||||||
build: {
|
build: {
|
||||||
|
|||||||
Reference in New Issue
Block a user