Merge drag to nav back on all views by kernel #1035
HE FUCKING DID IT LADS
Made a small tweak on the merge commit to update url to
damus-io/egui-nav upstream
William Casarin (2):
Merge drag to nav back on all views by kernel #1035
kernelkind (9):
TMP: update egui-nav
refactor scrolling for post, reply & quote views
enforce scroll_id for `ThreadView`
add `scroll_id` for all views with vertical scroll
add `DragSwitch`
use `DragSwitch` in `Column`
get scroll id for `Route`
add `route_uses_frame`
use `DragSwitch` to allow dragging anywhere in navigation
This commit is contained in:
Generated
+1
-1
@@ -1526,7 +1526,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "egui_nav"
|
name = "egui_nav"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/damus-io/egui-nav?rev=111de8ac40b5d18df53e9691eb18a50d49cb31d8#111de8ac40b5d18df53e9691eb18a50d49cb31d8"
|
source = "git+https://github.com/kernelkind/egui-nav?rev=3c67eb6298edbff36d46546897cfac33df4f04db#3c67eb6298edbff36d46546897cfac33df4f04db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"egui",
|
"egui",
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ egui = { version = "0.31.1", features = ["serde"] }
|
|||||||
egui-wgpu = "0.31.1"
|
egui-wgpu = "0.31.1"
|
||||||
egui_extras = { version = "0.31.1", features = ["all_loaders"] }
|
egui_extras = { version = "0.31.1", features = ["all_loaders"] }
|
||||||
egui-winit = { version = "0.31.1", features = ["android-game-activity", "clipboard"] }
|
egui-winit = { version = "0.31.1", features = ["android-game-activity", "clipboard"] }
|
||||||
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "111de8ac40b5d18df53e9691eb18a50d49cb31d8" }
|
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "3c67eb6298edbff36d46546897cfac33df4f04db" }
|
||||||
egui_tabs = { git = "https://github.com/damus-io/egui-tabs", rev = "6eb91740577b374a8a6658c09c9a4181299734d0" }
|
egui_tabs = { git = "https://github.com/damus-io/egui-tabs", rev = "6eb91740577b374a8a6658c09c9a4181299734d0" }
|
||||||
#egui_virtual_list = "0.6.0"
|
#egui_virtual_list = "0.6.0"
|
||||||
egui_virtual_list = { git = "https://github.com/jb55/hello_egui", rev = "a66b6794f5e707a2f4109633770e02b02fb722e1" }
|
egui_virtual_list = { git = "https://github.com/jb55/hello_egui", rev = "a66b6794f5e707a2f4109633770e02b02fb722e1" }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
actionbar::TimelineOpenResult,
|
actionbar::TimelineOpenResult,
|
||||||
|
drag::DragSwitch,
|
||||||
route::{Route, Router, SingletonRouter},
|
route::{Route, Router, SingletonRouter},
|
||||||
timeline::{Timeline, TimelineCache, TimelineKind},
|
timeline::{Timeline, TimelineCache, TimelineKind},
|
||||||
};
|
};
|
||||||
@@ -13,6 +14,7 @@ use tracing::warn;
|
|||||||
pub struct Column {
|
pub struct Column {
|
||||||
pub router: Router<Route>,
|
pub router: Router<Route>,
|
||||||
pub sheet_router: SingletonRouter<Route>,
|
pub sheet_router: SingletonRouter<Route>,
|
||||||
|
pub drag: DragSwitch,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Column {
|
impl Column {
|
||||||
@@ -21,6 +23,7 @@ impl Column {
|
|||||||
Column {
|
Column {
|
||||||
router,
|
router,
|
||||||
sheet_router: SingletonRouter::default(),
|
sheet_router: SingletonRouter::default(),
|
||||||
|
drag: DragSwitch::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
#[derive(Default, Clone, Debug)]
|
||||||
|
pub struct DragSwitch {
|
||||||
|
state: Option<DragState>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct DragState {
|
||||||
|
start_pos: egui::Pos2,
|
||||||
|
cur_direction: DragDirection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DragSwitch {
|
||||||
|
/// should call BEFORE both drag directions get rendered
|
||||||
|
pub fn update(&mut self, horizontal: egui::Id, vertical: egui::Id, ctx: &egui::Context) {
|
||||||
|
let horiz_being_dragged = ctx.is_being_dragged(horizontal);
|
||||||
|
let vert_being_dragged = ctx.is_being_dragged(vertical);
|
||||||
|
|
||||||
|
if !horiz_being_dragged && !vert_being_dragged {
|
||||||
|
self.state = None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(state) = &mut self.state else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(cur_pos) = ctx.pointer_interact_pos() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let dx = (state.start_pos.x - cur_pos.x).abs();
|
||||||
|
let dy = (state.start_pos.y - cur_pos.y).abs();
|
||||||
|
|
||||||
|
let new_direction = if dx > dy {
|
||||||
|
DragDirection::Horizontal
|
||||||
|
} else {
|
||||||
|
DragDirection::Vertical
|
||||||
|
};
|
||||||
|
|
||||||
|
if new_direction == DragDirection::Horizontal
|
||||||
|
&& state.cur_direction == DragDirection::Vertical
|
||||||
|
{
|
||||||
|
// drag is occuring mostly in the horizontal direction
|
||||||
|
ctx.set_dragged_id(horizontal);
|
||||||
|
let new_dir = DragDirection::Horizontal;
|
||||||
|
state.cur_direction = new_dir;
|
||||||
|
} else if new_direction == DragDirection::Vertical
|
||||||
|
&& state.cur_direction == DragDirection::Horizontal
|
||||||
|
{
|
||||||
|
// drag is occuring mostly in the vertical direction
|
||||||
|
let new_dir = DragDirection::Vertical;
|
||||||
|
state.cur_direction = new_dir;
|
||||||
|
ctx.set_dragged_id(vertical);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// should call AFTER both drag directions rendered
|
||||||
|
pub fn check_for_drag_start(
|
||||||
|
&mut self,
|
||||||
|
ctx: &egui::Context,
|
||||||
|
horizontal: egui::Id,
|
||||||
|
vertical: egui::Id,
|
||||||
|
) {
|
||||||
|
let Some(drag_id) = ctx.drag_started_id() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let cur_direction = if drag_id == horizontal {
|
||||||
|
DragDirection::Horizontal
|
||||||
|
} else if drag_id == vertical {
|
||||||
|
DragDirection::Vertical
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(cur_pos) = ctx.pointer_interact_pos() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.state = Some(DragState {
|
||||||
|
start_pos: cur_pos,
|
||||||
|
cur_direction,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
enum DragDirection {
|
||||||
|
Horizontal,
|
||||||
|
Vertical,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_drag_id(ui: &egui::Ui, scroll_id: egui::Id) -> egui::Id {
|
||||||
|
ui.id().with(egui::Id::new(scroll_id)).with("area")
|
||||||
|
}
|
||||||
|
|
||||||
|
// unfortunately a Frame makes a new id for the Ui
|
||||||
|
pub fn get_drag_id_through_frame(ui: &egui::Ui, scroll_id: egui::Id) -> egui::Id {
|
||||||
|
ui.id()
|
||||||
|
.with(egui::Id::new("child"))
|
||||||
|
.with(egui::Id::new(scroll_id))
|
||||||
|
.with("area")
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ pub mod column;
|
|||||||
mod deck_state;
|
mod deck_state;
|
||||||
mod decks;
|
mod decks;
|
||||||
mod draft;
|
mod draft;
|
||||||
|
mod drag;
|
||||||
mod key_parsing;
|
mod key_parsing;
|
||||||
pub mod login_manager;
|
pub mod login_manager;
|
||||||
mod media_upload;
|
mod media_upload;
|
||||||
|
|||||||
@@ -4,26 +4,28 @@ use crate::{
|
|||||||
column::ColumnsAction,
|
column::ColumnsAction,
|
||||||
deck_state::DeckState,
|
deck_state::DeckState,
|
||||||
decks::{Deck, DecksAction, DecksCache},
|
decks::{Deck, DecksAction, DecksCache},
|
||||||
|
drag::{get_drag_id, get_drag_id_through_frame},
|
||||||
options::AppOptions,
|
options::AppOptions,
|
||||||
profile::{ProfileAction, SaveProfileChanges},
|
profile::{ProfileAction, SaveProfileChanges},
|
||||||
route::{Route, Router, SingletonRouter},
|
route::{Route, Router, SingletonRouter},
|
||||||
timeline::{
|
timeline::{
|
||||||
route::{render_thread_route, render_timeline_route},
|
route::{render_thread_route, render_timeline_route},
|
||||||
TimelineCache,
|
TimelineCache, TimelineKind,
|
||||||
},
|
},
|
||||||
ui::{
|
ui::{
|
||||||
self,
|
self,
|
||||||
add_column::render_add_column_routes,
|
add_column::{render_add_column_routes, AddColumnView},
|
||||||
column::NavTitle,
|
column::NavTitle,
|
||||||
configure_deck::ConfigureDeckView,
|
configure_deck::ConfigureDeckView,
|
||||||
edit_deck::{EditDeckResponse, EditDeckView},
|
edit_deck::{EditDeckResponse, EditDeckView},
|
||||||
note::{custom_zap::CustomZapView, NewPostAction, PostAction, PostType},
|
note::{custom_zap::CustomZapView, NewPostAction, PostAction, PostType, QuoteRepostView},
|
||||||
profile::EditProfileView,
|
profile::EditProfileView,
|
||||||
search::{FocusState, SearchView},
|
search::{FocusState, SearchView},
|
||||||
settings::{SettingsAction, ShowNoteClientOptions},
|
settings::{SettingsAction, ShowNoteClientOptions},
|
||||||
support::SupportView,
|
support::SupportView,
|
||||||
wallet::{get_default_zap_state, WalletAction, WalletState, WalletView},
|
wallet::{get_default_zap_state, WalletAction, WalletState, WalletView},
|
||||||
RelayView, SettingsView,
|
AccountsView, PostReplyView, PostView, ProfileView, RelayView, SettingsView, ThreadView,
|
||||||
|
TimelineView,
|
||||||
},
|
},
|
||||||
Damus,
|
Damus,
|
||||||
};
|
};
|
||||||
@@ -631,27 +633,22 @@ fn render_nav_body(
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = egui::Id::new(("post", col, note.key().unwrap()));
|
|
||||||
let poster = ctx.accounts.selected_filled()?;
|
let poster = ctx.accounts.selected_filled()?;
|
||||||
|
|
||||||
let action = {
|
let action = {
|
||||||
let draft = app.drafts.reply_mut(note.id());
|
let draft = app.drafts.reply_mut(note.id());
|
||||||
|
|
||||||
let response = egui::ScrollArea::vertical()
|
let response = ui::PostReplyView::new(
|
||||||
.show(ui, |ui| {
|
&mut note_context,
|
||||||
ui::PostReplyView::new(
|
poster,
|
||||||
&mut note_context,
|
draft,
|
||||||
poster,
|
¬e,
|
||||||
draft,
|
inner_rect,
|
||||||
¬e,
|
app.note_options,
|
||||||
inner_rect,
|
&mut app.jobs,
|
||||||
app.note_options,
|
col,
|
||||||
&mut app.jobs,
|
)
|
||||||
)
|
.show(ui);
|
||||||
.id_source(id)
|
|
||||||
.show(ui)
|
|
||||||
})
|
|
||||||
.inner;
|
|
||||||
|
|
||||||
response.action
|
response.action
|
||||||
};
|
};
|
||||||
@@ -672,26 +669,20 @@ fn render_nav_body(
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = egui::Id::new(("post", col, note.key().unwrap()));
|
|
||||||
|
|
||||||
let poster = ctx.accounts.selected_filled()?;
|
let poster = ctx.accounts.selected_filled()?;
|
||||||
let draft = app.drafts.quote_mut(note.id());
|
let draft = app.drafts.quote_mut(note.id());
|
||||||
|
|
||||||
let response = egui::ScrollArea::vertical()
|
let response = crate::ui::note::QuoteRepostView::new(
|
||||||
.show(ui, |ui| {
|
&mut note_context,
|
||||||
crate::ui::note::QuoteRepostView::new(
|
poster,
|
||||||
&mut note_context,
|
draft,
|
||||||
poster,
|
¬e,
|
||||||
draft,
|
inner_rect,
|
||||||
¬e,
|
app.note_options,
|
||||||
inner_rect,
|
&mut app.jobs,
|
||||||
app.note_options,
|
col,
|
||||||
&mut app.jobs,
|
)
|
||||||
)
|
.show(ui);
|
||||||
.id_source(id)
|
|
||||||
.show(ui)
|
|
||||||
})
|
|
||||||
.inner;
|
|
||||||
|
|
||||||
response.action.map(Into::into)
|
response.action.map(Into::into)
|
||||||
}
|
}
|
||||||
@@ -964,47 +955,165 @@ pub fn render_nav(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let nav_response = Nav::new(
|
let routes = app
|
||||||
&app.columns(ctx.accounts)
|
.columns(ctx.accounts)
|
||||||
.column(col)
|
.column(col)
|
||||||
.router()
|
.router()
|
||||||
.routes()
|
.routes()
|
||||||
.clone(),
|
.clone();
|
||||||
)
|
let nav = Nav::new(&routes).id_source(egui::Id::new(("nav", col)));
|
||||||
.navigating(
|
|
||||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
|
||||||
.column_mut(col)
|
|
||||||
.router_mut()
|
|
||||||
.navigating,
|
|
||||||
)
|
|
||||||
.returning(
|
|
||||||
app.columns_mut(ctx.i18n, ctx.accounts)
|
|
||||||
.column_mut(col)
|
|
||||||
.router_mut()
|
|
||||||
.returning,
|
|
||||||
)
|
|
||||||
.id_source(egui::Id::new(("nav", col)))
|
|
||||||
.show_mut(ui, |ui, render_type, nav| match render_type {
|
|
||||||
NavUiType::Title => NavTitle::new(
|
|
||||||
ctx.ndb,
|
|
||||||
ctx.img_cache,
|
|
||||||
get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache),
|
|
||||||
nav.routes(),
|
|
||||||
col,
|
|
||||||
ctx.i18n,
|
|
||||||
)
|
|
||||||
.show_move_button(!narrow)
|
|
||||||
.show_delete_button(!narrow)
|
|
||||||
.show(ui),
|
|
||||||
|
|
||||||
NavUiType::Body => {
|
let drag_ids = 's: {
|
||||||
if let Some(top) = nav.routes().last() {
|
let Some(top_route) = &routes.last().cloned() else {
|
||||||
render_nav_body(ui, app, ctx, top, nav.routes().len(), col, inner_rect)
|
break 's None;
|
||||||
} else {
|
};
|
||||||
None
|
|
||||||
|
let Some(scroll_id) = get_scroll_id(
|
||||||
|
top_route,
|
||||||
|
app.columns(ctx.accounts)
|
||||||
|
.column(col)
|
||||||
|
.router()
|
||||||
|
.routes()
|
||||||
|
.len(),
|
||||||
|
&app.timeline_cache,
|
||||||
|
col,
|
||||||
|
) else {
|
||||||
|
break 's None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let vertical_drag_id = if route_uses_frame(top_route) {
|
||||||
|
get_drag_id_through_frame(ui, scroll_id)
|
||||||
|
} else {
|
||||||
|
get_drag_id(ui, scroll_id)
|
||||||
|
};
|
||||||
|
|
||||||
|
let horizontal_drag_id = nav.drag_id(ui);
|
||||||
|
|
||||||
|
let drag = &mut get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache)
|
||||||
|
.column_mut(col)
|
||||||
|
.drag;
|
||||||
|
|
||||||
|
drag.update(horizontal_drag_id, vertical_drag_id, ui.ctx());
|
||||||
|
|
||||||
|
Some((horizontal_drag_id, vertical_drag_id))
|
||||||
|
};
|
||||||
|
|
||||||
|
let nav_response = nav
|
||||||
|
.navigating(
|
||||||
|
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||||
|
.column_mut(col)
|
||||||
|
.router_mut()
|
||||||
|
.navigating,
|
||||||
|
)
|
||||||
|
.returning(
|
||||||
|
app.columns_mut(ctx.i18n, ctx.accounts)
|
||||||
|
.column_mut(col)
|
||||||
|
.router_mut()
|
||||||
|
.returning,
|
||||||
|
)
|
||||||
|
.show_mut(ui, |ui, render_type, nav| match render_type {
|
||||||
|
NavUiType::Title => NavTitle::new(
|
||||||
|
ctx.ndb,
|
||||||
|
ctx.img_cache,
|
||||||
|
get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache),
|
||||||
|
nav.routes(),
|
||||||
|
col,
|
||||||
|
ctx.i18n,
|
||||||
|
)
|
||||||
|
.show_move_button(!narrow)
|
||||||
|
.show_delete_button(!narrow)
|
||||||
|
.show(ui),
|
||||||
|
|
||||||
|
NavUiType::Body => {
|
||||||
|
if let Some(top) = nav.routes().last() {
|
||||||
|
render_nav_body(ui, app, ctx, top, nav.routes().len(), col, inner_rect)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
if let Some((horizontal_drag_id, vertical_drag_id)) = drag_ids {
|
||||||
|
let drag = &mut get_active_columns_mut(ctx.i18n, ctx.accounts, &mut app.decks_cache)
|
||||||
|
.column_mut(col)
|
||||||
|
.drag;
|
||||||
|
drag.check_for_drag_start(ui.ctx(), horizontal_drag_id, vertical_drag_id);
|
||||||
|
}
|
||||||
|
|
||||||
RenderNavResponse::new(col, NotedeckNavResponse::Nav(Box::new(nav_response)))
|
RenderNavResponse::new(col, NotedeckNavResponse::Nav(Box::new(nav_response)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_scroll_id(
|
||||||
|
top: &Route,
|
||||||
|
depth: usize,
|
||||||
|
timeline_cache: &TimelineCache,
|
||||||
|
col: usize,
|
||||||
|
) -> Option<egui::Id> {
|
||||||
|
match top {
|
||||||
|
Route::Timeline(timeline_kind) => match timeline_kind {
|
||||||
|
TimelineKind::List(_)
|
||||||
|
| TimelineKind::Search(_)
|
||||||
|
| TimelineKind::Algo(_)
|
||||||
|
| TimelineKind::Notifications(_)
|
||||||
|
| TimelineKind::Universe
|
||||||
|
| TimelineKind::Hashtag(_)
|
||||||
|
| TimelineKind::Generic(_) => {
|
||||||
|
TimelineView::scroll_id(timeline_cache, timeline_kind, col)
|
||||||
|
}
|
||||||
|
TimelineKind::Profile(pubkey) => {
|
||||||
|
if depth > 1 {
|
||||||
|
Some(ProfileView::scroll_id(col, pubkey))
|
||||||
|
} else {
|
||||||
|
TimelineView::scroll_id(timeline_cache, timeline_kind, col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Route::Thread(thread_selection) => Some(ThreadView::scroll_id(
|
||||||
|
thread_selection.selected_or_root(),
|
||||||
|
col,
|
||||||
|
)),
|
||||||
|
Route::Accounts(accounts_route) => match accounts_route {
|
||||||
|
crate::accounts::AccountsRoute::Accounts => Some(AccountsView::scroll_id()),
|
||||||
|
crate::accounts::AccountsRoute::AddAccount => None,
|
||||||
|
},
|
||||||
|
Route::Reply(note_id) => Some(PostReplyView::scroll_id(col, note_id.bytes())),
|
||||||
|
Route::Quote(note_id) => Some(QuoteRepostView::scroll_id(col, note_id.bytes())),
|
||||||
|
Route::Relays => Some(RelayView::scroll_id()),
|
||||||
|
Route::ComposeNote => Some(PostView::scroll_id()),
|
||||||
|
Route::AddColumn(add_column_route) => Some(AddColumnView::scroll_id(add_column_route)),
|
||||||
|
Route::EditProfile(_) => Some(EditProfileView::scroll_id()),
|
||||||
|
Route::Support => None,
|
||||||
|
Route::NewDeck => Some(ConfigureDeckView::scroll_id()),
|
||||||
|
Route::Search => Some(SearchView::scroll_id()),
|
||||||
|
Route::EditDeck(_) => None,
|
||||||
|
Route::Wallet(_) => None,
|
||||||
|
Route::CustomizeZapAmount(_) => None,
|
||||||
|
Route::Settings => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does the corresponding View for the route use a egui::Frame to wrap the ScrollArea?
|
||||||
|
/// TODO(kernelkind): this is quite hacky...
|
||||||
|
fn route_uses_frame(route: &Route) -> bool {
|
||||||
|
match route {
|
||||||
|
Route::Accounts(accounts_route) => match accounts_route {
|
||||||
|
crate::accounts::AccountsRoute::Accounts => true,
|
||||||
|
crate::accounts::AccountsRoute::AddAccount => false,
|
||||||
|
},
|
||||||
|
Route::Relays => true,
|
||||||
|
Route::Timeline(_) => false,
|
||||||
|
Route::Thread(_) => false,
|
||||||
|
Route::Reply(_) => false,
|
||||||
|
Route::Quote(_) => false,
|
||||||
|
Route::Settings => false,
|
||||||
|
Route::ComposeNote => false,
|
||||||
|
Route::AddColumn(_) => false,
|
||||||
|
Route::EditProfile(_) => false,
|
||||||
|
Route::Support => false,
|
||||||
|
Route::NewDeck => false,
|
||||||
|
Route::Search => false,
|
||||||
|
Route::EditDeck(_) => false,
|
||||||
|
Route::Wallet(_) => false,
|
||||||
|
Route::CustomizeZapAmount(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ pub fn render_thread_route(
|
|||||||
note_options,
|
note_options,
|
||||||
note_context,
|
note_context,
|
||||||
jobs,
|
jobs,
|
||||||
|
col,
|
||||||
)
|
)
|
||||||
.id_source(col)
|
|
||||||
.ui(ui)
|
.ui(ui)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ impl<'a> AccountsView<'a> {
|
|||||||
|
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
scroll_area()
|
scroll_area()
|
||||||
|
.id_salt(AccountsView::scroll_id())
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
Self::show_accounts(ui, self.accounts, self.ndb, self.img_cache, self.i18n)
|
Self::show_accounts(ui, self.accounts, self.ndb, self.img_cache, self.i18n)
|
||||||
})
|
})
|
||||||
@@ -59,6 +60,10 @@ impl<'a> AccountsView<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id() -> egui::Id {
|
||||||
|
egui::Id::new("accounts")
|
||||||
|
}
|
||||||
|
|
||||||
fn show_accounts(
|
fn show_accounts(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
accounts: &Accounts,
|
accounts: &Accounts,
|
||||||
|
|||||||
@@ -64,14 +64,14 @@ enum AddColumnOption {
|
|||||||
Individual(PubkeySource),
|
Individual(PubkeySource),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, Default)]
|
#[derive(Clone, Copy, Eq, PartialEq, Debug, Default, Hash)]
|
||||||
pub enum AddAlgoRoute {
|
pub enum AddAlgoRoute {
|
||||||
#[default]
|
#[default]
|
||||||
Base,
|
Base,
|
||||||
LastPerPubkey,
|
LastPerPubkey,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)]
|
||||||
pub enum AddColumnRoute {
|
pub enum AddColumnRoute {
|
||||||
Base,
|
Base,
|
||||||
UndecidedNotification,
|
UndecidedNotification,
|
||||||
@@ -187,8 +187,13 @@ impl<'a> AddColumnView<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id(route: &AddColumnRoute) -> egui::Id {
|
||||||
|
egui::Id::new(("add_column", route))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
|
pub fn ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
|
||||||
ScrollArea::vertical()
|
ScrollArea::vertical()
|
||||||
|
.id_salt(AddColumnView::scroll_id(&AddColumnRoute::Base))
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
let mut selected_option: Option<AddColumnResponse> = None;
|
let mut selected_option: Option<AddColumnResponse> = None;
|
||||||
for column_option_data in self.get_base_options(ui) {
|
for column_option_data in self.get_base_options(ui) {
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ impl<'a> ConfigureDeckView<'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id() -> egui::Id {
|
||||||
|
egui::Id::new("configure-deck")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ui(&mut self, ui: &mut Ui) -> Option<ConfigureDeckResponse> {
|
pub fn ui(&mut self, ui: &mut Ui) -> Option<ConfigureDeckResponse> {
|
||||||
let title_font = egui::FontId::new(
|
let title_font = egui::FontId::new(
|
||||||
notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Heading4),
|
notedeck::fonts::get_font_size(ui.ctx(), &NotedeckTextStyle::Heading4),
|
||||||
@@ -261,6 +265,7 @@ fn glyph_options_ui(
|
|||||||
) -> Option<char> {
|
) -> Option<char> {
|
||||||
let mut selected_glyph = None;
|
let mut selected_glyph = None;
|
||||||
egui::ScrollArea::vertical()
|
egui::ScrollArea::vertical()
|
||||||
|
.id_salt(ConfigureDeckView::scroll_id())
|
||||||
.max_height(max_height)
|
.max_height(max_height)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
let max_width = ui.available_width();
|
let max_width = ui.available_width();
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ pub struct PostView<'a, 'd> {
|
|||||||
draft: &'a mut Draft,
|
draft: &'a mut Draft,
|
||||||
post_type: PostType,
|
post_type: PostType,
|
||||||
poster: FilledKeypair<'a>,
|
poster: FilledKeypair<'a>,
|
||||||
id_source: Option<egui::Id>,
|
|
||||||
inner_rect: egui::Rect,
|
inner_rect: egui::Rect,
|
||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
@@ -112,12 +111,10 @@ impl<'a, 'd> PostView<'a, 'd> {
|
|||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let id_source: Option<egui::Id> = None;
|
|
||||||
PostView {
|
PostView {
|
||||||
note_context,
|
note_context,
|
||||||
draft,
|
draft,
|
||||||
poster,
|
poster,
|
||||||
id_source,
|
|
||||||
post_type,
|
post_type,
|
||||||
inner_rect,
|
inner_rect,
|
||||||
note_options,
|
note_options,
|
||||||
@@ -125,9 +122,12 @@ impl<'a, 'd> PostView<'a, 'd> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id_source(mut self, id_source: impl std::hash::Hash) -> Self {
|
fn id() -> egui::Id {
|
||||||
self.id_source = Some(egui::Id::new(id_source));
|
egui::Id::new("post")
|
||||||
self
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id() -> egui::Id {
|
||||||
|
PostView::id().with("scroll")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn editbox(&mut self, txn: &nostrdb::Transaction, ui: &mut egui::Ui) -> egui::Response {
|
fn editbox(&mut self, txn: &nostrdb::Transaction, ui: &mut egui::Ui) -> egui::Response {
|
||||||
@@ -213,7 +213,8 @@ impl<'a, 'd> PostView<'a, 'd> {
|
|||||||
|
|
||||||
let focused = out.response.has_focus();
|
let focused = out.response.has_focus();
|
||||||
|
|
||||||
ui.ctx().data_mut(|d| d.insert_temp(self.id(), focused));
|
ui.ctx()
|
||||||
|
.data_mut(|d| d.insert_temp(PostView::id(), focused));
|
||||||
|
|
||||||
out.response
|
out.response
|
||||||
}
|
}
|
||||||
@@ -305,11 +306,7 @@ impl<'a, 'd> PostView<'a, 'd> {
|
|||||||
|
|
||||||
fn focused(&self, ui: &egui::Ui) -> bool {
|
fn focused(&self, ui: &egui::Ui) -> bool {
|
||||||
ui.ctx()
|
ui.ctx()
|
||||||
.data(|d| d.get_temp::<bool>(self.id()).unwrap_or(false))
|
.data(|d| d.get_temp::<bool>(PostView::id()).unwrap_or(false))
|
||||||
}
|
|
||||||
|
|
||||||
fn id(&self) -> egui::Id {
|
|
||||||
self.id_source.unwrap_or_else(|| egui::Id::new("post"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outer_margin() -> i8 {
|
pub fn outer_margin() -> i8 {
|
||||||
@@ -321,6 +318,13 @@ impl<'a, 'd> PostView<'a, 'd> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ui(&mut self, txn: &Transaction, ui: &mut egui::Ui) -> PostResponse {
|
pub fn ui(&mut self, txn: &Transaction, ui: &mut egui::Ui) -> PostResponse {
|
||||||
|
ScrollArea::vertical()
|
||||||
|
.id_salt(PostView::scroll_id())
|
||||||
|
.show(ui, |ui| self.ui_no_scroll(txn, ui))
|
||||||
|
.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ui_no_scroll(&mut self, txn: &Transaction, ui: &mut egui::Ui) -> PostResponse {
|
||||||
let focused = self.focused(ui);
|
let focused = self.focused(ui);
|
||||||
let stroke = if focused {
|
let stroke = if focused {
|
||||||
ui.visuals().selection.stroke
|
ui.visuals().selection.stroke
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use crate::{
|
|||||||
ui::{self},
|
ui::{self},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use egui::ScrollArea;
|
||||||
use enostr::{FilledKeypair, NoteId};
|
use enostr::{FilledKeypair, NoteId};
|
||||||
use notedeck::NoteContext;
|
use notedeck::NoteContext;
|
||||||
use notedeck_ui::{jobs::JobsCache, NoteOptions};
|
use notedeck_ui::{jobs::JobsCache, NoteOptions};
|
||||||
@@ -13,7 +14,7 @@ pub struct QuoteRepostView<'a, 'd> {
|
|||||||
poster: FilledKeypair<'a>,
|
poster: FilledKeypair<'a>,
|
||||||
draft: &'a mut Draft,
|
draft: &'a mut Draft,
|
||||||
quoting_note: &'a nostrdb::Note<'a>,
|
quoting_note: &'a nostrdb::Note<'a>,
|
||||||
id_source: Option<egui::Id>,
|
scroll_id: egui::Id,
|
||||||
inner_rect: egui::Rect,
|
inner_rect: egui::Rect,
|
||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
@@ -29,22 +30,36 @@ impl<'a, 'd> QuoteRepostView<'a, 'd> {
|
|||||||
inner_rect: egui::Rect,
|
inner_rect: egui::Rect,
|
||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
|
col: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let id_source: Option<egui::Id> = None;
|
|
||||||
QuoteRepostView {
|
QuoteRepostView {
|
||||||
note_context,
|
note_context,
|
||||||
poster,
|
poster,
|
||||||
draft,
|
draft,
|
||||||
quoting_note,
|
quoting_note,
|
||||||
id_source,
|
scroll_id: QuoteRepostView::scroll_id(col, quoting_note.id()),
|
||||||
inner_rect,
|
inner_rect,
|
||||||
note_options,
|
note_options,
|
||||||
jobs,
|
jobs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn id(col: usize, note_id: &[u8; 32]) -> egui::Id {
|
||||||
|
egui::Id::new(("quote_repost", col, note_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id(col: usize, note_id: &[u8; 32]) -> egui::Id {
|
||||||
|
QuoteRepostView::id(col, note_id).with("scroll")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
||||||
let id = self.id();
|
ScrollArea::vertical()
|
||||||
|
.id_salt(self.scroll_id)
|
||||||
|
.show(ui, |ui| self.show_internal(ui))
|
||||||
|
.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_internal(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
||||||
let quoting_note_id = self.quoting_note.id();
|
let quoting_note_id = self.quoting_note.id();
|
||||||
|
|
||||||
let post_resp = ui::PostView::new(
|
let post_resp = ui::PostView::new(
|
||||||
@@ -56,18 +71,7 @@ impl<'a, 'd> QuoteRepostView<'a, 'd> {
|
|||||||
self.note_options,
|
self.note_options,
|
||||||
self.jobs,
|
self.jobs,
|
||||||
)
|
)
|
||||||
.id_source(id)
|
.ui_no_scroll(self.quoting_note.txn().unwrap(), ui);
|
||||||
.ui(self.quoting_note.txn().unwrap(), ui);
|
|
||||||
post_resp
|
post_resp
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id_source(mut self, id: egui::Id) -> Self {
|
|
||||||
self.id_source = Some(id);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> egui::Id {
|
|
||||||
self.id_source
|
|
||||||
.unwrap_or_else(|| egui::Id::new("quote-repost-view"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::ui::{
|
|||||||
note::{PostAction, PostResponse, PostType},
|
note::{PostAction, PostResponse, PostType},
|
||||||
};
|
};
|
||||||
|
|
||||||
use egui::{Rect, Response, Ui};
|
use egui::{Rect, Response, ScrollArea, Ui};
|
||||||
use enostr::{FilledKeypair, NoteId};
|
use enostr::{FilledKeypair, NoteId};
|
||||||
use notedeck::NoteContext;
|
use notedeck::NoteContext;
|
||||||
use notedeck_ui::jobs::JobsCache;
|
use notedeck_ui::jobs::JobsCache;
|
||||||
@@ -15,7 +15,7 @@ pub struct PostReplyView<'a, 'd> {
|
|||||||
poster: FilledKeypair<'a>,
|
poster: FilledKeypair<'a>,
|
||||||
draft: &'a mut Draft,
|
draft: &'a mut Draft,
|
||||||
note: &'a nostrdb::Note<'a>,
|
note: &'a nostrdb::Note<'a>,
|
||||||
id_source: Option<egui::Id>,
|
scroll_id: egui::Id,
|
||||||
inner_rect: egui::Rect,
|
inner_rect: egui::Rect,
|
||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
@@ -31,31 +31,37 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
|
|||||||
inner_rect: egui::Rect,
|
inner_rect: egui::Rect,
|
||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
|
col: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let id_source: Option<egui::Id> = None;
|
|
||||||
PostReplyView {
|
PostReplyView {
|
||||||
note_context,
|
note_context,
|
||||||
poster,
|
poster,
|
||||||
draft,
|
draft,
|
||||||
note,
|
note,
|
||||||
id_source,
|
scroll_id: PostReplyView::scroll_id(col, note.id()),
|
||||||
inner_rect,
|
inner_rect,
|
||||||
note_options,
|
note_options,
|
||||||
jobs,
|
jobs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id_source(mut self, id: egui::Id) -> Self {
|
fn id(col: usize, note_id: &[u8; 32]) -> egui::Id {
|
||||||
self.id_source = Some(id);
|
egui::Id::new(("reply_view", col, note_id))
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id(&self) -> egui::Id {
|
pub fn scroll_id(col: usize, note_id: &[u8; 32]) -> egui::Id {
|
||||||
self.id_source
|
PostReplyView::id(col, note_id).with("scroll")
|
||||||
.unwrap_or_else(|| egui::Id::new("post-reply-view"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
||||||
|
ScrollArea::vertical()
|
||||||
|
.id_salt(self.scroll_id)
|
||||||
|
.show(ui, |ui| self.show_internal(ui))
|
||||||
|
.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
// no scroll
|
||||||
|
fn show_internal(&mut self, ui: &mut egui::Ui) -> PostResponse {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
let avail_rect = ui.available_rect_before_wrap();
|
let avail_rect = ui.available_rect_before_wrap();
|
||||||
|
|
||||||
@@ -81,7 +87,6 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
|
|||||||
})
|
})
|
||||||
.inner;
|
.inner;
|
||||||
|
|
||||||
let id = self.id();
|
|
||||||
let replying_to = self.note.id();
|
let replying_to = self.note.id();
|
||||||
let rect_before_post = ui.min_rect();
|
let rect_before_post = ui.min_rect();
|
||||||
|
|
||||||
@@ -95,8 +100,7 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
|
|||||||
self.note_options,
|
self.note_options,
|
||||||
self.jobs,
|
self.jobs,
|
||||||
)
|
)
|
||||||
.id_source(id)
|
.ui_no_scroll(self.note.txn().unwrap(), ui)
|
||||||
.ui(self.note.txn().unwrap(), ui)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
post_response.action = post_response
|
post_response.action = post_response
|
||||||
|
|||||||
@@ -24,9 +24,14 @@ impl<'a> EditProfileView<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id() -> egui::Id {
|
||||||
|
egui::Id::new("edit_profile")
|
||||||
|
}
|
||||||
|
|
||||||
// return true to save
|
// return true to save
|
||||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> bool {
|
pub fn ui(&mut self, ui: &mut egui::Ui) -> bool {
|
||||||
ScrollArea::vertical()
|
ScrollArea::vertical()
|
||||||
|
.id_salt(EditProfileView::scroll_id())
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
banner(ui, self.state.banner(), 188.0);
|
banner(ui, self.state.banner(), 188.0);
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,12 @@ impl<'a, 'd> ProfileView<'a, 'd> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id(col_id: usize, profile_pubkey: &Pubkey) -> egui::Id {
|
||||||
|
egui::Id::new(("profile_scroll", col_id, profile_pubkey))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<ProfileViewAction> {
|
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<ProfileViewAction> {
|
||||||
let scroll_id = egui::Id::new(("profile_scroll", self.col_id, self.pubkey));
|
let scroll_id = ProfileView::scroll_id(self.col_id, self.pubkey);
|
||||||
let offset_id = scroll_id.with("scroll_offset");
|
let offset_id = scroll_id.with("scroll_offset");
|
||||||
|
|
||||||
let mut scroll_area = ScrollArea::vertical().id_salt(scroll_id);
|
let mut scroll_area = ScrollArea::vertical().id_salt(scroll_id);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ impl RelayView<'_> {
|
|||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
|
|
||||||
egui::ScrollArea::vertical()
|
egui::ScrollArea::vertical()
|
||||||
|
.id_salt(RelayView::scroll_id())
|
||||||
.scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden)
|
.scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysHidden)
|
||||||
.auto_shrink([false; 2])
|
.auto_shrink([false; 2])
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
@@ -51,6 +52,10 @@ impl RelayView<'_> {
|
|||||||
|
|
||||||
action
|
action
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id() -> egui::Id {
|
||||||
|
egui::Id::new("relay_scroll")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RelayView<'a> {
|
impl<'a> RelayView<'a> {
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ impl<'a, 'd> SearchView<'a, 'd> {
|
|||||||
|
|
||||||
fn show_search_results(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
fn show_search_results(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
||||||
egui::ScrollArea::vertical()
|
egui::ScrollArea::vertical()
|
||||||
|
.id_salt(SearchView::scroll_id())
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
let reversed = false;
|
let reversed = false;
|
||||||
TimelineTabView::new(
|
TimelineTabView::new(
|
||||||
@@ -165,6 +166,10 @@ impl<'a, 'd> SearchView<'a, 'd> {
|
|||||||
})
|
})
|
||||||
.inner
|
.inner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id() -> egui::Id {
|
||||||
|
egui::Id::new("search_results")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_search(
|
fn execute_search(
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ pub struct ThreadView<'a, 'd> {
|
|||||||
selected_note_id: &'a [u8; 32],
|
selected_note_id: &'a [u8; 32],
|
||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
col: usize,
|
col: usize,
|
||||||
id_source: egui::Id,
|
|
||||||
note_context: &'a mut NoteContext<'d>,
|
note_context: &'a mut NoteContext<'d>,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
}
|
}
|
||||||
@@ -27,37 +26,33 @@ impl<'a, 'd> ThreadView<'a, 'd> {
|
|||||||
note_options: NoteOptions,
|
note_options: NoteOptions,
|
||||||
note_context: &'a mut NoteContext<'d>,
|
note_context: &'a mut NoteContext<'d>,
|
||||||
jobs: &'a mut JobsCache,
|
jobs: &'a mut JobsCache,
|
||||||
|
col: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let id_source = egui::Id::new("threadscroll_threadview");
|
|
||||||
ThreadView {
|
ThreadView {
|
||||||
threads,
|
threads,
|
||||||
selected_note_id,
|
selected_note_id,
|
||||||
note_options,
|
note_options,
|
||||||
id_source,
|
|
||||||
note_context,
|
note_context,
|
||||||
jobs,
|
jobs,
|
||||||
col: 0,
|
col,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn id_source(mut self, col: usize) -> Self {
|
pub fn scroll_id(selected_note_id: &[u8; 32], col: usize) -> egui::Id {
|
||||||
self.col = col;
|
egui::Id::new(("threadscroll", selected_note_id, col))
|
||||||
self.id_source = egui::Id::new(("threadscroll", col));
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<NoteAction> {
|
||||||
let txn = Transaction::new(self.note_context.ndb).expect("txn");
|
let txn = Transaction::new(self.note_context.ndb).expect("txn");
|
||||||
|
|
||||||
|
let scroll_id = ThreadView::scroll_id(self.selected_note_id, self.col);
|
||||||
let mut scroll_area = egui::ScrollArea::vertical()
|
let mut scroll_area = egui::ScrollArea::vertical()
|
||||||
.id_salt(self.id_source)
|
.id_salt(scroll_id)
|
||||||
.animated(false)
|
.animated(false)
|
||||||
.auto_shrink([false, false])
|
.auto_shrink([false, false])
|
||||||
.scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysVisible);
|
.scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysVisible);
|
||||||
|
|
||||||
let offset_id = self
|
let offset_id = scroll_id.with(("scroll_offset", self.selected_note_id));
|
||||||
.id_source
|
|
||||||
.with(("scroll_offset", self.selected_note_id));
|
|
||||||
|
|
||||||
if let Some(offset) = ui.data(|i| i.get_temp::<f32>(offset_id)) {
|
if let Some(offset) = ui.data(|i| i.get_temp::<f32>(offset_id)) {
|
||||||
scroll_area = scroll_area.vertical_scroll_offset(offset);
|
scroll_area = scroll_area.vertical_scroll_offset(offset);
|
||||||
|
|||||||
@@ -74,6 +74,15 @@ impl<'a, 'd> TimelineView<'a, 'd> {
|
|||||||
self.reverse = true;
|
self.reverse = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_id(
|
||||||
|
timeline_cache: &TimelineCache,
|
||||||
|
timeline_id: &TimelineKind,
|
||||||
|
col: usize,
|
||||||
|
) -> Option<egui::Id> {
|
||||||
|
let timeline = timeline_cache.get(timeline_id)?;
|
||||||
|
Some(egui::Id::new(("tlscroll", timeline.view_id(col))))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@@ -95,7 +104,9 @@ fn timeline_ui(
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let scroll_id = {
|
let scroll_id = TimelineView::scroll_id(timeline_cache, timeline_id, col)?;
|
||||||
|
|
||||||
|
{
|
||||||
let timeline = if let Some(timeline) = timeline_cache.get_mut(timeline_id) {
|
let timeline = if let Some(timeline) = timeline_cache.get_mut(timeline_id) {
|
||||||
timeline
|
timeline
|
||||||
} else {
|
} else {
|
||||||
@@ -114,8 +125,6 @@ fn timeline_ui(
|
|||||||
|
|
||||||
// need this for some reason??
|
// need this for some reason??
|
||||||
ui.add_space(3.0);
|
ui.add_space(3.0);
|
||||||
|
|
||||||
egui::Id::new(("tlscroll", timeline.view_id(col)))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let show_top_button_id = ui.id().with((scroll_id, "at_top"));
|
let show_top_button_id = ui.id().with((scroll_id, "at_top"));
|
||||||
|
|||||||
Reference in New Issue
Block a user