Compare commits

...

4 Commits

Author SHA1 Message Date
Marc Brooks d540df23bd
Merge a5b07b4862 into 353099001f 2025-07-01 16:47:04 +02:00
Marc Brooks 353099001f
build: upgrade packages and move to GitHub runner
* Move to GitHub runner for build action

Lint action

* Move to go 1.24.4

* Upgrade go packages

 github.com/coreos/go-oidc/v3  v3.11.0 -> v3.14.1
github.com/creack/pty v1.1.23 -> v1.1.24
github.com/gwatts/rootcerts  v0.0.0-20240401182218-3ab9db955caf -> v0.0.0-20250601184604-370a9a75f341
github.com/pion/logging v0.2.3 -> v0.2.4
github.com/pion/webrtc/v4 v4.0.16 -> v4.1.2
github.com/prometheus/common v0.62.0 -> v0.65.0
github.com/vishvananda/netlink v1.3.1 -> v1.3.1
go.bug.st/serial v1.6.2 -> v1.6.4
2025-07-01 13:39:41 +02:00
Aveline 73f5659618
fix(usbgadget): add lock for logWithSupression (#653) 2025-07-01 12:54:38 +02:00
Marc Brooks a5b07b4862
refactor(ui): Refactor the keyboardLayouts
Add missing keyboard mappings for most layouts
Change  pasteModel.tsx to use the new structure and vastly clarified the way that keys are emitted.
Make each layout export just the KeyboardLayout object (which is a package of isoCode, name, and chars)
Made keyboardLayouts.ts export a function to select keyboard by `isoCode`, export the keyboards as label . value pairs (for a select list) and the list of keyboards.
Changed devices.$id.settings.keyboard.tsx use the exported keyboard option list.
2025-06-12 13:29:13 -05:00
27 changed files with 308 additions and 219 deletions

View File

@ -10,9 +10,9 @@ on:
jobs: jobs:
build: build:
runs-on: buildjet-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
name: Build name: Build
if: "github.event.review.state == 'approved' || github.event.event_type != 'pull_request_review'" if: github.event_name != 'pull_request_review' || github.event.review.state == 'approved'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@ -14,16 +14,16 @@ permissions:
jobs: jobs:
ui-lint: ui-lint:
name: UI Lint name: UI Lint
runs-on: buildjet-4vcpu-ubuntu-2204 runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: v21.1.0 node-version: "22"
cache: "npm" cache: "npm"
cache-dependency-path: "ui/package-lock.json" cache-dependency-path: "**/package-lock.json"
- name: Install dependencies - name: Install dependencies
run: | run: |
cd ui cd ui

46
go.mod
View File

@ -1,35 +1,33 @@
module github.com/jetkvm/kvm module github.com/jetkvm/kvm
go 1.23.4 go 1.24.4
toolchain go1.24.3
require ( require (
github.com/Masterminds/semver/v3 v3.3.1 github.com/Masterminds/semver/v3 v3.3.1
github.com/beevik/ntp v1.4.3 github.com/beevik/ntp v1.4.3
github.com/coder/websocket v1.8.13 github.com/coder/websocket v1.8.13
github.com/coreos/go-oidc/v3 v3.11.0 github.com/coreos/go-oidc/v3 v3.14.1
github.com/creack/pty v1.1.23 github.com/creack/pty v1.1.24
github.com/fsnotify/fsnotify v1.9.0 github.com/fsnotify/fsnotify v1.9.0
github.com/gin-contrib/logger v1.2.6 github.com/gin-contrib/logger v1.2.6
github.com/gin-gonic/gin v1.10.1 github.com/gin-gonic/gin v1.10.1
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/guregu/null/v6 v6.0.0 github.com/guregu/null/v6 v6.0.0
github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf github.com/gwatts/rootcerts v0.0.0-20250601184604-370a9a75f341
github.com/hanwen/go-fuse/v2 v2.8.0 github.com/hanwen/go-fuse/v2 v2.8.0
github.com/pion/logging v0.2.3 github.com/pion/logging v0.2.4
github.com/pion/mdns/v2 v2.0.7 github.com/pion/mdns/v2 v2.0.7
github.com/pion/webrtc/v4 v4.0.16 github.com/pion/webrtc/v4 v4.1.2
github.com/pojntfx/go-nbd v0.3.2 github.com/pojntfx/go-nbd v0.3.2
github.com/prometheus/client_golang v1.22.0 github.com/prometheus/client_golang v1.22.0
github.com/prometheus/common v0.62.0 github.com/prometheus/common v0.65.0
github.com/prometheus/procfs v0.16.1 github.com/prometheus/procfs v0.16.1
github.com/psanford/httpreadat v0.1.0 github.com/psanford/httpreadat v0.1.0
github.com/rs/zerolog v1.34.0 github.com/rs/zerolog v1.34.0
github.com/sourcegraph/tf-dag v0.2.2-0.20250131204052-3e8ff1477b4f github.com/sourcegraph/tf-dag v0.2.2-0.20250131204052-3e8ff1477b4f
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
github.com/vishvananda/netlink v1.3.0 github.com/vishvananda/netlink v1.3.1
go.bug.st/serial v1.6.2 go.bug.st/serial v1.6.4
golang.org/x/crypto v0.39.0 golang.org/x/crypto v0.39.0
golang.org/x/net v0.41.0 golang.org/x/net v0.41.0
golang.org/x/sys v0.33.0 golang.org/x/sys v0.33.0
@ -39,15 +37,15 @@ replace github.com/pojntfx/go-nbd v0.3.2 => github.com/chemhack/go-nbd v0.0.0-20
require ( require (
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic v1.13.2 // indirect github.com/bytedance/sonic v1.13.3 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect github.com/cloudwego/base64x v0.1.5 // indirect
github.com/creack/goselect v0.1.2 // indirect github.com/creack/goselect v0.1.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.9 // indirect github.com/gabriel-vasile/mimetype v1.4.9 // indirect
github.com/gin-contrib/sse v1.1.0 // indirect github.com/gin-contrib/sse v1.1.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.26.0 // indirect github.com/go-playground/validator/v10 v10.26.0 // indirect
@ -61,29 +59,29 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/pilebones/go-udev v0.9.0 // indirect github.com/pilebones/go-udev v0.9.1 // indirect
github.com/pion/datachannel v1.5.10 // indirect github.com/pion/datachannel v1.5.10 // indirect
github.com/pion/dtls/v3 v3.0.6 // indirect github.com/pion/dtls/v3 v3.0.6 // indirect
github.com/pion/ice/v4 v4.0.10 // indirect github.com/pion/ice/v4 v4.0.10 // indirect
github.com/pion/interceptor v0.1.40 // indirect github.com/pion/interceptor v0.1.40 // indirect
github.com/pion/randutil v0.1.0 // indirect github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.15 // indirect github.com/pion/rtcp v1.2.15 // indirect
github.com/pion/rtp v1.8.18 // indirect github.com/pion/rtp v1.8.19 // indirect
github.com/pion/sctp v1.8.39 // indirect github.com/pion/sctp v1.8.39 // indirect
github.com/pion/sdp/v3 v3.0.13 // indirect github.com/pion/sdp/v3 v3.0.14 // indirect
github.com/pion/srtp/v3 v3.0.5 // indirect github.com/pion/srtp/v3 v3.0.6 // indirect
github.com/pion/stun/v3 v3.0.0 // indirect github.com/pion/stun/v3 v3.0.0 // indirect
github.com/pion/transport/v3 v3.0.7 // indirect github.com/pion/transport/v3 v3.0.7 // indirect
github.com/pion/turn/v4 v4.0.2 // indirect github.com/pion/turn/v4 v4.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect github.com/ugorji/go/codec v1.3.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect github.com/vishvananda/netns v0.0.5 // indirect
github.com/wlynxg/anet v0.0.5 // indirect github.com/wlynxg/anet v0.0.5 // indirect
golang.org/x/arch v0.17.0 // indirect golang.org/x/arch v0.18.0 // indirect
golang.org/x/oauth2 v0.24.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/text v0.26.0 // indirect golang.org/x/text v0.26.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

84
go.sum
View File

@ -4,8 +4,8 @@ github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q= github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0=
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
@ -18,13 +18,13 @@ github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE= github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=
github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI= github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0= github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= github.com/creack/goselect v0.1.3 h1:MaGNMclRo7P2Jl21hBpR1Cn33ITSbKP6E49RtfblLKc=
github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= github.com/creack/goselect v0.1.3/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY=
github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -38,8 +38,8 @@ github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY=
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@ -58,8 +58,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/guregu/null/v6 v6.0.0 h1:N14VRS+4di81i1PXRiprbQJ9EM9gqBa0+KVMeS/QSjQ= github.com/guregu/null/v6 v6.0.0 h1:N14VRS+4di81i1PXRiprbQJ9EM9gqBa0+KVMeS/QSjQ=
github.com/guregu/null/v6 v6.0.0/go.mod h1:hrMIhIfrOZeLPZhROSn149tpw2gHkidAqxoXNyeX3iQ= github.com/guregu/null/v6 v6.0.0/go.mod h1:hrMIhIfrOZeLPZhROSn149tpw2gHkidAqxoXNyeX3iQ=
github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf h1:JO6ISZIvEUitto5zjQ3/VEnDM5rPbqIFuOhS0U0ByeA= github.com/gwatts/rootcerts v0.0.0-20250601184604-370a9a75f341 h1:zPrkLSKi7kKJoNJH4uUmsQ86+0/QqpwEns0NyNLwKv0=
github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf/go.mod h1:5Kt9XkWvkGi2OHOq0QsGxebHmhCcqJ8KCbNg/a6+n+g= github.com/gwatts/rootcerts v0.0.0-20250601184604-370a9a75f341/go.mod h1:5Kt9XkWvkGi2OHOq0QsGxebHmhCcqJ8KCbNg/a6+n+g=
github.com/hanwen/go-fuse/v2 v2.8.0 h1:wV8rG7rmCz8XHSOwBZhG5YcVqcYjkzivjmbaMafPlAs= github.com/hanwen/go-fuse/v2 v2.8.0 h1:wV8rG7rmCz8XHSOwBZhG5YcVqcYjkzivjmbaMafPlAs=
github.com/hanwen/go-fuse/v2 v2.8.0/go.mod h1:yE6D2PqWwm3CbYRxFXV9xUd8Md5d6NG0WBs5spCswmI= github.com/hanwen/go-fuse/v2 v2.8.0/go.mod h1:yE6D2PqWwm3CbYRxFXV9xUd8Md5d6NG0WBs5spCswmI=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@ -99,8 +99,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q= github.com/pilebones/go-udev v0.9.1 h1:uN72M1C1fgzhsVmBGEM8w9RD1JY4iVsPZpr+Z6rb3O8=
github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI= github.com/pilebones/go-udev v0.9.1/go.mod h1:Bgcl07crebF3JSeS4+nuaRvhWFdCeFoBhXXeAp93XNo=
github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E= github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E=
@ -109,45 +109,45 @@ github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4=
github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw=
github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4= github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4=
github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic= github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic=
github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8=
github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so=
github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM=
github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
github.com/pion/rtp v1.8.18 h1:yEAb4+4a8nkPCecWzQB6V/uEU18X1lQCGAQCjP+pyvU= github.com/pion/rtp v1.8.19 h1:jhdO/3XhL/aKm/wARFVmvTfq0lC/CvN1xwYKmduly3c=
github.com/pion/rtp v1.8.18/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= github.com/pion/rtp v1.8.19/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE=
github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
github.com/pion/sdp/v3 v3.0.13 h1:uN3SS2b+QDZnWXgdr69SM8KB4EbcnPnPf2Laxhty/l4= github.com/pion/sdp/v3 v3.0.14 h1:1h7gBr9FhOWH5GjWWY5lcw/U85MtdcibTyt/o6RxRUI=
github.com/pion/sdp/v3 v3.0.13/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= github.com/pion/sdp/v3 v3.0.14/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
github.com/pion/srtp/v3 v3.0.5 h1:8XLB6Dt3QXkMkRFpoqC3314BemkpMQK2mZeJc4pUKqo= github.com/pion/srtp/v3 v3.0.6 h1:E2gyj1f5X10sB/qILUGIkL4C2CqK269Xq167PbGCc/4=
github.com/pion/srtp/v3 v3.0.5/go.mod h1:r1G7y5r1scZRLe2QJI/is+/O83W2d+JoEsuIexpw+uM= github.com/pion/srtp/v3 v3.0.6/go.mod h1:BxvziG3v/armJHAaJ87euvkhHqWe9I7iiOy50K2QkhY=
github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw=
github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU=
github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps= github.com/pion/turn/v4 v4.0.2 h1:ZqgQ3+MjP32ug30xAbD6Mn+/K4Sxi3SdNOTFf+7mpps=
github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs= github.com/pion/turn/v4 v4.0.2/go.mod h1:pMMKP/ieNAG/fN5cZiN4SDuyKsXtNTr0ccN7IToA1zs=
github.com/pion/webrtc/v4 v4.0.16 h1:5f8QMVIbNvJr2mPRGi2QamkPa/LVUB6NWolOCwphKHA= github.com/pion/webrtc/v4 v4.1.2 h1:mpuUo/EJ1zMNKGE79fAdYNFZBX790KE7kQQpLMjjR54=
github.com/pion/webrtc/v4 v4.0.16/go.mod h1:C3uTCPzVafUA0eUzru9f47OgNt3nEO7ZJ6zNY6VSJno= github.com/pion/webrtc/v4 v4.1.2/go.mod h1:xsCXiNAmMEjIdFxAYU0MbB3RwRieJsegSB2JZsGN+8U=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/psanford/httpreadat v0.1.0 h1:VleW1HS2zO7/4c7c7zNl33fO6oYACSagjJIyMIwZLUE= github.com/psanford/httpreadat v0.1.0 h1:VleW1HS2zO7/4c7c7zNl33fO6oYACSagjJIyMIwZLUE=
github.com/psanford/httpreadat v0.1.0/go.mod h1:Zg7P+TlBm3bYbyHTKv/EdtSJZn3qwbPwpfZ/I9GKCRE= github.com/psanford/httpreadat v0.1.0/go.mod h1:Zg7P+TlBm3bYbyHTKv/EdtSJZn3qwbPwpfZ/I9GKCRE=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
@ -165,24 +165,24 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8= go.bug.st/serial v1.6.4 h1:7FmqNPgVp3pu2Jz5PoPtbZ9jJO5gnEnZIvnI1lzve8A=
go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= go.bug.st/serial v1.6.4/go.mod h1:nofMJxTeNVny/m6+KaafC6vJGj3miwQZ6vW4BZUGJPI=
golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -81,6 +81,7 @@ type UsbGadget struct {
log *zerolog.Logger log *zerolog.Logger
logSuppressionCounter map[string]int logSuppressionCounter map[string]int
logSuppressionLock sync.Mutex
} }
const configFSPath = "/sys/kernel/config" const configFSPath = "/sys/kernel/config"

View File

@ -82,6 +82,9 @@ func compareFileContent(oldContent []byte, newContent []byte, looserMatch bool)
} }
func (u *UsbGadget) logWithSupression(counterName string, every int, logger *zerolog.Logger, err error, msg string, args ...interface{}) { func (u *UsbGadget) logWithSupression(counterName string, every int, logger *zerolog.Logger, err error, msg string, args ...interface{}) {
u.logSuppressionLock.Lock()
defer u.logSuppressionLock.Unlock()
if _, ok := u.logSuppressionCounter[counterName]; !ok { if _, ok := u.logSuppressionCounter[counterName]; !ok {
u.logSuppressionCounter[counterName] = 0 u.logSuppressionCounter[counterName] = 0
} else { } else {
@ -100,6 +103,9 @@ func (u *UsbGadget) logWithSupression(counterName string, every int, logger *zer
} }
func (u *UsbGadget) resetLogSuppressionCounter(counterName string) { func (u *UsbGadget) resetLogSuppressionCounter(counterName string) {
u.logSuppressionLock.Lock()
defer u.logSuppressionLock.Unlock()
if _, ok := u.logSuppressionCounter[counterName]; !ok { if _, ok := u.logSuppressionCounter[counterName]; !ok {
u.logSuppressionCounter[counterName] = 0 u.logSuppressionCounter[counterName] = 0
} }

View File

@ -67,19 +67,19 @@ function Terminal({
}) { }) {
const enableTerminal = useUiStore(state => state.terminalType == type); const enableTerminal = useUiStore(state => state.terminalType == type);
const setTerminalType = useUiStore(state => state.setTerminalType); const setTerminalType = useUiStore(state => state.setTerminalType);
const setDisableKeyboardFocusTrap = useUiStore(state => state.setDisableVideoFocusTrap); const setDisableVideoFocusTrap = useUiStore(state => state.setDisableVideoFocusTrap);
const { instance, ref } = useXTerm({ options: TERMINAL_CONFIG }); const { instance, ref } = useXTerm({ options: TERMINAL_CONFIG });
useEffect(() => { useEffect(() => {
setTimeout(() => { setTimeout(() => {
setDisableKeyboardFocusTrap(enableTerminal); setDisableVideoFocusTrap(enableTerminal);
}, 500); }, 500);
return () => { return () => {
setDisableKeyboardFocusTrap(false); setDisableVideoFocusTrap(false);
}; };
}, [ref, instance, enableTerminal, setDisableKeyboardFocusTrap, type]); }, [enableTerminal, setDisableVideoFocusTrap]);
const readyState = dataChannel.readyState; const readyState = dataChannel.readyState;
useEffect(() => { useEffect(() => {
@ -116,7 +116,7 @@ function Terminal({
const { domEvent } = e; const { domEvent } = e;
if (domEvent.key === "Escape") { if (domEvent.key === "Escape") {
setTerminalType("none"); setTerminalType("none");
setDisableKeyboardFocusTrap(false); setDisableVideoFocusTrap(false);
domEvent.preventDefault(); domEvent.preventDefault();
} }
}); });
@ -131,7 +131,7 @@ function Terminal({
onDataHandler.dispose(); onDataHandler.dispose();
onKeyHandler.dispose(); onKeyHandler.dispose();
}; };
}, [instance, dataChannel, readyState, setDisableKeyboardFocusTrap, setTerminalType]); }, [dataChannel, instance, readyState, setDisableVideoFocusTrap, setTerminalType]);
useEffect(() => { useEffect(() => {
if (!instance) return; if (!instance) return;
@ -158,7 +158,7 @@ function Terminal({
return () => { return () => {
window.removeEventListener("resize", handleResize); window.removeEventListener("resize", handleResize);
}; };
}, [ref, instance]); }, [instance]);
return ( return (
<div <div

View File

@ -10,11 +10,11 @@ import { SettingsPageHeader } from "@components/SettingsPageheader";
import { useJsonRpc } from "@/hooks/useJsonRpc"; import { useJsonRpc } from "@/hooks/useJsonRpc";
import { useHidStore, useRTCStore, useUiStore, useSettingsStore } from "@/hooks/stores"; import { useHidStore, useRTCStore, useUiStore, useSettingsStore } from "@/hooks/stores";
import { keys, modifiers } from "@/keyboardMappings"; import { keys, modifiers } from "@/keyboardMappings";
import { layouts, chars } from "@/keyboardLayouts"; import { KeyStroke, KeyboardLayout, selectedKeyboard } from "@/keyboardLayouts";
import notifications from "@/notifications"; import notifications from "@/notifications";
const hidKeyboardPayload = (keys: number[], modifier: number) => { const hidKeyboardPayload = (modifier: number, keys: number[]) => {
return { keys, modifier }; return { modifier, keys };
}; };
const modifierCode = (shift?: boolean, altRight?: boolean) => { const modifierCode = (shift?: boolean, altRight?: boolean) => {
@ -62,49 +62,56 @@ export default function PasteModal() {
const onConfirmPaste = useCallback(async () => { const onConfirmPaste = useCallback(async () => {
setPasteMode(false); setPasteMode(false);
setDisableVideoFocusTrap(false); setDisableVideoFocusTrap(false);
if (rpcDataChannel?.readyState !== "open" || !TextAreaRef.current) return; if (rpcDataChannel?.readyState !== "open" || !TextAreaRef.current) return;
if (!safeKeyboardLayout) return; const keyboard: KeyboardLayout = selectedKeyboard(safeKeyboardLayout);
if (!chars[safeKeyboardLayout]) return; if (!keyboard) return;
const text = TextAreaRef.current.value; const text = TextAreaRef.current.value;
try { try {
for (const char of text) { for (const char of text) {
const { key, shift, altRight, deadKey, accentKey } = chars[safeKeyboardLayout][char] const keyprops = keyboard.chars[char];
if (!keyprops) continue;
const { key, shift, altRight, deadKey, accentKey } = keyprops;
if (!key) continue; if (!key) continue;
const keyz = [ keys[key] ]; // if this is an accented character, we need to send that accent FIRST
const modz = [ modifierCode(shift, altRight) ];
if (deadKey) {
keyz.push(keys["Space"]);
modz.push(noModifier);
}
if (accentKey) { if (accentKey) {
keyz.unshift(keys[accentKey.key]) await sendKeystroke({modifier: modifierCode(accentKey.shift, accentKey.altRight), keys: [ keys[accentKey.key] ] })
modz.unshift(modifierCode(accentKey.shift, accentKey.altRight))
} }
for (const [index, kei] of keyz.entries()) { // now send the actual key
await new Promise<void>((resolve, reject) => { await sendKeystroke({ modifier: modifierCode(shift, altRight), keys: [ keys[key] ]});
send(
"keyboardReport", // if what was requested was a dead key, we need to send an unmodified space to emit
hidKeyboardPayload([kei], modz[index]), // just the accent character
params => { if (deadKey) {
if ("error" in params) return reject(params.error); await sendKeystroke({ modifier: noModifier, keys: [ keys["Space"] ] });
send("keyboardReport", hidKeyboardPayload([], 0), params => {
if ("error" in params) return reject(params.error);
resolve();
});
},
);
});
} }
// now send a message with no keys down to "release" the keys
await sendKeystroke({ modifier: 0, keys: [] });
} }
} catch (error) { } catch (error) {
console.error(error); console.error("Failed to paste text:", error);
notifications.error("Failed to paste text"); notifications.error("Failed to paste text");
} }
}, [rpcDataChannel?.readyState, send, setDisableVideoFocusTrap, setPasteMode, safeKeyboardLayout]);
async function sendKeystroke(stroke: KeyStroke) {
await new Promise<void>((resolve, reject) => {
send(
"keyboardReport",
hidKeyboardPayload(stroke.modifier, stroke.keys),
params => {
if ("error" in params) return reject(params.error);
resolve();
}
);
});
}
}, [rpcDataChannel?.readyState, safeKeyboardLayout, send, setDisableVideoFocusTrap, setPasteMode]);
useEffect(() => { useEffect(() => {
if (TextAreaRef.current) { if (TextAreaRef.current) {
@ -154,7 +161,7 @@ export default function PasteModal() {
// @ts-expect-error TS doesn't recognize Intl.Segmenter in some environments // @ts-expect-error TS doesn't recognize Intl.Segmenter in some environments
[...new Intl.Segmenter().segment(value)] [...new Intl.Segmenter().segment(value)]
.map(x => x.segment) .map(x => x.segment)
.filter(char => !chars[safeKeyboardLayout][char]), .filter(char => !selectedKeyboard(safeKeyboardLayout).chars[char]),
), ),
]; ];
@ -175,7 +182,7 @@ export default function PasteModal() {
</div> </div>
<div className="space-y-4"> <div className="space-y-4">
<p className="text-xs text-slate-600 dark:text-slate-400"> <p className="text-xs text-slate-600 dark:text-slate-400">
Sending text using keyboard layout: {layouts[safeKeyboardLayout]} Sending text using keyboard layout: {selectedKeyboard(safeKeyboardLayout).name}
</p> </p>
</div> </div>
</div> </div>

View File

@ -14,7 +14,7 @@ import AddDeviceForm from "./AddDeviceForm";
export default function WakeOnLanModal() { export default function WakeOnLanModal() {
const [storedDevices, setStoredDevices] = useState<StoredDevice[]>([]); const [storedDevices, setStoredDevices] = useState<StoredDevice[]>([]);
const [showAddForm, setShowAddForm] = useState(false); const [showAddForm, setShowAddForm] = useState(false);
const setDisableFocusTrap = useUiStore(state => state.setDisableVideoFocusTrap); const setDisableVideoFocusTrap = useUiStore(state => state.setDisableVideoFocusTrap);
const rpcDataChannel = useRTCStore(state => state.rpcDataChannel); const rpcDataChannel = useRTCStore(state => state.rpcDataChannel);
@ -24,9 +24,9 @@ export default function WakeOnLanModal() {
const [addDeviceErrorMessage, setAddDeviceErrorMessage] = useState<string | null>(null); const [addDeviceErrorMessage, setAddDeviceErrorMessage] = useState<string | null>(null);
const onCancelWakeOnLanModal = useCallback(() => { const onCancelWakeOnLanModal = useCallback(() => {
setDisableVideoFocusTrap(false);
close(); close();
setDisableFocusTrap(false); }, [close, setDisableVideoFocusTrap]);
}, [close, setDisableFocusTrap]);
const onSendMagicPacket = useCallback( const onSendMagicPacket = useCallback(
(macAddress: string) => { (macAddress: string) => {
@ -43,12 +43,12 @@ export default function WakeOnLanModal() {
} }
} else { } else {
notifications.success("Magic Packet sent successfully"); notifications.success("Magic Packet sent successfully");
setDisableFocusTrap(false); setDisableVideoFocusTrap(false);
close(); close();
} }
}); });
}, },
[close, rpcDataChannel?.readyState, send, setDisableFocusTrap], [close, rpcDataChannel?.readyState, send, setDisableVideoFocusTrap],
); );
const syncStoredDevices = useCallback(() => { const syncStoredDevices = useCallback(() => {
@ -78,7 +78,7 @@ export default function WakeOnLanModal() {
} }
}); });
}, },
[storedDevices, send, syncStoredDevices], [send, storedDevices, syncStoredDevices],
); );
const onAddDevice = useCallback( const onAddDevice = useCallback(

View File

@ -941,5 +941,5 @@ export const useMacrosStore = create<MacrosState>((set, get) => ({
} finally { } finally {
set({ loading: false }); set({ loading: false });
} }
}, }
})); }));

View File

@ -1,45 +1,32 @@
import { chars as chars_fr_BE, name as name_fr_BE } from "@/keyboardLayouts/fr_BE" export interface KeyStroke { modifier: number; keys: number[]; }
import { chars as chars_cs_CZ, name as name_cs_CZ } from "@/keyboardLayouts/cs_CZ" export interface KeyInfo { key: string | number; shift?: boolean, altRight?: boolean }
import { chars as chars_en_UK, name as name_en_UK } from "@/keyboardLayouts/en_UK" export interface KeyCombo extends KeyInfo { deadKey?: boolean, accentKey?: KeyInfo }
import { chars as chars_en_US, name as name_en_US } from "@/keyboardLayouts/en_US" export interface KeyboardLayout { isoCode: string, name: string, chars: Record<string, KeyCombo> }
import { chars as chars_fr_FR, name as name_fr_FR } from "@/keyboardLayouts/fr_FR"
import { chars as chars_de_DE, name as name_de_DE } from "@/keyboardLayouts/de_DE"
import { chars as chars_it_IT, name as name_it_IT } from "@/keyboardLayouts/it_IT"
import { chars as chars_nb_NO, name as name_nb_NO } from "@/keyboardLayouts/nb_NO"
import { chars as chars_es_ES, name as name_es_ES } from "@/keyboardLayouts/es_ES"
import { chars as chars_sv_SE, name as name_sv_SE } from "@/keyboardLayouts/sv_SE"
import { chars as chars_fr_CH, name as name_fr_CH } from "@/keyboardLayouts/fr_CH"
import { chars as chars_de_CH, name as name_de_CH } from "@/keyboardLayouts/de_CH"
interface KeyInfo { key: string | number; shift?: boolean, altRight?: boolean } // to add a new layout, create a file like the above and add it to the list
export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } import { cs_CZ } from "@/keyboardLayouts/cs_CZ"
import { de_CH } from "@/keyboardLayouts/de_CH"
import { de_DE } from "@/keyboardLayouts/de_DE"
import { en_US } from "@/keyboardLayouts/en_US"
import { en_UK } from "@/keyboardLayouts/en_UK"
import { es_ES } from "@/keyboardLayouts/es_ES"
import { fr_BE } from "@/keyboardLayouts/fr_BE"
import { fr_CH } from "@/keyboardLayouts/fr_CH"
import { fr_FR } from "@/keyboardLayouts/fr_FR"
import { it_IT } from "@/keyboardLayouts/it_IT"
import { nb_NO } from "@/keyboardLayouts/nb_NO"
import { sv_SE } from "@/keyboardLayouts/sv_SE"
export const layouts: Record<string, string> = { export const keyboards: KeyboardLayout[] = [ cs_CZ, de_CH, de_DE, en_UK, en_US, es_ES, fr_BE, fr_CH, fr_FR, it_IT, nb_NO, sv_SE ];
be_FR: name_fr_BE,
cs_CZ: name_cs_CZ,
en_UK: name_en_UK,
en_US: name_en_US,
fr_FR: name_fr_FR,
de_DE: name_de_DE,
it_IT: name_it_IT,
nb_NO: name_nb_NO,
es_ES: name_es_ES,
sv_SE: name_sv_SE,
fr_CH: name_fr_CH,
de_CH: name_de_CH,
}
export const chars: Record<string, Record<string, KeyCombo>> = { export const selectedKeyboard = (isoCode: string): KeyboardLayout => {
be_FR: chars_fr_BE, // fallback to original behaviour of en-US if no isoCode given
cs_CZ: chars_cs_CZ, return keyboards.find(keyboard => keyboard.isoCode == isoCode)
en_UK: chars_en_UK, ?? keyboards.find(keyboard => keyboard.isoCode == "en-US")!;
en_US: chars_en_US,
fr_FR: chars_fr_FR,
de_DE: chars_de_DE,
it_IT: chars_it_IT,
nb_NO: chars_nb_NO,
es_ES: chars_es_ES,
sv_SE: chars_sv_SE,
fr_CH: chars_fr_CH,
de_CH: chars_de_CH,
}; };
export const keyboardOptions = () => {
return keyboards.map((keyboard) => {
return { label: keyboard.name, value: keyboard.isoCode }
});
}

View File

@ -1,6 +1,6 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Čeština"; const name = "Čeština";
const keyTrema = { key: "Backslash" } // tréma (umlaut), two dots placed above a vowel const keyTrema = { key: "Backslash" } // tréma (umlaut), two dots placed above a vowel
const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter
@ -13,7 +13,7 @@ const keyOverdot = { key: "Digit8", shift: true, altRight: true } // overdot (do
const keyHook = { key: "Digit6", shift: true, altRight: true } // ogonoek (little hook), mark ˛ placed beneath a letter const keyHook = { key: "Digit6", shift: true, altRight: true } // ogonoek (little hook), mark ˛ placed beneath a letter
const keyCedille = { key: "Equal", shift: true, altRight: true } // accent cedille (cedilla), mark ¸ placed beneath a letter const keyCedille = { key: "Equal", shift: true, altRight: true } // accent cedille (cedilla), mark ¸ placed beneath a letter
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
"Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, "Ä": { key: "KeyA", shift: true, accentKey: keyTrema },
"Á": { key: "KeyA", shift: true, accentKey: keyAcute }, "Á": { key: "KeyA", shift: true, accentKey: keyAcute },
@ -242,3 +242,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const cs_CZ: KeyboardLayout = {
isoCode: "cs-CZ",
name: name,
chars: chars
};

View File

@ -1,6 +1,6 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Schwiizerdütsch"; const name = "Schwiizerdütsch";
const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel
const keyAcute = { key: "Minus", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter const keyAcute = { key: "Minus", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter
@ -8,7 +8,7 @@ const keyHat = { key: "Equal" } // accent circonflexe (accent hat), mark ^ place
const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter
const keyTilde = { key: "Equal", altRight: true } // tilde, mark ~ placed above the letter const keyTilde = { key: "Equal", altRight: true } // tilde, mark ~ placed above the letter
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
"Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, "Ä": { key: "KeyA", shift: true, accentKey: keyTrema },
"Á": { key: "KeyA", shift: true, accentKey: keyAcute }, "Á": { key: "KeyA", shift: true, accentKey: keyAcute },
@ -163,3 +163,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const de_CH: KeyboardLayout = {
isoCode: "de-CH",
name: name,
chars: chars
};

View File

@ -1,12 +1,12 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Deutsch"; const name = "Deutsch";
const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter
const keyHat = { key: "Backquote" } // accent circonflexe (accent hat), mark ^ placed above the letter const keyHat = { key: "Backquote" } // accent circonflexe (accent hat), mark ^ placed above the letter
const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
"Á": { key: "KeyA", shift: true, accentKey: keyAcute }, "Á": { key: "KeyA", shift: true, accentKey: keyAcute },
"Â": { key: "KeyA", shift: true, accentKey: keyHat }, "Â": { key: "KeyA", shift: true, accentKey: keyHat },
@ -150,3 +150,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const de_DE: KeyboardLayout = {
isoCode: "de-DE",
name: name,
chars: chars
};

View File

@ -1,8 +1,8 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "English (UK)"; const name = "English (UK)";
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
B: { key: "KeyB", shift: true }, B: { key: "KeyB", shift: true },
C: { key: "KeyC", shift: true }, C: { key: "KeyC", shift: true },
@ -105,3 +105,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo> } as Record<string, KeyCombo>
export const en_UK: KeyboardLayout = {
isoCode: "en-UK",
name: name,
chars: chars
};

View File

@ -1,8 +1,8 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "English (US)"; const name = "English (US)";
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
B: { key: "KeyB", shift: true }, B: { key: "KeyB", shift: true },
C: { key: "KeyC", shift: true }, C: { key: "KeyC", shift: true },
@ -111,3 +111,9 @@ export const chars = {
Insert: { key: "Insert", shift: false }, Insert: { key: "Insert", shift: false },
Delete: { key: "Delete", shift: false }, Delete: { key: "Delete", shift: false },
} as Record<string, KeyCombo> } as Record<string, KeyCombo>
export const en_US: KeyboardLayout = {
isoCode: "en-US",
name: name,
chars: chars
};

View File

@ -1,6 +1,6 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Español"; const name = "Español";
const keyTrema = { key: "Quote", shift: true } // tréma (umlaut), two dots placed above a vowel const keyTrema = { key: "Quote", shift: true } // tréma (umlaut), two dots placed above a vowel
const keyAcute = { key: "Quote" } // accent aigu (acute accent), mark ´ placed above the letter const keyAcute = { key: "Quote" } // accent aigu (acute accent), mark ´ placed above the letter
@ -8,7 +8,7 @@ const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accen
const keyGrave = { key: "BracketRight" } // accent grave, mark ` placed above the letter const keyGrave = { key: "BracketRight" } // accent grave, mark ` placed above the letter
const keyTilde = { key: "Key4", altRight: true } // tilde, mark ~ placed above the letter const keyTilde = { key: "Key4", altRight: true } // tilde, mark ~ placed above the letter
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
"Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, "Ä": { key: "KeyA", shift: true, accentKey: keyTrema },
"Á": { key: "KeyA", shift: true, accentKey: keyAcute }, "Á": { key: "KeyA", shift: true, accentKey: keyAcute },
@ -166,3 +166,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const es_ES: KeyboardLayout = {
isoCode: "es-ES",
name: name,
chars: chars
};

View File

@ -1,6 +1,6 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Belgisch Nederlands"; const name = "Belgisch Nederlands";
const keyTrema = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel const keyTrema = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel
const keyHat = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter const keyHat = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter
@ -8,7 +8,7 @@ const keyAcute = { key: "Semicolon", altRight: true } // accent aigu (acute acce
const keyGrave = { key: "Quote", shift: true } // accent grave, mark ` placed above the letter const keyGrave = { key: "Quote", shift: true } // accent grave, mark ` placed above the letter
const keyTilde = { key: "Slash", altRight: true } // tilde, mark ~ placed above the letter const keyTilde = { key: "Slash", altRight: true } // tilde, mark ~ placed above the letter
export const chars = { const chars = {
A: { key: "KeyQ", shift: true }, A: { key: "KeyQ", shift: true },
"Ä": { key: "KeyQ", shift: true, accentKey: keyTrema }, "Ä": { key: "KeyQ", shift: true, accentKey: keyTrema },
"Â": { key: "KeyQ", shift: true, accentKey: keyHat }, "Â": { key: "KeyQ", shift: true, accentKey: keyHat },
@ -165,3 +165,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const fr_BE: KeyboardLayout = {
isoCode: "fr-BE",
name: name,
chars: chars
};

View File

@ -1,11 +1,11 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
import { chars as chars_de_CH } from "./de_CH" import { de_CH } from "./de_CH"
export const name = "Français de Suisse"; const name = "Français de Suisse";
export const chars = { const chars = {
...chars_de_CH, ...de_CH.chars,
"è": { key: "BracketLeft" }, "è": { key: "BracketLeft" },
"ü": { key: "BracketLeft", shift: true }, "ü": { key: "BracketLeft", shift: true },
"é": { key: "Semicolon" }, "é": { key: "Semicolon" },
@ -13,3 +13,9 @@ export const chars = {
"à": { key: "Quote" }, "à": { key: "Quote" },
"ä": { key: "Quote", shift: true }, "ä": { key: "Quote", shift: true },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const fr_CH: KeyboardLayout = {
isoCode: "fr-CH",
name: name,
chars: chars
};

View File

@ -1,11 +1,11 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Français"; const name = "Français";
const keyTrema = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel const keyTrema = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel
const keyHat = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter const keyHat = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter
export const chars = { const chars = {
A: { key: "KeyQ", shift: true }, A: { key: "KeyQ", shift: true },
"Ä": { key: "KeyQ", shift: true, accentKey: keyTrema }, "Ä": { key: "KeyQ", shift: true, accentKey: keyTrema },
"Â": { key: "KeyQ", shift: true, accentKey: keyHat }, "Â": { key: "KeyQ", shift: true, accentKey: keyHat },
@ -137,3 +137,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const fr_FR: KeyboardLayout = {
isoCode: "fr-FR",
name: name,
chars: chars
};

View File

@ -1,8 +1,8 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Italiano"; const name = "Italiano";
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
B: { key: "KeyB", shift: true }, B: { key: "KeyB", shift: true },
C: { key: "KeyC", shift: true }, C: { key: "KeyC", shift: true },
@ -111,3 +111,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const it_IT: KeyboardLayout = {
isoCode: "it-IT",
name: name,
chars: chars
};

View File

@ -1,6 +1,6 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Norsk bokmål"; const name = "Norsk bokmål";
const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel
const keyAcute = { key: "Equal", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter const keyAcute = { key: "Equal", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter
@ -8,7 +8,7 @@ const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accen
const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter
const keyTilde = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter const keyTilde = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
"Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, "Ä": { key: "KeyA", shift: true, accentKey: keyTrema },
"Á": { key: "KeyA", shift: true, accentKey: keyAcute }, "Á": { key: "KeyA", shift: true, accentKey: keyAcute },
@ -165,3 +165,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const nb_NO: KeyboardLayout = {
isoCode: "nb-NO",
name: name,
chars: chars
};

View File

@ -1,6 +1,6 @@
import { KeyCombo } from "../keyboardLayouts" import { KeyboardLayout, KeyCombo } from "../keyboardLayouts"
export const name = "Svenska"; const name = "Svenska";
const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel
const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter
@ -8,7 +8,7 @@ const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accen
const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter
const keyTilde = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter const keyTilde = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter
export const chars = { const chars = {
A: { key: "KeyA", shift: true }, A: { key: "KeyA", shift: true },
"Á": { key: "KeyA", shift: true, accentKey: keyAcute }, "Á": { key: "KeyA", shift: true, accentKey: keyAcute },
"Â": { key: "KeyA", shift: true, accentKey: keyHat }, "Â": { key: "KeyA", shift: true, accentKey: keyHat },
@ -162,3 +162,9 @@ export const chars = {
Enter: { key: "Enter" }, Enter: { key: "Enter" },
Tab: { key: "Tab" }, Tab: { key: "Tab" },
} as Record<string, KeyCombo>; } as Record<string, KeyCombo>;
export const sv_SE: KeyboardLayout = {
isoCode: "sv-SE",
name: name,
chars: chars
};

View File

@ -1,17 +1,19 @@
// Key codes and modifiers correspond to definitions in the // Key codes and modifiers correspond to definitions in the
// [Linux USB HID gadget driver](https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt) // [Linux USB HID gadget driver](https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt)
// [Section 10. Keyboard/Keypad Page 0x07](https://usb.org/sites/default/files/hut1_21.pdf)
export const keys = { export const keys = {
ArrowDown: 0x51, ArrowDown: 0x51,
ArrowLeft: 0x50, ArrowLeft: 0x50,
ArrowRight: 0x4f, ArrowRight: 0x4f,
ArrowUp: 0x52, ArrowUp: 0x52,
Backquote: 0x35, Backquote: 0x35, // aka Grave
Backslash: 0x31, Backslash: 0x31,
Backspace: 0x2a, Backspace: 0x2a,
BracketLeft: 0x2f, BracketLeft: 0x2f, // aka LeftBrace
BracketRight: 0x30, BracketRight: 0x30, // aka RightBrace
CapsLock: 0x39, CapsLock: 0x39,
Comma: 0x36, Comma: 0x36,
Compose: 0x65,
ContextMenu: 0, ContextMenu: 0,
Delete: 0x4c, Delete: 0x4c,
Digit0: 0x27, Digit0: 0x27,
@ -40,10 +42,21 @@ export const keys = {
F10: 0x43, F10: 0x43,
F11: 0x44, F11: 0x44,
F12: 0x45, F12: 0x45,
F13: 0x68, F14: 0x69,
F15: 0x6a,
F16: 0x6b,
F17: 0x6c,
F18: 0x6d,
F19: 0x6e,
F20: 0x6f,
F21: 0x70,
F22: 0x71,
F23: 0x72,
F24: 0x73,
Home: 0x4a, Home: 0x4a,
HashTilde: 0x32, // non-US # and ~
Insert: 0x49, Insert: 0x49,
IntlBackslash: 0x64, IntlBackslash: 0x64, // non-US \ and |
KeyA: 0x04, KeyA: 0x04,
KeyB: 0x05, KeyB: 0x05,
KeyC: 0x06, KeyC: 0x06,
@ -72,30 +85,35 @@ export const keys = {
KeyZ: 0x1d, KeyZ: 0x1d,
KeypadExclamation: 0xcf, KeypadExclamation: 0xcf,
Minus: 0x2d, Minus: 0x2d,
NumLock: 0x53, None: 0x00,
Numpad0: 0x62, NumLock: 0x53, // and Clear
Numpad1: 0x59, Numpad0: 0x62, // and Insert
Numpad2: 0x5a, Numpad1: 0x59, // and End
Numpad3: 0x5b, Numpad2: 0x5a, // and Down Arrow
Numpad4: 0x5c, Numpad3: 0x5b, // and Page Down
Numpad4: 0x5c, // and Left Arrow
Numpad5: 0x5d, Numpad5: 0x5d,
Numpad6: 0x5e, Numpad6: 0x5e, // and Right Arrow
Numpad7: 0x5f, Numpad7: 0x5f, // and Home
Numpad8: 0x60, Numpad8: 0x60, // and Up Arrow
Numpad9: 0x61, Numpad9: 0x61, // and Page Up
NumpadAdd: 0x57, NumpadAdd: 0x57,
NumpadComma: 0x85,
NumpadDecimal: 0x63,
NumpadDivide: 0x54, NumpadDivide: 0x54,
NumpadEnter: 0x58, NumpadEnter: 0x58,
NumpadEqual: 0x67, NumpadEqual: 0x67,
NumpadLeftParen: 0xb6,
NumpadMultiply: 0x55, NumpadMultiply: 0x55,
NumpadRightParen: 0xb7,
NumpadSubtract: 0x56, NumpadSubtract: 0x56,
NumpadDecimal: 0x63,
PageDown: 0x4e, PageDown: 0x4e,
PageUp: 0x4b, PageUp: 0x4b,
Period: 0x37, Period: 0x37,
PrintScreen: 0x46, PrintScreen: 0x46,
Pause: 0x48, Pause: 0x48,
Quote: 0x34, Power: 0x66,
Quote: 0x34, // aka Single Quote or Apostrophe
ScrollLock: 0x47, ScrollLock: 0x47,
Semicolon: 0x33, Semicolon: 0x33,
Slash: 0x38, Slash: 0x38,

View File

@ -4,7 +4,7 @@ import { KeyboardLedSync, useSettingsStore } from "@/hooks/stores";
import { useJsonRpc } from "@/hooks/useJsonRpc"; import { useJsonRpc } from "@/hooks/useJsonRpc";
import notifications from "@/notifications"; import notifications from "@/notifications";
import { SettingsPageHeader } from "@components/SettingsPageheader"; import { SettingsPageHeader } from "@components/SettingsPageheader";
import { layouts } from "@/keyboardLayouts"; import { keyboardOptions } from "@/keyboardLayouts";
import { Checkbox } from "@/components/Checkbox"; import { Checkbox } from "@/components/Checkbox";
import { SelectMenuBasic } from "../components/SelectMenuBasic"; import { SelectMenuBasic } from "../components/SelectMenuBasic";
@ -32,7 +32,7 @@ export default function SettingsKeyboardRoute() {
return "en_US"; return "en_US";
}, [keyboardLayout]); }, [keyboardLayout]);
const layoutOptions = Object.entries(layouts).map(([code, language]) => { return { value: code, label: language } }) const layoutOptions = keyboardOptions();
const ledSyncOptions = [ const ledSyncOptions = [
{ value: "auto", label: "Automatic" }, { value: "auto", label: "Automatic" },
{ value: "browser", label: "Browser Only" }, { value: "browser", label: "Browser Only" },

View File

@ -79,7 +79,7 @@ export default function SettingsRoute() {
return () => { return () => {
setDisableVideoFocusTrap(false); setDisableVideoFocusTrap(false);
}; };
}, [setDisableVideoFocusTrap, sendKeyboardEvent]); }, [sendKeyboardEvent, setDisableVideoFocusTrap]);
return ( return (
<div className="pointer-events-auto relative mx-auto max-w-4xl translate-x-0 transform text-left dark:text-white"> <div className="pointer-events-auto relative mx-auto max-w-4xl translate-x-0 transform text-left dark:text-white">

View File

@ -707,7 +707,7 @@ export default function KvmIdRoute() {
}, [diskChannel, file]); }, [diskChannel, file]);
// System update // System update
const disableKeyboardFocusTrap = useUiStore(state => state.disableVideoFocusTrap); const disableVideoFocusTrap = useUiStore(state => state.disableVideoFocusTrap);
const [kvmTerminal, setKvmTerminal] = useState<RTCDataChannel | null>(null); const [kvmTerminal, setKvmTerminal] = useState<RTCDataChannel | null>(null);
const [serialConsole, setSerialConsole] = useState<RTCDataChannel | null>(null); const [serialConsole, setSerialConsole] = useState<RTCDataChannel | null>(null);
@ -805,7 +805,7 @@ export default function KvmIdRoute() {
)} )}
<div className="relative h-full"> <div className="relative h-full">
<FocusTrap <FocusTrap
paused={disableKeyboardFocusTrap} paused={disableVideoFocusTrap}
focusTrapOptions={{ focusTrapOptions={{
allowOutsideClick: true, allowOutsideClick: true,
escapeDeactivates: false, escapeDeactivates: false,