treewide: fix various UI bugs; optimize crypto dependencies & format
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: If8fe8b38c1d9c4fecd40ff71f88d2ae06a6a6964
This commit is contained in:
parent
764aafa88d
commit
3ccddce7fd
178 changed files with 58285 additions and 54241 deletions
|
|
@ -1,217 +1,218 @@
|
|||
use axum::Json;
|
||||
use axum::extract::State;
|
||||
use axum::{Json, extract::State};
|
||||
|
||||
use crate::dto::*;
|
||||
use crate::error::ApiError;
|
||||
use crate::state::AppState;
|
||||
use crate::{dto::*, error::ApiError, state::AppState};
|
||||
|
||||
pub async fn get_config(State(state): State<AppState>) -> Result<Json<ConfigResponse>, ApiError> {
|
||||
let config = state.config.read().await;
|
||||
let roots = state.storage.list_root_dirs().await?;
|
||||
pub async fn get_config(
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Json<ConfigResponse>, ApiError> {
|
||||
let config = state.config.read().await;
|
||||
let roots = state.storage.list_root_dirs().await?;
|
||||
|
||||
let config_path = state
|
||||
.config_path
|
||||
.as_ref()
|
||||
.map(|p| p.to_string_lossy().to_string());
|
||||
let config_writable = match &state.config_path {
|
||||
Some(path) => {
|
||||
if path.exists() {
|
||||
std::fs::metadata(path)
|
||||
.map(|m| !m.permissions().readonly())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
path.parent()
|
||||
.map(|parent| {
|
||||
std::fs::metadata(parent)
|
||||
.map(|m| !m.permissions().readonly())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
};
|
||||
let config_path = state
|
||||
.config_path
|
||||
.as_ref()
|
||||
.map(|p| p.to_string_lossy().to_string());
|
||||
let config_writable = match &state.config_path {
|
||||
Some(path) => {
|
||||
if path.exists() {
|
||||
std::fs::metadata(path)
|
||||
.map(|m| !m.permissions().readonly())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
path
|
||||
.parent()
|
||||
.map(|parent| {
|
||||
std::fs::metadata(parent)
|
||||
.map(|m| !m.permissions().readonly())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
},
|
||||
None => false,
|
||||
};
|
||||
|
||||
Ok(Json(ConfigResponse {
|
||||
backend: format!("{:?}", config.storage.backend).to_lowercase(),
|
||||
database_path: config
|
||||
.storage
|
||||
.sqlite
|
||||
.as_ref()
|
||||
.map(|s| s.path.to_string_lossy().to_string()),
|
||||
roots: roots
|
||||
.iter()
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.collect(),
|
||||
scanning: ScanningConfigResponse {
|
||||
watch: config.scanning.watch,
|
||||
poll_interval_secs: config.scanning.poll_interval_secs,
|
||||
ignore_patterns: config.scanning.ignore_patterns.clone(),
|
||||
},
|
||||
server: ServerConfigResponse {
|
||||
host: config.server.host.clone(),
|
||||
port: config.server.port,
|
||||
},
|
||||
ui: UiConfigResponse::from(&config.ui),
|
||||
config_path,
|
||||
config_writable,
|
||||
}))
|
||||
Ok(Json(ConfigResponse {
|
||||
backend: format!("{:?}", config.storage.backend).to_lowercase(),
|
||||
database_path: config
|
||||
.storage
|
||||
.sqlite
|
||||
.as_ref()
|
||||
.map(|s| s.path.to_string_lossy().to_string()),
|
||||
roots: roots
|
||||
.iter()
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.collect(),
|
||||
scanning: ScanningConfigResponse {
|
||||
watch: config.scanning.watch,
|
||||
poll_interval_secs: config.scanning.poll_interval_secs,
|
||||
ignore_patterns: config.scanning.ignore_patterns.clone(),
|
||||
},
|
||||
server: ServerConfigResponse {
|
||||
host: config.server.host.clone(),
|
||||
port: config.server.port,
|
||||
},
|
||||
ui: UiConfigResponse::from(&config.ui),
|
||||
config_path,
|
||||
config_writable,
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn get_ui_config(
|
||||
State(state): State<AppState>,
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Json<UiConfigResponse>, ApiError> {
|
||||
let config = state.config.read().await;
|
||||
Ok(Json(UiConfigResponse::from(&config.ui)))
|
||||
let config = state.config.read().await;
|
||||
Ok(Json(UiConfigResponse::from(&config.ui)))
|
||||
}
|
||||
|
||||
pub async fn update_ui_config(
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<UpdateUiConfigRequest>,
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<UpdateUiConfigRequest>,
|
||||
) -> Result<Json<UiConfigResponse>, ApiError> {
|
||||
let mut config = state.config.write().await;
|
||||
if let Some(theme) = req.theme {
|
||||
config.ui.theme = theme;
|
||||
}
|
||||
if let Some(default_view) = req.default_view {
|
||||
config.ui.default_view = default_view;
|
||||
}
|
||||
if let Some(default_page_size) = req.default_page_size {
|
||||
config.ui.default_page_size = default_page_size;
|
||||
}
|
||||
if let Some(default_view_mode) = req.default_view_mode {
|
||||
config.ui.default_view_mode = default_view_mode;
|
||||
}
|
||||
if let Some(auto_play) = req.auto_play_media {
|
||||
config.ui.auto_play_media = auto_play;
|
||||
}
|
||||
if let Some(show_thumbs) = req.show_thumbnails {
|
||||
config.ui.show_thumbnails = show_thumbs;
|
||||
}
|
||||
if let Some(collapsed) = req.sidebar_collapsed {
|
||||
config.ui.sidebar_collapsed = collapsed;
|
||||
}
|
||||
let mut config = state.config.write().await;
|
||||
if let Some(theme) = req.theme {
|
||||
config.ui.theme = theme;
|
||||
}
|
||||
if let Some(default_view) = req.default_view {
|
||||
config.ui.default_view = default_view;
|
||||
}
|
||||
if let Some(default_page_size) = req.default_page_size {
|
||||
config.ui.default_page_size = default_page_size;
|
||||
}
|
||||
if let Some(default_view_mode) = req.default_view_mode {
|
||||
config.ui.default_view_mode = default_view_mode;
|
||||
}
|
||||
if let Some(auto_play) = req.auto_play_media {
|
||||
config.ui.auto_play_media = auto_play;
|
||||
}
|
||||
if let Some(show_thumbs) = req.show_thumbnails {
|
||||
config.ui.show_thumbnails = show_thumbs;
|
||||
}
|
||||
if let Some(collapsed) = req.sidebar_collapsed {
|
||||
config.ui.sidebar_collapsed = collapsed;
|
||||
}
|
||||
|
||||
if let Some(ref path) = state.config_path {
|
||||
config.save_to_file(path).map_err(ApiError)?;
|
||||
}
|
||||
if let Some(ref path) = state.config_path {
|
||||
config.save_to_file(path).map_err(ApiError)?;
|
||||
}
|
||||
|
||||
Ok(Json(UiConfigResponse::from(&config.ui)))
|
||||
Ok(Json(UiConfigResponse::from(&config.ui)))
|
||||
}
|
||||
|
||||
pub async fn update_scanning_config(
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<UpdateScanningRequest>,
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<UpdateScanningRequest>,
|
||||
) -> Result<Json<ConfigResponse>, ApiError> {
|
||||
let mut config = state.config.write().await;
|
||||
if let Some(watch) = req.watch {
|
||||
config.scanning.watch = watch;
|
||||
}
|
||||
if let Some(interval) = req.poll_interval_secs {
|
||||
config.scanning.poll_interval_secs = interval;
|
||||
}
|
||||
if let Some(patterns) = req.ignore_patterns {
|
||||
config.scanning.ignore_patterns = patterns;
|
||||
}
|
||||
let mut config = state.config.write().await;
|
||||
if let Some(watch) = req.watch {
|
||||
config.scanning.watch = watch;
|
||||
}
|
||||
if let Some(interval) = req.poll_interval_secs {
|
||||
config.scanning.poll_interval_secs = interval;
|
||||
}
|
||||
if let Some(patterns) = req.ignore_patterns {
|
||||
config.scanning.ignore_patterns = patterns;
|
||||
}
|
||||
|
||||
// Persist to disk if we have a config path
|
||||
if let Some(ref path) = state.config_path {
|
||||
config.save_to_file(path).map_err(ApiError)?;
|
||||
}
|
||||
// Persist to disk if we have a config path
|
||||
if let Some(ref path) = state.config_path {
|
||||
config.save_to_file(path).map_err(ApiError)?;
|
||||
}
|
||||
|
||||
let roots = state.storage.list_root_dirs().await?;
|
||||
let roots = state.storage.list_root_dirs().await?;
|
||||
|
||||
let config_path = state
|
||||
.config_path
|
||||
.as_ref()
|
||||
.map(|p| p.to_string_lossy().to_string());
|
||||
let config_writable = match &state.config_path {
|
||||
Some(path) => {
|
||||
if path.exists() {
|
||||
std::fs::metadata(path)
|
||||
.map(|m| !m.permissions().readonly())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
path.parent()
|
||||
.map(|parent| {
|
||||
std::fs::metadata(parent)
|
||||
.map(|m| !m.permissions().readonly())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
};
|
||||
let config_path = state
|
||||
.config_path
|
||||
.as_ref()
|
||||
.map(|p| p.to_string_lossy().to_string());
|
||||
let config_writable = match &state.config_path {
|
||||
Some(path) => {
|
||||
if path.exists() {
|
||||
std::fs::metadata(path)
|
||||
.map(|m| !m.permissions().readonly())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
path
|
||||
.parent()
|
||||
.map(|parent| {
|
||||
std::fs::metadata(parent)
|
||||
.map(|m| !m.permissions().readonly())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
},
|
||||
None => false,
|
||||
};
|
||||
|
||||
Ok(Json(ConfigResponse {
|
||||
backend: format!("{:?}", config.storage.backend).to_lowercase(),
|
||||
database_path: config
|
||||
.storage
|
||||
.sqlite
|
||||
.as_ref()
|
||||
.map(|s| s.path.to_string_lossy().to_string()),
|
||||
roots: roots
|
||||
.iter()
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.collect(),
|
||||
scanning: ScanningConfigResponse {
|
||||
watch: config.scanning.watch,
|
||||
poll_interval_secs: config.scanning.poll_interval_secs,
|
||||
ignore_patterns: config.scanning.ignore_patterns.clone(),
|
||||
},
|
||||
server: ServerConfigResponse {
|
||||
host: config.server.host.clone(),
|
||||
port: config.server.port,
|
||||
},
|
||||
ui: UiConfigResponse::from(&config.ui),
|
||||
config_path,
|
||||
config_writable,
|
||||
}))
|
||||
Ok(Json(ConfigResponse {
|
||||
backend: format!("{:?}", config.storage.backend).to_lowercase(),
|
||||
database_path: config
|
||||
.storage
|
||||
.sqlite
|
||||
.as_ref()
|
||||
.map(|s| s.path.to_string_lossy().to_string()),
|
||||
roots: roots
|
||||
.iter()
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.collect(),
|
||||
scanning: ScanningConfigResponse {
|
||||
watch: config.scanning.watch,
|
||||
poll_interval_secs: config.scanning.poll_interval_secs,
|
||||
ignore_patterns: config.scanning.ignore_patterns.clone(),
|
||||
},
|
||||
server: ServerConfigResponse {
|
||||
host: config.server.host.clone(),
|
||||
port: config.server.port,
|
||||
},
|
||||
ui: UiConfigResponse::from(&config.ui),
|
||||
config_path,
|
||||
config_writable,
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn add_root(
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<RootDirRequest>,
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<RootDirRequest>,
|
||||
) -> Result<Json<ConfigResponse>, ApiError> {
|
||||
let path = std::path::PathBuf::from(&req.path);
|
||||
let path = std::path::PathBuf::from(&req.path);
|
||||
|
||||
if !path.exists() {
|
||||
return Err(ApiError(pinakes_core::error::PinakesError::FileNotFound(
|
||||
path,
|
||||
)));
|
||||
if !path.exists() {
|
||||
return Err(ApiError(pinakes_core::error::PinakesError::FileNotFound(
|
||||
path,
|
||||
)));
|
||||
}
|
||||
|
||||
state.storage.add_root_dir(path.clone()).await?;
|
||||
|
||||
{
|
||||
let mut config = state.config.write().await;
|
||||
if !config.directories.roots.contains(&path) {
|
||||
config.directories.roots.push(path);
|
||||
}
|
||||
|
||||
state.storage.add_root_dir(path.clone()).await?;
|
||||
|
||||
{
|
||||
let mut config = state.config.write().await;
|
||||
if !config.directories.roots.contains(&path) {
|
||||
config.directories.roots.push(path);
|
||||
}
|
||||
if let Some(ref config_path) = state.config_path {
|
||||
config.save_to_file(config_path).map_err(ApiError)?;
|
||||
}
|
||||
if let Some(ref config_path) = state.config_path {
|
||||
config.save_to_file(config_path).map_err(ApiError)?;
|
||||
}
|
||||
}
|
||||
|
||||
get_config(State(state)).await
|
||||
get_config(State(state)).await
|
||||
}
|
||||
|
||||
pub async fn remove_root(
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<RootDirRequest>,
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<RootDirRequest>,
|
||||
) -> Result<Json<ConfigResponse>, ApiError> {
|
||||
let path = std::path::PathBuf::from(&req.path);
|
||||
let path = std::path::PathBuf::from(&req.path);
|
||||
|
||||
state.storage.remove_root_dir(&path).await?;
|
||||
state.storage.remove_root_dir(&path).await?;
|
||||
|
||||
{
|
||||
let mut config = state.config.write().await;
|
||||
config.directories.roots.retain(|r| r != &path);
|
||||
if let Some(ref config_path) = state.config_path {
|
||||
config.save_to_file(config_path).map_err(ApiError)?;
|
||||
}
|
||||
{
|
||||
let mut config = state.config.write().await;
|
||||
config.directories.roots.retain(|r| r != &path);
|
||||
if let Some(ref config_path) = state.config_path {
|
||||
config.save_to_file(config_path).map_err(ApiError)?;
|
||||
}
|
||||
}
|
||||
|
||||
get_config(State(state)).await
|
||||
get_config(State(state)).await
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue