Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
080b9c46d6
|
|||
|
3807294333
|
|||
|
9c89cfbe9c
|
|||
|
9326f93576
|
|||
|
9858460696
|
|||
| 9550fa1f72 | |||
|
e0061af9ce
|
|||
| 64bc5222fc |
@@ -36,8 +36,15 @@ jobs:
|
|||||||
~/.cargo/bin
|
~/.cargo/bin
|
||||||
key: ${{ runner.os }}-${{ matrix.arch }}-cargo-leptos-${{ hashFiles('Cargo.lock') }}
|
key: ${{ runner.os }}-${{ matrix.arch }}-cargo-leptos-${{ hashFiles('Cargo.lock') }}
|
||||||
|
|
||||||
|
- name: Install cargo-binstall
|
||||||
|
run: |
|
||||||
|
command -v cargo-binstall || \
|
||||||
|
curl -L --proto '=https' --tlsv1.2 -sSf \
|
||||||
|
https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh \
|
||||||
|
| bash
|
||||||
|
|
||||||
- name: Install cargo-leptos
|
- name: Install cargo-leptos
|
||||||
run: command -v cargo-leptos || cargo install cargo-leptos --locked
|
run: command -v cargo-leptos || cargo binstall cargo-leptos --locked --no-confirm
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo leptos build --release
|
run: cargo leptos build --release
|
||||||
|
|||||||
Generated
+1
-1
@@ -345,7 +345,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cnats"
|
name = "cnats"
|
||||||
version = "0.2.0"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-nats",
|
"async-nats",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "cnats"
|
name = "cnats"
|
||||||
version = "0.2.0"
|
version = "0.2.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# Maintainer: Bendik Aagaard Lynghaug <bendik.lynghaug@gmail.com>
|
# Maintainer: Bendik Aagaard Lynghaug <bendik.lynghaug@gmail.com>
|
||||||
pkgname=cnats
|
pkgname=cnats
|
||||||
pkgver=0.2.0
|
pkgver=0.2.4
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Web chat over NATS subjects with Kanidm SSO (Leptos SSR)"
|
pkgdesc="Web chat over NATS subjects with Kanidm SSO (Leptos SSR)"
|
||||||
arch=('x86_64' 'aarch64')
|
arch=('x86_64' 'aarch64')
|
||||||
|
|||||||
+60
-13
@@ -450,9 +450,19 @@ fn CallPanel(room: Memo<String>, me: String) -> impl IntoView {
|
|||||||
|
|
||||||
// Mirror the local MediaStream into the preview <video> element -
|
// Mirror the local MediaStream into the preview <video> element -
|
||||||
// `srcObject` has no HTML attribute form, has to be set via JS.
|
// `srcObject` has no HTML attribute form, has to be set via JS.
|
||||||
|
//
|
||||||
|
// Also force `.muted` via the JS property here, not just the
|
||||||
|
// `muted` attribute on the element below: every video tile in this
|
||||||
|
// app is built client-side via `document.createElement` (never
|
||||||
|
// parsed from HTML), and browsers only seed the live `.muted`
|
||||||
|
// property from the `muted` *attribute* for parser-inserted
|
||||||
|
// elements. Without this, the local preview plays back the user's
|
||||||
|
// own mic through their speakers - audible as feedback in a
|
||||||
|
// solo call.
|
||||||
Effect::new(move |_| {
|
Effect::new(move |_| {
|
||||||
let stream = call_state.get_value().local_stream().get();
|
let stream = call_state.get_value().local_stream().get();
|
||||||
if let Some(el) = local_video_ref.get() {
|
if let Some(el) = local_video_ref.get() {
|
||||||
|
el.set_muted(true);
|
||||||
el.set_src_object(stream.as_ref());
|
el.set_src_object(stream.as_ref());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -472,16 +482,61 @@ fn CallPanel(room: Memo<String>, me: String) -> impl IntoView {
|
|||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div class="call-panel">
|
<div class="call-panel">
|
||||||
<Show
|
{move || {
|
||||||
when=move || in_call.get()
|
if in_call.get() {
|
||||||
fallback=move || {
|
view! {
|
||||||
|
<CallActive
|
||||||
|
local_video_ref=local_video_ref
|
||||||
|
call_state=call_state.get_value()
|
||||||
|
on_leave=on_leave
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
.into_any()
|
||||||
|
} else {
|
||||||
view! {
|
view! {
|
||||||
<button class="call-join" on:click=on_join>
|
<button class="call-join" on:click=on_join>
|
||||||
"☎ join call"
|
"☎ join call"
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
.into_any()
|
||||||
}
|
}
|
||||||
>
|
}}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
.into_any()
|
||||||
|
}
|
||||||
|
// Must mirror the hydrate branch's default (not-in-call) markup exactly -
|
||||||
|
// hydration reconciles this SSR output against what the hydrate branch
|
||||||
|
// above expects to find, and an empty div here (vs. the button hydrate
|
||||||
|
// wants) is a hydration mismatch that panics and traps the whole wasm
|
||||||
|
// instance, killing all reactivity on the page.
|
||||||
|
#[cfg(not(feature = "hydrate"))]
|
||||||
|
{
|
||||||
|
let _ = (room, me);
|
||||||
|
view! {
|
||||||
|
<div class="call-panel">
|
||||||
|
<button class="call-join" disabled=true>
|
||||||
|
"☎ join call"
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
.into_any()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The in-call subtree (video grid + leave button), split out of
|
||||||
|
/// `CallPanel` so its `<For>`-over-peers view doesn't get inlined as a type
|
||||||
|
/// parameter of `CallPanel`'s own `if`/`else` branch - that inlining is what
|
||||||
|
/// was blowing the compiler's query recursion limit once mesh calling's
|
||||||
|
/// nested `Show`/`For` landed inside `ChatShell`'s own `Show`.
|
||||||
|
#[cfg(feature = "hydrate")]
|
||||||
|
#[component]
|
||||||
|
fn CallActive(
|
||||||
|
local_video_ref: NodeRef<leptos::html::Video>,
|
||||||
|
call_state: crate::webrtc::CallState,
|
||||||
|
on_leave: impl Fn(leptos::ev::MouseEvent) + 'static,
|
||||||
|
) -> impl IntoView {
|
||||||
|
view! {
|
||||||
<div class="call-active">
|
<div class="call-active">
|
||||||
<div class="video-grid">
|
<div class="video-grid">
|
||||||
<video
|
<video
|
||||||
@@ -492,7 +547,7 @@ fn CallPanel(room: Memo<String>, me: String) -> impl IntoView {
|
|||||||
playsinline=true
|
playsinline=true
|
||||||
></video>
|
></video>
|
||||||
<For
|
<For
|
||||||
each=move || call_state.get_value().peer_streams()
|
each=move || call_state.peer_streams()
|
||||||
key=|(id, _)| id.clone()
|
key=|(id, _)| id.clone()
|
||||||
children=move |(_id, stream)| {
|
children=move |(_id, stream)| {
|
||||||
view! { <PeerVideoTile stream=stream/> }
|
view! { <PeerVideoTile stream=stream/> }
|
||||||
@@ -503,14 +558,6 @@ fn CallPanel(room: Memo<String>, me: String) -> impl IntoView {
|
|||||||
"⏏ leave call"
|
"⏏ leave call"
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "hydrate"))]
|
|
||||||
{
|
|
||||||
let _ = (room, me);
|
|
||||||
view! { <div class="call-panel"></div> }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user