Added event handlers, input bindings and button states.

This commit is contained in:
ghost 2025-08-19 16:10:46 +02:00
parent 3b152d2251
commit c6a119c494
2 changed files with 165 additions and 22 deletions

View File

@ -57,8 +57,12 @@ header p {
color: #1f2937; color: #1f2937;
} }
/* Input Group Layout */
.input-group { .input-group {
margin-bottom: 16px; margin-bottom: 16px;
display: flex;
align-items: flex-end;
gap: 8px;
} }
.input-group label { .input-group label {
@ -75,6 +79,7 @@ header p {
border-radius: 6px; border-radius: 6px;
font-size: 14px; font-size: 14px;
transition: border-color 0.2s; transition: border-color 0.2s;
flex: 1;
} }
.input-group input:focus { .input-group input:focus {
@ -93,6 +98,15 @@ button {
transition: all 0.2s; transition: all 0.2s;
} }
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
button:disabled:hover {
background-color: inherit;
}
.connect-btn { .connect-btn {
background-color: #2563eb; background-color: #2563eb;
color: white; color: white;
@ -170,6 +184,7 @@ button {
.status-item { .status-item {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
margin-bottom: 12px; margin-bottom: 12px;
padding: 8px 0; padding: 8px 0;
border-bottom: 1px solid #f3f4f6; border-bottom: 1px solid #f3f4f6;
@ -202,3 +217,45 @@ button {
grid-column: 1 / -1; grid-column: 1 / -1;
} }
} }
/* Readonly Input */
.readonly-input {
background-color: #f9fafb !important;
cursor: not-allowed;
color: #6b7280;
}
/* Copy Button */
.copy-btn {
margin-left: 8px;
padding: 8px 12px;
background-color: #6b7280;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.copy-btn:hover {
background-color: #4b5563;
}
/* Muted Button State */
.muted {
background-color: #ef4444 !important;
}
.muted:hover {
background-color: #dc2626 !important;
}
/* Peer ID Display */
.peer-id {
font-family: 'Courier New', monospace;
font-size: 12px;
background-color: #f3f4f6;
padding: 2px 6px;
border-radius: 4px;
color: #374151;
}

View File

@ -26,6 +26,7 @@ fn App() -> Element {
#[component] #[component]
pub fn Content() ->Element { pub fn Content() ->Element {
// State for connection status and audio
let mut connected = use_signal(|| false); // Status: Verbindung aufgebaut? let mut connected = use_signal(|| false); // Status: Verbindung aufgebaut?
let mut audio_enabled = use_signal(|| true); // Status: Mikro aktiviert? let mut audio_enabled = use_signal(|| true); // Status: Mikro aktiviert?
@ -49,19 +50,37 @@ pub fn Content() ->Element {
// Connection Panel // Connection Panel
ConnectionPanel { ConnectionPanel {
connected, connected,
on_connect: move |_| connected.set(true) local_peer_id,
remote_peer_id,
on_connect: move |_| {
log::info!("Verbindung wird hergestellt...");
connected.set(true);
}
} }
// Call Controls // Call Controls
CallControls { CallControls {
connected,
audio_enabled, audio_enabled,
on_toggle_audio: move |_| audio_enabled.set(!audio_enabled()) on_start_call: move |_| {
log::info!("Anruf wird gestartet mit Remote Peer: {}", remote_peer_id());
},
on_end_call: move |_| {
log::info!("Anruf wird beendet");
connected.set(false);
},
on_toggle_audio: move |_| {
audio_enabled.set(!audio_enabled());
log::info!("Audio Status: {}", if audio_enabled() { "Aktiviert" } else { "Deaktiviert" });
}
} }
// Status Display // Status Display
StatusDisplay { StatusDisplay {
connected, connected,
audio_enabled audio_enabled,
local_peer_id,
remote_peer_id
} }
} }
} }
@ -70,7 +89,12 @@ pub fn Content() ->Element {
// Komponente für Verbindungseinstellungen // Komponente für Verbindungseinstellungen
#[component] #[component]
fn ConnectionPanel(connected: Signal<bool>, on_connect: EventHandler<MouseEvent>) -> Element { fn ConnectionPanel(
connected: Signal<bool>,
local_peer_id: Signal<String>,
mut remote_peer_id: Signal<String>,
on_connect: EventHandler<MouseEvent>
) -> Element {
rsx! { rsx! {
div { div {
class: "connection-panel", class: "connection-panel",
@ -78,21 +102,36 @@ fn ConnectionPanel(connected: Signal<bool>, on_connect: EventHandler<MouseEvent>
div { div {
class: "input-group", class: "input-group",
label { "for": "peer-id", "Peer ID:" } label { "for": "local-peer-id", "Ihre Peer ID:" }
input { input {
id: "peer-id", id: "local-peer-id",
class: "readonly-input",
r#type: "text", r#type: "text",
placeholder: "Wird autmatisch generiert" value: "{local_peer_id}",
readonly: true
}
button {
class:"copy-btn",
onclick: move |_| {
// Später: Implementierung für Copy-to-Clipboard
log::info!("Peer-ID kopiert: {}", local_peer_id());
},
"📋"
} }
} }
div { div {
class: "input-group", class: "input-group",
label { "for": "remote-peer", "Remote Peer-ID:" } label { "for": "remote-peer-id", "Remote Peer-ID:" }
input { input {
id: "remote-peer", id: "remote-peer-id",
r#type: "text", r#type: "text",
placeholder: "ID des anderen Teilnehmers eingeben" placeholder: "ID des anderen Teilnehmers eingeben",
value: "{remote_peer_id()}",
oninput: move |event| {
remote_peer_id.set(event.value());
log::info!("Remote Peer-ID eingegeben: {}", event.value());
}
} }
} }
@ -113,7 +152,13 @@ fn ConnectionPanel(connected: Signal<bool>, on_connect: EventHandler<MouseEvent>
// Komponente für Anruf-Steuerungen // Komponente für Anruf-Steuerungen
#[component] #[component]
fn CallControls(audio_enabled: Signal<bool>, on_toggle_audio: EventHandler<MouseEvent>) -> Element { fn CallControls(
connected: Signal<bool>,
audio_enabled: Signal<bool>,
on_start_call: EventHandler<MouseEvent>,
on_end_call: EventHandler<MouseEvent>,
on_toggle_audio: EventHandler<MouseEvent>
) -> Element {
rsx! { rsx! {
div { div {
class: "call-controls", class: "call-controls",
@ -123,21 +168,30 @@ fn CallControls(audio_enabled: Signal<bool>, on_toggle_audio: EventHandler<Mouse
class: "control-buttons", class: "control-buttons",
button { button {
class: "call-btn primary", class: "call-btn primary",
"Anruf starten" onclick: on_start_call,
disabled: !connected(),
"📞 Anruf starten"
} }
button { button {
class: "mute-btn", class: if audio_enabled() {
"mute-btn"
} else {
"mute-btn-muted"
},
onclick: on_toggle_audio, onclick: on_toggle_audio,
disabled: !connected(),
if audio_enabled() { if audio_enabled() {
"Mute" "🎤 Mikrofon"
} }
else { else {
"Unmute" "🔇 Stumm"
} }
} }
button { button {
class: "end-btn danger", class: "end-btn danger",
"Anruf beenden" onclick: on_end_call,
disabled: !connected(),
"📵 Anruf beenden"
} }
} }
} }
@ -146,7 +200,12 @@ fn CallControls(audio_enabled: Signal<bool>, on_toggle_audio: EventHandler<Mouse
// Komponente für Status-Anzeige // Komponente für Status-Anzeige
#[component] #[component]
fn StatusDisplay(connected: Signal<bool>, audio_enabled: Signal<bool>) -> Element { fn StatusDisplay(
connected: Signal<bool>,
audio_enabled: Signal<bool>,
local_peer_id: Signal<String>,
remote_peer_id: Signal<String>
) -> Element {
rsx! { rsx! {
div { div {
class: "status-display", class: "status-display",
@ -210,10 +269,37 @@ fn StatusDisplay(connected: Signal<bool>, audio_enabled: Signal<bool>) -> Elemen
} }
} }
} }
div {
class: "status-item",
span {
class: "status-label",
"Lokale Peer-ID:"
}
span {
class: "status-value peer-id",
"{local_peer_id()}"
}
}
if !remote_peer_id().is_empty() {
div {
class: "status-item",
span {
class: "status-label",
"Remote Peer-ID:"
}
span {
class: "status-value peer-id",
"{remote_peer_id()}"
}
}
}
} }
} }
} }
// Funktion zum Generieren einer eindeutigen Peer-ID
fn generate_peer_id() -> String { fn generate_peer_id() -> String {
use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::atomic::{AtomicU32, Ordering};