title bar
add title bar to columns with title specific to the column type. also add column deletion button Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
241
src/nav.rs
241
src/nav.rs
@@ -1,5 +1,7 @@
|
||||
use crate::{
|
||||
account_manager::render_accounts_route,
|
||||
app_style::{get_font_size, NotedeckTextStyle},
|
||||
fonts::NamedFontFamily,
|
||||
relay_pool_manager::RelayPoolManager,
|
||||
route::Route,
|
||||
thread::thread_unsubscribe,
|
||||
@@ -7,91 +9,105 @@ use crate::{
|
||||
ui::{
|
||||
self,
|
||||
add_column::{AddColumnResponse, AddColumnView},
|
||||
anim::{AnimationHelper, ICON_EXPANSION_MULTIPLE},
|
||||
note::PostAction,
|
||||
RelayView, View,
|
||||
},
|
||||
Damus,
|
||||
};
|
||||
|
||||
use egui::{pos2, Color32, InnerResponse};
|
||||
use egui_nav::{Nav, NavAction};
|
||||
|
||||
pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||
let col_id = app.columns.get_column_id_at_index(col);
|
||||
// TODO(jb55): clean up this router_mut mess by using Router<R> in egui-nav directly
|
||||
let nav_response = Nav::new(app.columns().column(col).router().routes().clone())
|
||||
let routes = app
|
||||
.columns()
|
||||
.column(col)
|
||||
.router()
|
||||
.routes()
|
||||
.iter()
|
||||
.map(|r| r.get_titled_route(&app.columns, &app.ndb))
|
||||
.collect();
|
||||
let nav_response = Nav::new(routes)
|
||||
.navigating(app.columns_mut().column_mut(col).router_mut().navigating)
|
||||
.returning(app.columns_mut().column_mut(col).router_mut().returning)
|
||||
.title(false)
|
||||
.show_mut(ui, |ui, nav| match nav.top() {
|
||||
Route::Timeline(tlr) => render_timeline_route(
|
||||
&app.ndb,
|
||||
&mut app.columns,
|
||||
&mut app.pool,
|
||||
&mut app.drafts,
|
||||
&mut app.img_cache,
|
||||
&mut app.note_cache,
|
||||
&mut app.threads,
|
||||
&mut app.accounts,
|
||||
*tlr,
|
||||
col,
|
||||
app.textmode,
|
||||
ui,
|
||||
),
|
||||
Route::Accounts(amr) => {
|
||||
render_accounts_route(
|
||||
ui,
|
||||
.title(48.0, title_bar)
|
||||
.show_mut(col_id, ui, |ui, nav| {
|
||||
let column = app.columns.column_mut(col);
|
||||
match &nav.top().route {
|
||||
Route::Timeline(tlr) => render_timeline_route(
|
||||
&app.ndb,
|
||||
col,
|
||||
&mut app.columns,
|
||||
&mut app.img_cache,
|
||||
&mut app.accounts,
|
||||
&mut app.view_state.login,
|
||||
*amr,
|
||||
);
|
||||
None
|
||||
}
|
||||
Route::Relays => {
|
||||
let manager = RelayPoolManager::new(app.pool_mut());
|
||||
RelayView::new(manager).ui(ui);
|
||||
None
|
||||
}
|
||||
Route::ComposeNote => {
|
||||
let kp = app.accounts.selected_or_first_nsec()?;
|
||||
let draft = app.drafts.compose_mut();
|
||||
|
||||
let txn = nostrdb::Transaction::new(&app.ndb).expect("txn");
|
||||
let post_response = ui::PostView::new(
|
||||
&app.ndb,
|
||||
draft,
|
||||
crate::draft::DraftSource::Compose,
|
||||
&mut app.pool,
|
||||
&mut app.drafts,
|
||||
&mut app.img_cache,
|
||||
&mut app.note_cache,
|
||||
kp,
|
||||
)
|
||||
.ui(&txn, ui);
|
||||
|
||||
if let Some(action) = post_response.action {
|
||||
PostAction::execute(kp, &action, &mut app.pool, draft, |np, seckey| {
|
||||
np.to_note(seckey)
|
||||
});
|
||||
app.columns_mut().column_mut(col).router_mut().go_back();
|
||||
&mut app.threads,
|
||||
&mut app.accounts,
|
||||
*tlr,
|
||||
col,
|
||||
app.textmode,
|
||||
ui,
|
||||
),
|
||||
Route::Accounts(amr) => {
|
||||
render_accounts_route(
|
||||
ui,
|
||||
&app.ndb,
|
||||
col,
|
||||
&mut app.columns,
|
||||
&mut app.img_cache,
|
||||
&mut app.accounts,
|
||||
&mut app.view_state.login,
|
||||
*amr,
|
||||
);
|
||||
None
|
||||
}
|
||||
Route::Relays => {
|
||||
let manager = RelayPoolManager::new(app.pool_mut());
|
||||
RelayView::new(manager).ui(ui);
|
||||
None
|
||||
}
|
||||
Route::ComposeNote => {
|
||||
let kp = app.accounts.selected_or_first_nsec()?;
|
||||
let draft = app.drafts.compose_mut();
|
||||
|
||||
None
|
||||
}
|
||||
Route::AddColumn => {
|
||||
let resp = AddColumnView::new(&app.ndb, app.accounts.get_selected_account()).ui(ui);
|
||||
let txn = nostrdb::Transaction::new(&app.ndb).expect("txn");
|
||||
let post_response = ui::PostView::new(
|
||||
&app.ndb,
|
||||
draft,
|
||||
crate::draft::DraftSource::Compose,
|
||||
&mut app.img_cache,
|
||||
&mut app.note_cache,
|
||||
kp,
|
||||
)
|
||||
.ui(&txn, ui);
|
||||
|
||||
if let Some(resp) = resp {
|
||||
match resp {
|
||||
AddColumnResponse::Timeline(timeline) => {
|
||||
let id = timeline.id;
|
||||
if app.columns_mut().add_timeline_to_column(col, timeline) {
|
||||
if let Some(action) = post_response.action {
|
||||
PostAction::execute(kp, &action, &mut app.pool, draft, |np, seckey| {
|
||||
np.to_note(seckey)
|
||||
});
|
||||
column.router_mut().go_back();
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
Route::AddColumn => {
|
||||
let resp =
|
||||
AddColumnView::new(&app.ndb, app.accounts.get_selected_account()).ui(ui);
|
||||
|
||||
if let Some(resp) = resp {
|
||||
match resp {
|
||||
AddColumnResponse::Timeline(timeline) => {
|
||||
let id = timeline.id;
|
||||
app.columns_mut().add_timeline_to_column(col, timeline);
|
||||
app.subscribe_new_timeline(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
@@ -128,4 +144,103 @@ pub fn render_nav(col: usize, app: &mut Damus, ui: &mut egui::Ui) {
|
||||
cur_router.remove_previous_route();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(title_response) = nav_response.title_response {
|
||||
match title_response {
|
||||
TitleResponse::RemoveColumn => {
|
||||
app.columns_mut().request_deletion_at_index(col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn title_bar(
|
||||
ui: &mut egui::Ui,
|
||||
title_name: String,
|
||||
allocated_response: egui::Response,
|
||||
) -> egui::InnerResponse<Option<TitleResponse>> {
|
||||
let icon_width = 32.0;
|
||||
let padding = 16.0;
|
||||
title(ui, title_name, allocated_response.rect, icon_width, padding);
|
||||
let button_resp = delete_column_button(ui, allocated_response, icon_width, padding);
|
||||
let title_response = if button_resp.clicked() {
|
||||
Some(TitleResponse::RemoveColumn)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
InnerResponse::new(title_response, button_resp)
|
||||
}
|
||||
|
||||
fn delete_column_button(
|
||||
ui: &mut egui::Ui,
|
||||
title_bar_resp: egui::Response,
|
||||
icon_width: f32,
|
||||
padding: f32,
|
||||
) -> egui::Response {
|
||||
let img_size = 16.0;
|
||||
let max_size = icon_width * ICON_EXPANSION_MULTIPLE;
|
||||
|
||||
let img_data = egui::include_image!("../assets/icons/column_delete_icon_4x.png");
|
||||
let img = egui::Image::new(img_data).max_width(img_size);
|
||||
|
||||
let button_rect = {
|
||||
let titlebar_rect = title_bar_resp.rect;
|
||||
let titlebar_width = titlebar_rect.width();
|
||||
let titlebar_center = titlebar_rect.center();
|
||||
let button_center_y = titlebar_center.y;
|
||||
let button_center_x =
|
||||
titlebar_center.x + (titlebar_width / 2.0) - (max_size / 2.0) - padding;
|
||||
egui::Rect::from_center_size(
|
||||
pos2(button_center_x, button_center_y),
|
||||
egui::vec2(max_size, max_size),
|
||||
)
|
||||
};
|
||||
|
||||
let helper = AnimationHelper::new_from_rect(ui, "delete-column-button", button_rect);
|
||||
|
||||
let cur_img_size = helper.scale_1d_pos(img_size);
|
||||
|
||||
let animation_rect = helper.get_animation_rect();
|
||||
let animation_resp = helper.take_animation_response();
|
||||
if title_bar_resp.union(animation_resp.clone()).hovered() {
|
||||
img.paint_at(ui, animation_rect.shrink((max_size - cur_img_size) / 2.0));
|
||||
}
|
||||
|
||||
animation_resp
|
||||
}
|
||||
|
||||
fn title(
|
||||
ui: &mut egui::Ui,
|
||||
title_name: String,
|
||||
titlebar_rect: egui::Rect,
|
||||
icon_width: f32,
|
||||
padding: f32,
|
||||
) {
|
||||
let painter = ui.painter_at(titlebar_rect);
|
||||
|
||||
let font = egui::FontId::new(
|
||||
get_font_size(ui.ctx(), &NotedeckTextStyle::Body),
|
||||
egui::FontFamily::Name(NamedFontFamily::Bold.as_str().into()),
|
||||
);
|
||||
|
||||
let max_title_width = titlebar_rect.width() - icon_width - padding * 2.;
|
||||
let title_galley =
|
||||
ui.fonts(|f| f.layout(title_name, font, ui.visuals().text_color(), max_title_width));
|
||||
|
||||
let pos = {
|
||||
let titlebar_center = titlebar_rect.center();
|
||||
let titlebar_width = titlebar_rect.width();
|
||||
let text_height = title_galley.rect.height();
|
||||
|
||||
let galley_pos_x = titlebar_center.x - (titlebar_width / 2.) + padding;
|
||||
let galley_pos_y = titlebar_center.y - (text_height / 2.);
|
||||
pos2(galley_pos_x, galley_pos_y)
|
||||
};
|
||||
|
||||
painter.galley(pos, title_galley, Color32::WHITE);
|
||||
}
|
||||
|
||||
enum TitleResponse {
|
||||
RemoveColumn,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user