added other dsconnect settings

This commit is contained in:
2026-02-19 11:13:14 +01:00
parent 019c60689e
commit 09af99946e
13 changed files with 204 additions and 35 deletions
+41 -7
View File
@@ -26,9 +26,10 @@ type Handler struct {
DetachDevice func(clientID, busID string) error
SetAutoConnect func(vendorID, productID string, enabled bool) error
IsAutoConnect func(vendorID, productID string) bool
InstallService func() error
UninstallService func() error
GetStatus func() map[string]interface{}
ForceDetachDevice func(clientID, busID string) error
InstallService func() error
UninstallService func() error
GetStatus func() map[string]interface{}
}
// NewHandler creates a new web handler
@@ -57,6 +58,7 @@ func (h *Handler) setupRoutes() {
h.mux.HandleFunc("/api/generate-token", h.handleGenerateToken)
h.mux.HandleFunc("/api/apply-tokens", h.handleApplyTokens)
h.mux.HandleFunc("/api/auto-connect", h.handleAutoConnect)
h.mux.HandleFunc("/api/force-detach", h.handleForceDetach)
h.mux.HandleFunc("/api/service/install", h.handleServiceInstall)
h.mux.HandleFunc("/api/service/uninstall", h.handleServiceUninstall)
}
@@ -164,10 +166,11 @@ func (h *Handler) handleConfig(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
var updates struct {
RelayAddr string `json:"relay_addr"`
Mode string `json:"mode"`
Name string `json:"name"`
WebPort int `json:"web_port"`
RelayAddr string `json:"relay_addr"`
Mode string `json:"mode"`
Name string `json:"name"`
WebPort int `json:"web_port"`
AllowForceDetach *bool `json:"allow_force_detach,omitempty"`
}
if err := json.NewDecoder(r.Body).Decode(&updates); err != nil {
writeJSON(w, map[string]interface{}{"ok": false, "error": "invalid request"})
@@ -186,6 +189,9 @@ func (h *Handler) handleConfig(w http.ResponseWriter, r *http.Request) {
if updates.WebPort > 0 {
h.cfg.WebPort = updates.WebPort
}
if updates.AllowForceDetach != nil {
h.cfg.AllowForceDetach = *updates.AllowForceDetach
}
if err := h.cfg.Save(h.cfgPath); err != nil {
writeJSON(w, map[string]interface{}{"ok": false, "error": err.Error()})
@@ -284,6 +290,34 @@ func (h *Handler) handleAutoConnect(w http.ResponseWriter, r *http.Request) {
writeJSON(w, map[string]interface{}{"ok": true})
}
func (h *Handler) handleForceDetach(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", 405)
return
}
var req struct {
ClientID string `json:"client_id"`
BusID string `json:"bus_id"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeJSON(w, map[string]interface{}{"ok": false, "error": "invalid request"})
return
}
if h.ForceDetachDevice == nil {
writeJSON(w, map[string]interface{}{"ok": false, "error": "not in use mode"})
return
}
if err := h.ForceDetachDevice(req.ClientID, req.BusID); err != nil {
writeJSON(w, map[string]interface{}{"ok": false, "error": err.Error()})
return
}
writeJSON(w, map[string]interface{}{"ok": true})
}
func (h *Handler) handleServiceInstall(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", 405)
+22 -1
View File
@@ -147,7 +147,8 @@ function renderUseDevices(container, available, attached) {
</div>
<div class="device-status">
${dev.status === 'in_use'
? '<span class="badge in-use">In Benutzung</span>'
? `<span class="badge in-use">In Benutzung</span>
${dev.allow_force_detach ? `<button class="btn small danger" onclick="forceDetach('${clientId}', '${dev.bus_id}')">Trennen</button>` : ''}`
: isAttached
? '<span class="badge attached">Verbunden</span>'
: `<span class="badge available">Verfuegbar</span>
@@ -197,6 +198,24 @@ async function detachDevice(clientId, busId) {
}
}
// Force detach
async function forceDetach(clientId, busId) {
try {
const resp = await fetch(API_BASE + '/api/force-detach', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ client_id: clientId, bus_id: busId })
});
const data = await resp.json();
if (!data.ok) {
alert('Fehler: ' + (data.error || 'Unbekannt'));
}
updateDevices();
} catch (e) {
alert('Verbindungsfehler: ' + e.message);
}
}
// Auto-connect toggle
async function toggleAutoConnect(vendorId, productId, enabled) {
try {
@@ -226,6 +245,7 @@ async function loadSettings() {
document.getElementById('mode').value = cfg.mode || 'use';
document.getElementById('client-name').value = cfg.name || '';
document.getElementById('web-port').value = cfg.web_port || 8080;
document.getElementById('allow-force-detach').checked = cfg.allow_force_detach || false;
document.getElementById('token1').value = cfg.token1 || '';
document.getElementById('token2').value = cfg.token2 || '';
document.getElementById('token3').value = cfg.token3 || '';
@@ -248,6 +268,7 @@ document.getElementById('settings-form').addEventListener('submit', async (e) =>
mode: document.getElementById('mode').value,
name: document.getElementById('client-name').value,
web_port: parseInt(document.getElementById('web-port').value),
allow_force_detach: document.getElementById('allow-force-detach').checked,
})
});
const data = await resp.json();
+7
View File
@@ -55,6 +55,13 @@
<label for="web-port">Web-UI Port</label>
<input type="number" id="web-port" value="8080">
</div>
<div class="form-group">
<label class="auto-connect-label">
<input type="checkbox" id="allow-force-detach">
Andere Clients duerfen Geraete trennen (Share-Modus)
</label>
<small>Erlaubt Use-Clients, Geraete die von anderen benutzt werden zu trennen</small>
</div>
<button type="submit" class="btn primary">Speichern</button>
</form>
</section>