commit fab1257f6eb0681ee492c82d135f83be61f99f40
parent 6c9693dbf0892c1e907b2fef4c4092a2508580f3
Author: William Casarin <jb55@jb55.com>
Date: Tue, 12 Nov 2024 14:00:57 -0800
paths: remove hardcoded basepath
Before we were hardcoding the basepath with dirs, which isn't that
useful for testing, previews, or for android. Let's fix that.
This also moves the db and cache directories into our root DataPaths.
This is a breaking change, we don't have a migration step. sorry.
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
11 files changed, 169 insertions(+), 146 deletions(-)
diff --git a/src/app.rs b/src/app.rs
@@ -15,7 +15,7 @@ use crate::{
notecache::{CachedNote, NoteCache},
notes_holder::NotesHolderStorage,
profile::Profile,
- storage::{Directory, FileKeyStorage, KeyStorageType},
+ storage::{DataPath, DataPathType, Directory, FileKeyStorage, KeyStorageType},
subscriptions::{SubKind, Subscriptions},
support::Support,
thread::Thread,
@@ -23,7 +23,7 @@ use crate::{
ui::{self, DesktopSidePanel},
unknowns::UnknownIds,
view_state::ViewState,
- DataPaths, Result,
+ Result,
};
use enostr::{ClientMessage, RelayEvent, RelayMessage, RelayPool};
@@ -67,6 +67,7 @@ pub struct Damus {
frame_history: crate::frame_history::FrameHistory,
+ pub path: DataPath,
// TODO: make these bitflags
pub debug: bool,
pub since_optimize: bool,
@@ -660,31 +661,25 @@ impl Damus {
let data_path = parsed_args
.datapath
.unwrap_or(data_path.as_ref().to_str().expect("db path ok").to_string());
- let dbpath = parsed_args.dbpath.unwrap_or(data_path.clone());
+ let path = DataPath::new(&data_path);
+ let dbpath_ = path.path(DataPathType::Db);
+ let dbpath = dbpath_.to_str().unwrap();
- let _ = std::fs::create_dir_all(dbpath.clone());
+ let _ = std::fs::create_dir_all(dbpath);
- let imgcache_dir = format!("{}/{}", data_path, ImageCache::rel_datadir());
+ let imgcache_dir = path.path(DataPathType::Cache).join(ImageCache::rel_dir());
let _ = std::fs::create_dir_all(imgcache_dir.clone());
let mut config = Config::new();
config.set_ingester_threads(4);
let keystore = if parsed_args.use_keystore {
- if let Ok(keys_path) = DataPaths::Keys.get_path() {
- if let Ok(selected_key_path) = DataPaths::SelectedKey.get_path() {
- KeyStorageType::FileSystem(FileKeyStorage::new(
- Directory::new(keys_path),
- Directory::new(selected_key_path),
- ))
- } else {
- error!("Could not find path for selected key");
- KeyStorageType::None
- }
- } else {
- error!("Could not find data path for keys");
- KeyStorageType::None
- }
+ let keys_path = path.path(DataPathType::Keys);
+ let selected_key_path = path.path(DataPathType::SelectedKey);
+ KeyStorageType::FileSystem(FileKeyStorage::new(
+ Directory::new(keys_path),
+ Directory::new(selected_key_path),
+ ))
} else {
KeyStorageType::None
};
@@ -725,7 +720,7 @@ impl Damus {
.get_selected_account()
.as_ref()
.map(|a| a.pubkey.bytes());
- let ndb = Ndb::new(&dbpath, &config).expect("ndb");
+ let ndb = Ndb::new(dbpath, &config).expect("ndb");
let mut columns: Columns = Columns::new();
for col in parsed_args.columns {
@@ -740,6 +735,9 @@ impl Damus {
columns.new_column_picker();
}
+ let app_rect_handler = AppSizeHandler::new(&path);
+ let support = Support::new(&path);
+
Self {
pool,
debug,
@@ -750,7 +748,7 @@ impl Damus {
profiles: NotesHolderStorage::default(),
drafts: Drafts::default(),
state: DamusState::Initializing,
- img_cache: ImageCache::new(imgcache_dir.into()),
+ img_cache: ImageCache::new(imgcache_dir),
note_cache: NoteCache::default(),
columns,
textmode: parsed_args.textmode,
@@ -758,8 +756,9 @@ impl Damus {
accounts,
frame_history: FrameHistory::default(),
view_state: ViewState::default(),
- app_rect_handler: AppSizeHandler::default(),
- support: Support::default(),
+ path,
+ app_rect_handler,
+ support,
}
}
@@ -819,12 +818,17 @@ impl Damus {
columns.add_new_timeline_column(timeline);
- let imgcache_dir = data_path.as_ref().join(ImageCache::rel_datadir());
+ let path = DataPath::new(&data_path);
+ let imgcache_dir = path.path(DataPathType::Cache).join(ImageCache::rel_dir());
let _ = std::fs::create_dir_all(imgcache_dir.clone());
let debug = true;
+ let app_rect_handler = AppSizeHandler::new(&path);
+ let support = Support::new(&path);
+
let mut config = Config::new();
config.set_ingester_threads(2);
+
Self {
debug,
unknown_ids: UnknownIds::default(),
@@ -839,12 +843,20 @@ impl Damus {
note_cache: NoteCache::default(),
columns,
textmode: false,
- ndb: Ndb::new(data_path.as_ref().to_str().expect("db path ok"), &config).expect("ndb"),
+ ndb: Ndb::new(
+ path.path(DataPathType::Db)
+ .to_str()
+ .expect("db path should be ok"),
+ &config,
+ )
+ .expect("ndb"),
accounts: AccountManager::new(KeyStorageType::None),
frame_history: FrameHistory::default(),
view_state: ViewState::default(),
- app_rect_handler: AppSizeHandler::default(),
- support: Support::default(),
+
+ path,
+ app_rect_handler,
+ support,
}
}
diff --git a/src/app_creation.rs b/src/app_creation.rs
@@ -1,25 +1,32 @@
-use crate::app_size_handler::AppSizeHandler;
-use crate::app_style::{
- create_custom_style, dark_mode, desktop_font_size, light_mode, mobile_font_size,
+use crate::{
+ app_size_handler::AppSizeHandler,
+ app_style::{create_custom_style, dark_mode, desktop_font_size, light_mode, mobile_font_size},
+ fonts::setup_fonts,
+ storage::DataPath,
};
-use crate::fonts::setup_fonts;
+
use eframe::NativeOptions;
//pub const UI_SCALE_FACTOR: f32 = 0.2;
-pub fn generate_native_options() -> NativeOptions {
- generate_native_options_with_builder_modifiers(|builder| {
+pub fn generate_native_options(paths: DataPath) -> NativeOptions {
+ let window_builder = Box::new(move |builder: egui::ViewportBuilder| {
let builder = builder
.with_fullsize_content_view(true)
.with_titlebar_shown(false)
.with_title_shown(false);
- if let Some(window_size) = AppSizeHandler::default().get_app_size() {
+ if let Some(window_size) = AppSizeHandler::new(&paths).get_app_size() {
builder.with_inner_size(window_size)
} else {
builder
}
- })
+ });
+
+ eframe::NativeOptions {
+ window_builder: Some(window_builder),
+ ..Default::default()
+ }
}
fn generate_native_options_with_builder_modifiers(
diff --git a/src/app_size_handler.rs b/src/app_size_handler.rs
@@ -1,15 +1,12 @@
use std::time::{Duration, Instant};
use egui::Context;
-use tracing::{error, info};
+use tracing::info;
-use crate::{
- storage::{write_file, Directory},
- DataPaths,
-};
+use crate::storage::{write_file, DataPath, DataPathType, Directory};
pub struct AppSizeHandler {
- directory: Option<Directory>,
+ directory: Directory,
saved_size: Option<egui::Vec2>,
last_saved: Instant,
}
@@ -17,15 +14,9 @@ pub struct AppSizeHandler {
static FILE_NAME: &str = "app_size.json";
static DELAY: Duration = Duration::from_millis(500);
-impl Default for AppSizeHandler {
- fn default() -> Self {
- let directory = match DataPaths::Setting.get_path() {
- Ok(path) => Some(Directory::new(path)),
- Err(e) => {
- error!("Could not load settings path: {}", e);
- None
- }
- };
+impl AppSizeHandler {
+ pub fn new(path: &DataPath) -> Self {
+ let directory = Directory::new(path.path(DataPathType::Setting));
Self {
directory,
@@ -33,16 +24,12 @@ impl Default for AppSizeHandler {
last_saved: Instant::now() - DELAY,
}
}
-}
-impl AppSizeHandler {
pub fn try_save_app_size(&mut self, ctx: &Context) {
- if let Some(interactor) = &self.directory {
- // There doesn't seem to be a way to check if user is resizing window, so if the rect is different than last saved, we'll wait DELAY before saving again to avoid spamming io
- if self.last_saved.elapsed() >= DELAY {
- internal_try_save_app_size(interactor, &mut self.saved_size, ctx);
- self.last_saved = Instant::now();
- }
+ // There doesn't seem to be a way to check if user is resizing window, so if the rect is different than last saved, we'll wait DELAY before saving again to avoid spamming io
+ if self.last_saved.elapsed() >= DELAY {
+ internal_try_save_app_size(&self.directory, &mut self.saved_size, ctx);
+ self.last_saved = Instant::now();
}
}
@@ -51,14 +38,12 @@ impl AppSizeHandler {
return self.saved_size;
}
- if let Some(directory) = &self.directory {
- if let Ok(file_contents) = directory.get_file(FILE_NAME.to_owned()) {
- if let Ok(rect) = serde_json::from_str::<egui::Vec2>(&file_contents) {
- return Some(rect);
- }
- } else {
- info!("Could not find {}", FILE_NAME);
+ if let Ok(file_contents) = self.directory.get_file(FILE_NAME.to_owned()) {
+ if let Ok(rect) = serde_json::from_str::<egui::Vec2>(&file_contents) {
+ return Some(rect);
}
+ } else {
+ info!("Could not find {}", FILE_NAME);
}
None
diff --git a/src/bin/notedeck.rs b/src/bin/notedeck.rs
@@ -1,7 +1,12 @@
#![warn(clippy::all, rust_2018_idioms)]
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
-use notedeck::app_creation::generate_native_options;
-use notedeck::Damus;
+use notedeck::{
+ app_creation::generate_native_options,
+ storage::{DataPath, DataPathType},
+ Damus,
+};
+use std::{path::PathBuf, str::FromStr};
+
use tracing_subscriber::EnvFilter;
// Entry point for wasm
@@ -12,34 +17,35 @@ use tracing_subscriber::EnvFilter;
#[cfg(not(target_arch = "wasm32"))]
#[tokio::main]
async fn main() {
+ let base_path = DataPath::default_base().unwrap_or(PathBuf::from_str(".").unwrap());
+ let path = DataPath::new(&base_path);
+
#[allow(unused_variables)] // need guard to live for lifetime of program
- let (maybe_non_blocking, maybe_guard) =
- if let Ok(log_path) = notedeck::DataPaths::Log.get_path() {
- // Setup logging to file
- use std::panic;
-
- use tracing::error;
- use tracing_appender::{
- non_blocking,
- rolling::{RollingFileAppender, Rotation},
- };
-
- let file_appender = RollingFileAppender::new(
- Rotation::DAILY,
- log_path,
- format!("notedeck-{}.log", env!("CARGO_PKG_VERSION")),
- );
- panic::set_hook(Box::new(|panic_info| {
- error!("Notedeck panicked: {:?}", panic_info);
- }));
-
- let (non_blocking, _guard) = non_blocking(file_appender);
-
- (Some(non_blocking), Some(_guard))
- } else {
- (None, None)
+ let (maybe_non_blocking, maybe_guard) = {
+ let log_path = path.path(DataPathType::Log);
+ // Setup logging to file
+ use std::panic;
+
+ use tracing::error;
+ use tracing_appender::{
+ non_blocking,
+ rolling::{RollingFileAppender, Rotation},
};
+ let file_appender = RollingFileAppender::new(
+ Rotation::DAILY,
+ log_path,
+ format!("notedeck-{}.log", env!("CARGO_PKG_VERSION")),
+ );
+ panic::set_hook(Box::new(|panic_info| {
+ error!("Notedeck panicked: {:?}", panic_info);
+ }));
+
+ let (non_blocking, _guard) = non_blocking(file_appender);
+
+ (Some(non_blocking), Some(_guard))
+ };
+
// Log to stdout (if you run with `RUST_LOG=debug`).
if let Some(non_blocking_writer) = maybe_non_blocking {
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};
@@ -68,8 +74,14 @@ async fn main() {
let _res = eframe::run_native(
"Damus NoteDeck",
- generate_native_options(),
- Box::new(|cc| Ok(Box::new(Damus::new(cc, ".", std::env::args().collect())))),
+ generate_native_options(path),
+ Box::new(|cc| {
+ Ok(Box::new(Damus::new(
+ cc,
+ base_path,
+ std::env::args().collect(),
+ )))
+ }),
);
}
diff --git a/src/imgcache.rs b/src/imgcache.rs
@@ -25,8 +25,8 @@ impl ImageCache {
}
}
- pub fn rel_datadir() -> &'static str {
- "cache/img"
+ pub fn rel_dir() -> &'static str {
+ "img"
}
pub fn write(cache_dir: &path::Path, url: &str, data: ColorImage) -> Result<()> {
diff --git a/src/lib.rs b/src/lib.rs
@@ -46,12 +46,11 @@ mod view_state;
#[macro_use]
mod test_utils;
-mod storage;
+pub mod storage;
pub use app::Damus;
pub use error::Error;
pub use profile::DisplayName;
-pub use storage::DataPaths;
#[cfg(target_os = "android")]
use winit::platform::android::EventLoopBuilderExtAndroid;
diff --git a/src/storage/file_storage.rs b/src/storage/file_storage.rs
@@ -8,33 +8,45 @@ use std::{
use crate::Error;
-pub enum DataPaths {
+#[derive(Debug, Clone)]
+pub struct DataPath {
+ base: PathBuf,
+}
+
+impl DataPath {
+ pub fn new(base: impl AsRef<Path>) -> Self {
+ let base = base.as_ref().to_path_buf();
+ Self { base }
+ }
+
+ pub fn default_base() -> Option<PathBuf> {
+ dirs::data_local_dir().map(|pb| pb.join("notedeck"))
+ }
+}
+
+pub enum DataPathType {
Log,
Setting,
Keys,
SelectedKey,
+ Db,
+ Cache,
}
-impl DataPaths {
- pub fn get_path(&self) -> Result<PathBuf, Error> {
- let base_path = match self {
- DataPaths::Log => dirs::data_local_dir(),
- DataPaths::Setting | DataPaths::Keys | DataPaths::SelectedKey => {
- dirs::config_local_dir()
- }
+impl DataPath {
+ pub fn rel_path(&self, typ: DataPathType) -> PathBuf {
+ match typ {
+ DataPathType::Log => PathBuf::from("logs"),
+ DataPathType::Setting => PathBuf::from("settings"),
+ DataPathType::Keys => PathBuf::from("storage").join("accounts"),
+ DataPathType::SelectedKey => PathBuf::from("storage").join("selected_account"),
+ DataPathType::Db => PathBuf::from("db"),
+ DataPathType::Cache => PathBuf::from("cache"),
}
- .ok_or(Error::Generic(
- "Could not open well known OS directory".to_owned(),
- ))?;
-
- let specific_path = match self {
- DataPaths::Log => PathBuf::from("logs"),
- DataPaths::Setting => PathBuf::from("settings"),
- DataPaths::Keys => PathBuf::from("storage").join("accounts"),
- DataPaths::SelectedKey => PathBuf::from("storage").join("selected_account"),
- };
-
- Ok(base_path.join("notedeck").join(specific_path))
+ }
+
+ pub fn path(&self, typ: DataPathType) -> PathBuf {
+ self.base.join(self.rel_path(typ))
}
}
diff --git a/src/storage/mod.rs b/src/storage/mod.rs
@@ -3,8 +3,8 @@ mod file_storage;
pub use file_key_storage::FileKeyStorage;
pub use file_storage::write_file;
-pub use file_storage::DataPaths;
pub use file_storage::Directory;
+pub use file_storage::{DataPath, DataPathType};
#[cfg(target_os = "macos")]
mod security_framework_key_storage;
diff --git a/src/support.rs b/src/support.rs
@@ -1,26 +1,20 @@
use tracing::error;
-use crate::{storage::Directory, DataPaths};
+use crate::storage::{DataPath, DataPathType, Directory};
pub struct Support {
- directory: Option<Directory>,
+ directory: Directory,
mailto_url: String,
most_recent_log: Option<String>,
}
-fn new_log_dir() -> Option<Directory> {
- match DataPaths::Log.get_path() {
- Ok(path) => Some(Directory::new(path)),
- Err(e) => {
- error!("Support could not open directory: {}", e.to_string());
- None
- }
- }
+fn new_log_dir(paths: &DataPath) -> Directory {
+ Directory::new(paths.path(DataPathType::Log))
}
-impl Default for Support {
- fn default() -> Self {
- let directory = new_log_dir();
+impl Support {
+ pub fn new(path: &DataPath) -> Self {
+ let directory = new_log_dir(path);
Self {
mailto_url: MailtoBuilder::new(SUPPORT_EMAIL.to_string())
@@ -39,11 +33,7 @@ static EMAIL_TEMPLATE: &str = "Describe the bug you have encountered:\n<-- your
impl Support {
pub fn refresh(&mut self) {
- if let Some(directory) = &self.directory {
- self.most_recent_log = get_log_str(directory);
- } else {
- self.directory = new_log_dir();
- }
+ self.most_recent_log = get_log_str(&self.directory);
}
pub fn get_mailto_url(&self) -> &str {
@@ -51,7 +41,7 @@ impl Support {
}
pub fn get_log_dir(&self) -> Option<&str> {
- self.directory.as_ref()?.file_path.to_str()
+ self.directory.file_path.to_str()
}
pub fn get_most_recent_log(&self) -> Option<&String> {
diff --git a/src/ui/profile/preview.rs b/src/ui/profile/preview.rs
@@ -1,5 +1,6 @@
use crate::app_style::NotedeckTextStyle;
use crate::imgcache::ImageCache;
+use crate::storage::{DataPath, DataPathType};
use crate::ui::ProfilePic;
use crate::user_account::UserAccount;
use crate::{colors, images, DisplayName};
@@ -126,7 +127,10 @@ mod previews {
impl<'a> ProfilePreviewPreview<'a> {
pub fn new() -> Self {
let profile = test_profile_record();
- let cache = ImageCache::new(ImageCache::rel_datadir().into());
+ let path = DataPath::new("previews")
+ .path(DataPathType::Cache)
+ .join(ImageCache::rel_dir());
+ let cache = ImageCache::new(path);
ProfilePreviewPreview { profile, cache }
}
}
diff --git a/src/ui_preview/main.rs b/src/ui_preview/main.rs
@@ -1,10 +1,11 @@
-use notedeck::app_creation::{
- generate_mobile_emulator_native_options, generate_native_options, setup_cc,
-};
-use notedeck::ui::add_column::AddColumnView;
use notedeck::ui::{
- account_login_view::AccountLoginView, account_management::AccountsView, DesktopSidePanel,
- PostView, Preview, PreviewApp, PreviewConfig, ProfilePic, ProfilePreview, RelayView,
+ account_login_view::AccountLoginView, account_management::AccountsView,
+ add_column::AddColumnView, DesktopSidePanel, PostView, Preview, PreviewApp, PreviewConfig,
+ ProfilePic, ProfilePreview, RelayView,
+};
+use notedeck::{
+ app_creation::{generate_mobile_emulator_native_options, generate_native_options, setup_cc},
+ storage::DataPath,
};
use std::env;
@@ -30,7 +31,8 @@ impl PreviewRunner {
let native_options = if self.force_mobile {
generate_mobile_emulator_native_options()
} else {
- generate_native_options()
+ // TODO: tmp preview pathbuf?
+ generate_native_options(DataPath::new("previews"))
};
let is_mobile = self.force_mobile;