treewide: fix various UI bugs; optimize crypto dependencies & format

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: If8fe8b38c1d9c4fecd40ff71f88d2ae06a6a6964
This commit is contained in:
raf 2026-02-10 12:56:05 +03:00
commit 3ccddce7fd
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
178 changed files with 58342 additions and 54241 deletions

View file

@ -1,7 +1,15 @@
use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::{
FaChartBar, FaCircle, FaClock, FaDatabase, FaFolder, FaLink, FaTags,
use dioxus_free_icons::{
Icon,
icons::fa_solid_icons::{
FaChartBar,
FaCircle,
FaClock,
FaDatabase,
FaFolder,
FaLink,
FaTags,
},
};
use super::utils::format_size;
@ -9,262 +17,262 @@ use crate::client::LibraryStatisticsResponse;
#[component]
pub fn Statistics(
stats: Option<LibraryStatisticsResponse>,
#[props(default)] error: Option<String>,
on_refresh: EventHandler<()>,
stats: Option<LibraryStatisticsResponse>,
#[props(default)] error: Option<String>,
on_refresh: EventHandler<()>,
) -> Element {
rsx! {
div { class: "statistics-page",
div { class: "card",
div { class: "card-header",
h3 { class: "card-title", "Library Statistics" }
button {
class: "btn btn-sm btn-secondary",
onclick: move |_| on_refresh.call(()),
"\u{21bb} Refresh"
}
}
rsx! {
div { class: "statistics-page",
div { class: "card",
div { class: "card-header",
h3 { class: "card-title", "Library Statistics" }
button {
class: "btn btn-sm btn-secondary",
onclick: move |_| on_refresh.call(()),
"\u{21bb} Refresh"
}
}
if let Some(ref err) = error {
div { class: "alert alert-error mb-8",
span { "{err}" }
button {
class: "btn btn-sm btn-secondary ml-8",
onclick: move |_| on_refresh.call(()),
"Retry"
}
}
}
if let Some(ref err) = error {
div { class: "alert alert-error mb-8",
span { "{err}" }
button {
class: "btn btn-sm btn-secondary ml-8",
onclick: move |_| on_refresh.call(()),
"Retry"
}
}
}
match stats.as_ref() {
Some(s) => {
let total_size = format_size(s.total_size_bytes);
let avg_size = format_size(s.avg_file_size_bytes);
rsx! {
div { class: "stats-overview",
div { class: "stat-card stat-primary",
div { class: "stat-icon",
Icon { icon: FaFolder, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{s.total_media}" }
div { class: "stat-label", "Total Media" }
}
}
div { class: "stat-card stat-success",
div { class: "stat-icon",
Icon { icon: FaDatabase, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{total_size}" }
div { class: "stat-label", "Total Size" }
}
}
div { class: "stat-card stat-info",
div { class: "stat-icon",
Icon { icon: FaChartBar, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{avg_size}" }
div { class: "stat-label", "Average Size" }
}
}
div { class: "stat-card stat-warning",
div { class: "stat-icon",
Icon { icon: FaTags, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{s.total_tags}" }
div { class: "stat-label", "Tags" }
}
}
div { class: "stat-card stat-purple",
div { class: "stat-icon",
Icon { icon: FaCircle, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{s.total_collections}" }
div { class: "stat-label", "Collections" }
}
}
div { class: "stat-card stat-danger",
div { class: "stat-icon",
Icon { icon: FaLink, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{s.total_duplicates}" }
div { class: "stat-label", "Duplicates" }
}
}
}
match stats.as_ref() {
Some(s) => {
let total_size = format_size(s.total_size_bytes);
let avg_size = format_size(s.avg_file_size_bytes);
rsx! {
div { class: "stats-overview",
div { class: "stat-card stat-primary",
div { class: "stat-icon",
Icon { icon: FaFolder, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{s.total_media}" }
div { class: "stat-label", "Total Media" }
}
}
div { class: "stat-card stat-success",
div { class: "stat-icon",
Icon { icon: FaDatabase, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{total_size}" }
div { class: "stat-label", "Total Size" }
}
}
div { class: "stat-card stat-info",
div { class: "stat-icon",
Icon { icon: FaChartBar, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{avg_size}" }
div { class: "stat-label", "Average Size" }
}
}
div { class: "stat-card stat-warning",
div { class: "stat-icon",
Icon { icon: FaTags, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{s.total_tags}" }
div { class: "stat-label", "Tags" }
}
}
div { class: "stat-card stat-purple",
div { class: "stat-icon",
Icon { icon: FaCircle, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{s.total_collections}" }
div { class: "stat-label", "Collections" }
}
}
div { class: "stat-card stat-danger",
div { class: "stat-icon",
Icon { icon: FaLink, width: 20, height: 20 }
}
div { class: "stat-content",
div { class: "stat-value", "{s.total_duplicates}" }
div { class: "stat-label", "Duplicates" }
}
}
}
if !s.media_by_type.is_empty() {
{
let max_count = s.media_by_type.iter().map(|i| i.count).max().unwrap_or(1)
if !s.media_by_type.is_empty() {
{
let max_count = s.media_by_type.iter().map(|i| i.count).max().unwrap_or(1)
as f64;
rsx! {
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaChartBar,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Media by Type"
}
div { class: "chart-bars",
for item in s.media_by_type.iter() {
{
let percentage = (item.count as f64 / max_count) * 100.0;
let name = item.name.clone();
let count = item.count;
rsx! {
div { key: "{name}", class: "bar-item",
div { class: "bar-label", "{name}" }
div { class: "bar-track",
div { class: "bar-fill bar-primary", style: "width: {percentage}%" }
}
div { class: "bar-value", "{count}" }
}
}
}
}
}
}
}
}
}
as f64;
rsx! {
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaChartBar,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Media by Type"
}
div { class: "chart-bars",
for item in s.media_by_type.iter() {
{
let percentage = (item.count as f64 / max_count) * 100.0;
let name = item.name.clone();
let count = item.count;
rsx! {
div { key: "{name}", class: "bar-item",
div { class: "bar-label", "{name}" }
div { class: "bar-track",
div { class: "bar-fill bar-primary", style: "width: {percentage}%" }
}
div { class: "bar-value", "{count}" }
}
}
}
}
}
}
}
}
}
if !s.storage_by_type.is_empty() {
{
let max_size = s.storage_by_type.iter().map(|i| i.count).max().unwrap_or(1)
if !s.storage_by_type.is_empty() {
{
let max_size = s.storage_by_type.iter().map(|i| i.count).max().unwrap_or(1)
as f64;
rsx! {
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaDatabase,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Storage by Type"
}
div { class: "chart-bars",
for item in s.storage_by_type.iter() {
{
let percentage = (item.count as f64 / max_size) * 100.0;
let name = item.name.clone();
let size_str = format_size(item.count);
rsx! {
div { key: "{name}", class: "bar-item",
div { class: "bar-label", "{name}" }
div { class: "bar-track",
div { class: "bar-fill bar-success", style: "width: {percentage}%" }
}
div { class: "bar-value", "{size_str}" }
}
}
}
}
}
}
}
}
}
as f64;
rsx! {
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaDatabase,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Storage by Type"
}
div { class: "chart-bars",
for item in s.storage_by_type.iter() {
{
let percentage = (item.count as f64 / max_size) * 100.0;
let name = item.name.clone();
let size_str = format_size(item.count);
rsx! {
div { key: "{name}", class: "bar-item",
div { class: "bar-label", "{name}" }
div { class: "bar-track",
div { class: "bar-fill bar-success", style: "width: {percentage}%" }
}
div { class: "bar-value", "{size_str}" }
}
}
}
}
}
}
}
}
}
if !s.top_tags.is_empty() {
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaTags,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Top Tags"
}
div { class: "tag-list",
for item in s.top_tags.iter() {
div { class: "tag-item",
span { class: "tag-badge", "{item.name}" }
span { class: "tag-count", "{item.count}" }
}
}
}
}
}
if !s.top_tags.is_empty() {
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaTags,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Top Tags"
}
div { class: "tag-list",
for item in s.top_tags.iter() {
div { class: "tag-item",
span { class: "tag-badge", "{item.name}" }
span { class: "tag-count", "{item.count}" }
}
}
}
}
}
if !s.top_collections.is_empty() {
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaCircle,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Top Collections"
}
div { class: "collection-list",
for item in s.top_collections.iter() {
div { class: "collection-item",
Icon {
icon: FaFolder,
width: 16,
height: 16,
class: "collection-icon",
}
span { class: "collection-name", "{item.name}" }
span { class: "collection-count", "{item.count}" }
}
}
}
}
}
if !s.top_collections.is_empty() {
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaCircle,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Top Collections"
}
div { class: "collection-list",
for item in s.top_collections.iter() {
div { class: "collection-item",
Icon {
icon: FaFolder,
width: 16,
height: 16,
class: "collection-icon",
}
span { class: "collection-name", "{item.name}" }
span { class: "collection-count", "{item.count}" }
}
}
}
}
}
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaClock,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Date Range"
}
div { class: "date-range",
div { class: "date-item",
Icon { icon: FaClock, width: 16, height: 16 }
div { class: "date-content",
div { class: "date-label", "Oldest Item" }
div { class: "date-value", "{s.oldest_item.as_deref().unwrap_or(\"N/A\")}" }
}
}
div { class: "date-item",
Icon { icon: FaClock, width: 16, height: 16 }
div { class: "date-content",
div { class: "date-label", "Newest Item" }
div { class: "date-value", "{s.newest_item.as_deref().unwrap_or(\"N/A\")}" }
}
}
}
}
}
}
None => rsx! {
div { class: "empty-state",
div { class: "spinner" }
p { "Loading statistics..." }
}
},
}
}
}
}
div { class: "stats-section",
h4 { class: "section-title",
Icon {
icon: FaClock,
width: 16,
height: 16,
style: "margin-right: 8px; vertical-align: middle;",
}
"Date Range"
}
div { class: "date-range",
div { class: "date-item",
Icon { icon: FaClock, width: 16, height: 16 }
div { class: "date-content",
div { class: "date-label", "Oldest Item" }
div { class: "date-value", "{s.oldest_item.as_deref().unwrap_or(\"N/A\")}" }
}
}
div { class: "date-item",
Icon { icon: FaClock, width: 16, height: 16 }
div { class: "date-content",
div { class: "date-label", "Newest Item" }
div { class: "date-value", "{s.newest_item.as_deref().unwrap_or(\"N/A\")}" }
}
}
}
}
}
}
None => rsx! {
div { class: "empty-state",
div { class: "spinner" }
p { "Loading statistics..." }
}
},
}
}
}
}
}