Desktop client with egui + wgpu UI, audio pipeline (cpal/opus/rodio), networking (LNEx protocol), and identity management with encrypted vault. Jitter buffer module extracted from voice-node for standalone operation.
144 lines
5.6 KiB
Rust
144 lines
5.6 KiB
Rust
pub mod icons;
|
|
pub mod widgets;
|
|
|
|
pub use widgets::{avatar, icon_btn, icon_btn_drawn};
|
|
|
|
use eframe::egui::{self, Color32, CornerRadius, FontDefinitions, Stroke, Visuals};
|
|
|
|
pub const BG_BASE: Color32 = Color32::from_rgb(13, 13, 13);
|
|
pub const BG_SURFACE: Color32 = Color32::from_rgb(22, 22, 22);
|
|
pub const BG_ELEVATED: Color32 = Color32::from_rgb(28, 28, 28);
|
|
pub const BG_INTERACTIVE: Color32 = Color32::from_rgb(30, 30, 30);
|
|
|
|
pub const ACCENT: Color32 = Color32::from_rgb(230, 126, 34);
|
|
pub const ACCENT_HOVER: Color32 = Color32::from_rgb(245, 145, 55);
|
|
pub const ACCENT_SOFT: Color32 = Color32::from_rgb(200, 110, 30);
|
|
pub const ACCENT_10: Color32 = Color32::from_rgba_premultiplied(230, 126, 34, 25);
|
|
pub const ACCENT_20: Color32 = Color32::from_rgba_premultiplied(230, 126, 34, 50);
|
|
pub const BORDER_ACCENT: Color32 = Color32::from_rgba_premultiplied(230, 126, 34, 60);
|
|
|
|
pub const SUCCESS: Color32 = Color32::from_rgb(80, 180, 90);
|
|
pub const WARNING: Color32 = Color32::from_rgb(220, 170, 60);
|
|
pub const ERROR: Color32 = Color32::from_rgb(210, 90, 80);
|
|
pub const INFO: Color32 = Color32::from_rgb(90, 155, 210);
|
|
|
|
pub const TEXT_PRIMARY: Color32 = Color32::from_rgb(224, 224, 224);
|
|
pub const TEXT_SECONDARY: Color32 = Color32::from_rgb(170, 170, 170);
|
|
pub const TEXT_MUTED: Color32 = Color32::from_rgb(136, 136, 136);
|
|
pub const TEXT_DISABLED: Color32 = Color32::from_rgb(90, 90, 90);
|
|
pub const TEXT_DEAD: Color32 = Color32::from_rgb(55, 55, 55);
|
|
|
|
pub const BORDER_SUBTLE: Color32 = Color32::from_rgb(42, 42, 42);
|
|
pub const BORDER_DEFAULT: Color32 = Color32::from_rgb(51, 51, 51);
|
|
pub const BORDER_STRONG: Color32 = Color32::from_rgb(64, 64, 64);
|
|
|
|
pub const BG_STRIP: Color32 = BG_SURFACE;
|
|
pub const BG_PANEL: Color32 = BG_SURFACE;
|
|
pub const BORDER: Color32 = BORDER_DEFAULT;
|
|
pub const BORDER_FAINT: Color32 = BORDER_SUBTLE;
|
|
pub const BORDER_MID: Color32 = BORDER_STRONG;
|
|
pub const WARN: Color32 = WARNING;
|
|
pub const DANGER: Color32 = ERROR;
|
|
pub const BLUE: Color32 = INFO;
|
|
pub const TEXT_GHOST: Color32 = TEXT_DISABLED;
|
|
pub const TEXT_DIM: Color32 = TEXT_MUTED;
|
|
pub const ACCENT_DIM: Color32 = Color32::from_rgb(160, 90, 25);
|
|
pub const TEXT_FAINT: Color32 = TEXT_DEAD;
|
|
|
|
pub const R_SM: CornerRadius = CornerRadius::same(6);
|
|
pub const R_MD: CornerRadius = CornerRadius::same(10);
|
|
pub const R_LG: CornerRadius = CornerRadius::same(14);
|
|
pub const R_FULL: CornerRadius = CornerRadius::same(255);
|
|
|
|
const NAME_PALETTE: [Color32; 6] = [
|
|
Color32::from_rgb(170, 170, 170),
|
|
Color32::from_rgb(106, 158, 207),
|
|
Color32::from_rgb(124, 184, 122),
|
|
Color32::from_rgb(220, 170, 60),
|
|
Color32::from_rgb(190, 140, 200),
|
|
Color32::from_rgb(120, 190, 180),
|
|
];
|
|
|
|
pub fn user_color(user_id: &str) -> Color32 {
|
|
if user_id.is_empty() {
|
|
return TEXT_SECONDARY;
|
|
}
|
|
let hash: usize = user_id
|
|
.bytes()
|
|
.fold(0usize, |acc, b| acc.wrapping_add(b as usize));
|
|
NAME_PALETTE[hash % NAME_PALETTE.len()]
|
|
}
|
|
|
|
pub fn apply_visuals(ctx: &egui::Context) {
|
|
let mut v = Visuals::dark();
|
|
|
|
v.window_fill = BG_BASE;
|
|
v.panel_fill = BG_BASE;
|
|
v.extreme_bg_color = BG_INTERACTIVE;
|
|
v.faint_bg_color = BG_ELEVATED;
|
|
v.code_bg_color = BG_SURFACE;
|
|
v.hyperlink_color = ACCENT;
|
|
v.override_text_color = Some(TEXT_PRIMARY);
|
|
|
|
v.widgets.noninteractive.bg_fill = BG_SURFACE;
|
|
v.widgets.noninteractive.bg_stroke = Stroke::new(1.0, BORDER_SUBTLE);
|
|
v.widgets.noninteractive.fg_stroke = Stroke::new(1.0, TEXT_MUTED);
|
|
v.widgets.noninteractive.corner_radius = R_MD;
|
|
|
|
v.widgets.inactive.bg_fill = Color32::TRANSPARENT;
|
|
v.widgets.inactive.bg_stroke = Stroke::new(1.0, BORDER_DEFAULT);
|
|
v.widgets.inactive.fg_stroke = Stroke::new(1.0, TEXT_MUTED);
|
|
v.widgets.inactive.corner_radius = R_MD;
|
|
|
|
v.widgets.hovered.bg_fill = BG_INTERACTIVE;
|
|
v.widgets.hovered.bg_stroke = Stroke::new(1.0, BORDER_STRONG);
|
|
v.widgets.hovered.fg_stroke = Stroke::new(1.0, TEXT_PRIMARY);
|
|
v.widgets.hovered.corner_radius = R_MD;
|
|
|
|
v.widgets.active.bg_fill = BG_INTERACTIVE;
|
|
v.widgets.active.bg_stroke = Stroke::new(1.0, BORDER_ACCENT);
|
|
v.widgets.active.fg_stroke = Stroke::new(1.0, TEXT_PRIMARY);
|
|
v.widgets.active.corner_radius = R_MD;
|
|
|
|
v.widgets.open.bg_fill = BG_INTERACTIVE;
|
|
v.widgets.open.bg_stroke = Stroke::new(1.0, BORDER_STRONG);
|
|
v.widgets.open.fg_stroke = Stroke::new(1.0, TEXT_PRIMARY);
|
|
v.widgets.open.corner_radius = R_MD;
|
|
|
|
v.selection.bg_fill = ACCENT_10;
|
|
v.selection.stroke = Stroke::new(0.0, Color32::TRANSPARENT);
|
|
|
|
v.window_corner_radius = R_LG;
|
|
v.window_shadow = egui::epaint::Shadow::NONE;
|
|
v.popup_shadow = egui::epaint::Shadow::NONE;
|
|
v.window_stroke = Stroke::new(1.0, BORDER_DEFAULT);
|
|
|
|
ctx.set_visuals(v);
|
|
set_fonts(ctx);
|
|
set_spacing(ctx);
|
|
}
|
|
|
|
fn set_fonts(ctx: &egui::Context) {
|
|
let fonts = FontDefinitions::default();
|
|
ctx.set_fonts(fonts);
|
|
}
|
|
|
|
fn set_spacing(ctx: &egui::Context) {
|
|
let mut s = (*ctx.style()).clone();
|
|
s.text_styles = [
|
|
(egui::TextStyle::Small, egui::FontId::proportional(11.0)),
|
|
(egui::TextStyle::Body, egui::FontId::proportional(13.0)),
|
|
(egui::TextStyle::Button, egui::FontId::proportional(13.0)),
|
|
(egui::TextStyle::Heading, egui::FontId::proportional(15.0)),
|
|
(egui::TextStyle::Monospace, egui::FontId::monospace(12.0)),
|
|
]
|
|
.into();
|
|
s.spacing.item_spacing = egui::vec2(6.0, 4.0);
|
|
s.spacing.button_padding = egui::vec2(10.0, 5.0);
|
|
s.spacing.window_margin = egui::Margin::same(0);
|
|
s.spacing.menu_margin = egui::Margin::same(4);
|
|
s.spacing.indent = 16.0;
|
|
s.spacing.interact_size = egui::vec2(40.0, 28.0);
|
|
s.spacing.scroll.bar_width = 4.0;
|
|
ctx.set_style(s);
|
|
}
|