Load posters by UUID from XDG data directory

This commit is contained in:
Reinout Meliesie 2025-03-21 13:18:24 +01:00
parent ab2e4ab0ad
commit 0d841f95c4
Signed by: zedfrigg
GPG key ID: 3AFCC06481308BC6
2 changed files with 37 additions and 36 deletions

View file

@ -21,12 +21,12 @@ pub struct DataManager {
impl DataManager { impl DataManager {
pub async fn new () -> Result <Self> { pub async fn new () -> Result <Self> {
let home_dir = var_os ("HOME") . unwrap () ; let home_directory = var_os ("HOME") . unwrap () ;
let xdg_data_home = var_os ("XDG_DATA_HOME") ; let xdg_data_home = var_os ("XDG_DATA_HOME") ;
let data_dir = match xdg_data_home { let data_dir = match xdg_data_home {
Some (xdg_data_home) => concat_os_str ! ( xdg_data_home , "/zoodex" ) , Some (xdg_data_home) => concat_os_str ! ( xdg_data_home , "/zoodex" ) ,
None => concat_os_str ! ( home_dir , "/.local/share/zoodex" ) , None => concat_os_str ! ( home_directory , "/.local/share/zoodex" ) ,
} ; } ;
let sqlite_client_shared = ClientBuilder :: new () let sqlite_client_shared = ClientBuilder :: new ()
@ -51,7 +51,7 @@ impl DataManager {
let collection_overview = self . sqlite_client_shared . conn ( |sqlite_connection| { let collection_overview = self . sqlite_client_shared . conn ( |sqlite_connection| {
let films = sqlite_connection let films = sqlite_connection
. prepare ( " . prepare ( "
select uuid , name , original_name , release_date , runtime_minutes , poster_file_path select uuid , name , original_name , release_date , runtime_minutes
from films from films
" ) ? " ) ?
. query (()) ? . query (()) ?
@ -60,7 +60,7 @@ impl DataManager {
let series = sqlite_connection let series = sqlite_connection
. prepare ( " . prepare ( "
select series . uuid , series . name , series . original_name , series . poster_file_path , select series . uuid , series . name , series . original_name ,
min ( episodes . release_date ) min ( episodes . release_date )
from series , seasons , episodes from series , seasons , episodes
where series . uuid = seasons . series and seasons . uuid = episodes . season where series . uuid = seasons . series and seasons . uuid = episodes . season
@ -85,7 +85,6 @@ impl DataManager {
films . original_name , films . original_name ,
films . release_date , films . release_date ,
films . runtime_minutes , films . runtime_minutes ,
films . poster_file_path ,
sources . media_uuid , sources . media_uuid ,
sources . bittorrent_hash , sources . bittorrent_hash ,
sources . file_path , sources . file_path ,
@ -118,7 +117,6 @@ pub trait MediaOverview : Clone {
fn get_original_name ( & self ) -> Option <String> ; fn get_original_name ( & self ) -> Option <String> ;
fn get_release_date ( & self ) -> String ; fn get_release_date ( & self ) -> String ;
fn get_runtime_minutes ( & self ) -> Option <u32> ; fn get_runtime_minutes ( & self ) -> Option <u32> ;
fn get_poster_file_path ( & self ) -> Option <PathBuf> ;
} }
# [ derive (Clone) ] pub struct FilmOverview { # [ derive (Clone) ] pub struct FilmOverview {
@ -127,14 +125,12 @@ pub trait MediaOverview : Clone {
pub original_name : Option <String> , pub original_name : Option <String> ,
pub release_date : String , // TODO: Switch to chrono types, I think rusqlite has crate option for it pub release_date : String , // TODO: Switch to chrono types, I think rusqlite has crate option for it
pub runtime_minutes : u32 , pub runtime_minutes : u32 ,
pub poster_file_path : Option <PathBuf> ,
} }
# [ derive (Clone) ] pub struct SeriesOverview { # [ derive (Clone) ] pub struct SeriesOverview {
pub uuid : String , pub uuid : String ,
pub name : String , pub name : String ,
pub original_name : Option <String> , pub original_name : Option <String> ,
pub first_release_date : String , // TODO: Switch to chrono types, I think rusqlite has crate option for it pub first_release_date : String , // TODO: Switch to chrono types, I think rusqlite has crate option for it
pub poster_file_path : Option <PathBuf> ,
} }
impl MediaOverview for FilmOverview { impl MediaOverview for FilmOverview {
@ -143,7 +139,6 @@ impl MediaOverview for FilmOverview {
fn get_original_name ( & self ) -> Option <String> { self . original_name . clone () } fn get_original_name ( & self ) -> Option <String> { self . original_name . clone () }
fn get_release_date ( & self ) -> String { self . release_date . clone () } fn get_release_date ( & self ) -> String { self . release_date . clone () }
fn get_runtime_minutes ( & self ) -> Option <u32> { Some ( self . runtime_minutes ) } fn get_runtime_minutes ( & self ) -> Option <u32> { Some ( self . runtime_minutes ) }
fn get_poster_file_path ( & self ) -> Option <PathBuf> { self . poster_file_path . clone () }
} }
impl MediaOverview for SeriesOverview { impl MediaOverview for SeriesOverview {
fn get_uuid ( & self ) -> String { self . uuid . clone () } fn get_uuid ( & self ) -> String { self . uuid . clone () }
@ -151,7 +146,6 @@ impl MediaOverview for SeriesOverview {
fn get_original_name ( & self ) -> Option <String> { self . original_name . clone () } fn get_original_name ( & self ) -> Option <String> { self . original_name . clone () }
fn get_release_date ( & self ) -> String { self . first_release_date . clone () } fn get_release_date ( & self ) -> String { self . first_release_date . clone () }
fn get_runtime_minutes ( & self ) -> Option <u32> { None } fn get_runtime_minutes ( & self ) -> Option <u32> { None }
fn get_poster_file_path ( & self ) -> Option <PathBuf> { self . poster_file_path . clone () }
} }
fn row_to_film_overview ( row : & Row ) -> rusqlite :: Result <FilmOverview> { fn row_to_film_overview ( row : & Row ) -> rusqlite :: Result <FilmOverview> {
@ -160,8 +154,6 @@ fn row_to_film_overview ( row : & Row ) -> rusqlite :: Result <FilmOverview> {
let original_name = row . get (2) ? ; let original_name = row . get (2) ? ;
let release_date = row . get (3) ? ; let release_date = row . get (3) ? ;
let runtime_minutes = row . get (4) ? ; let runtime_minutes = row . get (4) ? ;
let poster_file_path = row . get :: < _ , Option <String> > (5) ?
. map ( PathBuf :: from ) ;
Ok ( FilmOverview { Ok ( FilmOverview {
uuid , uuid ,
@ -169,23 +161,19 @@ fn row_to_film_overview ( row : & Row ) -> rusqlite :: Result <FilmOverview> {
original_name , original_name ,
release_date , release_date ,
runtime_minutes , runtime_minutes ,
poster_file_path ,
} ) } )
} }
fn row_to_series_overview ( row : & Row ) -> rusqlite :: Result <SeriesOverview> { fn row_to_series_overview ( row : & Row ) -> rusqlite :: Result <SeriesOverview> {
let uuid = row . get (0) ? ; let uuid = row . get (0) ? ;
let name = row . get (1) ? ; let name = row . get (1) ? ;
let original_name = row . get (2) ? ; let original_name = row . get (2) ? ;
let poster_file_path = row. get :: < _ , Option <String> > (3) ? let first_release_date = row . get (3) ? ;
. map ( PathBuf :: from ) ;
let first_release_date = row . get (4) ? ;
Ok ( SeriesOverview { Ok ( SeriesOverview {
uuid , uuid ,
name , name ,
original_name , original_name ,
first_release_date , first_release_date ,
poster_file_path ,
} ) } )
} }
@ -197,7 +185,6 @@ fn row_to_series_overview ( row : & Row ) -> rusqlite :: Result <SeriesOverview>
pub original_name : Option <String> , pub original_name : Option <String> ,
pub release_date : String , pub release_date : String ,
pub runtime_minutes : u32 , pub runtime_minutes : u32 ,
pub poster_file_path : Option <PathBuf> ,
pub source : Option <SourceDetails> , pub source : Option <SourceDetails> ,
} }
# [ derive (Clone) ] pub struct SourceDetails { # [ derive (Clone) ] pub struct SourceDetails {
@ -213,15 +200,14 @@ fn row_to_film_details ( row : & Row ) -> rusqlite :: Result <FilmDetails> {
let original_name = row . get (2) ? ; let original_name = row . get (2) ? ;
let release_date = row . get (3) ? ; let release_date = row . get (3) ? ;
let runtime_minutes = row . get (4) ? ; let runtime_minutes = row . get (4) ? ;
let poster_file_path = row . get :: < _ , Option <String> > (5) ? . map ( PathBuf :: from ) ;
let source_media_uuid = row . get :: < _ , Option <String> > (6) ? ; let source_media_uuid = row . get :: < _ , Option <String> > (5) ? ;
let source = match source_media_uuid { let source = match source_media_uuid {
Some (_) => { Some (_) => {
let bittorrent_hash = row . get (7) ? ; let bittorrent_hash = row . get (6) ? ;
let file_path = PathBuf :: from ( row . get :: < _ , String > (8) ? ) ; let file_path = PathBuf :: from ( row . get :: < _ , String > (7) ? ) ;
let audio_track = row . get (9) ? ; let audio_track = row . get (8) ? ;
let subtitle_track = row . get (10) ? ; let subtitle_track = row . get (9) ? ;
Some ( SourceDetails { Some ( SourceDetails {
bittorrent_hash , bittorrent_hash ,
@ -239,7 +225,6 @@ fn row_to_film_details ( row : & Row ) -> rusqlite :: Result <FilmDetails> {
original_name , original_name ,
release_date , release_date ,
runtime_minutes , runtime_minutes ,
poster_file_path ,
source , source ,
} ) } )
} }

View file

@ -8,8 +8,8 @@ use gtk4 :: pango :: * ;
use gtk4 :: pango :: Weight :: * ; use gtk4 :: pango :: Weight :: * ;
use gtk4 :: prelude :: * ; use gtk4 :: prelude :: * ;
use std :: cell :: * ; use std :: cell :: * ;
use std :: env :: * ;
use std :: iter :: * ; use std :: iter :: * ;
use std :: path :: PathBuf ;
use crate :: ui :: collatable_container :: * ; use crate :: ui :: collatable_container :: * ;
use crate :: ui :: component :: * ; use crate :: ui :: component :: * ;
@ -63,20 +63,36 @@ impl < A : MediaAdapter > CollatedMediaGrid <A> {
@ margin_top : 20 ; @ margin_top : 20 ;
@ margin_bottom : 20 ; @ margin_bottom : 20 ;
match media . get_poster_file_path () { {
Some (poster_file_path) => { let home_directory = var_os ("HOME") . unwrap () ;
let poster_file_path = PathBuf :: from (poster_file_path) ; // God forbid `Path` would work with `clone ! ()` let xdg_data_home = var_os ("XDG_DATA_HOME") ;
let poster_texture = spawn_blocking (
move || Texture :: from_filename (poster_file_path) . unwrap () , let data_dir = match xdg_data_home {
) . await . unwrap () ; Some (xdg_data_home) => concat_os_str ! ( xdg_data_home , "/zoodex" ) ,
Some ( image ! ( None => concat_os_str ! ( home_directory , "/.local/share/zoodex" ) ,
} ;
let poster_file_path = concat_os_str ! ( data_dir , "/posters/" , media . get_uuid () ) ;
let poster_texture = spawn_blocking (
move || Texture :: from_filename (poster_file_path) ,
) . await . unwrap () ;
match poster_texture {
Ok (poster_texture) => Some ( image ! (
@ paintable : & poster_texture ; @ paintable : & poster_texture ;
@ width_request : 300 ; @ width_request : 300 ;
@ height_request : 300 ; @ height_request : 300 ;
@ margin_bottom : 10 ; @ margin_bottom : 10 ;
) ) ) ) ,
} , Err (error) => {
None => None , if error . matches ( IOErrorEnum :: NotFound ) {
None // The file not existing simply means there is no poster for this piece of media
} else {
panic ! ( "{}" , error ) // Any other error means something unexpected went wrong
}
} ,
}
} . as_ref () , } . as_ref () ,
Some ( & label ! ( Some ( & label ! (