initial navigation
This commit is contained in:
42
Cargo.lock
generated
42
Cargo.lock
generated
@@ -1035,15 +1035,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "egui-tabs"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "git+https://github.com/damus-io/egui-tabs?rev=75f47141aebcf876986fad00dd83a69a7bb04840#75f47141aebcf876986fad00dd83a69a7bb04840"
|
|
||||||
dependencies = [
|
|
||||||
"egui",
|
|
||||||
"egui_extras",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "egui-wgpu"
|
name = "egui-wgpu"
|
||||||
version = "0.27.2"
|
version = "0.27.2"
|
||||||
@@ -1111,6 +1102,25 @@ dependencies = [
|
|||||||
"puffin",
|
"puffin",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
|
"winit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "egui_nav"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/damus-io/egui-nav?rev=9f640df83494a79cd7aa0b5983c83290d284d6ee#9f640df83494a79cd7aa0b5983c83290d284d6ee"
|
||||||
|
dependencies = [
|
||||||
|
"egui",
|
||||||
|
"egui_extras",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "egui_tabs"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/damus-io/egui-tabs?rev=120971fc43db6ba0b6f194f4bd4a66f7e00a4e22#120971fc43db6ba0b6f194f4bd4a66f7e00a4e22"
|
||||||
|
dependencies = [
|
||||||
|
"egui",
|
||||||
|
"egui_extras",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1178,7 +1188,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"shatter",
|
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2454,8 +2463,9 @@ dependencies = [
|
|||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"eframe",
|
"eframe",
|
||||||
"egui",
|
"egui",
|
||||||
"egui-tabs",
|
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
|
"egui_nav",
|
||||||
|
"egui_tabs",
|
||||||
"egui_virtual_list",
|
"egui_virtual_list",
|
||||||
"ehttp 0.2.0",
|
"ehttp 0.2.0",
|
||||||
"enostr",
|
"enostr",
|
||||||
@@ -3524,16 +3534,6 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "shatter"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c72d316f805789a3a026fd327dd854ece0fbdc5fb4f57ac9d1319f3670a4177"
|
|
||||||
dependencies = [
|
|
||||||
"env_logger 0.10.2",
|
|
||||||
"log",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
|||||||
17
Cargo.toml
17
Cargo.toml
@@ -14,12 +14,25 @@ crate-type = ["lib", "cdylib"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
#egui-android = { git = "https://github.com/jb55/egui-android.git" }
|
#egui-android = { git = "https://github.com/jb55/egui-android.git" }
|
||||||
egui = "0.27.2"
|
egui = "0.27.2"
|
||||||
eframe = { version = "0.27.2", default-features = false, features = [ "glow", "wgpu", "android-native-activity" ] }
|
eframe = { version = "0.27.2", default-features = false, features = [ "glow", "wgpu", "x11", "wayland", "android-native-activity" ] }
|
||||||
|
|
||||||
|
#
|
||||||
|
# TODO default features:
|
||||||
|
#
|
||||||
|
#"accesskit",
|
||||||
|
#"default_fonts",
|
||||||
|
#"glow",
|
||||||
|
#"wayland",
|
||||||
|
#"web_screen_reader",
|
||||||
|
#"winit/default",
|
||||||
|
#"x11",
|
||||||
|
|
||||||
#eframe = { version = "0.27.2", default-features = false, features = [ "glow", "android-native-activity" ] }
|
#eframe = { version = "0.27.2", default-features = false, features = [ "glow", "android-native-activity" ] }
|
||||||
#eframe = "0.22.0"
|
#eframe = "0.22.0"
|
||||||
egui_extras = { version = "0.27.2", features = ["all_loaders"] }
|
egui_extras = { version = "0.27.2", features = ["all_loaders"] }
|
||||||
ehttp = "0.2.0"
|
ehttp = "0.2.0"
|
||||||
egui-tabs = { git = "https://github.com/damus-io/egui-tabs", rev = "75f47141aebcf876986fad00dd83a69a7bb04840" }
|
egui_tabs = { git = "https://github.com/damus-io/egui-tabs", rev = "120971fc43db6ba0b6f194f4bd4a66f7e00a4e22" }
|
||||||
|
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "9f640df83494a79cd7aa0b5983c83290d284d6ee" }
|
||||||
reqwest = { version = "0.12.4", default-features = false, features = [ "rustls-tls-native-roots" ] }
|
reqwest = { version = "0.12.4", default-features = false, features = [ "rustls-tls-native-roots" ] }
|
||||||
image = { version = "0.24", features = ["jpeg", "png", "webp"] }
|
image = { version = "0.24", features = ["jpeg", "png", "webp"] }
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ serde_derive = "1"
|
|||||||
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
|
||||||
serde_json = "1.0.89"
|
serde_json = "1.0.89"
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
shatter = "0.1.1"
|
|
||||||
nostr = { version = "0.30.0" }
|
nostr = { version = "0.30.0" }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ mod error;
|
|||||||
mod event;
|
mod event;
|
||||||
mod filter;
|
mod filter;
|
||||||
mod keypair;
|
mod keypair;
|
||||||
|
mod note;
|
||||||
mod profile;
|
mod profile;
|
||||||
mod pubkey;
|
mod pubkey;
|
||||||
mod relay;
|
mod relay;
|
||||||
@@ -14,6 +15,7 @@ pub use ewebsock;
|
|||||||
pub use filter::Filter;
|
pub use filter::Filter;
|
||||||
pub use keypair::{FullKeypair, Keypair};
|
pub use keypair::{FullKeypair, Keypair};
|
||||||
pub use nostr::SecretKey;
|
pub use nostr::SecretKey;
|
||||||
|
pub use note::NoteId;
|
||||||
pub use profile::Profile;
|
pub use profile::Profile;
|
||||||
pub use pubkey::Pubkey;
|
pub use pubkey::Pubkey;
|
||||||
pub use relay::message::{RelayEvent, RelayMessage};
|
pub use relay::message::{RelayEvent, RelayMessage};
|
||||||
|
|||||||
@@ -1,87 +1,12 @@
|
|||||||
use crate::Event;
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
use shatter::shard::Shards;
|
pub struct NoteId([u8; 32]);
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
impl NoteId {
|
||||||
struct RefId(i32);
|
pub fn new(bytes: [u8; 32]) -> Self {
|
||||||
|
NoteId(bytes)
|
||||||
struct Ref<'a> {
|
|
||||||
ref_tag: u8,
|
|
||||||
relay_id: Option<&'a str>,
|
|
||||||
id: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> RefId {
|
|
||||||
fn get_ref(self, tags: &'a Vec<Vec<String>>) -> Option<Ref<'a>> {
|
|
||||||
let ind = self.0 as usize;
|
|
||||||
|
|
||||||
if ind > tags.len() - 1 {
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let tag = &tags[ind];
|
pub fn bytes(&self) -> &[u8; 32] {
|
||||||
|
&self.0
|
||||||
if tag.len() < 2 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if tag[0].len() != 1 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ref_tag = if let Some(rtag) = tag[0].as_bytes().first() {
|
|
||||||
*rtag
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
let id = &tag[1];
|
|
||||||
if id.len() != 64 {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let relay_id = if tag[2].len() == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(&*tag[2])
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(Ref {
|
|
||||||
ref_tag,
|
|
||||||
relay_id,
|
|
||||||
id,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MentionType {
|
|
||||||
Pubkey,
|
|
||||||
Event,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Mention {
|
|
||||||
index: Option<i32>,
|
|
||||||
typ: MentionType,
|
|
||||||
refid: RefId,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum EventRef {
|
|
||||||
Mention(Mention),
|
|
||||||
ThreadId(RefId),
|
|
||||||
Reply(RefId),
|
|
||||||
ReplyToRoot(RefId),
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EventRefs {
|
|
||||||
refs: Vec<EventRef>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DM {
|
|
||||||
decrypted: Option<String>,
|
|
||||||
shards: Shards,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Note {
|
|
||||||
event: NostrEvent,
|
|
||||||
shards: Shards,
|
|
||||||
refs: EventRef,
|
|
||||||
}
|
|
||||||
|
|||||||
103
src/app.rs
103
src/app.rs
@@ -5,13 +5,17 @@ use crate::error::Error;
|
|||||||
use crate::frame_history::FrameHistory;
|
use crate::frame_history::FrameHistory;
|
||||||
use crate::imgcache::ImageCache;
|
use crate::imgcache::ImageCache;
|
||||||
use crate::notecache::{CachedNote, NoteCache};
|
use crate::notecache::{CachedNote, NoteCache};
|
||||||
|
use crate::relay_pool_manager::RelayPoolManager;
|
||||||
use crate::route::Route;
|
use crate::route::Route;
|
||||||
use crate::timeline;
|
use crate::timeline;
|
||||||
use crate::timeline::{MergeKind, NoteRef, Timeline, ViewFilter};
|
use crate::timeline::{MergeKind, NoteRef, Timeline, ViewFilter};
|
||||||
use crate::ui;
|
use crate::ui;
|
||||||
use crate::ui::profile::SimpleProfilePreviewController;
|
use crate::ui::{DesktopSidePanel, RelayView, SidePanelAction, View};
|
||||||
use crate::ui::DesktopSidePanel;
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
use egui_nav::{Nav, NavAction};
|
||||||
|
use enostr::RelayPool;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use egui::{Context, Frame, Style};
|
use egui::{Context, Frame, Style};
|
||||||
use egui_extras::{Size, StripBuilder};
|
use egui_extras::{Size, StripBuilder};
|
||||||
@@ -25,8 +29,6 @@ use std::path::Path;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
use enostr::RelayPool;
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
pub enum DamusState {
|
pub enum DamusState {
|
||||||
Initializing,
|
Initializing,
|
||||||
@@ -42,7 +44,7 @@ pub struct Damus {
|
|||||||
is_mobile: bool,
|
is_mobile: bool,
|
||||||
|
|
||||||
/// global navigation for account management popups, etc.
|
/// global navigation for account management popups, etc.
|
||||||
_nav: Vec<Route>,
|
//nav: Vec<Route>,
|
||||||
pub textmode: bool,
|
pub textmode: bool,
|
||||||
|
|
||||||
pub timelines: Vec<Timeline>,
|
pub timelines: Vec<Timeline>,
|
||||||
@@ -354,7 +356,9 @@ fn poll_notes_for_timeline<'a>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let new_note_ids = damus.ndb.poll_for_notes(sub, 100);
|
let new_note_ids = damus.ndb.poll_for_notes(sub, 100);
|
||||||
if !new_note_ids.is_empty() {
|
if new_note_ids.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
debug!("{} new notes! {:?}", new_note_ids.len(), new_note_ids);
|
debug!("{} new notes! {:?}", new_note_ids.len(), new_note_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,6 +420,10 @@ fn insert_notes_into_timeline(
|
|||||||
let timeline = &mut app.timelines[timeline_ind];
|
let timeline = &mut app.timelines[timeline_ind];
|
||||||
let num_prev_items = timeline.notes(filter).len();
|
let num_prev_items = timeline.notes(filter).len();
|
||||||
let (notes, merge_kind) = timeline::merge_sorted_vecs(timeline.notes(filter), new_refs);
|
let (notes, merge_kind) = timeline::merge_sorted_vecs(timeline.notes(filter), new_refs);
|
||||||
|
debug!(
|
||||||
|
"got merge kind {:?} for {:?} on timeline {}",
|
||||||
|
merge_kind, filter, timeline_ind
|
||||||
|
);
|
||||||
|
|
||||||
timeline.view_mut(filter).notes = notes;
|
timeline.view_mut(filter).notes = notes;
|
||||||
let new_items = timeline.notes(filter).len() - num_prev_items;
|
let new_items = timeline.notes(filter).len() - num_prev_items;
|
||||||
@@ -697,7 +705,6 @@ impl Damus {
|
|||||||
img_cache: ImageCache::new(imgcache_dir),
|
img_cache: ImageCache::new(imgcache_dir),
|
||||||
note_cache: NoteCache::default(),
|
note_cache: NoteCache::default(),
|
||||||
selected_timeline: 0,
|
selected_timeline: 0,
|
||||||
_nav: Vec::with_capacity(6),
|
|
||||||
timelines,
|
timelines,
|
||||||
textmode: false,
|
textmode: false,
|
||||||
ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"),
|
ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"),
|
||||||
@@ -730,7 +737,6 @@ impl Damus {
|
|||||||
note_cache: NoteCache::default(),
|
note_cache: NoteCache::default(),
|
||||||
selected_timeline: 0,
|
selected_timeline: 0,
|
||||||
timelines,
|
timelines,
|
||||||
_nav: vec![],
|
|
||||||
textmode: false,
|
textmode: false,
|
||||||
ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"),
|
ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"),
|
||||||
account_manager: AccountManager::new(None, crate::key_storage::KeyStorage::None),
|
account_manager: AccountManager::new(None, crate::key_storage::KeyStorage::None),
|
||||||
@@ -862,14 +868,71 @@ fn render_panel(ctx: &egui::Context, app: &mut Damus, timeline_ind: usize) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_nav(routes: Vec<Route>, timeline_ind: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||||
|
let app_ctx = Rc::new(RefCell::new(app));
|
||||||
|
|
||||||
|
let nav_response = Nav::new(routes).show(ui, |ui, nav| match nav.top() {
|
||||||
|
Route::Timeline(_n) => {
|
||||||
|
timeline::timeline_view(ui, &mut app_ctx.borrow_mut(), timeline_ind);
|
||||||
|
}
|
||||||
|
|
||||||
|
Route::ManageAccount => {
|
||||||
|
ui.label("account management view");
|
||||||
|
}
|
||||||
|
|
||||||
|
Route::Thread(_key) => {
|
||||||
|
ui.label("thread view");
|
||||||
|
}
|
||||||
|
|
||||||
|
Route::Relays => {
|
||||||
|
let pool = &mut app_ctx.borrow_mut().pool;
|
||||||
|
let manager = RelayPoolManager::new(pool);
|
||||||
|
RelayView::new(manager).ui(ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
Route::Reply(id) => {
|
||||||
|
let app = app_ctx.borrow();
|
||||||
|
let txn = if let Ok(txn) = Transaction::new(&app.ndb) {
|
||||||
|
txn
|
||||||
|
} else {
|
||||||
|
ui.label("Reply to unknown note");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let note = if let Ok(note) = app.ndb.get_note_by_id(&txn, id.bytes()) {
|
||||||
|
note
|
||||||
|
} else {
|
||||||
|
ui.label("Reply to unknown note");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.label(format!(
|
||||||
|
"Replying to note by {}",
|
||||||
|
app.ndb
|
||||||
|
.get_profile_by_pubkey(&txn, note.pubkey())
|
||||||
|
.as_ref()
|
||||||
|
.ok()
|
||||||
|
.and_then(|pr| Some(crate::profile::get_profile_name(pr)?.username()))
|
||||||
|
.unwrap_or("??")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(NavAction::Returned) = nav_response.action {
|
||||||
|
app_ctx.borrow_mut().timelines[timeline_ind].routes.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn render_damus_mobile(ctx: &egui::Context, app: &mut Damus) {
|
fn render_damus_mobile(ctx: &egui::Context, app: &mut Damus) {
|
||||||
//render_panel(ctx, app, 0);
|
//render_panel(ctx, app, 0);
|
||||||
|
|
||||||
#[cfg(feature = "profiling")]
|
#[cfg(feature = "profiling")]
|
||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
|
|
||||||
|
//let routes = app.timelines[0].routes.clone();
|
||||||
|
|
||||||
main_panel(&ctx.style(), app.is_mobile()).show(ctx, |ui| {
|
main_panel(&ctx.style(), app.is_mobile()).show(ctx, |ui| {
|
||||||
timeline::timeline_view(ui, app, 0);
|
render_nav(app.timelines[0].routes.clone(), 0, app, ui);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,21 +984,27 @@ fn timelines_view(ui: &mut egui::Ui, sizes: Size, app: &mut Damus, timelines: us
|
|||||||
.clip(true)
|
.clip(true)
|
||||||
.horizontal(|mut strip| {
|
.horizontal(|mut strip| {
|
||||||
strip.cell(|ui| {
|
strip.cell(|ui| {
|
||||||
let side_panel = DesktopSidePanel::new(
|
let side_panel = DesktopSidePanel::new(app).show(ui);
|
||||||
app.account_manager
|
|
||||||
.get_selected_account()
|
|
||||||
.map(|a| a.pubkey.bytes()),
|
|
||||||
SimpleProfilePreviewController::new(&app.ndb, &mut app.img_cache),
|
|
||||||
)
|
|
||||||
.show(ui);
|
|
||||||
|
|
||||||
if side_panel.response.clicked() {
|
if side_panel.response.clicked() {
|
||||||
info!("clicked {:?}", side_panel.action);
|
info!("clicked {:?}", side_panel.action);
|
||||||
|
if let SidePanelAction::Account = side_panel.action {
|
||||||
|
app.timelines[0].routes.push(Route::ManageAccount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for timeline_ind in 0..timelines {
|
for timeline_ind in 0..timelines {
|
||||||
strip.cell(|ui| timeline::timeline_view(ui, app, timeline_ind));
|
strip.cell(|ui| {
|
||||||
|
render_nav(
|
||||||
|
app.timelines[timeline_ind].routes.clone(),
|
||||||
|
timeline_ind,
|
||||||
|
app,
|
||||||
|
ui,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
//strip.cell(|ui| timeline::timeline_view(ui, app, timeline_ind));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/route.rs
23
src/route.rs
@@ -1,9 +1,24 @@
|
|||||||
//use nostrdb::NoteKey;
|
use enostr::NoteId;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
/// App routing. These describe different places you can go inside Notedeck.
|
/// App routing. These describe different places you can go inside Notedeck.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub enum Route {
|
pub enum Route {
|
||||||
/*
|
Timeline(String),
|
||||||
ManageAccount,
|
ManageAccount,
|
||||||
Thread(NoteKey),
|
Thread(NoteId),
|
||||||
*/
|
Reply(NoteId),
|
||||||
|
Relays,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Route {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Route::ManageAccount => write!(f, "Manage Account"),
|
||||||
|
Route::Timeline(name) => write!(f, "{}", name),
|
||||||
|
Route::Thread(_id) => write!(f, "Thread"),
|
||||||
|
Route::Reply(_id) => write!(f, "Reply"),
|
||||||
|
Route::Relays => write!(f, "Relays"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use enostr::{FullKeypair, Pubkey, RelayPool};
|
use enostr::{FullKeypair, Pubkey, RelayPool};
|
||||||
use nostrdb::{Config, Ndb, ProfileRecord};
|
use nostrdb::ProfileRecord;
|
||||||
|
|
||||||
use crate::{
|
use crate::{account_manager::UserAccount, Damus};
|
||||||
account_manager::{AccountManager, UserAccount},
|
|
||||||
imgcache::ImageCache,
|
|
||||||
key_storage::KeyStorage,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
pub fn sample_pool() -> RelayPool {
|
pub fn sample_pool() -> RelayPool {
|
||||||
@@ -87,20 +83,15 @@ pub fn get_test_accounts() -> Vec<UserAccount> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_accmgr_and_ndb_and_imgcache() -> (AccountManager, Ndb, ImageCache) {
|
pub fn get_account_manager_test_app(is_mobile: bool) -> Damus {
|
||||||
let mut account_manager = AccountManager::new(None, KeyStorage::None);
|
|
||||||
let accounts = get_test_accounts();
|
|
||||||
for account in accounts {
|
|
||||||
account_manager.add_account(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut config = Config::new();
|
|
||||||
config.set_ingester_threads(2);
|
|
||||||
|
|
||||||
let db_dir = Path::new(".");
|
let db_dir = Path::new(".");
|
||||||
let path = db_dir.to_str().unwrap();
|
let path = db_dir.to_str().unwrap();
|
||||||
let ndb = Ndb::new(path, &config).expect("ndb");
|
let mut app = Damus::mock(path, is_mobile);
|
||||||
let imgcache_dir = db_dir.join("cache/img");
|
|
||||||
let img_cache = ImageCache::new(imgcache_dir);
|
let accounts = get_test_accounts();
|
||||||
(account_manager, ndb, img_cache)
|
for account in accounts {
|
||||||
|
app.account_manager.add_account(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
app
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
use crate::notecache::CachedNote;
|
use crate::notecache::CachedNote;
|
||||||
use crate::{ui, Damus};
|
use crate::{ui, Damus};
|
||||||
|
|
||||||
|
use crate::route::Route;
|
||||||
use egui::containers::scroll_area::ScrollBarVisibility;
|
use egui::containers::scroll_area::ScrollBarVisibility;
|
||||||
use egui::{Direction, Layout};
|
use egui::{Direction, Layout};
|
||||||
|
|
||||||
|
use crate::ui::BarAction;
|
||||||
use egui_tabs::TabColor;
|
use egui_tabs::TabColor;
|
||||||
use egui_virtual_list::VirtualList;
|
use egui_virtual_list::VirtualList;
|
||||||
use enostr::Filter;
|
use enostr::{Filter, NoteId};
|
||||||
use nostrdb::{Note, NoteKey, Subscription, Transaction};
|
use nostrdb::{Note, NoteKey, Subscription, Transaction};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@@ -35,7 +38,7 @@ impl PartialOrd for NoteRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
pub enum ViewFilter {
|
pub enum ViewFilter {
|
||||||
Notes,
|
Notes,
|
||||||
NotesAndReplies,
|
NotesAndReplies,
|
||||||
@@ -122,6 +125,7 @@ pub struct Timeline {
|
|||||||
pub filter: Vec<Filter>,
|
pub filter: Vec<Filter>,
|
||||||
pub views: Vec<TimelineView>,
|
pub views: Vec<TimelineView>,
|
||||||
pub selected_view: i32,
|
pub selected_view: i32,
|
||||||
|
pub routes: Vec<Route>,
|
||||||
|
|
||||||
/// Our nostrdb subscription
|
/// Our nostrdb subscription
|
||||||
pub subscription: Option<Subscription>,
|
pub subscription: Option<Subscription>,
|
||||||
@@ -134,12 +138,14 @@ impl Timeline {
|
|||||||
let replies = TimelineView::new(ViewFilter::NotesAndReplies);
|
let replies = TimelineView::new(ViewFilter::NotesAndReplies);
|
||||||
let views = vec![notes, replies];
|
let views = vec![notes, replies];
|
||||||
let selected_view = 0;
|
let selected_view = 0;
|
||||||
|
let routes = vec![Route::Timeline("Timeline".to_string())];
|
||||||
|
|
||||||
Timeline {
|
Timeline {
|
||||||
filter,
|
filter,
|
||||||
views,
|
views,
|
||||||
subscription,
|
subscription,
|
||||||
selected_view,
|
selected_view,
|
||||||
|
routes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +239,7 @@ fn tabs_ui(timeline: &mut Timeline, ui: &mut egui::Ui) {
|
|||||||
|
|
||||||
let stroke = egui::Stroke {
|
let stroke = egui::Stroke {
|
||||||
color: ui.visuals().hyperlink_color,
|
color: ui.visuals().hyperlink_color,
|
||||||
width: 3.0,
|
width: 2.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let speed = 0.1f32;
|
let speed = 0.1f32;
|
||||||
@@ -298,8 +304,19 @@ pub fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
|
|||||||
|
|
||||||
ui::padding(8.0, ui, |ui| {
|
ui::padding(8.0, ui, |ui| {
|
||||||
let textmode = app.textmode;
|
let textmode = app.textmode;
|
||||||
ui.add(ui::Note::new(app, ¬e).note_previews(!textmode));
|
let resp = ui::Note::new(app, ¬e).note_previews(!textmode).show(ui);
|
||||||
|
if let Some(action) = resp.action {
|
||||||
|
debug!("bar action: {:?}", action);
|
||||||
|
match action {
|
||||||
|
BarAction::Reply => {
|
||||||
|
app.timelines[timeline]
|
||||||
|
.routes
|
||||||
|
.push(Route::Reply(NoteId::new(note.id().to_owned())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ui::hline(ui);
|
ui::hline(ui);
|
||||||
//ui.add(egui::Separator::default().spacing(0.0));
|
//ui.add(egui::Separator::default().spacing(0.0));
|
||||||
|
|
||||||
@@ -308,6 +325,7 @@ pub fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum MergeKind {
|
pub enum MergeKind {
|
||||||
FrontInsert,
|
FrontInsert,
|
||||||
Spliced,
|
Spliced,
|
||||||
|
|||||||
@@ -2,103 +2,69 @@ use crate::colors::PINK;
|
|||||||
use crate::{
|
use crate::{
|
||||||
account_manager::AccountManager,
|
account_manager::AccountManager,
|
||||||
app_style::NotedeckTextStyle,
|
app_style::NotedeckTextStyle,
|
||||||
ui::{Preview, PreviewConfig, View},
|
ui::{profile_preview_controller, Preview, PreviewConfig, View},
|
||||||
|
Damus,
|
||||||
};
|
};
|
||||||
use egui::{Align, Button, Frame, Image, Layout, RichText, ScrollArea, Vec2};
|
use egui::{Align, Button, Frame, Image, Layout, RichText, ScrollArea, Vec2};
|
||||||
|
|
||||||
use super::profile::preview::SimpleProfilePreview;
|
use super::profile::preview::SimpleProfilePreview;
|
||||||
use super::profile::{ProfilePreviewOp, SimpleProfilePreviewController};
|
use super::profile::ProfilePreviewOp;
|
||||||
|
|
||||||
pub struct AccountManagementView<'a> {
|
pub struct AccountManagementView {}
|
||||||
mobile: bool,
|
|
||||||
account_manager: &'a mut AccountManager,
|
|
||||||
simple_preview_controller: SimpleProfilePreviewController<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> View for AccountManagementView<'a> {
|
impl AccountManagementView {
|
||||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
fn show(app: &mut Damus, ui: &mut egui::Ui) {
|
||||||
if self.mobile {
|
|
||||||
self.show_mobile(ui);
|
|
||||||
} else {
|
|
||||||
self.show(ui);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> AccountManagementView<'a> {
|
|
||||||
pub fn new(
|
|
||||||
mobile: bool,
|
|
||||||
account_manager: &'a mut AccountManager,
|
|
||||||
simple_preview_controller: SimpleProfilePreviewController<'a>,
|
|
||||||
) -> Self {
|
|
||||||
AccountManagementView {
|
|
||||||
mobile,
|
|
||||||
account_manager,
|
|
||||||
simple_preview_controller,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn show(&mut self, ui: &mut egui::Ui) {
|
|
||||||
Frame::none().outer_margin(24.0).show(ui, |ui| {
|
Frame::none().outer_margin(24.0).show(ui, |ui| {
|
||||||
self.top_section_buttons_widget(ui);
|
Self::top_section_buttons_widget(ui);
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
scroll_area().show(ui, |ui| {
|
scroll_area().show(ui, |ui| {
|
||||||
self.show_accounts(ui);
|
Self::show_accounts(app, ui);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_accounts(&mut self, ui: &mut egui::Ui) {
|
fn show_accounts(app: &mut Damus, ui: &mut egui::Ui) {
|
||||||
let maybe_remove = self.simple_preview_controller.set_profile_previews(
|
let maybe_remove =
|
||||||
self.account_manager,
|
profile_preview_controller::set_profile_previews(app, ui, account_card_ui());
|
||||||
ui,
|
|
||||||
account_card_ui(),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.maybe_remove_accounts(maybe_remove);
|
Self::maybe_remove_accounts(&mut app.account_manager, maybe_remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_accounts_mobile(&mut self, ui: &mut egui::Ui) {
|
fn show_accounts_mobile(app: &mut Damus, ui: &mut egui::Ui) {
|
||||||
ui.allocate_ui_with_layout(
|
ui.allocate_ui_with_layout(
|
||||||
Vec2::new(ui.available_size_before_wrap().x, 32.0),
|
Vec2::new(ui.available_size_before_wrap().x, 32.0),
|
||||||
Layout::top_down(egui::Align::Min),
|
Layout::top_down(egui::Align::Min),
|
||||||
|ui| {
|
|ui| {
|
||||||
// create all account 'cards' and get the indicies the user requested to remove
|
// create all account 'cards' and get the indicies the user requested to remove
|
||||||
let maybe_remove = self.simple_preview_controller.set_profile_previews(
|
let maybe_remove = profile_preview_controller::set_profile_previews(
|
||||||
self.account_manager,
|
app,
|
||||||
ui,
|
ui,
|
||||||
account_card_ui(), // closure for creating an account 'card'
|
account_card_ui(), // closure for creating an account 'card'
|
||||||
);
|
);
|
||||||
|
|
||||||
// remove all account indicies user requested
|
// remove all account indicies user requested
|
||||||
self.maybe_remove_accounts(maybe_remove);
|
Self::maybe_remove_accounts(&mut app.account_manager, maybe_remove);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_remove_accounts(&mut self, account_indices: Option<Vec<usize>>) {
|
fn maybe_remove_accounts(manager: &mut AccountManager, account_indices: Option<Vec<usize>>) {
|
||||||
if let Some(to_remove) = account_indices {
|
if let Some(to_remove) = account_indices {
|
||||||
to_remove
|
to_remove
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|index| self.account_manager.remove_account(*index));
|
.for_each(|index| manager.remove_account(*index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_mobile(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
fn show_mobile(app: &mut Damus, ui: &mut egui::Ui) {
|
||||||
egui::CentralPanel::default()
|
|
||||||
.show(ui.ctx(), |ui| {
|
|
||||||
mobile_title(ui);
|
mobile_title(ui);
|
||||||
self.top_section_buttons_widget(ui);
|
Self::top_section_buttons_widget(ui);
|
||||||
|
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
scroll_area().show(ui, |ui| {
|
scroll_area().show(ui, |ui| Self::show_accounts_mobile(app, ui));
|
||||||
self.show_accounts_mobile(ui);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn top_section_buttons_widget(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
fn top_section_buttons_widget(ui: &mut egui::Ui) -> egui::Response {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.allocate_ui_with_layout(
|
ui.allocate_ui_with_layout(
|
||||||
Vec2::new(ui.available_size_before_wrap().x, 32.0),
|
Vec2::new(ui.available_size_before_wrap().x, 32.0),
|
||||||
@@ -233,44 +199,36 @@ fn selected_widget() -> impl egui::Widget {
|
|||||||
// PREVIEWS
|
// PREVIEWS
|
||||||
|
|
||||||
mod preview {
|
mod preview {
|
||||||
use nostrdb::Ndb;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{imgcache::ImageCache, test_data::get_accmgr_and_ndb_and_imgcache};
|
use crate::test_data::get_account_manager_test_app;
|
||||||
|
|
||||||
pub struct AccountManagementPreview {
|
pub struct AccountManagementPreview {
|
||||||
is_mobile: bool,
|
is_mobile: bool,
|
||||||
account_manager: AccountManager,
|
app: Damus,
|
||||||
ndb: Ndb,
|
|
||||||
img_cache: ImageCache,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountManagementPreview {
|
impl AccountManagementPreview {
|
||||||
fn new(is_mobile: bool) -> Self {
|
fn new(is_mobile: bool) -> Self {
|
||||||
let (account_manager, ndb, img_cache) = get_accmgr_and_ndb_and_imgcache();
|
let app = get_account_manager_test_app(is_mobile);
|
||||||
|
|
||||||
AccountManagementPreview {
|
AccountManagementPreview { is_mobile, app }
|
||||||
is_mobile,
|
|
||||||
account_manager,
|
|
||||||
ndb,
|
|
||||||
img_cache,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for AccountManagementPreview {
|
impl View for AccountManagementPreview {
|
||||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
ui.add_space(24.0);
|
ui.add_space(24.0);
|
||||||
AccountManagementView::new(
|
if self.is_mobile {
|
||||||
self.is_mobile,
|
AccountManagementView::show_mobile(&mut self.app, ui);
|
||||||
&mut self.account_manager,
|
} else {
|
||||||
SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache),
|
AccountManagementView::show(&mut self.app, ui);
|
||||||
)
|
}
|
||||||
.ui(ui);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Preview for AccountManagementView<'a> {
|
impl Preview for AccountManagementView {
|
||||||
type Prev = AccountManagementPreview;
|
type Prev = AccountManagementPreview;
|
||||||
|
|
||||||
fn preview(cfg: PreviewConfig) -> Self::Prev {
|
fn preview(cfg: PreviewConfig) -> Self::Prev {
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
account_manager::{AccountManager, UserAccount},
|
account_manager::UserAccount, colors::PINK, profile::DisplayName,
|
||||||
colors::PINK,
|
ui::profile_preview_controller, Damus, Result,
|
||||||
profile::DisplayName,
|
|
||||||
Result,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use nostrdb::Ndb;
|
||||||
|
|
||||||
use egui::{
|
use egui::{
|
||||||
Align, Button, Color32, Frame, Id, Image, Layout, Margin, RichText, Rounding, ScrollArea,
|
Align, Button, Color32, Frame, Id, Image, Layout, Margin, RichText, Rounding, ScrollArea,
|
||||||
Sense, Vec2,
|
Sense, Vec2,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::profile::{preview::SimpleProfilePreview, SimpleProfilePreviewController};
|
use super::profile::preview::SimpleProfilePreview;
|
||||||
|
|
||||||
pub struct AccountSelectionWidget<'a> {
|
pub struct AccountSelectionWidget {}
|
||||||
is_mobile: bool,
|
|
||||||
account_manager: &'a AccountManager,
|
|
||||||
simple_preview_controller: SimpleProfilePreviewController<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AccountSelectAction {
|
enum AccountSelectAction {
|
||||||
RemoveAccount { _index: usize },
|
RemoveAccount { _index: usize },
|
||||||
@@ -28,36 +25,24 @@ struct AccountSelectResponse {
|
|||||||
action: Option<AccountSelectAction>,
|
action: Option<AccountSelectAction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AccountSelectionWidget<'a> {
|
impl AccountSelectionWidget {
|
||||||
pub fn new(
|
pub fn ui(app: &mut Damus, ui: &mut egui::Ui) {
|
||||||
is_mobile: bool,
|
if app.is_mobile() {
|
||||||
account_manager: &'a AccountManager,
|
Self::show_mobile(ui);
|
||||||
simple_preview_controller: SimpleProfilePreviewController<'a>,
|
|
||||||
) -> Self {
|
|
||||||
AccountSelectionWidget {
|
|
||||||
is_mobile,
|
|
||||||
account_manager,
|
|
||||||
simple_preview_controller,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ui(&'a mut self, ui: &mut egui::Ui) {
|
|
||||||
if self.is_mobile {
|
|
||||||
self.show_mobile(ui);
|
|
||||||
} else {
|
} else {
|
||||||
self.show(ui);
|
Self::show(app, ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&mut self, ui: &mut egui::Ui) -> AccountSelectResponse {
|
fn show(app: &mut Damus, ui: &mut egui::Ui) -> AccountSelectResponse {
|
||||||
let mut res = AccountSelectResponse::default();
|
let mut res = AccountSelectResponse::default();
|
||||||
let mut selected_index = self.account_manager.get_selected_account_index();
|
let mut selected_index = app.account_manager.get_selected_account_index();
|
||||||
|
|
||||||
Frame::none().outer_margin(8.0).show(ui, |ui| {
|
Frame::none().outer_margin(8.0).show(ui, |ui| {
|
||||||
res = top_section_widget(ui);
|
res = top_section_widget(ui);
|
||||||
|
|
||||||
scroll_area().show(ui, |ui| {
|
scroll_area().show(ui, |ui| {
|
||||||
if let Some(_index) = self.show_accounts(ui) {
|
if let Some(_index) = Self::show_accounts(app, ui) {
|
||||||
selected_index = Some(_index);
|
selected_index = Some(_index);
|
||||||
res.action = Some(AccountSelectAction::SelectAccount { _index });
|
res.action = Some(AccountSelectAction::SelectAccount { _index });
|
||||||
}
|
}
|
||||||
@@ -66,9 +51,9 @@ impl<'a> AccountSelectionWidget<'a> {
|
|||||||
ui.add(add_account_button());
|
ui.add(add_account_button());
|
||||||
|
|
||||||
if let Some(_index) = selected_index {
|
if let Some(_index) = selected_index {
|
||||||
if let Some(account) = self.account_manager.get_account(_index) {
|
if let Some(account) = app.account_manager.get_account(_index) {
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
if self.handle_sign_out(ui, account) {
|
if Self::handle_sign_out(&app.ndb, ui, account) {
|
||||||
res.action = Some(AccountSelectAction::RemoveAccount { _index })
|
res.action = Some(AccountSelectAction::RemoveAccount { _index })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,29 +65,30 @@ impl<'a> AccountSelectionWidget<'a> {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_sign_out(&mut self, ui: &mut egui::Ui, account: &UserAccount) -> bool {
|
fn handle_sign_out(ndb: &Ndb, ui: &mut egui::Ui, account: &UserAccount) -> bool {
|
||||||
if let Ok(response) = self.sign_out_button(ui, account) {
|
if let Ok(response) = Self::sign_out_button(ndb, ui, account) {
|
||||||
response.clicked()
|
response.clicked()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_mobile(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
fn show_mobile(ui: &mut egui::Ui) -> egui::Response {
|
||||||
let _ = ui;
|
let _ = ui;
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_accounts(&mut self, ui: &mut egui::Ui) -> Option<usize> {
|
fn show_accounts(app: &mut Damus, ui: &mut egui::Ui) -> Option<usize> {
|
||||||
self.simple_preview_controller.view_profile_previews(
|
profile_preview_controller::view_profile_previews(app, ui, account_switcher_card_ui)
|
||||||
self.account_manager,
|
|
||||||
ui,
|
|
||||||
account_switcher_card_ui(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_out_button(&self, ui: &mut egui::Ui, account: &UserAccount) -> Result<egui::Response> {
|
fn sign_out_button(
|
||||||
self.simple_preview_controller.show_with_nickname(
|
ndb: &Ndb,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
account: &UserAccount,
|
||||||
|
) -> Result<egui::Response> {
|
||||||
|
profile_preview_controller::show_with_nickname(
|
||||||
|
ndb,
|
||||||
ui,
|
ui,
|
||||||
account.pubkey.bytes(),
|
account.pubkey.bytes(),
|
||||||
|ui: &mut egui::Ui, username: &DisplayName| {
|
|ui: &mut egui::Ui, username: &DisplayName| {
|
||||||
@@ -122,14 +108,13 @@ impl<'a> AccountSelectionWidget<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn account_switcher_card_ui() -> fn(
|
fn account_switcher_card_ui(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
preview: SimpleProfilePreview,
|
preview: SimpleProfilePreview,
|
||||||
width: f32,
|
width: f32,
|
||||||
is_selected: bool,
|
is_selected: bool,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|ui, preview, width, is_selected, index| {
|
|
||||||
let resp = ui.add_sized(Vec2::new(width, 50.0), |ui: &mut egui::Ui| {
|
let resp = ui.add_sized(Vec2::new(width, 50.0), |ui: &mut egui::Ui| {
|
||||||
Frame::none()
|
Frame::none()
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
@@ -157,7 +142,6 @@ fn account_switcher_card_ui() -> fn(
|
|||||||
|
|
||||||
ui.interact(resp.rect, Id::new(index), Sense::click())
|
ui.interact(resp.rect, Id::new(index), Sense::click())
|
||||||
.clicked()
|
.clicked()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selection_widget() -> impl egui::Widget {
|
fn selection_widget() -> impl egui::Widget {
|
||||||
@@ -215,48 +199,33 @@ fn add_account_button() -> egui::Button<'static> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod previews {
|
mod previews {
|
||||||
use nostrdb::Ndb;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account_manager::AccountManager,
|
|
||||||
imgcache::ImageCache,
|
|
||||||
test_data,
|
test_data,
|
||||||
ui::{profile::SimpleProfilePreviewController, Preview, PreviewConfig, View},
|
ui::{Preview, PreviewConfig, View},
|
||||||
|
Damus,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::AccountSelectionWidget;
|
use super::AccountSelectionWidget;
|
||||||
|
|
||||||
pub struct AccountSelectionPreview {
|
pub struct AccountSelectionPreview {
|
||||||
is_mobile: bool,
|
app: Damus,
|
||||||
account_manager: AccountManager,
|
|
||||||
ndb: Ndb,
|
|
||||||
img_cache: ImageCache,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountSelectionPreview {
|
impl AccountSelectionPreview {
|
||||||
fn new(is_mobile: bool) -> Self {
|
fn new(is_mobile: bool) -> Self {
|
||||||
let (account_manager, ndb, img_cache) = test_data::get_accmgr_and_ndb_and_imgcache();
|
let app = test_data::get_account_manager_test_app(is_mobile);
|
||||||
AccountSelectionPreview {
|
AccountSelectionPreview { app }
|
||||||
is_mobile,
|
|
||||||
account_manager,
|
|
||||||
ndb,
|
|
||||||
img_cache,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for AccountSelectionPreview {
|
impl View for AccountSelectionPreview {
|
||||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
AccountSelectionWidget::new(
|
AccountSelectionWidget::show(&mut self.app, ui);
|
||||||
self.is_mobile,
|
|
||||||
&self.account_manager,
|
|
||||||
SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache),
|
|
||||||
)
|
|
||||||
.ui(ui);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Preview for AccountSelectionWidget<'a> {
|
impl Preview for AccountSelectionWidget {
|
||||||
type Prev = AccountSelectionPreview;
|
type Prev = AccountSelectionPreview;
|
||||||
|
|
||||||
fn preview(cfg: PreviewConfig) -> Self::Prev {
|
fn preview(cfg: PreviewConfig) -> Self::Prev {
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ pub mod username;
|
|||||||
pub use account_management::AccountManagementView;
|
pub use account_management::AccountManagementView;
|
||||||
pub use account_switcher::AccountSelectionWidget;
|
pub use account_switcher::AccountSelectionWidget;
|
||||||
pub use mention::Mention;
|
pub use mention::Mention;
|
||||||
pub use note::Note;
|
pub use note::{BarAction, Note, NoteResponse};
|
||||||
pub use preview::{Preview, PreviewApp, PreviewConfig};
|
pub use preview::{Preview, PreviewApp, PreviewConfig};
|
||||||
pub use profile::{ProfilePic, ProfilePreview};
|
pub use profile::{profile_preview_controller, ProfilePic, ProfilePreview};
|
||||||
pub use relay::RelayView;
|
pub use relay::RelayView;
|
||||||
pub use side_panel::DesktopSidePanel;
|
pub use side_panel::{DesktopSidePanel, SidePanelAction};
|
||||||
pub use username::Username;
|
pub use username::Username;
|
||||||
|
|
||||||
use egui::Margin;
|
use egui::Margin;
|
||||||
|
|||||||
@@ -15,12 +15,17 @@ pub struct Note<'a> {
|
|||||||
flags: NoteOptions,
|
flags: NoteOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NoteResponse {
|
||||||
|
pub response: egui::Response,
|
||||||
|
pub action: Option<BarAction>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> egui::Widget for Note<'a> {
|
impl<'a> egui::Widget for Note<'a> {
|
||||||
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
||||||
if self.app.textmode {
|
if self.app.textmode {
|
||||||
self.textmode_ui(ui)
|
self.textmode_ui(ui)
|
||||||
} else {
|
} else {
|
||||||
self.standard_ui(ui)
|
self.show(ui).response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,13 +191,15 @@ impl<'a> Note<'a> {
|
|||||||
.response
|
.response
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn standard_ui(self, ui: &mut egui::Ui) -> egui::Response {
|
pub fn show(self, ui: &mut egui::Ui) -> NoteResponse {
|
||||||
#[cfg(feature = "profiling")]
|
#[cfg(feature = "profiling")]
|
||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
let note_key = self.note.key().expect("todo: support non-db notes");
|
let note_key = self.note.key().expect("todo: support non-db notes");
|
||||||
let txn = self.note.txn().expect("todo: support non-db notes");
|
let txn = self.note.txn().expect("todo: support non-db notes");
|
||||||
|
let mut note_action: Option<BarAction> = None;
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
|
let response = ui
|
||||||
|
.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
|
||||||
ui.spacing_mut().item_spacing.x = 16.0;
|
ui.spacing_mut().item_spacing.x = 16.0;
|
||||||
|
|
||||||
let profile = self.app.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
|
let profile = self.app.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
|
||||||
@@ -274,15 +281,25 @@ impl<'a> Note<'a> {
|
|||||||
));
|
));
|
||||||
|
|
||||||
if self.options().has_actionbar() {
|
if self.options().has_actionbar() {
|
||||||
render_note_actionbar(ui);
|
note_action = render_note_actionbar(ui).inner;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.response
|
.response;
|
||||||
|
|
||||||
|
NoteResponse {
|
||||||
|
response,
|
||||||
|
action: note_action,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_note_actionbar(ui: &mut egui::Ui) -> egui::InnerResponse<()> {
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||||
|
pub enum BarAction {
|
||||||
|
Reply,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_note_actionbar(ui: &mut egui::Ui) -> egui::InnerResponse<Option<BarAction>> {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let img_data = if ui.style().visuals.dark_mode {
|
let img_data = if ui.style().visuals.dark_mode {
|
||||||
egui::include_image!("../../../assets/icons/reply.png")
|
egui::include_image!("../../../assets/icons/reply.png")
|
||||||
@@ -299,9 +316,11 @@ fn render_note_actionbar(ui: &mut egui::Ui) -> egui::InnerResponse<()> {
|
|||||||
.fill(ui.style().visuals.panel_fill),
|
.fill(ui.style().visuals.panel_fill),
|
||||||
)
|
)
|
||||||
.clicked()
|
.clicked()
|
||||||
{}
|
{
|
||||||
|
Some(BarAction::Reply)
|
||||||
//if ui.add(egui::Button::new("like")).clicked() {}
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
pub mod picture;
|
pub mod picture;
|
||||||
pub mod preview;
|
pub mod preview;
|
||||||
mod profile_preview_controller;
|
pub mod profile_preview_controller;
|
||||||
|
|
||||||
pub use picture::ProfilePic;
|
pub use picture::ProfilePic;
|
||||||
pub use preview::ProfilePreview;
|
pub use preview::ProfilePreview;
|
||||||
pub use profile_preview_controller::{ProfilePreviewOp, SimpleProfilePreviewController};
|
pub use profile_preview_controller::ProfilePreviewOp;
|
||||||
|
|||||||
@@ -1,31 +1,20 @@
|
|||||||
use nostrdb::{Ndb, Transaction};
|
use nostrdb::{Ndb, Transaction};
|
||||||
|
|
||||||
use crate::{account_manager::AccountManager, imgcache::ImageCache, DisplayName, Result};
|
use crate::{Damus, DisplayName, Result};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
preview::{get_display_name, get_profile_url, SimpleProfilePreview},
|
preview::{get_display_name, get_profile_url, SimpleProfilePreview},
|
||||||
ProfilePic,
|
ProfilePic,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct SimpleProfilePreviewController<'a> {
|
|
||||||
ndb: &'a Ndb,
|
|
||||||
img_cache: &'a mut ImageCache,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ProfilePreviewOp {
|
pub enum ProfilePreviewOp {
|
||||||
RemoveAccount,
|
RemoveAccount,
|
||||||
SwitchTo,
|
SwitchTo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SimpleProfilePreviewController<'a> {
|
pub fn set_profile_previews(
|
||||||
pub fn new(ndb: &'a Ndb, img_cache: &'a mut ImageCache) -> Self {
|
app: &mut Damus,
|
||||||
SimpleProfilePreviewController { ndb, img_cache }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_profile_previews(
|
|
||||||
&mut self,
|
|
||||||
account_manager: &mut AccountManager,
|
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
add_preview_ui: fn(
|
add_preview_ui: fn(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
@@ -33,34 +22,34 @@ impl<'a> SimpleProfilePreviewController<'a> {
|
|||||||
width: f32,
|
width: f32,
|
||||||
is_selected: bool,
|
is_selected: bool,
|
||||||
) -> Option<ProfilePreviewOp>,
|
) -> Option<ProfilePreviewOp>,
|
||||||
) -> Option<Vec<usize>> {
|
) -> Option<Vec<usize>> {
|
||||||
let mut to_remove: Option<Vec<usize>> = None;
|
let mut to_remove: Option<Vec<usize>> = None;
|
||||||
|
|
||||||
let width = ui.available_width();
|
let width = ui.available_width();
|
||||||
|
|
||||||
let txn = if let Ok(txn) = Transaction::new(self.ndb) {
|
let txn = if let Ok(txn) = Transaction::new(&app.ndb) {
|
||||||
txn
|
txn
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
for i in 0..account_manager.num_accounts() {
|
for i in 0..app.account_manager.num_accounts() {
|
||||||
let account = if let Some(account) = account_manager.get_account(i) {
|
let account = if let Some(account) = app.account_manager.get_account(i) {
|
||||||
account
|
account
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let profile =
|
let profile =
|
||||||
if let Ok(profile) = self.ndb.get_profile_by_pubkey(&txn, account.pubkey.bytes()) {
|
if let Ok(profile) = app.ndb.get_profile_by_pubkey(&txn, account.pubkey.bytes()) {
|
||||||
profile
|
profile
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let preview = SimpleProfilePreview::new(&profile, self.img_cache);
|
let preview = SimpleProfilePreview::new(&profile, &mut app.img_cache);
|
||||||
|
|
||||||
let is_selected = if let Some(selected) = account_manager.get_selected_account_index() {
|
let is_selected = if let Some(selected) = app.account_manager.get_selected_account_index() {
|
||||||
i == selected
|
i == selected
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -79,16 +68,15 @@ impl<'a> SimpleProfilePreviewController<'a> {
|
|||||||
}
|
}
|
||||||
to_remove.as_mut().unwrap().push(i);
|
to_remove.as_mut().unwrap().push(i);
|
||||||
}
|
}
|
||||||
ProfilePreviewOp::SwitchTo => account_manager.select_account(i),
|
ProfilePreviewOp::SwitchTo => app.account_manager.select_account(i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
to_remove
|
to_remove
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_profile_previews(
|
pub fn view_profile_previews(
|
||||||
&mut self,
|
app: &mut Damus,
|
||||||
account_manager: &AccountManager,
|
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
add_preview_ui: fn(
|
add_preview_ui: fn(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
@@ -97,32 +85,32 @@ impl<'a> SimpleProfilePreviewController<'a> {
|
|||||||
is_selected: bool,
|
is_selected: bool,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> bool,
|
) -> bool,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
let width = ui.available_width();
|
let width = ui.available_width();
|
||||||
|
|
||||||
let txn = if let Ok(txn) = Transaction::new(self.ndb) {
|
let txn = if let Ok(txn) = Transaction::new(&app.ndb) {
|
||||||
txn
|
txn
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
for i in 0..account_manager.num_accounts() {
|
for i in 0..app.account_manager.num_accounts() {
|
||||||
let account = if let Some(account) = account_manager.get_account(i) {
|
let account = if let Some(account) = app.account_manager.get_account(i) {
|
||||||
account
|
account
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let profile =
|
let profile =
|
||||||
if let Ok(profile) = self.ndb.get_profile_by_pubkey(&txn, account.pubkey.bytes()) {
|
if let Ok(profile) = app.ndb.get_profile_by_pubkey(&txn, account.pubkey.bytes()) {
|
||||||
profile
|
profile
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let preview = SimpleProfilePreview::new(&profile, self.img_cache);
|
let preview = SimpleProfilePreview::new(&profile, &mut app.img_cache);
|
||||||
|
|
||||||
let is_selected = if let Some(selected) = account_manager.get_selected_account_index() {
|
let is_selected = if let Some(selected) = app.account_manager.get_selected_account_index() {
|
||||||
i == selected
|
i == selected
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -134,35 +122,34 @@ impl<'a> SimpleProfilePreviewController<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_with_nickname(
|
pub fn show_with_nickname(
|
||||||
&self,
|
ndb: &Ndb,
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
key: &[u8; 32],
|
key: &[u8; 32],
|
||||||
ui_element: fn(ui: &mut egui::Ui, username: &DisplayName) -> egui::Response,
|
ui_element: fn(ui: &mut egui::Ui, username: &DisplayName) -> egui::Response,
|
||||||
) -> Result<egui::Response> {
|
) -> Result<egui::Response> {
|
||||||
let txn = Transaction::new(self.ndb)?;
|
let txn = Transaction::new(ndb)?;
|
||||||
let profile = self.ndb.get_profile_by_pubkey(&txn, key)?;
|
let profile = ndb.get_profile_by_pubkey(&txn, key)?;
|
||||||
Ok(ui_element(ui, &get_display_name(&profile)))
|
Ok(ui_element(ui, &get_display_name(&profile)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show_with_pfp(
|
pub fn show_with_pfp(
|
||||||
self,
|
app: &mut Damus,
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
key: &[u8; 32],
|
key: &[u8; 32],
|
||||||
ui_element: fn(ui: &mut egui::Ui, pfp: ProfilePic) -> egui::Response,
|
ui_element: fn(ui: &mut egui::Ui, pfp: ProfilePic) -> egui::Response,
|
||||||
) -> Option<egui::Response> {
|
) -> Option<egui::Response> {
|
||||||
if let Ok(txn) = Transaction::new(self.ndb) {
|
if let Ok(txn) = Transaction::new(&app.ndb) {
|
||||||
let profile = self.ndb.get_profile_by_pubkey(&txn, key);
|
let profile = app.ndb.get_profile_by_pubkey(&txn, key);
|
||||||
|
|
||||||
if let Ok(profile) = profile {
|
if let Ok(profile) = profile {
|
||||||
return Some(ui_element(
|
return Some(ui_element(
|
||||||
ui,
|
ui,
|
||||||
ProfilePic::new(self.img_cache, get_profile_url(&profile)),
|
ProfilePic::new(&mut app.img_cache, get_profile_url(&profile)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
use egui::{Button, Layout, SidePanel, Vec2, Widget};
|
use egui::{Button, Layout, SidePanel, Vec2, Widget};
|
||||||
|
|
||||||
use crate::account_manager::AccountManager;
|
use crate::{ui::profile_preview_controller, Damus};
|
||||||
|
|
||||||
use super::{profile::SimpleProfilePreviewController, ProfilePic, View};
|
use super::{ProfilePic, View};
|
||||||
|
|
||||||
pub struct DesktopSidePanel<'a> {
|
pub struct DesktopSidePanel<'a> {
|
||||||
selected_account: Option<&'a [u8; 32]>,
|
app: &'a mut Damus,
|
||||||
simple_preview_controller: SimpleProfilePreviewController<'a>,
|
}
|
||||||
|
|
||||||
|
impl<'a> View for DesktopSidePanel<'a> {
|
||||||
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
|
self.show(ui);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
@@ -28,21 +33,9 @@ impl SidePanelResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Widget for DesktopSidePanel<'a> {
|
|
||||||
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
|
||||||
self.show(ui).response
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DesktopSidePanel<'a> {
|
impl<'a> DesktopSidePanel<'a> {
|
||||||
pub fn new(
|
pub fn new(app: &'a mut Damus) -> Self {
|
||||||
selected_account: Option<&'a [u8; 32]>,
|
DesktopSidePanel { app }
|
||||||
simple_preview_controller: SimpleProfilePreviewController<'a>,
|
|
||||||
) -> Self {
|
|
||||||
DesktopSidePanel {
|
|
||||||
selected_account,
|
|
||||||
simple_preview_controller,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn panel() -> SidePanel {
|
pub fn panel() -> SidePanel {
|
||||||
@@ -51,7 +44,7 @@ impl<'a> DesktopSidePanel<'a> {
|
|||||||
.exact_width(40.0)
|
.exact_width(40.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show(self, ui: &mut egui::Ui) -> SidePanelResponse {
|
pub fn show(&mut self, ui: &mut egui::Ui) -> SidePanelResponse {
|
||||||
let dark_mode = ui.ctx().style().visuals.dark_mode;
|
let dark_mode = ui.ctx().style().visuals.dark_mode;
|
||||||
let spacing_amt = 16.0;
|
let spacing_amt = 16.0;
|
||||||
|
|
||||||
@@ -77,12 +70,15 @@ impl<'a> DesktopSidePanel<'a> {
|
|||||||
SidePanelResponse::new(inner.inner, inner.response)
|
SidePanelResponse::new(inner.inner, inner.response)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pfp_button(self, ui: &mut egui::Ui) -> egui::Response {
|
fn pfp_button(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
||||||
if let Some(selected_account) = self.selected_account {
|
let selected_account = self.app.account_manager.get_selected_account();
|
||||||
if let Some(response) =
|
if let Some(selected_account) = selected_account {
|
||||||
self.simple_preview_controller
|
if let Some(response) = profile_preview_controller::show_with_pfp(
|
||||||
.show_with_pfp(ui, selected_account, show_pfp())
|
self.app,
|
||||||
{
|
ui,
|
||||||
|
&selected_account.pubkey.bytes().clone(),
|
||||||
|
show_pfp(),
|
||||||
|
) {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,10 +119,9 @@ fn add_column_button(dark_mode: bool) -> egui::Button<'static> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod preview {
|
mod preview {
|
||||||
use nostrdb::Ndb;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
imgcache::ImageCache,
|
|
||||||
test_data,
|
test_data,
|
||||||
ui::{Preview, PreviewConfig},
|
ui::{Preview, PreviewConfig},
|
||||||
};
|
};
|
||||||
@@ -134,33 +129,25 @@ mod preview {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub struct DesktopSidePanelPreview {
|
pub struct DesktopSidePanelPreview {
|
||||||
account_manager: AccountManager,
|
app: Damus,
|
||||||
ndb: Ndb,
|
|
||||||
img_cache: ImageCache,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopSidePanelPreview {
|
impl DesktopSidePanelPreview {
|
||||||
fn new() -> Self {
|
fn new(is_mobile: bool) -> Self {
|
||||||
let (account_manager, ndb, img_cache) = test_data::get_accmgr_and_ndb_and_imgcache();
|
let app = test_data::get_account_manager_test_app(is_mobile);
|
||||||
DesktopSidePanelPreview {
|
DesktopSidePanelPreview { app }
|
||||||
account_manager,
|
|
||||||
ndb,
|
|
||||||
img_cache,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for DesktopSidePanelPreview {
|
impl View for DesktopSidePanelPreview {
|
||||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
let selected_account = self
|
let _selected_account = self
|
||||||
|
.app
|
||||||
.account_manager
|
.account_manager
|
||||||
.get_selected_account()
|
.get_selected_account()
|
||||||
.map(|x| x.pubkey.bytes());
|
.map(|x| x.pubkey.bytes());
|
||||||
|
|
||||||
let panel = DesktopSidePanel::new(
|
let mut panel = DesktopSidePanel::new(&mut self.app);
|
||||||
selected_account,
|
|
||||||
SimpleProfilePreviewController::new(&self.ndb, &mut self.img_cache),
|
|
||||||
);
|
|
||||||
|
|
||||||
DesktopSidePanel::panel().show(ui.ctx(), |ui| panel.ui(ui));
|
DesktopSidePanel::panel().show(ui.ctx(), |ui| panel.ui(ui));
|
||||||
}
|
}
|
||||||
@@ -169,8 +156,8 @@ mod preview {
|
|||||||
impl<'a> Preview for DesktopSidePanel<'a> {
|
impl<'a> Preview for DesktopSidePanel<'a> {
|
||||||
type Prev = DesktopSidePanelPreview;
|
type Prev = DesktopSidePanelPreview;
|
||||||
|
|
||||||
fn preview(_cfg: PreviewConfig) -> Self::Prev {
|
fn preview(cfg: PreviewConfig) -> Self::Prev {
|
||||||
DesktopSidePanelPreview::new()
|
DesktopSidePanelPreview::new(cfg.is_mobile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user