More UI work

This commit is contained in:
Mike Dilger 2022-12-21 11:45:15 +13:00
parent 8911270edc
commit 0200cbe3d2
11 changed files with 310 additions and 18 deletions

45
Cargo.lock generated
View File

@ -26,6 +26,7 @@ checksum = "3083ac5a97521e35388ca80cf365b6be5210962cc59f11ee238cd92ac2fa9524"
dependencies = [
"enumset",
"kurbo",
"serde",
]
[[package]]
@ -115,6 +116,7 @@ checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
dependencies = [
"cfg-if",
"once_cell",
"serde",
"version_check",
]
@ -937,6 +939,16 @@ dependencies = [
"subtle",
]
[[package]]
name = "directories-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc"
dependencies = [
"cfg-if",
"dirs-sys-next",
]
[[package]]
name = "dirs"
version = "4.0.0"
@ -957,6 +969,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dispatch"
version = "0.2.0"
@ -1017,6 +1040,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b601108bca3af7650440ace4ca55b2daf52c36f2635be3587d77b16efd8d0691"
dependencies = [
"bytemuck",
"serde",
]
[[package]]
@ -1027,6 +1051,7 @@ checksum = "5ea929ec5819fef373728bb0e55003ce921975039cfec3ca8305bb024e5b7b32"
dependencies = [
"bytemuck",
"dark-light",
"directories-next",
"egui",
"egui-winit",
"egui_glow",
@ -1035,6 +1060,8 @@ dependencies = [
"js-sys",
"percent-encoding",
"raw-window-handle 0.5.0",
"ron",
"serde",
"tracing",
"wasm-bindgen",
"wasm-bindgen-futures",
@ -1052,6 +1079,8 @@ dependencies = [
"ahash 0.8.2",
"epaint",
"nohash-hasher",
"ron",
"serde",
"tracing",
]
@ -1065,6 +1094,7 @@ dependencies = [
"arboard",
"egui",
"instant",
"serde",
"smithay-clipboard",
"tracing",
"webbrowser",
@ -1133,6 +1163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5277249c8c3430e7127e4f2c40a77485e7baf11ae132ce9b3253a8ed710df0a0"
dependencies = [
"bytemuck",
"serde",
]
[[package]]
@ -1172,6 +1203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753"
dependencies = [
"enumset_derive",
"serde",
]
[[package]]
@ -1200,6 +1232,7 @@ dependencies = [
"emath",
"nohash-hasher",
"parking_lot",
"serde",
]
[[package]]
@ -1988,6 +2021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a53776d271cfb873b17c618af0298445c88afc52837f3e948fa3fafd131f449"
dependencies = [
"arrayvec 0.7.2",
"serde",
]
[[package]]
@ -2929,6 +2963,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "ron"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff"
dependencies = [
"base64 0.13.1",
"bitflags",
"serde",
]
[[package]]
name = "roxmltree"
version = "0.14.1"

View File

@ -14,7 +14,7 @@ edition = "2021"
[dependencies]
base64 = "0.13"
dirs = "4.0"
eframe = { version = "0.20", features = [ "dark-light" ] }
eframe = { version = "0.20", features = [ "dark-light", "persistence" ] }
egui_extras = { version = "0.20", features = [ "svg", "tracing" ] }
futures = "0.3"
http = "0.2"

7
src/ui/about.rs Normal file
View File

@ -0,0 +1,7 @@
use super::GossipUi;
use eframe::egui;
use egui::{Context, Ui};
pub(super) fn update(_app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
ui.label("ABOUT PAGE - Coming Soon".to_string());
}

7
src/ui/feed.rs Normal file
View File

@ -0,0 +1,7 @@
use super::GossipUi;
use eframe::egui;
use egui::{Context, Ui};
pub(super) fn update(_app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
ui.label("FEED PAGE - Coming Soon".to_string());
}

View File

@ -1,6 +1,15 @@
mod about;
mod feed;
mod people;
mod relays;
mod settings;
mod stats;
mod style;
mod you;
use crate::error::Error;
use eframe::{egui, IconData, Theme};
use egui::style::Style;
use egui::Context;
pub fn run() -> Result<(), Error> {
let icon_bytes = include_bytes!("../../gossip.png");
@ -9,6 +18,7 @@ pub fn run() -> Result<(), Error> {
let options = eframe::NativeOptions {
decorated: true,
drag_and_drop_support: true,
default_theme: Theme::Light,
icon_data: Some(IconData {
rgba: icon.into_raw(),
@ -16,14 +26,15 @@ pub fn run() -> Result<(), Error> {
height: icon_height,
}),
initial_window_size: Some(egui::vec2(700.0, 900.0)),
resizable: true,
centered: true,
..Default::default()
};
eframe::run_native(
"Gossip",
"gossip",
options,
Box::new(|_cc| Box::new(GossipUi::default())),
Box::new(|cc| Box::new(GossipUi::new(cc))),
);
Ok(())
@ -42,37 +53,67 @@ enum Page {
struct GossipUi {
page: Page,
initial_dark_mode_set: bool,
fonts_installed: bool,
}
impl Default for GossipUi {
fn default() -> Self {
Self { page: Page::Feed }
impl GossipUi {
fn new(_cc: &eframe::CreationContext<'_>) -> Self {
GossipUi {
page: Page::Feed,
initial_dark_mode_set: false,
fonts_installed: false,
}
}
}
impl eframe::App for GossipUi {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
//ui.heading("Gossip");
fn update(&mut self, ctx: &Context, frame: &mut eframe::Frame) {
let darkmode: bool = ctx.style().visuals.dark_mode;
ui.horizontal(|ui| {
// light-dark switcher
let style: Style = (*ui.ctx().style()).clone();
let new_visuals = style.visuals.light_dark_small_toggle_button(ui);
if let Some(visuals) = new_visuals {
ui.ctx().set_visuals(visuals);
if ! self.initial_dark_mode_set {
if darkmode {
ctx.set_visuals(style::dark_mode_visuals());
} else {
ctx.set_visuals(style::light_mode_visuals());
};
self.initial_dark_mode_set = true;
}
if ! self.fonts_installed {
ctx.set_fonts(style::font_definitions());
self.fonts_installed = true;
}
egui::TopBottomPanel::top("menu").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.selectable_value(&mut self.page, Page::Feed, "Feed");
ui.separator();
ui.selectable_value(&mut self.page, Page::People, "People");
ui.separator();
ui.selectable_value(&mut self.page, Page::You, "You");
ui.separator();
ui.selectable_value(&mut self.page, Page::Relays, "Relays");
ui.separator();
ui.selectable_value(&mut self.page, Page::Settings, "Settings");
ui.separator();
ui.selectable_value(&mut self.page, Page::Stats, "Stats");
ui.separator();
ui.selectable_value(&mut self.page, Page::About, "About");
ui.separator();
});
});
ui.label("Hello World".to_string());
egui::CentralPanel::default().show(ctx, |ui| match self.page {
Page::Feed => feed::update(self, ctx, frame, ui),
Page::People => people::update(self, ctx, frame, ui),
Page::You => you::update(self, ctx, frame, ui),
Page::Relays => relays::update(self, ctx, frame, ui),
Page::Settings => settings::update(self, ctx, frame, ui, darkmode),
Page::Stats => stats::update(self, ctx, frame, ui),
Page::About => about::update(self, ctx, frame, ui),
});
}
}

7
src/ui/people.rs Normal file
View File

@ -0,0 +1,7 @@
use super::GossipUi;
use eframe::egui;
use egui::{Context, Ui};
pub(super) fn update(_app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
ui.label("PEOPLE PAGE - Coming Soon".to_string());
}

7
src/ui/relays.rs Normal file
View File

@ -0,0 +1,7 @@
use super::GossipUi;
use eframe::egui;
use egui::{Context, Ui};
pub(super) fn update(_app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
ui.label("RELAYS PAGE - Coming Soon".to_string());
}

35
src/ui/settings.rs Normal file
View File

@ -0,0 +1,35 @@
use super::GossipUi;
use eframe::egui;
use egui::widgets::Button;
use egui::{Context, Ui};
pub(super) fn update(
_app: &mut GossipUi,
_ctx: &Context,
_frame: &mut eframe::Frame,
ui: &mut Ui,
darkmode: bool,
) {
ui.heading("Settings");
#[allow(clippy::collapsible_else_if)]
if darkmode {
if ui
.add(Button::new("☀ Light"))
.on_hover_text("Switch to light mode")
.clicked()
{
ui.ctx().set_visuals(super::style::light_mode_visuals());
}
} else {
if ui
.add(Button::new("🌙 Dark"))
.on_hover_text("Switch to dark mode")
.clicked()
{
ui.ctx().set_visuals(super::style::dark_mode_visuals());
}
}
ui.label("SETTINGS PAGE - Coming Soon".to_string());
}

7
src/ui/stats.rs Normal file
View File

@ -0,0 +1,7 @@
use super::GossipUi;
use eframe::egui;
use egui::{Context, Ui};
pub(super) fn update(_app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
ui.label("STATS PAGE - Coming Soon".to_string());
}

129
src/ui/style.rs Normal file
View File

@ -0,0 +1,129 @@
use eframe::{egui, epaint};
use egui::style::{Selection, Visuals, Widgets};
use egui::{Color32, FontData, FontDefinitions, FontFamily, FontTweak, Rounding, Stroke};
use epaint::Shadow;
use std::collections::BTreeMap;
pub(super) fn dark_mode_visuals() -> Visuals {
Visuals {
dark_mode: true,
override_text_color: None,
widgets: Widgets::default(),
selection: Selection {
bg_fill: Color32::from_rgb(0xb1, 0xa2, 0x96), // DONE
stroke: Stroke::new(1.0, Color32::from_rgb(0x37, 0x96, 0x83)), // DONE
},
hyperlink_color: Color32::from_rgb(0x73, 0x95, 0xae), // DONE
faint_bg_color: Color32::from_gray(0x30), // DONE
extreme_bg_color: Color32::from_gray(0), // e.g. TextEdit background
code_bg_color: Color32::from_gray(64),
warn_fg_color: Color32::from_rgb(255, 143, 0), // orange
error_fg_color: Color32::from_rgb(255, 0, 0), // red
window_rounding: Rounding::same(6.0),
window_shadow: Shadow::big_dark(),
window_fill: Color32::from_gray(0x24), // DONE
window_stroke: Stroke::new(1.0, Color32::from_rgb(0x37, 0x96, 0x83)), // DONE
panel_fill: Color32::from_gray(0x24), // DONE
popup_shadow: Shadow::small_dark(),
resize_corner_size: 12.0,
text_cursor_width: 2.0,
text_cursor_preview: false,
clip_rect_margin: 3.0, // should be at least half the size of the widest frame stroke + max WidgetVisuals::expansion
button_frame: true,
collapsing_header_frame: false,
}
}
pub(super) fn light_mode_visuals() -> Visuals {
Visuals {
dark_mode: false,
override_text_color: None,
widgets: Widgets::light(),
selection: Selection {
bg_fill: Color32::from_rgb(0xb1, 0xa2, 0x96), // DONE
stroke: Stroke::new(1.0, Color32::from_rgb(0x5d, 0x5c, 0x61)), // DONE
},
hyperlink_color: Color32::from_rgb(0x55, 0x7a, 0x95), // DONE
faint_bg_color: Color32::from_gray(0xf0), // DONE
extreme_bg_color: Color32::from_gray(0xff), // e.g. TextEdit background
code_bg_color: Color32::from_gray(230),
warn_fg_color: Color32::from_rgb(255, 100, 0), // slightly orange red. it's difficult to find a warning color that pops on bright background.
error_fg_color: Color32::from_rgb(255, 0, 0), // red
window_rounding: Rounding::same(6.0),
window_shadow: Shadow::big_light(),
window_fill: Color32::from_gray(0xF8), // DONE
window_stroke: Stroke::new(1.0, Color32::from_rgb(0x5d, 0x5c, 0x61)), // DONE
panel_fill: Color32::from_gray(0xF8), // DONE
popup_shadow: Shadow::small_light(),
resize_corner_size: 12.0,
text_cursor_width: 2.0,
text_cursor_preview: false,
clip_rect_margin: 3.0, // should be at least half the size of the widest frame stroke + max WidgetVisuals::expansion
button_frame: true,
collapsing_header_frame: false,
}
}
pub(super) fn font_definitions() -> FontDefinitions {
let mut font_data: BTreeMap<String, FontData> = BTreeMap::new();
let mut families = BTreeMap::new();
// Cantarell - gnome default
// code fonts - Inconsolata-g, Hack
font_data.insert(
"Inconsolata".to_owned(),
FontData::from_static(include_bytes!("../../fonts/Inconsolata-Regular.ttf")),
);
font_data.insert(
"FreeSans".to_owned(),
FontData::from_static(include_bytes!("../../fonts/freefont-20120503/FreeSans.otf")),
);
// Some good looking emojis. Use as first priority:
font_data.insert(
"NotoColorEmoji".to_owned(),
FontData::from_static(include_bytes!("../../fonts/NotoColorEmoji.ttf")).tweak(
FontTweak {
scale: 0.81, // make it smaller
y_offset_factor: -0.2, // move it up
y_offset: 0.0,
},
),
);
font_data.insert(
"NotoSansRegular".to_owned(),
FontData::from_static(include_bytes!("../../fonts/NotoSans-Regular.ttf")),
);
font_data.insert(
"NotoSansMonoRegular".to_owned(),
FontData::from_static(include_bytes!("../../fonts/NotoSansMono-Regular.ttf")),
);
families.insert(
FontFamily::Monospace,
vec![
"Inconsolata".to_owned(),
"NotoColorEmoji".to_owned(),
"NotoSansMonoRegular".to_owned(),
],
);
families.insert(
FontFamily::Proportional,
vec![
"FreeSans".to_owned(),
"NotoColorEmoji".to_owned(),
"NotoSansRegular".to_owned(),
],
);
FontDefinitions {
font_data,
families,
}
}

7
src/ui/you.rs Normal file
View File

@ -0,0 +1,7 @@
use super::GossipUi;
use eframe::egui;
use egui::{Context, Ui};
pub(super) fn update(_app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
ui.label("YOU PAGE - Coming Soon".to_string());
}