Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
1f47337c40
|
|||
|
e2caee536f
|
|||
|
080b9c46d6
|
|||
|
3807294333
|
|||
|
9c89cfbe9c
|
|||
|
9326f93576
|
|||
|
9858460696
|
|||
| 9550fa1f72 |
@@ -36,8 +36,15 @@ jobs:
|
||||
~/.cargo/bin
|
||||
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
|
||||
run: command -v cargo-leptos || cargo install cargo-leptos --locked
|
||||
run: command -v cargo-leptos || cargo binstall cargo-leptos --locked --no-confirm
|
||||
|
||||
- name: Build
|
||||
run: cargo leptos build --release
|
||||
|
||||
Generated
+1
-1
@@ -345,7 +345,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cnats"
|
||||
version = "0.2.1"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-nats",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cnats"
|
||||
version = "0.2.1"
|
||||
version = "0.2.5"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Maintainer: Bendik Aagaard Lynghaug <bendik.lynghaug@gmail.com>
|
||||
pkgname=cnats
|
||||
pkgver=0.2.1
|
||||
pkgver=0.2.5
|
||||
pkgrel=1
|
||||
pkgdesc="Web chat over NATS subjects with Kanidm SSO (Leptos SSR)"
|
||||
arch=('x86_64' 'aarch64')
|
||||
|
||||
+23
-1
@@ -450,9 +450,19 @@ fn CallPanel(room: Memo<String>, me: String) -> impl IntoView {
|
||||
|
||||
// Mirror the local MediaStream into the preview <video> element -
|
||||
// `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 |_| {
|
||||
let stream = call_state.get_value().local_stream().get();
|
||||
if let Some(el) = local_video_ref.get() {
|
||||
el.set_muted(true);
|
||||
el.set_src_object(stream.as_ref());
|
||||
}
|
||||
});
|
||||
@@ -495,10 +505,22 @@ fn CallPanel(room: Memo<String>, me: String) -> impl IntoView {
|
||||
}
|
||||
.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"></div> }.into_any()
|
||||
view! {
|
||||
<div class="call-panel">
|
||||
<button class="call-join" disabled=true>
|
||||
"☎ join call"
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
.into_any()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
-8
@@ -1,8 +1,10 @@
|
||||
/* ── cnats · message-bus console ─────────────────────────────────────────
|
||||
dark phosphor terminal: deep green-black ground, mint signal, amber id.
|
||||
phosphor terminal in two prints: dark (green-black ground, mint signal)
|
||||
and light (green-tinted paper, forest signal), following the OS scheme.
|
||||
type: Archivo (UI voice) + IBM Plex Mono (wire voice). */
|
||||
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
--ink-0: #060a09;
|
||||
--ink-1: #0b1210;
|
||||
--ink-2: #101a17;
|
||||
@@ -16,10 +18,34 @@
|
||||
--signal-dim: #2a8f6c;
|
||||
--amber: #ffb454;
|
||||
--alarm: #ff6b6b;
|
||||
--scanline: rgba(255, 255, 255, 0.015);
|
||||
--vignette: rgba(0, 0, 0, 0.45);
|
||||
--card-shadow: rgba(0, 0, 0, 0.55);
|
||||
--mono: "IBM Plex Mono", ui-monospace, monospace;
|
||||
--sans: "Archivo", system-ui, sans-serif;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--ink-0: #f3f6f4;
|
||||
--ink-1: #eaf0ec;
|
||||
--ink-2: #dfe8e2;
|
||||
--ink-3: #d2ded6;
|
||||
--line: #c3d2c9;
|
||||
--line-hot: #a3bcae;
|
||||
--text: #14211c;
|
||||
--text-dim: #46584f;
|
||||
--text-faint: #74887e;
|
||||
--signal: #0b7a52;
|
||||
--signal-dim: #2f8a66;
|
||||
--amber: #a85f00;
|
||||
--alarm: #c73f3f;
|
||||
--scanline: rgba(6, 10, 9, 0.02);
|
||||
--vignette: rgba(6, 10, 9, 0.06);
|
||||
--card-shadow: rgba(20, 33, 28, 0.18);
|
||||
}
|
||||
}
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
html, body { height: 100%; }
|
||||
@@ -39,8 +65,8 @@ body::before {
|
||||
pointer-events: none;
|
||||
z-index: 999;
|
||||
background:
|
||||
repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.015) 0 1px, transparent 1px 3px),
|
||||
radial-gradient(ellipse 120% 90% at 50% 40%, transparent 55%, rgba(0, 0, 0, 0.45));
|
||||
repeating-linear-gradient(0deg, var(--scanline) 0 1px, transparent 1px 3px),
|
||||
radial-gradient(ellipse 120% 90% at 50% 40%, transparent 55%, var(--vignette));
|
||||
}
|
||||
|
||||
::selection { background: var(--signal); color: var(--ink-0); }
|
||||
@@ -53,7 +79,7 @@ body::before {
|
||||
place-items: center;
|
||||
padding: 2rem;
|
||||
background:
|
||||
radial-gradient(ellipse 60% 45% at 50% 0%, rgba(78, 240, 177, 0.07), transparent 70%),
|
||||
radial-gradient(ellipse 60% 45% at 50% 0%, color-mix(in srgb, var(--signal) 7%, transparent), transparent 70%),
|
||||
linear-gradient(var(--ink-0), var(--ink-1));
|
||||
}
|
||||
|
||||
@@ -69,7 +95,7 @@ body::before {
|
||||
background: linear-gradient(160deg, var(--ink-2), var(--ink-1) 60%);
|
||||
padding: 3rem 2.75rem 2.5rem;
|
||||
position: relative;
|
||||
box-shadow: 0 40px 80px rgba(0, 0, 0, 0.55);
|
||||
box-shadow: 0 40px 80px var(--card-shadow);
|
||||
animation: rise 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both;
|
||||
}
|
||||
|
||||
@@ -129,7 +155,8 @@ body::before {
|
||||
.gate-btn:hover {
|
||||
background: transparent;
|
||||
color: var(--signal);
|
||||
box-shadow: 0 0 24px rgba(78, 240, 177, 0.25), inset 0 0 12px rgba(78, 240, 177, 0.08);
|
||||
box-shadow: 0 0 24px color-mix(in srgb, var(--signal) 25%, transparent),
|
||||
inset 0 0 12px color-mix(in srgb, var(--signal) 8%, transparent);
|
||||
}
|
||||
|
||||
.gate-btn-glyph { font-size: 1.05rem; }
|
||||
@@ -458,7 +485,7 @@ body::before {
|
||||
|
||||
.composer:focus-within {
|
||||
border-color: var(--signal-dim);
|
||||
box-shadow: 0 0 0 1px var(--signal-dim), 0 0 30px rgba(78, 240, 177, 0.08);
|
||||
box-shadow: 0 0 0 1px var(--signal-dim), 0 0 30px color-mix(in srgb, var(--signal) 8%, transparent);
|
||||
}
|
||||
|
||||
.composer-prompt {
|
||||
@@ -551,7 +578,7 @@ body::before {
|
||||
transition: background 120ms;
|
||||
}
|
||||
|
||||
.call-leave:hover { background: rgba(255, 90, 90, 0.12); }
|
||||
.call-leave:hover { background: color-mix(in srgb, var(--alarm) 12%, transparent); }
|
||||
|
||||
/* motion */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user