use egui::{Ui, Color32, Vec2, Stroke, Frame, Margin, CornerRadius, RichText, FontFamily, FontId};
use crate::theme::{with_alpha, MonolithSurfaces};
pub fn surface_card<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> R {
let fill_color = MonolithSurfaces::SURFACE_4;
let stroke_color = MonolithSurfaces::SURFACE_6;
Frame::NONE
.fill(fill_color)
.inner_margin(Margin::same(14))
.corner_radius(CornerRadius::same(6)) .stroke(Stroke::new(1.0, stroke_color))
.show(ui, add_contents)
.inner
}
pub fn sunken_well<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> R {
let fill_color = MonolithSurfaces::SURFACE_0;
let border_color = MonolithSurfaces::SURFACE_3;
Frame::NONE
.fill(fill_color)
.inner_margin(Margin::same(12))
.corner_radius(CornerRadius::same(4)) .stroke(Stroke::new(1.0, border_color))
.show(ui, add_contents)
.inner
}
pub fn status_dot(ui: &mut Ui, status: &str) {
let color = match status {
"Active" | "Complete" | "Online" => Color32::from_rgb(0x34, 0xa8, 0x53),
"Queued" | "Warning" | "Paused" => Color32::from_rgb(0xfb, 0xbf, 0x24),
_ => Color32::from_rgb(0xf2, 0x8b, 0x82),
};
let (rect, _response) = ui.allocate_exact_size(Vec2::new(14.0, 14.0), egui::Sense::hover());
let painter = ui.painter();
painter.circle_filled(rect.center(), 4.0, color);
if status == "Active" || status == "Online" {
painter.circle_filled(rect.center(), 6.5, with_alpha(color, 0.25));
}
}
pub fn brand_pill(ui: &mut Ui, text: &str, color: Color32) {
Frame::NONE
.fill(with_alpha(color, 0.08))
.stroke(Stroke::new(1.0, with_alpha(color, 0.22)))
.inner_margin(Margin::symmetric(8, 3))
.corner_radius(CornerRadius::same(4)) .show(ui, |ui| {
ui.label(
RichText::new(text)
.color(color)
.font(FontId::new(10.5, FontFamily::Monospace)) );
});
}
pub fn platform_pill(ui: &mut Ui, platform: &str) {
let color = match platform.to_lowercase().as_str() {
"youtube" => Color32::from_rgb(255, 85, 85),
"instagram" => Color32::from_rgb(255, 120, 200),
"tiktok" => Color32::from_rgb(85, 255, 255),
"twitch" => Color32::from_rgb(180, 100, 255),
"torrent" => Color32::from_rgb(85, 255, 120),
_ => Color32::from_rgb(168, 85, 247), };
let glyph = match platform.to_lowercase().as_str() {
"youtube" => "",
"instagram" => "",
"tiktok" => "",
"twitch" => "",
"torrent" => "",
_ => "",
};
let text = format!("{} {}", glyph, platform.to_uppercase());
brand_pill(ui, &text, color);
}
pub fn section_header(ui: &mut Ui, title: &str) {
ui.vertical(|ui| {
ui.add_space(4.0);
ui.label(
RichText::new(title)
.font(FontId::new(16.0, FontFamily::Proportional))
.strong()
.color(Color32::from_rgb(0xf3, 0xf4, 0xf6))
);
ui.add_space(6.0);
});
}