mirror of
https://github.com/damus-io/notedeck.git
synced 2024-09-18 21:03:31 +00:00
progress
This commit is contained in:
parent
ce21e10c90
commit
46f9bde257
1051
Cargo.lock
generated
1051
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,11 @@ rust-version = "1.60"
|
|||||||
egui = "0.19.0"
|
egui = "0.19.0"
|
||||||
eframe = { version = "0.19.0", features = ["persistence"] }
|
eframe = { version = "0.19.0", features = ["persistence"] }
|
||||||
serde = { version = "1", features = ["derive"] } # You only need this if you want app persistence
|
serde = { version = "1", features = ["derive"] } # You only need this if you want app persistence
|
||||||
|
nostr_rust = { git = "git://jb55.com/nostr_rust", rev = "ccf7e521fe3bb9ca8f86516aef2c1f71db0213ed" }
|
||||||
|
ehttp = "0.2.0"
|
||||||
|
image = { version = "0.24", features = ["jpeg", "png", "webp"] }
|
||||||
|
egui_extras = { version = "0.19.0", features = ["image", "svg"] }
|
||||||
|
poll-promise = "0.2.0"
|
||||||
|
|
||||||
# native:
|
# native:
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
1
rust-toolchain
Normal file
1
rust-toolchain
Normal file
@ -0,0 +1 @@
|
|||||||
|
nightly
|
175
src/app.rs
175
src/app.rs
@ -1,3 +1,12 @@
|
|||||||
|
use egui::{Align, Layout, RichText, WidgetText};
|
||||||
|
use egui_extras::RetainedImage;
|
||||||
|
use nostr_rust::events::Event;
|
||||||
|
use poll_promise::Promise;
|
||||||
|
use std::borrow::{Borrow, Cow};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
type ImageCache = HashMap<String, Promise<ehttp::Result<RetainedImage>>>;
|
||||||
|
|
||||||
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(default)] // if we add new fields, give them default values when deserializing old state
|
#[serde(default)] // if we add new fields, give them default values when deserializing old state
|
||||||
@ -5,6 +14,12 @@ pub struct Damus {
|
|||||||
// Example stuff:
|
// Example stuff:
|
||||||
label: String,
|
label: String,
|
||||||
|
|
||||||
|
#[serde(skip)]
|
||||||
|
events: Vec<Event>,
|
||||||
|
|
||||||
|
#[serde(skip)]
|
||||||
|
img_cache: ImageCache,
|
||||||
|
|
||||||
// this how you opt-out of serialization of a member
|
// this how you opt-out of serialization of a member
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
value: f32,
|
value: f32,
|
||||||
@ -15,6 +30,8 @@ impl Default for Damus {
|
|||||||
Self {
|
Self {
|
||||||
// Example stuff:
|
// Example stuff:
|
||||||
label: "Hello World!".to_owned(),
|
label: "Hello World!".to_owned(),
|
||||||
|
events: vec![],
|
||||||
|
img_cache: HashMap::new(),
|
||||||
value: 2.7,
|
value: 2.7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,19 +53,78 @@ impl Damus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timeline_view(app: &mut Damus, ui: &mut egui::Ui) {
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
ui.heading("Timeline");
|
fn parse_response(response: ehttp::Response) -> Result<RetainedImage, String> {
|
||||||
|
let content_type = response.content_type().unwrap_or_default();
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
if content_type.starts_with("image/svg+xml") {
|
||||||
ui.label("Write something: ");
|
RetainedImage::from_svg_bytes(&response.url, &response.bytes)
|
||||||
ui.text_edit_singleline(&mut app.label);
|
} else if content_type.starts_with("image/") {
|
||||||
});
|
RetainedImage::from_image_bytes(&response.url, &response.bytes)
|
||||||
|
} else {
|
||||||
ui.add(egui::Slider::new(&mut app.value, 0.0..=10.0).text("value"));
|
Err(format!(
|
||||||
if ui.button("Increment").clicked() {
|
"Expected image, found content-type {:?}",
|
||||||
app.value += 1.0;
|
content_type
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fetch_img(ctx: &egui::Context, url: &str) -> Promise<ehttp::Result<RetainedImage>> {
|
||||||
|
let (sender, promise) = Promise::new();
|
||||||
|
let request = ehttp::Request::get(url);
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
ehttp::fetch(request, move |response| {
|
||||||
|
let image = response.and_then(parse_response);
|
||||||
|
sender.send(image); // send the results back to the UI thread. ctx.request_repaint();
|
||||||
|
});
|
||||||
|
promise
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_pfp(ctx: &egui::Context, img_cache: &mut ImageCache, ui: &mut egui::Ui, url: String) {
|
||||||
|
let m_cached_promise = img_cache.get_mut(&url);
|
||||||
|
if m_cached_promise.is_none() {
|
||||||
|
img_cache.insert(url.clone(), fetch_img(ctx, &url));
|
||||||
|
}
|
||||||
|
|
||||||
|
match img_cache[&url].ready() {
|
||||||
|
None => {
|
||||||
|
ui.spinner(); // still loading
|
||||||
|
}
|
||||||
|
Some(Err(err)) => {
|
||||||
|
ui.colored_label(ui.visuals().error_fg_color, err); // something went wrong
|
||||||
|
}
|
||||||
|
Some(Ok(image)) => {
|
||||||
|
image.show_max_size(ui, egui::vec2(64.0, 64.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_event(ctx: &egui::Context, img_cache: &mut ImageCache, ui: &mut egui::Ui, ev: &Event) {
|
||||||
|
render_pfp(
|
||||||
|
ctx,
|
||||||
|
img_cache,
|
||||||
|
ui,
|
||||||
|
//"https://damus.io/img/damus.svg".into(),
|
||||||
|
"http://cdn.jb55.com/img/red-me.jpg".into(),
|
||||||
|
);
|
||||||
|
ui.label(&ev.content);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_events(ctx: &egui::Context, app: &mut Damus, ui: &mut egui::Ui) {
|
||||||
|
for ev in &app.events {
|
||||||
|
ui.spacing_mut().item_spacing.y = 10.0;
|
||||||
|
render_event(ctx, &mut app.img_cache, ui, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn timeline_view(ctx: &egui::Context, app: &mut Damus, ui: &mut egui::Ui) {
|
||||||
|
ui.heading("Timeline");
|
||||||
|
|
||||||
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||||
|
render_events(ctx, app, ui);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.spacing_mut().item_spacing.x = 0.0;
|
ui.spacing_mut().item_spacing.x = 0.0;
|
||||||
@ -62,6 +138,35 @@ fn timeline_view(app: &mut Damus, ui: &mut egui::Ui) {
|
|||||||
ui.label(".");
|
ui.label(".");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_damus(ctx: &egui::Context, _frame: &mut eframe::Frame, app: &mut Damus) {
|
||||||
|
#[cfg(not(target_arch = "wasm32"))] // no File->Quit on web pages!
|
||||||
|
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||||
|
// The top panel is often a good place for a menu bar:
|
||||||
|
egui::menu::bar(ui, |ui| {
|
||||||
|
ui.menu_button("File", |ui| {
|
||||||
|
if ui.button("Quit").clicked() {
|
||||||
|
_frame.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
egui::SidePanel::left("side_panel").show(ctx, |ui| timeline_view(ctx, app, ui));
|
||||||
|
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
// The central panel the region left after adding TopPanel's and SidePanel's
|
||||||
|
|
||||||
|
ui.heading("eframe template");
|
||||||
|
ui.hyperlink("https://github.com/emilk/eframe_template");
|
||||||
|
ui.add(egui::github_link_file!(
|
||||||
|
"https://github.com/emilk/eframe_template/blob/master/",
|
||||||
|
"Source code."
|
||||||
|
));
|
||||||
|
egui::warn_if_debug_build(ui);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl eframe::App for Damus {
|
impl eframe::App for Damus {
|
||||||
@ -78,39 +183,25 @@ impl eframe::App for Damus {
|
|||||||
// Tip: a good default choice is to just keep the `CentralPanel`.
|
// Tip: a good default choice is to just keep the `CentralPanel`.
|
||||||
// For inspiration and more examples, go to https://emilk.github.io/egui
|
// For inspiration and more examples, go to https://emilk.github.io/egui
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))] // no File->Quit on web pages!
|
let test_event = Event {
|
||||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
id: "6938e3cd841f3111dbdbd909f87fd52c3d1f1e4a07fd121d1243196e532811cb".to_string(),
|
||||||
// The top panel is often a good place for a menu bar:
|
pub_key: "f0a6ff7f70b872de6d82c8daec692a433fd23b6a49f25923c6f034df715cdeec".to_string(),
|
||||||
egui::menu::bar(ui, |ui| {
|
created_at: 1667781968,
|
||||||
ui.menu_button("File", |ui| {
|
kind: 1,
|
||||||
if ui.button("Quit").clicked() {
|
tags: vec![],
|
||||||
_frame.close();
|
content: "yello\nthere".to_string(),
|
||||||
|
sig: "af02c971015995f79e07fa98aaf98adeeb6a56d0005e451ee4e78844cff712a6bc0f2109f72a878975f162dcefde4173b65ebd4c3d3ab3b520a9dcac6acf092d".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.events.len() == 0 {
|
||||||
|
self.events.push(test_event.clone());
|
||||||
|
println!("{}", &self.events[0].content);
|
||||||
|
self.events.push(test_event.clone());
|
||||||
|
println!("{}", &self.events[1].content);
|
||||||
|
self.events.push(test_event.clone());
|
||||||
|
println!("{}", &self.events[2].content);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
egui::SidePanel::left("side_panel").show(ctx, |ui| timeline_view(self, ui));
|
render_damus(ctx, _frame, self);
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
|
||||||
// The central panel the region left after adding TopPanel's and SidePanel's
|
|
||||||
|
|
||||||
ui.heading("eframe template");
|
|
||||||
ui.hyperlink("https://github.com/emilk/eframe_template");
|
|
||||||
ui.add(egui::github_link_file!(
|
|
||||||
"https://github.com/emilk/eframe_template/blob/master/",
|
|
||||||
"Source code."
|
|
||||||
));
|
|
||||||
egui::warn_if_debug_build(ui);
|
|
||||||
});
|
|
||||||
|
|
||||||
if false {
|
|
||||||
egui::Window::new("Window").show(ctx, |ui| {
|
|
||||||
ui.label("Windows can be moved by dragging them.");
|
|
||||||
ui.label("They are automatically sized based on contents.");
|
|
||||||
ui.label("You can turn on resizing and scrolling if you like.");
|
|
||||||
ui.label("You would normally chose either panels OR windows.");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user