Merge note context menu #328
This merges kernel's note context menu with a bunch of refactorings on top, closing #328 and #318 William Casarin (7): refactor: remove processs_note_selection refactor: make options_button a NoteOptions note: switch to muted menu_options_button color context: move note context button to its own file context: fix hitbox, float on far right context: set cursor icon on hover kernelkind (3): Add 'more options' to each note can left click note more options button process 'more options' for previews
This commit is contained in:
@@ -68,6 +68,10 @@ impl Pubkey {
|
|||||||
Ok(Pubkey(data.1.try_into().unwrap()))
|
Ok(Pubkey(data.1.try_into().unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_bech(&self) -> Option<String> {
|
||||||
|
nostr::bech32::encode::<nostr::bech32::Bech32>(HRP_NPUB, &self.0).ok()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Pubkey {
|
impl fmt::Display for Pubkey {
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ impl NoteCache {
|
|||||||
pub struct CachedNote {
|
pub struct CachedNote {
|
||||||
reltime: TimeCached<String>,
|
reltime: TimeCached<String>,
|
||||||
pub reply: NoteReplyBuf,
|
pub reply: NoteReplyBuf,
|
||||||
pub bar_open: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedNote {
|
impl CachedNote {
|
||||||
@@ -46,12 +45,7 @@ impl CachedNote {
|
|||||||
Box::new(move || time_ago_since(created_at)),
|
Box::new(move || time_ago_since(created_at)),
|
||||||
);
|
);
|
||||||
let reply = NoteReply::new(note.tags()).to_owned();
|
let reply = NoteReply::new(note.tags()).to_owned();
|
||||||
let bar_open = false;
|
CachedNote { reltime, reply }
|
||||||
CachedNote {
|
|
||||||
reltime,
|
|
||||||
reply,
|
|
||||||
bar_open,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reltime_str_mut(&mut self) -> &str {
|
pub fn reltime_str_mut(&mut self) -> &str {
|
||||||
|
|||||||
@@ -103,12 +103,17 @@ pub fn render_note_preview(
|
|||||||
ui.visuals().noninteractive().bg_stroke.color,
|
ui.visuals().noninteractive().bg_stroke.color,
|
||||||
))
|
))
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
ui::NoteView::new(ndb, note_cache, img_cache, ¬e)
|
let resp = ui::NoteView::new(ndb, note_cache, img_cache, ¬e)
|
||||||
.actionbar(false)
|
.actionbar(false)
|
||||||
.small_pfp(true)
|
.small_pfp(true)
|
||||||
.wide(true)
|
.wide(true)
|
||||||
.note_previews(false)
|
.note_previews(false)
|
||||||
|
.options_button(true)
|
||||||
.show(ui);
|
.show(ui);
|
||||||
|
|
||||||
|
if let Some(context) = resp.context_selection {
|
||||||
|
context.process(ui, ¬e);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.response
|
.response
|
||||||
}
|
}
|
||||||
|
|||||||
177
src/ui/note/context.rs
Normal file
177
src/ui/note/context.rs
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
use crate::colors;
|
||||||
|
use egui::{Rect, Vec2};
|
||||||
|
use enostr::{NoteId, Pubkey};
|
||||||
|
use nostrdb::{Note, NoteKey};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
#[allow(clippy::enum_variant_names)]
|
||||||
|
pub enum NoteContextSelection {
|
||||||
|
CopyText,
|
||||||
|
CopyPubkey,
|
||||||
|
CopyNoteId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NoteContextSelection {
|
||||||
|
pub fn process(&self, ui: &mut egui::Ui, note: &Note<'_>) {
|
||||||
|
match self {
|
||||||
|
NoteContextSelection::CopyText => {
|
||||||
|
ui.output_mut(|w| {
|
||||||
|
w.copied_text = note.content().to_string();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
NoteContextSelection::CopyPubkey => {
|
||||||
|
ui.output_mut(|w| {
|
||||||
|
if let Some(bech) = Pubkey::new(*note.pubkey()).to_bech() {
|
||||||
|
w.copied_text = bech;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
NoteContextSelection::CopyNoteId => {
|
||||||
|
ui.output_mut(|w| {
|
||||||
|
if let Some(bech) = NoteId::new(*note.id()).to_bech() {
|
||||||
|
w.copied_text = bech;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NoteContextButton {
|
||||||
|
put_at: Option<Rect>,
|
||||||
|
note_key: NoteKey,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl egui::Widget for NoteContextButton {
|
||||||
|
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
||||||
|
let r = if let Some(r) = self.put_at {
|
||||||
|
r
|
||||||
|
} else {
|
||||||
|
let mut place = ui.available_rect_before_wrap();
|
||||||
|
let size = Self::max_width();
|
||||||
|
place.set_width(size);
|
||||||
|
place.set_height(size);
|
||||||
|
place
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::show(ui, self.note_key, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NoteContextButton {
|
||||||
|
pub fn new(note_key: NoteKey) -> Self {
|
||||||
|
let put_at: Option<Rect> = None;
|
||||||
|
NoteContextButton { note_key, put_at }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn place_at(mut self, rect: Rect) -> Self {
|
||||||
|
self.put_at = Some(rect);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_width() -> f32 {
|
||||||
|
Self::max_radius() * 3.0 + Self::max_distance_between_circles() * 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size() -> Vec2 {
|
||||||
|
let width = Self::max_width();
|
||||||
|
egui::vec2(width, width)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_radius() -> f32 {
|
||||||
|
8.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min_radius() -> f32 {
|
||||||
|
Self::max_radius() / Self::expansion_multiple()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_distance_between_circles() -> f32 {
|
||||||
|
2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expansion_multiple() -> f32 {
|
||||||
|
2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min_distance_between_circles() -> f32 {
|
||||||
|
Self::max_distance_between_circles() / Self::expansion_multiple()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn show(ui: &mut egui::Ui, note_key: NoteKey, put_at: Rect) -> egui::Response {
|
||||||
|
let id = ui.id().with(("more_options_anim", note_key));
|
||||||
|
|
||||||
|
let min_radius = Self::min_radius();
|
||||||
|
let anim_speed = 0.05;
|
||||||
|
let response = ui.interact(put_at, id, egui::Sense::click());
|
||||||
|
|
||||||
|
let hovered = response.hovered();
|
||||||
|
let animation_progress = ui.ctx().animate_bool_with_time(id, hovered, anim_speed);
|
||||||
|
|
||||||
|
if hovered {
|
||||||
|
ui.ctx().set_cursor_icon(egui::CursorIcon::PointingHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
let min_distance = Self::min_distance_between_circles();
|
||||||
|
let cur_distance = min_distance
|
||||||
|
+ (Self::max_distance_between_circles() - min_distance) * animation_progress;
|
||||||
|
|
||||||
|
let cur_radius = min_radius + (Self::max_radius() - min_radius) * animation_progress;
|
||||||
|
|
||||||
|
let center = put_at.center();
|
||||||
|
let left_circle_center = center - egui::vec2(cur_distance + cur_radius, 0.0);
|
||||||
|
let right_circle_center = center + egui::vec2(cur_distance + cur_radius, 0.0);
|
||||||
|
|
||||||
|
let translated_radius = (cur_radius - 1.0) / 2.0;
|
||||||
|
|
||||||
|
// This works in both themes
|
||||||
|
let color = colors::GRAY_SECONDARY;
|
||||||
|
|
||||||
|
// Draw circles
|
||||||
|
let painter = ui.painter_at(put_at);
|
||||||
|
painter.circle_filled(left_circle_center, translated_radius, color);
|
||||||
|
painter.circle_filled(center, translated_radius, color);
|
||||||
|
painter.circle_filled(right_circle_center, translated_radius, color);
|
||||||
|
|
||||||
|
response
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn menu(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
button_response: egui::Response,
|
||||||
|
) -> Option<NoteContextSelection> {
|
||||||
|
let mut context_selection: Option<NoteContextSelection> = None;
|
||||||
|
|
||||||
|
stationary_arbitrary_menu_button(ui, button_response, |ui| {
|
||||||
|
ui.set_max_width(200.0);
|
||||||
|
if ui.button("Copy text").clicked() {
|
||||||
|
context_selection = Some(NoteContextSelection::CopyText);
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
if ui.button("Copy user public key").clicked() {
|
||||||
|
context_selection = Some(NoteContextSelection::CopyPubkey);
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
if ui.button("Copy note id").clicked() {
|
||||||
|
context_selection = Some(NoteContextSelection::CopyNoteId);
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
context_selection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stationary_arbitrary_menu_button<R>(
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
button_response: egui::Response,
|
||||||
|
add_contents: impl FnOnce(&mut egui::Ui) -> R,
|
||||||
|
) -> egui::InnerResponse<Option<R>> {
|
||||||
|
let bar_id = ui.id();
|
||||||
|
let mut bar_state = egui::menu::BarState::load(ui.ctx(), bar_id);
|
||||||
|
|
||||||
|
let inner = bar_state.bar_menu(&button_response, add_contents);
|
||||||
|
|
||||||
|
bar_state.store(ui.ctx(), bar_id);
|
||||||
|
egui::InnerResponse::new(inner.map(|r| r.inner), button_response)
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
pub mod contents;
|
pub mod contents;
|
||||||
|
pub mod context;
|
||||||
pub mod options;
|
pub mod options;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod quote_repost;
|
pub mod quote_repost;
|
||||||
pub mod reply;
|
pub mod reply;
|
||||||
|
|
||||||
pub use contents::NoteContents;
|
pub use contents::NoteContents;
|
||||||
|
pub use context::{NoteContextButton, NoteContextSelection};
|
||||||
pub use options::NoteOptions;
|
pub use options::NoteOptions;
|
||||||
pub use post::{PostAction, PostResponse, PostView};
|
pub use post::{PostAction, PostResponse, PostView};
|
||||||
pub use quote_repost::QuoteRepostView;
|
pub use quote_repost::QuoteRepostView;
|
||||||
@@ -18,7 +20,7 @@ use crate::{
|
|||||||
notecache::{CachedNote, NoteCache},
|
notecache::{CachedNote, NoteCache},
|
||||||
ui::{self, View},
|
ui::{self, View},
|
||||||
};
|
};
|
||||||
use egui::{Id, Label, Response, RichText, Sense};
|
use egui::{Id, Label, Pos2, Rect, Response, RichText, Sense};
|
||||||
use enostr::NoteId;
|
use enostr::NoteId;
|
||||||
use nostrdb::{Ndb, Note, NoteKey, NoteReply, Transaction};
|
use nostrdb::{Ndb, Note, NoteKey, NoteReply, Transaction};
|
||||||
|
|
||||||
@@ -35,6 +37,28 @@ pub struct NoteView<'a> {
|
|||||||
pub struct NoteResponse {
|
pub struct NoteResponse {
|
||||||
pub response: egui::Response,
|
pub response: egui::Response,
|
||||||
pub action: Option<BarAction>,
|
pub action: Option<BarAction>,
|
||||||
|
pub context_selection: Option<NoteContextSelection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NoteResponse {
|
||||||
|
pub fn new(response: egui::Response) -> Self {
|
||||||
|
Self {
|
||||||
|
response,
|
||||||
|
action: None,
|
||||||
|
context_selection: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_action(self, action: Option<BarAction>) -> Self {
|
||||||
|
Self { action, ..self }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn select_option(self, context_selection: Option<NoteContextSelection>) -> Self {
|
||||||
|
Self {
|
||||||
|
context_selection,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> View for NoteView<'a> {
|
impl<'a> View for NoteView<'a> {
|
||||||
@@ -215,6 +239,11 @@ impl<'a> NoteView<'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn options_button(mut self, enable: bool) -> Self {
|
||||||
|
self.options_mut().set_options_button(enable);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn options(&self) -> NoteOptions {
|
pub fn options(&self) -> NoteOptions {
|
||||||
self.flags
|
self.flags
|
||||||
}
|
}
|
||||||
@@ -324,10 +353,7 @@ impl<'a> NoteView<'a> {
|
|||||||
|
|
||||||
pub fn show(&mut self, ui: &mut egui::Ui) -> NoteResponse {
|
pub fn show(&mut self, ui: &mut egui::Ui) -> NoteResponse {
|
||||||
if self.options().has_textmode() {
|
if self.options().has_textmode() {
|
||||||
NoteResponse {
|
NoteResponse::new(self.textmode_ui(ui))
|
||||||
response: self.textmode_ui(ui),
|
|
||||||
action: None,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let txn = self.note.txn().expect("txn");
|
let txn = self.note.txn().expect("txn");
|
||||||
if let Some(note_to_repost) = get_reposted_note(self.ndb, txn, self.note) {
|
if let Some(note_to_repost) = get_reposted_note(self.ndb, txn, self.note) {
|
||||||
@@ -369,17 +395,33 @@ impl<'a> NoteView<'a> {
|
|||||||
note_cache: &mut NoteCache,
|
note_cache: &mut NoteCache,
|
||||||
note: &Note,
|
note: &Note,
|
||||||
profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>,
|
profile: &Result<nostrdb::ProfileRecord<'_>, nostrdb::Error>,
|
||||||
) -> egui::Response {
|
options: NoteOptions,
|
||||||
|
container_right: Pos2,
|
||||||
|
) -> NoteResponse {
|
||||||
let note_key = note.key().unwrap();
|
let note_key = note.key().unwrap();
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
let inner_response = ui.horizontal(|ui| {
|
||||||
ui.spacing_mut().item_spacing.x = 2.0;
|
ui.spacing_mut().item_spacing.x = 2.0;
|
||||||
ui.add(ui::Username::new(profile.as_ref().ok(), note.pubkey()).abbreviated(20));
|
ui.add(ui::Username::new(profile.as_ref().ok(), note.pubkey()).abbreviated(20));
|
||||||
|
|
||||||
let cached_note = note_cache.cached_note_or_insert_mut(note_key, note);
|
let cached_note = note_cache.cached_note_or_insert_mut(note_key, note);
|
||||||
render_reltime(ui, cached_note, true);
|
render_reltime(ui, cached_note, true);
|
||||||
})
|
|
||||||
.response
|
if options.has_options_button() {
|
||||||
|
let context_pos = {
|
||||||
|
let size = NoteContextButton::max_width();
|
||||||
|
let min = Pos2::new(container_right.x - size, container_right.y);
|
||||||
|
Rect::from_min_size(min, egui::vec2(size, size))
|
||||||
|
};
|
||||||
|
|
||||||
|
let resp = ui.add(NoteContextButton::new(note_key).place_at(context_pos));
|
||||||
|
NoteContextButton::menu(ui, resp.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
NoteResponse::new(inner_response.response).select_option(inner_response.inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_standard(&mut self, ui: &mut egui::Ui) -> NoteResponse {
|
fn show_standard(&mut self, ui: &mut egui::Ui) -> NoteResponse {
|
||||||
@@ -388,8 +430,15 @@ impl<'a> NoteView<'a> {
|
|||||||
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;
|
let mut note_action: Option<BarAction> = None;
|
||||||
|
let mut selected_option: Option<NoteContextSelection> = None;
|
||||||
let profile = self.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
|
let profile = self.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
|
||||||
let maybe_hitbox = maybe_note_hitbox(ui, note_key);
|
let maybe_hitbox = maybe_note_hitbox(ui, note_key);
|
||||||
|
let container_right = {
|
||||||
|
let r = ui.available_rect_before_wrap();
|
||||||
|
let x = r.max.x;
|
||||||
|
let y = r.min.y;
|
||||||
|
Pos2::new(x, y)
|
||||||
|
};
|
||||||
|
|
||||||
// wide design
|
// wide design
|
||||||
let response = if self.options().has_wide() {
|
let response = if self.options().has_wide() {
|
||||||
@@ -400,7 +449,15 @@ impl<'a> NoteView<'a> {
|
|||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
ui.add_sized([size.x, self.options().pfp_size()], |ui: &mut egui::Ui| {
|
ui.add_sized([size.x, self.options().pfp_size()], |ui: &mut egui::Ui| {
|
||||||
ui.horizontal_centered(|ui| {
|
ui.horizontal_centered(|ui| {
|
||||||
NoteView::note_header(ui, self.note_cache, self.note, &profile);
|
selected_option = NoteView::note_header(
|
||||||
|
ui,
|
||||||
|
self.note_cache,
|
||||||
|
self.note,
|
||||||
|
&profile,
|
||||||
|
self.options(),
|
||||||
|
container_right,
|
||||||
|
)
|
||||||
|
.context_selection;
|
||||||
})
|
})
|
||||||
.response
|
.response
|
||||||
});
|
});
|
||||||
@@ -440,8 +497,15 @@ impl<'a> NoteView<'a> {
|
|||||||
self.pfp(note_key, &profile, ui);
|
self.pfp(note_key, &profile, ui);
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
|
ui.with_layout(egui::Layout::top_down(egui::Align::LEFT), |ui| {
|
||||||
NoteView::note_header(ui, self.note_cache, self.note, &profile);
|
selected_option = NoteView::note_header(
|
||||||
|
ui,
|
||||||
|
self.note_cache,
|
||||||
|
self.note,
|
||||||
|
&profile,
|
||||||
|
self.options(),
|
||||||
|
container_right,
|
||||||
|
)
|
||||||
|
.context_selection;
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.spacing_mut().item_spacing.x = 2.0;
|
ui.spacing_mut().item_spacing.x = 2.0;
|
||||||
|
|
||||||
@@ -483,10 +547,9 @@ impl<'a> NoteView<'a> {
|
|||||||
note_action,
|
note_action,
|
||||||
);
|
);
|
||||||
|
|
||||||
NoteResponse {
|
NoteResponse::new(response)
|
||||||
response,
|
.with_action(note_action)
|
||||||
action: note_action,
|
.select_option(selected_option)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ bitflags! {
|
|||||||
// Attributes can be applied to flags types
|
// Attributes can be applied to flags types
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct NoteOptions: u32 {
|
pub struct NoteOptions: u64 {
|
||||||
const actionbar = 0b00000001;
|
const actionbar = 0b0000000000000001;
|
||||||
const note_previews = 0b00000010;
|
const note_previews = 0b0000000000000010;
|
||||||
const small_pfp = 0b00000100;
|
const small_pfp = 0b0000000000000100;
|
||||||
const medium_pfp = 0b00001000;
|
const medium_pfp = 0b0000000000001000;
|
||||||
const wide = 0b00010000;
|
const wide = 0b0000000000010000;
|
||||||
const selectable_text = 0b00100000;
|
const selectable_text = 0b0000000000100000;
|
||||||
const textmode = 0b01000000;
|
const textmode = 0b0000000001000000;
|
||||||
|
const options_button = 0b0000000010000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +37,8 @@ impl NoteOptions {
|
|||||||
create_setter!(set_selectable_text, selectable_text);
|
create_setter!(set_selectable_text, selectable_text);
|
||||||
create_setter!(set_textmode, textmode);
|
create_setter!(set_textmode, textmode);
|
||||||
create_setter!(set_actionbar, actionbar);
|
create_setter!(set_actionbar, actionbar);
|
||||||
|
create_setter!(set_wide, wide);
|
||||||
|
create_setter!(set_options_button, options_button);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_actionbar(self) -> bool {
|
pub fn has_actionbar(self) -> bool {
|
||||||
@@ -67,6 +70,16 @@ impl NoteOptions {
|
|||||||
(self & NoteOptions::medium_pfp) == NoteOptions::medium_pfp
|
(self & NoteOptions::medium_pfp) == NoteOptions::medium_pfp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn has_wide(self) -> bool {
|
||||||
|
(self & NoteOptions::wide) == NoteOptions::wide
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn has_options_button(self) -> bool {
|
||||||
|
(self & NoteOptions::options_button) == NoteOptions::options_button
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pfp_size(&self) -> f32 {
|
pub fn pfp_size(&self) -> f32 {
|
||||||
if self.has_small_pfp() {
|
if self.has_small_pfp() {
|
||||||
ProfilePic::small_size()
|
ProfilePic::small_size()
|
||||||
@@ -76,18 +89,4 @@ impl NoteOptions {
|
|||||||
ProfilePic::default_size()
|
ProfilePic::default_size()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn has_wide(self) -> bool {
|
|
||||||
(self & NoteOptions::wide) == NoteOptions::wide
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn set_wide(&mut self, enable: bool) {
|
|
||||||
if enable {
|
|
||||||
*self |= NoteOptions::wide;
|
|
||||||
} else {
|
|
||||||
*self &= !NoteOptions::wide;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ impl<'a> PostReplyView<'a> {
|
|||||||
ui::NoteView::new(self.ndb, self.note_cache, self.img_cache, self.note)
|
ui::NoteView::new(self.ndb, self.note_cache, self.img_cache, self.note)
|
||||||
.actionbar(false)
|
.actionbar(false)
|
||||||
.medium_pfp(true)
|
.medium_pfp(true)
|
||||||
|
.options_button(true)
|
||||||
.show(ui);
|
.show(ui);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -115,15 +115,19 @@ impl<'a> ThreadView<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ui::padding(8.0, ui, |ui| {
|
ui::padding(8.0, ui, |ui| {
|
||||||
if let Some(bar_action) =
|
let note_response =
|
||||||
ui::NoteView::new(self.ndb, self.note_cache, self.img_cache, ¬e)
|
ui::NoteView::new(self.ndb, self.note_cache, self.img_cache, ¬e)
|
||||||
.note_previews(!self.textmode)
|
.note_previews(!self.textmode)
|
||||||
.textmode(self.textmode)
|
.textmode(self.textmode)
|
||||||
.show(ui)
|
.options_button(!self.textmode)
|
||||||
.action
|
.show(ui);
|
||||||
{
|
if let Some(bar_action) = note_response.action {
|
||||||
action = Some(bar_action);
|
action = Some(bar_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(selection) = note_response.context_selection {
|
||||||
|
selection.process(ui, ¬e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ui::hline(ui);
|
ui::hline(ui);
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ fn timeline_ui(
|
|||||||
let resp = ui::NoteView::new(ndb, note_cache, img_cache, ¬e)
|
let resp = ui::NoteView::new(ndb, note_cache, img_cache, ¬e)
|
||||||
.note_previews(!textmode)
|
.note_previews(!textmode)
|
||||||
.selectable_text(false)
|
.selectable_text(false)
|
||||||
|
.options_button(true)
|
||||||
.show(ui);
|
.show(ui);
|
||||||
|
|
||||||
if let Some(ba) = resp.action {
|
if let Some(ba) = resp.action {
|
||||||
@@ -156,6 +157,10 @@ fn timeline_ui(
|
|||||||
} else if resp.response.clicked() {
|
} else if resp.response.clicked() {
|
||||||
debug!("clicked note");
|
debug!("clicked note");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(context) = resp.context_selection {
|
||||||
|
context.process(ui, ¬e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ui::hline(ui);
|
ui::hline(ui);
|
||||||
|
|||||||
Reference in New Issue
Block a user