generated from PlexSheep/rs-base
fix(store): store is now actually saved and loaded
cargo devel CI / cargo CI (push) Successful in 3m14s
Details
cargo devel CI / cargo CI (push) Successful in 3m14s
Details
This commit is contained in:
parent
cc0bc95ba2
commit
6a5cbcdbea
|
@ -19,6 +19,7 @@ backend-jellyfin = []
|
|||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
clap = { version = "4.5.16", features = ["derive"] }
|
||||
directories = "5.0.1"
|
||||
eframe = { version = "0.28.1", optional = false }
|
||||
egui = { version = "0.28.1", optional = false }
|
||||
egui_extras = { version = "0.28.1", features = ["image"] }
|
||||
|
@ -29,6 +30,7 @@ image = { version = "0.25.2", default-features = true, features = [
|
|||
] }
|
||||
|
||||
libpt = { version = "0.6.0", features = ["cli", "full"] }
|
||||
rmp-serde = "1.3.0"
|
||||
serde = { version = "1.0.208", features = ["derive"] }
|
||||
strum = { version = "0.26.3", features = ["derive"] }
|
||||
thiserror = "1.0.63"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
@ -6,4 +8,21 @@ pub enum Error {
|
|||
UiError(#[from] eframe::Error),
|
||||
#[error(transparent)]
|
||||
Other(#[from] anyhow::Error),
|
||||
#[error(
|
||||
r"The system does not seem to have the usual project dirs, like:
|
||||
Linux: /home/alice/.config/barapp
|
||||
MS Windows: C:\Users\Alice\AppData\Roaming\Foo Corp\Bar App\config
|
||||
Mac: /Users/Alice/Library/Application Support/com.Foo-Corp.Bar-App
|
||||
|
||||
Closing as to not break your files accidentally."
|
||||
)]
|
||||
NoProjDir,
|
||||
#[error(r"The store file '{0}' where Beatbär stores it's metadata is not a regular file, refusing to save or load to keep your files safe.")]
|
||||
BadStoreFile(PathBuf),
|
||||
#[error(r"Could not convert the store to the binary format for saving it to the disk.")]
|
||||
RmpEncode(#[from] rmp_serde::encode::Error),
|
||||
#[error(r"Could not decode the store from the binary format for loading it from the disk. Is your store file broken?")]
|
||||
RmpDecode(#[from] rmp_serde::decode::Error),
|
||||
#[error(r"Error while reading or writing to the disk. Source: {0}")]
|
||||
IO(#[from] std::io::Error),
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use clap::Parser;
|
||||
use eframe::CreationContext;
|
||||
use egui::Stroke;
|
||||
use libpt::cli::args::VerbosityLevel;
|
||||
use libpt::log::{debug, info};
|
||||
|
||||
|
@ -27,10 +28,15 @@ pub struct Player {
|
|||
kind: Kind,
|
||||
|
||||
#[clap(skip)]
|
||||
store: Store,
|
||||
store: Option<Store>,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
#[inline]
|
||||
pub fn store(&self) -> &Store {
|
||||
&self.store.as_ref().unwrap()
|
||||
}
|
||||
|
||||
pub fn build() -> Result<Self, Error> {
|
||||
let mut app = Player::parse();
|
||||
|
||||
|
@ -63,7 +69,7 @@ impl Player {
|
|||
Ok(app)
|
||||
}
|
||||
pub fn init(&mut self, _cc: &CreationContext) {
|
||||
// we can use the creation context to do some customizing, but idc right now
|
||||
self.store = Some(Store::load().expect("could not load store"));
|
||||
}
|
||||
|
||||
fn set_category(&mut self, kind: Kind) {
|
||||
|
@ -80,11 +86,15 @@ impl Player {
|
|||
|
||||
fn entries(&self) -> Vec<Entry> {
|
||||
match self.category() {
|
||||
Kind::Album => self.store.albums(),
|
||||
Kind::Song => self.store.songs(),
|
||||
Kind::Playlist => self.store.playlists(),
|
||||
Kind::Artist => self.store.artists(),
|
||||
Kind::Genre => self.store.genres(),
|
||||
Kind::Album => self.store().albums(),
|
||||
Kind::Song => self.store().songs(),
|
||||
Kind::Playlist => self.store().playlists(),
|
||||
Kind::Artist => self.store().artists(),
|
||||
Kind::Genre => self.store().genres(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end(&mut self) -> Result<(), Error> {
|
||||
self.store().save()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use egui::{IconData, Sense};
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
use libpt::log::{trace, warn};
|
||||
use libpt::log::{error, trace, warn};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
pub mod entry;
|
||||
|
@ -174,4 +174,12 @@ impl eframe::App for Player {
|
|||
});
|
||||
egui::TopBottomPanel::bottom("bot_panel").show(ctx, Self::bottom_label);
|
||||
}
|
||||
fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) {
|
||||
match self.store().save() {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
error!("{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,104 @@
|
|||
#[derive(Default)]
|
||||
pub struct Store {}
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Write};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use libpt::log::{debug, error, info, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||
pub struct Store {
|
||||
dummy: String,
|
||||
}
|
||||
|
||||
impl Store {
|
||||
pub fn projdir() -> Option<directories::ProjectDirs> {
|
||||
directories::ProjectDirs::from("de.cscherr", "Beatbär", "Beatbär")
|
||||
}
|
||||
|
||||
pub fn genres(&self) -> Vec<crate::player::ui::entry::Entry> {
|
||||
todo!()
|
||||
vec![]
|
||||
}
|
||||
|
||||
pub fn artists(&self) -> Vec<crate::player::ui::entry::Entry> {
|
||||
todo!()
|
||||
vec![]
|
||||
}
|
||||
|
||||
pub fn playlists(&self) -> Vec<crate::player::ui::entry::Entry> {
|
||||
todo!()
|
||||
vec![]
|
||||
}
|
||||
|
||||
pub fn songs(&self) -> Vec<crate::player::ui::entry::Entry> {
|
||||
todo!()
|
||||
vec![]
|
||||
}
|
||||
|
||||
pub fn albums(&self) -> Vec<crate::player::ui::entry::Entry> {
|
||||
todo!()
|
||||
vec![]
|
||||
}
|
||||
|
||||
pub fn save(&self) -> Result<(), Error> {
|
||||
info!("saving the store to file");
|
||||
debug!("Store: {self:#?}");
|
||||
if let Some(dirs) = Self::projdir() {
|
||||
let mut store_path: PathBuf = dirs.data_local_dir().into();
|
||||
store_path.push("store.msgpack");
|
||||
|
||||
if !store_path.exists() {
|
||||
std::fs::create_dir_all(
|
||||
store_path
|
||||
.parent()
|
||||
.expect("beatbär storefile has no parent????"),
|
||||
)?;
|
||||
warn!("The Beatbär store at '{}' does not exist. Creating it anew. This is normal if you start Beatbär for the first time.", store_path.as_path().to_string_lossy());
|
||||
} else if !store_path.is_file() {
|
||||
let e = Error::BadStoreFile(store_path);
|
||||
error!("{e}");
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
let mut file = File::options()
|
||||
.write(true)
|
||||
.append(false)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(store_path)?;
|
||||
let repr = rmp_serde::to_vec(self)?;
|
||||
file.write_all(&repr)?;
|
||||
info!("store file was written");
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::NoProjDir)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load() -> Result<Self, Error> {
|
||||
info!("loading the store to file");
|
||||
if let Some(dirs) = Self::projdir() {
|
||||
let mut store_path: PathBuf = dirs.data_local_dir().into();
|
||||
store_path.push("store.msgpack");
|
||||
|
||||
if !store_path.exists() {
|
||||
warn!(
|
||||
"The Beatbär store at '{}' does not exist. Loading an empty store instead.",
|
||||
store_path.as_path().to_string_lossy()
|
||||
);
|
||||
return Ok(Self::default());
|
||||
} else if !store_path.is_file() {
|
||||
let e = Error::BadStoreFile(store_path);
|
||||
error!("{e}");
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
let file = File::options().read(true).write(false).open(store_path)?;
|
||||
let store = rmp_serde::from_read(file)?;
|
||||
info!("store file was loaded");
|
||||
debug!("Store: {store:#?}");
|
||||
Ok(store)
|
||||
} else {
|
||||
let e = Error::NoProjDir;
|
||||
error!("{}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue