Compare commits
7 commits
e6a690272e
...
82f5db3890
Author | SHA1 | Date | |
---|---|---|---|
82f5db3890 | |||
aa4f359349 | |||
9339cdbd93 | |||
d1cefa4131 | |||
7915a0dbe4 | |||
7128ba2425 | |||
a3ee86f81b |
2
Makefile
2
Makefile
|
@ -19,4 +19,4 @@ build: deps
|
|||
CGO_ENABLED=$(CGO_ENABLED) GOARCH=amd64 GOOS=linux $(CC) $(CFLAGS) -o $(BUILD_DIR)/$(LINUX_BIN) -ldflags="$(LDFLAGS)" -gcflags="$(GCFLAGS)" -asmflags="$(ASMFLAGS)"
|
||||
|
||||
watch:
|
||||
gowatch -o build/app-live-linux-amd64
|
||||
gowatch -o build/app-live-linux-amd64 -args='./config.yaml'
|
||||
|
|
Binary file not shown.
57
config.go
Normal file
57
config.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v3"
|
||||
"os"
|
||||
)
|
||||
|
||||
type ServerAuthConfig struct {
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Listen string `yaml:"listen"`
|
||||
Auth ServerAuthConfig `yaml:"auth"`
|
||||
}
|
||||
|
||||
type RemoteItemConfigItem struct {
|
||||
Label string `yaml:"label"`
|
||||
Message string `yaml:"message"`
|
||||
}
|
||||
|
||||
type RemoteItemConfig struct {
|
||||
Type string `yaml:"type"`
|
||||
Label string `yaml:"label"`
|
||||
Items []RemoteItemConfigItem `yaml:"items"`
|
||||
}
|
||||
|
||||
type RemoteItem struct {
|
||||
Label string `yaml:"label"`
|
||||
Items []RemoteItemConfig `yaml:"items"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig `yaml:"server"`
|
||||
Remote []RemoteItem `yaml:"remote"`
|
||||
}
|
||||
|
||||
func createConfigFromFile(file string) (Config, error) {
|
||||
data, err := os.ReadFile(file)
|
||||
value := Config{}
|
||||
|
||||
if err != nil {
|
||||
return value, err
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(data, &value)
|
||||
|
||||
if err != nil {
|
||||
return value, err
|
||||
}
|
||||
|
||||
fmt.Printf("%+v\n", value)
|
||||
|
||||
return value, nil
|
||||
}
|
104
config.yaml
Normal file
104
config.yaml
Normal file
|
@ -0,0 +1,104 @@
|
|||
server:
|
||||
auth:
|
||||
username: admin
|
||||
password: admin
|
||||
listen: 0.0.0.0:4000
|
||||
|
||||
remote:
|
||||
- label: Keyboard
|
||||
items:
|
||||
- type: live_text
|
||||
label: Live text
|
||||
- type: text
|
||||
label: Text
|
||||
- type: keys
|
||||
label: Keys
|
||||
- type: shortcuts
|
||||
label: Shortcuts
|
||||
- label: i3
|
||||
items:
|
||||
- type: messages
|
||||
label: Workspaces
|
||||
items:
|
||||
- label: '1. DBL'
|
||||
message: '{"type":"workspace","value":"1. DBL"}'
|
||||
- label: '2. WWW'
|
||||
message: '{"type":"workspace","value":"2. WWW"}'
|
||||
- label: '3. MAIL'
|
||||
message: '{"type":"workspace","value":"3. MAIL"}'
|
||||
- label: '4. IM'
|
||||
message: '{"type":"workspace","value":"4. IM"}'
|
||||
- label: '5'
|
||||
message: '{"type":"workspace","value":"5"}'
|
||||
- label: '6. MEDIA'
|
||||
message: '{"type":"workspace","value":"6. MEDIA"}'
|
||||
- label: '7. DEV'
|
||||
message: '{"type":"workspace","value":"7. DEV"}'
|
||||
- label: '8. DEV'
|
||||
message: '{"type":"workspace","value":"8. DEV"}'
|
||||
- label: '9. DEV'
|
||||
message: '{"type":"workspace","value":"9. DEV"}'
|
||||
- label: '10'
|
||||
message: '{"type":"workspace","value":"10"}'
|
||||
- label: '11'
|
||||
message: '{"type":"workspace","value":"11"}'
|
||||
- label: '12'
|
||||
message: '{"type":"workspace","value":"12"}'
|
||||
|
||||
- type: messages
|
||||
label: Software
|
||||
items:
|
||||
- label: 'alacritty'
|
||||
message: '{"type":"messages","value":[{"type":"keys","value":"win,d"},{"type":"text","value":"alacritty"},{"type":"key","value":"enter"}]}'
|
||||
- label: 'dmenu'
|
||||
message: '{"type":"keys","value":"win,d"}'
|
||||
|
||||
- type: messages
|
||||
label: UI
|
||||
items:
|
||||
- label: 'win+z'
|
||||
message: '{"type":"keys","value":"win,z"}'
|
||||
- label: 'win+e'
|
||||
message: '{"type":"keys","value":"win,e"}'
|
||||
- label: 'zp'
|
||||
message: '{"type":"messages","value":[{"type":"text","value":"zp"},{"type":"key","value":"enter"}]}'
|
||||
- label: 'zm'
|
||||
message: '{"type":"messages","value":[{"type":"text","value":"zm"},{"type":"key","value":"enter"}]}'
|
||||
|
||||
- type: messages
|
||||
label: Screensaver
|
||||
items:
|
||||
- label: 'ON'
|
||||
message: '{"type":"messages","value":[{"type":"keys","value":"win,d"},{"type":"text","value":"no-screensaver"},{"type":"key","value":"enter"}]}'
|
||||
- label: 'OFF'
|
||||
message: '{"type":"messages","value":[{"type":"keys","value":"win,d"},{"type":"text","value":"pkill no-screensaver"},{"type":"key","value":"enter"}]}'
|
||||
|
||||
- type: messages
|
||||
label: Movie
|
||||
items:
|
||||
- label: 'v;mll'
|
||||
message: '{"type":"messages","value":[{"type":"text","value":"v;mll"},{"type":"key","value":"enter"}]}'
|
||||
- label: 'mup'
|
||||
message: '{"type":"messages","value":[{"type":"text","value":"mup"},{"type":"key","value":"enter"}]}'
|
||||
- label: 'mug'
|
||||
message: '{"type":"messages","value":[{"type":"text","value":"mug"},{"type":"key","value":"enter"}]}'
|
||||
- label: 'mup 1'
|
||||
message: '{"type":"messages","value":[{"type":"text","value":"mup 1"},{"type":"key","value":"enter"}]}'
|
||||
- label: 'mug 1'
|
||||
message: '{"type":"messages","value":[{"type":"text","value":"mug 1"},{"type":"key","value":"enter"}]}'
|
||||
|
||||
- label: Mouse
|
||||
items:
|
||||
- type: mouse
|
||||
- label: Media
|
||||
items:
|
||||
- type: spotify
|
||||
label: Spotify
|
||||
- type: volume
|
||||
label: Volume
|
||||
- label: Desktop
|
||||
items:
|
||||
- type: screenshot
|
||||
label: Screenshot
|
||||
- type: live_video
|
||||
label: Live video
|
1
go.mod
1
go.mod
|
@ -21,4 +21,5 @@ require (
|
|||
golang.org/x/sys v0.11.0 // indirect
|
||||
golang.org/x/text v0.12.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
2
go.sum
2
go.sum
|
@ -65,3 +65,5 @@ golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -5,6 +5,12 @@ import (
|
|||
"net/http"
|
||||
)
|
||||
|
||||
func homeController(c echo.Context) error {
|
||||
return c.HTML(http.StatusOK, view("views/page/home.html", nil))
|
||||
type HomeViewParams struct {
|
||||
Config Config
|
||||
}
|
||||
|
||||
func homeController(c echo.Context) error {
|
||||
return c.HTML(http.StatusOK, view("views/page/home.html", HomeViewParams{
|
||||
Config: config,
|
||||
}))
|
||||
}
|
||||
|
|
34
main.go
34
main.go
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"crypto/subtle"
|
||||
"embed"
|
||||
"fmt"
|
||||
rice "github.com/GeertJohan/go.rice"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
|
@ -16,41 +17,48 @@ var (
|
|||
//go:embed static
|
||||
staticFiles embed.FS
|
||||
//go:embed views/layout views/page
|
||||
views embed.FS
|
||||
views embed.FS
|
||||
config Config
|
||||
)
|
||||
|
||||
func main() {
|
||||
e := echo.New()
|
||||
e.HideBanner = true
|
||||
|
||||
RI3_USERNAME := os.Getenv("RI3_USERNAME")
|
||||
RI3_PASSWORD := os.Getenv("RI3_PASSWORD")
|
||||
RI3_BIND := os.Getenv("RI3_BIND")
|
||||
|
||||
if RI3_BIND == "" {
|
||||
RI3_BIND = "0.0.0.0:4000"
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Errorf("Configuration required!")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
assetHandler := http.FileServer(rice.MustFindBox("static").HTTPBox())
|
||||
value, err := createConfigFromFile(os.Args[1])
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Configuration error:")
|
||||
fmt.Printf("%+v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
config = value
|
||||
e.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
|
||||
if RI3_USERNAME == "" && RI3_PASSWORD == "" {
|
||||
if config.Server.Auth.Username == "" && config.Server.Auth.Password == "" {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
isValidUsername := subtle.ConstantTimeCompare([]byte(username), []byte(RI3_USERNAME)) == 1
|
||||
isValidPassword := subtle.ConstantTimeCompare([]byte(password), []byte(RI3_PASSWORD)) == 1
|
||||
isValidUsername := subtle.ConstantTimeCompare([]byte(username), []byte(config.Server.Auth.Username)) == 1
|
||||
isValidPassword := subtle.ConstantTimeCompare([]byte(password), []byte(config.Server.Auth.Password)) == 1
|
||||
|
||||
if isValidUsername && isValidPassword {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}))
|
||||
|
||||
e.GET("/", echo.WrapHandler(assetHandler))
|
||||
assetHandler := http.FileServer(rice.MustFindBox("static").HTTPBox())
|
||||
|
||||
e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", assetHandler)))
|
||||
e.GET("/", homeController)
|
||||
e.GET("/ws", wsController)
|
||||
|
||||
e.Logger.Fatal(e.Start(RI3_BIND))
|
||||
e.Logger.Fatal(e.Start(config.Server.Listen))
|
||||
}
|
||||
|
|
12
rice-box.go
12
rice-box.go
File diff suppressed because one or more lines are too long
|
@ -58,9 +58,12 @@ a {
|
|||
}
|
||||
|
||||
#pointer {
|
||||
height: calc(100vh - 80px);
|
||||
height: calc(100vh - 33px - 38px);
|
||||
top: calc(33px + 38px);
|
||||
margin: auto;
|
||||
background: #ccc;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
|
@ -78,24 +81,17 @@ a {
|
|||
right: 0;
|
||||
}
|
||||
|
||||
.fullscreen #scrollbar {
|
||||
height: calc(100vh - 150px);
|
||||
}
|
||||
|
||||
.fullscreen #pointer {
|
||||
height: calc(100vh - 150px);
|
||||
}
|
||||
|
||||
#pane-pointer .form-group {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#pointer-buttons {
|
||||
position: absolute;
|
||||
margin-top: -42px;
|
||||
width: 100%;
|
||||
z-index: 110;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#pointer-buttons .btn {
|
||||
|
|
|
@ -257,11 +257,9 @@ var documentHashHandler = function() {
|
|||
var hash = window.location.hash;
|
||||
|
||||
if (hash) {
|
||||
$(hash).show();
|
||||
$('a[href="' + hash + '"]').addClass('active');
|
||||
$('a[href="' + hash + '"]').click();
|
||||
} else {
|
||||
$('#pane-keyboard').show();
|
||||
$('#nav a').first().addClass('active');
|
||||
$('#nav > li:first-child a').click();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,10 +292,10 @@ var addListeners = function() {
|
|||
}
|
||||
|
||||
var bootstrap = function() {
|
||||
documentHashHandler();
|
||||
shortcutsSpecialKeysOnChangeHandler();
|
||||
createWebSocketConnection();
|
||||
addListeners();
|
||||
documentHashHandler();
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
|
|
@ -4,21 +4,11 @@
|
|||
<div class="row no-margin">
|
||||
<div class="col-12 no-padding">
|
||||
<ul class="nav nav-pills nav-fill" id="nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link no-radius" href="#pane-keyboard">KEYBOARD</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link no-radius" href="#pane-i3">I3</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link no-radius" href="#pane-pointer">MOUSE</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link no-radius" href="#pane-media">MEDIA</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link no-radius" href="#pane-desktop">DESKTOP</a>
|
||||
</li>
|
||||
{{range $key, $tab := .Config.Remote}}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link no-radius" href="#tab-{{$key}}">{{$tab.Label}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link no-radius btn-fullscreen" data-target="html" href="#">💻</a>
|
||||
</li>
|
||||
|
@ -28,76 +18,138 @@
|
|||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div id="pane-keyboard" class="pane">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="legend">Live text</p>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<input type="text" class="form-control live-text" name="text">
|
||||
</div>
|
||||
{{range $key, $tab := .Config.Remote}}
|
||||
<div id="tab-{{$key}}" class="pane">
|
||||
{{range $key2, $value := $tab.Items}}
|
||||
<div class="row" {{if eq $value.Type "mouse"}} id="pane-pointer"{{end}}>
|
||||
{{if ne $value.Label ""}}
|
||||
<div class="col-12">
|
||||
<p class="legend">{{$value.Label}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "live_text"}}
|
||||
<div class="form-group col-12">
|
||||
<input type="text" class="form-control live-text" name="text">
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "text"}}
|
||||
<div class="form-group col-6">
|
||||
<input type="text" class="form-control" id="text">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button type="button" id="text-send" class="btn btn-primary">Send</button>
|
||||
<button type="button" id="text-clear" class="btn btn-secondary">Clear</button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "keys"}}
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"key","value":"left"}' class="btn btn-secondary">←</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"up"}' class="btn btn-secondary">↑</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"down"}' class="btn btn-secondary">↓</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"right"}' class="btn btn-secondary">→</button>
|
||||
</div>
|
||||
<div class="line col-12"></div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"key","value":"escape"}' class="btn btn-secondary">Escape</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"tab"}' class="btn btn-secondary">TAB</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"backspace"}' class="btn btn-secondary">Backspace</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"enter"}' class="btn btn-secondary">Enter</button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "shortcuts"}}
|
||||
<div class="col-9" id="shortcuts_special_keys">
|
||||
<label class="btn btn-secondary" for="shortcuts_special_key_ctrl">
|
||||
<input type="checkbox" value="ctrl" id="shortcuts_special_key_ctrl">
|
||||
ctrl
|
||||
</label>
|
||||
<label class="btn btn-secondary" for="shortcuts_special_key_shift">
|
||||
<input type="checkbox" value="shift" id="shortcuts_special_key_shift">
|
||||
shift
|
||||
</label>
|
||||
<label class="btn btn-secondary" for="shortcuts_special_key_alt">
|
||||
<input type="checkbox" value="alt" id="shortcuts_special_key_alt">
|
||||
alt
|
||||
</label>
|
||||
<label class="btn btn-secondary" for="shortcuts_special_key_win">
|
||||
<input type="checkbox" value="win" id="shortcuts_special_key_win">
|
||||
win
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group col-3">
|
||||
<input type="text" id="shortcut-key" class="form-control" name="shortcuts_char">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" id="shortcut-send" class="btn btn-primary">Send</button>
|
||||
<button type="button" id="shortcut-clear" class="btn btn-secondary">Clear</button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "spotify"}}
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"media","value":"playpause"}' class="btn btn-secondary">Play/Pause</button>
|
||||
<button type="button" data-msg='{"type":"media","value":"next"}' class="btn btn-secondary">Next</button>
|
||||
<button type="button" data-msg='{"type":"media","value":"prev"}' class="btn btn-secondary">Previous</button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "volume"}}
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"volume","value":"0"}' class="btn btn-secondary">0%</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"25"}' class="btn btn-secondary">25%</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"50"}' class="btn btn-secondary">50%</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"75"}' class="btn btn-secondary">75%</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"100"}' class="btn btn-secondary">100%</button>
|
||||
</div>
|
||||
<div class="line col-12"></div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"volume","value":"down"}' class="btn btn-secondary">-</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"up"}' class="btn btn-secondary">+</button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "mouse"}}
|
||||
<div class="form-group col-12">
|
||||
<input type="text" class="form-control live-text" placeholder="Live text" name="text">
|
||||
</div/>
|
||||
<div id="scrollbar"></div>
|
||||
<div id="pointer"></div>
|
||||
<div id="pointer-buttons">
|
||||
<button type="button" data-msg='{"type":"pointer","click":"left"}' class="btn btn-primary no-radius col-5"> </button><button type="button no-margin" data-msg='{"type":"pointer","click":"middle"}' class="btn btn-secondary no-radius col-2"> </button><button type="button no-margin" data-msg='{"type":"pointer","click":"right"}' class="btn btn-primary no-radius col-5"> </button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "screenshot"}}
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"screenshot","quality":"hq"}' class="btn btn-secondary">Screenshot HQ</button>
|
||||
<button type="button" data-msg='{"type":"screenshot","quality":"lq"}' class="btn btn-secondary">Screenshot LQ</button>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "live_video"}}
|
||||
<div class="col-12">
|
||||
<button type="button" id="live-hq" class="btn btn-secondary">Live HQ</button>
|
||||
<button type="button" id="live-lq" class="btn btn-secondary">Live LQ</button>
|
||||
<div id="screenshot"><img class="btn-fullscreen" data-target="#screenshot img" src="data:image/png; base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gIJDjc3srQk8gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAADElEQVQI12P48+cPAAXsAvVTWDc6AAAAAElFTkSuQmCC"></div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if eq $value.Type "messages"}}
|
||||
<div class="col-12">
|
||||
{{range $key3, $item := $value.Items}}
|
||||
<button type="button" data-msg='{{$item.Message}}' class="btn btn-secondary mb-1">{{$item.Label}}</button>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="line col-12"></div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="legend">TEXT</p>
|
||||
</div>
|
||||
<div class="form-group col-6">
|
||||
<input type="text" class="form-control" id="text">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<button type="button" id="text-send" class="btn btn-primary">Send</button>
|
||||
<button type="button" id="text-clear" class="btn btn-secondary">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="legend">Keys</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"key","value":"left"}' class="btn btn-secondary">←</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"up"}' class="btn btn-secondary">↑</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"down"}' class="btn btn-secondary">↓</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"right"}' class="btn btn-secondary">→</button>
|
||||
</div>
|
||||
<div class="line col-12"></div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"key","value":"escape"}' class="btn btn-secondary">Escape</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"tab"}' class="btn btn-secondary">TAB</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"backspace"}' class="btn btn-secondary">Backspace</button>
|
||||
<button type="button" data-msg='{"type":"key","value":"enter"}' class="btn btn-secondary">Enter</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="legend">Shortcuts</p>
|
||||
</div>
|
||||
<div class="col-9" id="shortcuts_special_keys">
|
||||
<label class="btn btn-secondary" for="shortcuts_special_key_ctrl">
|
||||
<input type="checkbox" value="ctrl" id="shortcuts_special_key_ctrl">
|
||||
ctrl
|
||||
</label>
|
||||
<label class="btn btn-secondary" for="shortcuts_special_key_shift">
|
||||
<input type="checkbox" value="shift" id="shortcuts_special_key_shift">
|
||||
shift
|
||||
</label>
|
||||
<label class="btn btn-secondary" for="shortcuts_special_key_alt">
|
||||
<input type="checkbox" value="alt" id="shortcuts_special_key_alt">
|
||||
alt
|
||||
</label>
|
||||
<label class="btn btn-secondary" for="shortcuts_special_key_win">
|
||||
<input type="checkbox" value="win" id="shortcuts_special_key_win">
|
||||
win
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group col-3">
|
||||
<input type="text" id="shortcut-key" class="form-control" name="shortcuts_char">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" id="shortcut-send" class="btn btn-primary">Send</button>
|
||||
<button type="button" id="shortcut-clear" class="btn btn-secondary">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div id="pane-i3" class="pane">
|
||||
<div class="row">
|
||||
|
@ -121,97 +173,6 @@
|
|||
<button type="button" data-msg='{"type":"workspace","value":"12"}' class="btn btn-secondary btn-sm">12</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="legend">Software</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"keys","value":"win,d"},{"type":"text","value":"urxvt"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">urxvt</button>
|
||||
<button type="button" data-msg='{"type":"keys","value":"win,d"}' class="btn btn-secondary">dmenu</button>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<p class="legend">UI</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"keys","value":"win,z"}' class="btn btn-secondary">win+z</button>
|
||||
<button type="button" data-msg='{"type":"keys","value":"win,x"}' class="btn btn-secondary">win+x</button>
|
||||
<button type="button" data-msg='{"type":"keys","value":"win,c"}' class="btn btn-secondary">win+c</button>
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"text","value":"zp"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">zp</button>
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"text","value":"zm"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">zm</button>
|
||||
</div>
|
||||
<div class="line col-12"></div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"keys","value":"win,d"},{"type":"text","value":"no-screensaver"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">no-screensaver[on]</button>
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"keys","value":"win,d"},{"type":"text","value":"pkill no-screensaver"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">no-screensaver[off]</button>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<p class="legend">Movie</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"text","value":"v;mll"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">v;mll</button>
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"text","value":"rt -l"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">rt -l</button>
|
||||
</div>
|
||||
<div class="line col-12"></div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"text","value":"mug"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">mug</button>
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"text","value":"mup"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">mup</button>
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"text","value":"mug 1"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">mug 1</button>
|
||||
<button type="button" data-msg='{"type":"messages","value":[{"type":"text","value":"mup 1"},{"type":"key","value":"enter"}]}' class="btn btn-secondary">mup 1</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row pane" id="pane-pointer">
|
||||
<div class="form-group col-12">
|
||||
<input type="text" class="form-control live-text" placeholder="Live text" name="text">
|
||||
</div/>
|
||||
<div id="scrollbar"></div>
|
||||
<div id="pointer"></div>
|
||||
<div id="pointer-buttons">
|
||||
<button type="button" data-msg='{"type":"pointer","click":"left"}' class="btn btn-primary no-radius col-5"> </button><button type="button no-margin" data-msg='{"type":"pointer","click":"middle"}' class="btn btn-secondary no-radius col-2"> </button><button type="button no-margin" data-msg='{"type":"pointer","click":"right"}' class="btn btn-primary no-radius col-5"> </button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row pane" id="pane-media">
|
||||
<div class="col-12">
|
||||
<p class="legend">Spotify</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"media","value":"playpause"}' class="btn btn-secondary">Play/Pause</button>
|
||||
<button type="button" data-msg='{"type":"media","value":"next"}' class="btn btn-secondary">Next</button>
|
||||
<button type="button" data-msg='{"type":"media","value":"prev"}' class="btn btn-secondary">Previous</button>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<p class="legend">Volume</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"volume","value":"0"}' class="btn btn-secondary">0%</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"25"}' class="btn btn-secondary">25%</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"50"}' class="btn btn-secondary">50%</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"75"}' class="btn btn-secondary">75%</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"100"}' class="btn btn-secondary">100%</button>
|
||||
</div>
|
||||
<div class="line col-12"></div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"volume","value":"down"}' class="btn btn-secondary">-</button>
|
||||
<button type="button" data-msg='{"type":"volume","value":"up"}' class="btn btn-secondary">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pane" id="pane-desktop">
|
||||
<div class="col-12">
|
||||
<p class="legend">Desktop</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<button type="button" data-msg='{"type":"screenshot","quality":"hq"}' class="btn btn-sm btn-secondary">Screenshot HQ</button>
|
||||
<button type="button" data-msg='{"type":"screenshot","quality":"lq"}' class="btn btn-sm btn-secondary">Screenshot LQ</button>
|
||||
<button type="button" id="live-hq" class="btn btn-sm btn-secondary">Live HQ</button>
|
||||
<button type="button" id="live-lq" class="btn btn-sm btn-secondary">Live LQ</button>
|
||||
<div id="screenshot"><img class="btn-fullscreen" data-target="#screenshot img" src="data:image/png; base64, iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gIJDjc3srQk8gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAADElEQVQI12P48+cPAAXsAvVTWDc6AAAAAElFTkSuQmCC"></div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
Loading…
Reference in a new issue