Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions crates/notedeck/src/persist/settings_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub struct Settings {
#[serde(default = "default_animate_nav_transitions")]
pub animate_nav_transitions: bool,
pub max_hashtags_per_note: usize,
pub load_media_by_default: bool,
}

fn default_animate_nav_transitions() -> bool {
Expand All @@ -57,6 +58,7 @@ impl Default for Settings {
note_body_font_size: DEFAULT_NOTE_BODY_FONT_SIZE,
animate_nav_transitions: default_animate_nav_transitions(),
max_hashtags_per_note: DEFAULT_MAX_HASHTAGS_PER_NOTE,
load_media_by_default: false,
}
}
}
Expand All @@ -75,7 +77,7 @@ impl SettingsHandler {
}
}

fn read_from_zomfactor_file(&self) -> Option<f32> {
fn read_from_zoomfactor_file(&self) -> Option<f32> {
match self.directory.get_file(ZOOM_FACTOR_FILE.to_string()) {
Ok(contents) => serde_json::from_str::<f32>(&contents).ok(),
Err(_) => None,
Expand All @@ -97,11 +99,11 @@ impl SettingsHandler {
};

// if zoom_factor.txt exists migrate
if let Some(zom_factor) = self.read_from_zomfactor_file() {
if let Some(zoom_factor) = self.read_from_zoomfactor_file() {
info!("migrating theme preference from zom_factor file");
_ = delete_file(&self.directory.file_path, ZOOM_FACTOR_FILE.to_string());

settings.zoom_factor = zom_factor;
settings.zoom_factor = zoom_factor;
migrated = true;
} else {
info!("zoom_factor.txt exists migrate file not found, using default zoom factor");
Expand Down Expand Up @@ -196,6 +198,11 @@ impl SettingsHandler {
self.try_save_settings();
}

pub fn set_load_media_by_default(&mut self, value: bool) {
self.get_settings_mut().load_media_by_default = value;
self.try_save_settings();
}

pub fn set_note_body_font_size(&mut self, value: f32) {
self.get_settings_mut().note_body_font_size = value;
self.try_save_settings();
Expand Down Expand Up @@ -264,6 +271,13 @@ impl SettingsHandler {
self.current_settings.is_some()
}

pub fn load_media_by_default(&self) -> bool {
self.current_settings
.as_ref()
.map(|s| s.load_media_by_default)
.unwrap_or(false)
}

pub fn note_body_font_size(&self) -> f32 {
self.current_settings
.as_ref()
Expand Down
41 changes: 41 additions & 0 deletions crates/notedeck/src/ui.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,48 @@
use egui::{Color32, Stroke};

use crate::NotedeckTextStyle;

pub const NARROW_SCREEN_WIDTH: f32 = 550.0;

pub fn toggle_ui(ui: &mut egui::Ui, on: &mut bool) -> egui::Response {
let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0, 1.0);
let (rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click());
if response.clicked() {
*on = !*on;
response.mark_changed();
}
response.widget_info(|| {
egui::WidgetInfo::selected(egui::WidgetType::Checkbox, ui.is_enabled(), *on, "")
});

if ui.is_rect_visible(rect) {
let how_on = ui.ctx().animate_bool_responsive(response.id, *on);
let visuals = ui.style().interact_selectable(&response, *on);
let rect = rect.expand(visuals.expansion);
let radius = 0.5 * rect.height();
let stroke_color = if ui.visuals().dark_mode {
Color32::WHITE
} else {
Color32::BLACK
};
let stroke = Stroke::new(visuals.fg_stroke.width, stroke_color);

ui.painter().rect(
rect,
radius,
visuals.bg_fill,
visuals.bg_stroke,
egui::StrokeKind::Inside,
);
let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on);
let center = egui::pos2(circle_x, rect.center().y);
ui.painter()
.circle(center, 0.75 * radius, visuals.bg_fill, stroke);
}

response
}

pub fn richtext_small<S>(text: S) -> egui::RichText
where
S: Into<String>,
Expand Down
11 changes: 10 additions & 1 deletion crates/notedeck_columns/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ pub struct Damus {
/// Were columns loaded from the commandline? If so disable persistence.
pub options: AppOptions,
pub note_options: NoteOptions,

pub unrecognized_args: BTreeSet<String>,

/// keep track of follow packs
Expand Down Expand Up @@ -436,6 +435,11 @@ fn render_damus(damus: &mut Damus, app_ctx: &mut AppContext<'_>, ui: &mut egui::
.note_options
.set(NoteOptions::Wide, is_narrow(ui.ctx()));

damus.note_options.set(
NoteOptions::LoadMediaByDefault,
app_ctx.settings.load_media_by_default(),
);

let app_resp = if notedeck::ui::is_narrow(ui.ctx()) {
render_damus_mobile(damus, app_ctx, ui)
} else {
Expand Down Expand Up @@ -662,6 +666,11 @@ impl Damus {
fn get_note_options(args: ColumnsArgs, settings_handler: &mut SettingsHandler) -> NoteOptions {
let mut note_options = NoteOptions::default();

note_options.set(
NoteOptions::LoadMediaByDefault,
settings_handler.load_media_by_default(),
);

note_options.set(
NoteOptions::Textmode,
args.is_flag_set(ColumnsFlag::Textmode),
Expand Down
61 changes: 46 additions & 15 deletions crates/notedeck_columns/src/ui/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ use egui_extras::{Size, StripBuilder};
use enostr::NoteId;
use nostrdb::Transaction;
use notedeck::{
tr, ui::richtext_small, Images, JobsCache, LanguageIdentifier, Localization, NoteContext,
NotedeckTextStyle, Settings, SettingsHandler, DEFAULT_MAX_HASHTAGS_PER_NOTE,
DEFAULT_NOTE_BODY_FONT_SIZE,
tr,
ui::{richtext_small, toggle_ui},
Images, JobsCache, LanguageIdentifier, Localization, NoteContext, NotedeckTextStyle, Settings,
SettingsHandler, DEFAULT_MAX_HASHTAGS_PER_NOTE, DEFAULT_NOTE_BODY_FONT_SIZE,
};
use notedeck_ui::{
app_images::{copy_to_clipboard_dark_image, copy_to_clipboard_image},
Expand All @@ -30,6 +31,7 @@ const RESET_ZOOM: f32 = 1.0;

pub enum SettingsAction {
SetZoomFactor(f32),
SetLoadMediaByDefault(bool),
SetTheme(ThemePreference),
SetLocale(LanguageIdentifier),
SetRepliestNewestFirst(bool),
Expand Down Expand Up @@ -100,6 +102,12 @@ impl SettingsAction {
settings.set_max_hashtags_per_note(value);
accounts.update_max_hashtags_per_note(value);
}
Self::SetLoadMediaByDefault(load_media) => {
app.note_options
.set(NoteOptions::LoadMediaByDefault, load_media);

settings.set_load_media_by_default(load_media);
}
}
route_action
}
Expand Down Expand Up @@ -468,18 +476,7 @@ impl<'a> SettingsView<'a> {
"Label for Sort replies newest first, others settings section",
)));

if ui
.toggle_value(
&mut self.settings.show_replies_newest_first,
RichText::new(tr!(
self.note_context.i18n,
"On",
"Setting to turn on sorting replies so that the newest are shown first"
))
.text_style(NotedeckTextStyle::Small.text_style()),
)
.changed()
{
if toggle_ui(ui, &mut self.settings.show_replies_newest_first).changed() {
action = Some(SettingsAction::SetRepliestNewestFirst(
self.settings.show_replies_newest_first,
));
Expand Down Expand Up @@ -733,6 +730,10 @@ impl<'a> SettingsView<'a> {

ui.add_space(5.0);

self.media_section(ui);

ui.add_space(5.0);

if let Some(new_action) = self.storage_section(ui) {
action = Some(new_action);
}
Expand All @@ -759,6 +760,36 @@ impl<'a> SettingsView<'a> {

BodyResponse::scroll(scroll_out)
}

fn media_section(&mut self, ui: &mut egui::Ui) -> Option<SettingsAction> {
let mut action = None;

let title = tr!(
self.note_context.i18n,
"Media",
"label for media setting section"
);

settings_group(ui, title, |ui| {
ui.horizontal_wrapped(|ui| {
ui.label(richtext_small(tr!(
self.note_context.i18n,
"Load media by default",
"Label for load media by default, Media settings section",
)));

if toggle_ui(ui, &mut self.settings.load_media_by_default).changed() {
action = Some(SettingsAction::SetLoadMediaByDefault(
self.settings.load_media_by_default,
));
}
});

ui.end_row();
});

action
}
}

pub fn format_size(size_bytes: u64) -> String {
Expand Down
5 changes: 4 additions & 1 deletion crates/notedeck_ui/src/note/media.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,16 @@ pub fn image_carousel(
let mut media_action: Option<(usize, MediaUIAction)> = None;

for (i, media) in medias.iter().enumerate() {
let trusted_media = note_options.contains(NoteOptions::TrustMedia)
|| note_options.contains(NoteOptions::LoadMediaByDefault);

let media_response = render_media(
ui,
img_cache,
job_pool,
jobs,
media,
note_options.contains(NoteOptions::TrustMedia),
trusted_media,
i18n,
size,
if note_options.contains(NoteOptions::NoAnimations) {
Expand Down
3 changes: 3 additions & 0 deletions crates/notedeck_ui/src/note/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ bitflags! {

/// There is enough trust to show media in this note
const TrustMedia = 1 << 20;

/// show media by default
const LoadMediaByDefault = 1 << 21;
}
}

Expand Down