Compare commits

..

No commits in common. "c2b4c5b243658509007c738e06fe8513e71f1cf0" and "a1e9b85eb176cdbc23cebbee9633c8c357ad2275" have entirely different histories.

7 changed files with 149 additions and 177 deletions

View File

@ -9,19 +9,6 @@
},
"mounts": [
"source=${localEnv:HOME}/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached"
],
"customizations": {
"vscode": {
"extensions": [
"bradlc.vscode-tailwindcss",
"GitHub.vscode-pull-request-github",
"dbaeumer.vscode-eslint",
"golang.go",
"ms-vscode.makefile-tools",
"esbenp.prettier-vscode",
"github.vscode-github-actions"
]
}
}
}

View File

@ -1,3 +0,0 @@
{
"tailwindCSS.classFunctions": ["cva", "cx"]
}

View File

@ -85,7 +85,6 @@ type Config struct {
HashedPassword string `json:"hashed_password"`
LocalAuthToken string `json:"local_auth_token"`
LocalAuthMode string `json:"localAuthMode"` //TODO: fix it with migration
LocalLoopbackOnly bool `json:"local_loopback_only"`
WakeOnLanDevices []WakeOnLanDevice `json:"wake_on_lan_devices"`
KeyboardMacros []KeyboardMacro `json:"keyboard_macros"`
KeyboardLayout string `json:"keyboard_layout"`
@ -96,6 +95,7 @@ type Config struct {
DisplayDimAfterSec int `json:"display_dim_after_sec"`
DisplayOffAfterSec int `json:"display_off_after_sec"`
TLSMode string `json:"tls_mode"` // options: "self-signed", "user-defined", ""
LocalWebServerLoopbackOnly bool `json:"local_web_server_loopback_only"`
UsbConfig *usbgadget.Config `json:"usb_config"`
UsbDevices *usbgadget.Devices `json:"usb_devices"`
NetworkConfig *network.NetworkConfig `json:"network_config"`
@ -116,6 +116,7 @@ var defaultConfig = &Config{
DisplayDimAfterSec: 120, // 2 minutes
DisplayOffAfterSec: 1800, // 30 minutes
TLSMode: "",
LocalWebServerLoopbackOnly: false, // Allow access from any network interface by default
UsbConfig: &usbgadget.Config{
VendorId: "0x1d6b", //The Linux Foundation
ProductId: "0x0104", //Multifunction Composite Gadget

View File

@ -1006,18 +1006,18 @@ func setKeyboardMacros(params KeyboardMacrosParams) (interface{}, error) {
return nil, nil
}
func rpcGetLocalLoopbackOnly() (bool, error) {
return config.LocalLoopbackOnly, nil
func rpcGetLocalWebServerLoopbackOnly() (bool, error) {
return config.LocalWebServerLoopbackOnly, nil
}
func rpcSetLocalLoopbackOnly(enabled bool) error {
func rpcSetLocalWebServerLoopbackOnly(enabled bool) error {
// Check if the setting is actually changing
if config.LocalLoopbackOnly == enabled {
if config.LocalWebServerLoopbackOnly == enabled {
return nil
}
// Update the setting
config.LocalLoopbackOnly = enabled
config.LocalWebServerLoopbackOnly = enabled
if err := SaveConfig(); err != nil {
return fmt.Errorf("failed to save config: %w", err)
}
@ -1102,6 +1102,6 @@ var rpcHandlers = map[string]RPCHandler{
"setKeyboardLayout": {Func: rpcSetKeyboardLayout, Params: []string{"layout"}},
"getKeyboardMacros": {Func: getKeyboardMacros},
"setKeyboardMacros": {Func: setKeyboardMacros, Params: []string{"params"}},
"getLocalLoopbackOnly": {Func: rpcGetLocalLoopbackOnly},
"setLocalLoopbackOnly": {Func: rpcSetLocalLoopbackOnly, Params: []string{"enabled"}},
"getLocalWebServerLoopbackOnly": {Func: rpcGetLocalWebServerLoopbackOnly},
"setLocalWebServerLoopbackOnly": {Func: rpcSetLocalWebServerLoopbackOnly, Params: []string{"enabled"}},
}

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { LuCornerDownLeft } from "react-icons/lu";
import { ExclamationCircleIcon } from "@heroicons/react/16/solid";
import { useClose } from "@headlessui/react";
@ -39,13 +39,6 @@ export default function PasteModal() {
state => state.setKeyboardLayout,
);
// this ensures we always get the original en-US if it hasn't been set yet
const safeKeyboardLayout = useMemo(() => {
if (keyboardLayout && keyboardLayout.length > 0)
return keyboardLayout;
return "en-US";
}, [keyboardLayout]);
useEffect(() => {
send("getKeyboardLayout", {}, resp => {
if ("error" in resp) return;
@ -63,13 +56,14 @@ export default function PasteModal() {
setPasteMode(false);
setDisableVideoFocusTrap(false);
if (rpcDataChannel?.readyState !== "open" || !TextAreaRef.current) return;
if (!safeKeyboardLayout) return;
if (!chars[safeKeyboardLayout]) return;
if (!keyboardLayout) return;
if (!chars[keyboardLayout]) return;
const text = TextAreaRef.current.value;
try {
for (const char of text) {
const { key, shift, altRight, deadKey, accentKey } = chars[safeKeyboardLayout][char]
const { key, shift, altRight, deadKey, accentKey } = chars[keyboardLayout][char]
if (!key) continue;
const keyz = [ keys[key] ];
@ -104,7 +98,7 @@ export default function PasteModal() {
console.error(error);
notifications.error("Failed to paste text");
}
}, [rpcDataChannel?.readyState, send, setDisableVideoFocusTrap, setPasteMode, safeKeyboardLayout]);
}, [rpcDataChannel?.readyState, send, setDisableVideoFocusTrap, setPasteMode, keyboardLayout]);
useEffect(() => {
if (TextAreaRef.current) {
@ -154,7 +148,7 @@ export default function PasteModal() {
// @ts-expect-error TS doesn't recognize Intl.Segmenter in some environments
[...new Intl.Segmenter().segment(value)]
.map(x => x.segment)
.filter(char => !chars[safeKeyboardLayout][char]),
.filter(char => !chars[keyboardLayout][char]),
),
];
@ -175,7 +169,7 @@ export default function PasteModal() {
</div>
<div className="space-y-4">
<p className="text-xs text-slate-600 dark:text-slate-400">
Sending text using keyboard layout: {layouts[safeKeyboardLayout]}
Sending text using keyboard layout: {layouts[keyboardLayout]}
</p>
</div>
</div>

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo } from "react";
import { useCallback, useEffect } from "react";
import { KeyboardLedSync, useSettingsStore } from "@/hooks/stores";
import { useJsonRpc } from "@/hooks/useJsonRpc";
@ -20,13 +20,6 @@ export default function SettingsKeyboardRoute() {
state => state.setKeyboardLedSync,
);
// this ensures we always get the original en-US if it hasn't been set yet
const safeKeyboardLayout = useMemo(() => {
if (keyboardLayout && keyboardLayout.length > 0)
return keyboardLayout;
return "en-US";
}, [keyboardLayout]);
const layoutOptions = Object.entries(layouts).map(([code, language]) => { return { value: code, label: language } })
const ledSyncOptions = [
{ value: "auto", label: "Automatic" },
@ -76,7 +69,7 @@ export default function SettingsKeyboardRoute() {
size="SM"
label=""
fullWidth
value={safeKeyboardLayout}
value={keyboardLayout}
onChange={onKeyboardLayoutChange}
options={layoutOptions}
/>

8
web.go
View File

@ -54,7 +54,7 @@ type ChangePasswordRequest struct {
type LocalDevice struct {
AuthMode *string `json:"authMode"`
DeviceID string `json:"deviceId"`
LoopbackOnly bool `json:"loopbackOnly"`
LocalWebServerLoopbackOnly bool `json:"localWebServerLoopbackOnly"`
}
type DeviceStatus struct {
@ -536,11 +536,11 @@ func RunWebServer() {
// Determine the binding address based on the config
bindAddress := ":80" // Default to all interfaces
if config.LocalLoopbackOnly {
if config.LocalWebServerLoopbackOnly {
bindAddress = "localhost:80" // Loopback only (both IPv4 and IPv6)
}
logger.Info().Str("bindAddress", bindAddress).Bool("loopbackOnly", config.LocalLoopbackOnly).Msg("Starting web server")
logger.Info().Str("bindAddress", bindAddress).Bool("loopbackOnly", config.LocalWebServerLoopbackOnly).Msg("Starting web server")
err := r.Run(bindAddress)
if err != nil {
panic(err)
@ -551,7 +551,7 @@ func handleDevice(c *gin.Context) {
response := LocalDevice{
AuthMode: &config.LocalAuthMode,
DeviceID: GetDeviceID(),
LoopbackOnly: config.LocalLoopbackOnly,
LocalWebServerLoopbackOnly: config.LocalWebServerLoopbackOnly,
}
c.JSON(http.StatusOK, response)