A photo manager for VRChat.

Compare changes

Choose any two refs to compare.

Changed files
+70 -12
src
Components
src-tauri
gen
src
frontend_calls
+1 -1
build-release.sh
··· 1 #!/bin/bash 2 3 - VERSION=0.2.6-hot1 4 5 # Linux builds 6 NO_STRIP=true pnpm tauri build
··· 1 #!/bin/bash 2 3 + VERSION=0.2.7-hot1 4 5 # Linux builds 6 NO_STRIP=true pnpm tauri build
+10 -1
changelog
··· 121 122 Hotfix 1: 123 - Fixed loading when an image file is corrupted 124 - - Fixed update prompt when not connected to internet
··· 121 122 Hotfix 1: 123 - Fixed loading when an image file is corrupted 124 + - Fixed update prompt when not connected to internet 125 + 126 + v0.2.7: 127 + - Fixed image resizing when window is thinner than image 128 + - Fixed closing settings with keybinds 129 + - Fixed the behaviour of changing the photo path 130 + - Fixed loading photos in folders that aren't VRChat folders 131 + 132 + Hotfix 1: 133 + - Fixed resizing images (again)
+4 -5
src/Components/PhotoViewer.tsx
··· 154 let dstWidth; 155 let dstHeight; 156 157 - let imgHeight = imageViewer.height; 158 - let imgWidth = imageViewer.width; 159 160 if( 161 imgWidth / window.innerWidth < ··· 178 utils.set(photoLayerManager, { translateY: '20px', opacity: 0, display: 'none' }); 179 180 window.addEventListener('keyup', switchPhotoWithKey); 181 - 182 - resizeImage(); 183 - 184 window.addEventListener('resize', () => resizeImage()); 185 186 let contextMenuOpen = false; ··· 262 if(photo){ 263 imageViewer.src = (window.OS === "windows" ? "http://photo.localhost/" : 'photo://localhost/') + window.PhotoViewerManager.CurrentPhoto()?.path.split('\\').join('/') + "?full"; 264 imageViewer.crossOrigin = 'anonymous'; 265 266 animate(imageViewer, { 267 opacity: 1,
··· 154 let dstWidth; 155 let dstHeight; 156 157 + let imgHeight = imageViewer.naturalHeight; 158 + let imgWidth = imageViewer.naturalWidth; 159 160 if( 161 imgWidth / window.innerWidth < ··· 178 utils.set(photoLayerManager, { translateY: '20px', opacity: 0, display: 'none' }); 179 180 window.addEventListener('keyup', switchPhotoWithKey); 181 window.addEventListener('resize', () => resizeImage()); 182 183 let contextMenuOpen = false; ··· 259 if(photo){ 260 imageViewer.src = (window.OS === "windows" ? "http://photo.localhost/" : 'photo://localhost/') + window.PhotoViewerManager.CurrentPhoto()?.path.split('\\').join('/') + "?full"; 261 imageViewer.crossOrigin = 'anonymous'; 262 + 263 + imageViewer.onload = () => { resizeImage(); } 264 265 animate(imageViewer, { 266 opacity: 1,
+1 -1
src-tauri/Cargo.lock
··· 4 5 [[package]] 6 name = "VRChatPhotoManager" 7 - version = "0.2.6-hot1" 8 dependencies = [ 9 "arboard", 10 "dirs",
··· 4 5 [[package]] 6 name = "VRChatPhotoManager" 7 + version = "0.2.7" 8 dependencies = [ 9 "arboard", 10 "dirs",
+1 -1
src-tauri/Cargo.toml
··· 1 [package] 2 name = "VRChatPhotoManager" 3 - version = "0.2.6-hot1" 4 description = "VRChat Photo Manager" 5 authors = ["_phaz"] 6 edition = "2021"
··· 1 [package] 2 name = "VRChatPhotoManager" 3 + version = "0.2.7-hot1" 4 description = "VRChat Photo Manager" 5 authors = ["_phaz"] 6 edition = "2021"
+50 -2
src-tauri/gen/schemas/windows-schema.json
··· 519 "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" 520 }, 521 { 522 - "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`", 523 "type": "string", 524 "const": "core:app:default", 525 - "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`" 526 }, 527 { 528 "description": "Enables the app_hide command without any pre-configured scope.", ··· 567 "markdownDescription": "Enables the name command without any pre-configured scope." 568 }, 569 { 570 "description": "Enables the remove_data_store command without any pre-configured scope.", 571 "type": "string", 572 "const": "core:app:allow-remove-data-store", 573 "markdownDescription": "Enables the remove_data_store command without any pre-configured scope." 574 }, 575 { 576 "description": "Enables the set_app_theme command without any pre-configured scope.", 577 "type": "string", 578 "const": "core:app:allow-set-app-theme", ··· 639 "markdownDescription": "Denies the name command without any pre-configured scope." 640 }, 641 { 642 "description": "Denies the remove_data_store command without any pre-configured scope.", 643 "type": "string", 644 "const": "core:app:deny-remove-data-store", 645 "markdownDescription": "Denies the remove_data_store command without any pre-configured scope." 646 }, 647 { 648 "description": "Denies the set_app_theme command without any pre-configured scope.", ··· 1827 "markdownDescription": "Enables the set_focus command without any pre-configured scope." 1828 }, 1829 { 1830 "description": "Enables the set_fullscreen command without any pre-configured scope.", 1831 "type": "string", 1832 "const": "core:window:allow-set-fullscreen", ··· 1897 "type": "string", 1898 "const": "core:window:allow-set-shadow", 1899 "markdownDescription": "Enables the set_shadow command without any pre-configured scope." 1900 }, 1901 { 1902 "description": "Enables the set_size command without any pre-configured scope.", ··· 2271 "markdownDescription": "Denies the set_focus command without any pre-configured scope." 2272 }, 2273 { 2274 "description": "Denies the set_fullscreen command without any pre-configured scope.", 2275 "type": "string", 2276 "const": "core:window:deny-set-fullscreen", ··· 2341 "type": "string", 2342 "const": "core:window:deny-set-shadow", 2343 "markdownDescription": "Denies the set_shadow command without any pre-configured scope." 2344 }, 2345 { 2346 "description": "Denies the set_size command without any pre-configured scope.",
··· 519 "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" 520 }, 521 { 522 + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`", 523 "type": "string", 524 "const": "core:app:default", 525 + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`" 526 }, 527 { 528 "description": "Enables the app_hide command without any pre-configured scope.", ··· 567 "markdownDescription": "Enables the name command without any pre-configured scope." 568 }, 569 { 570 + "description": "Enables the register_listener command without any pre-configured scope.", 571 + "type": "string", 572 + "const": "core:app:allow-register-listener", 573 + "markdownDescription": "Enables the register_listener command without any pre-configured scope." 574 + }, 575 + { 576 "description": "Enables the remove_data_store command without any pre-configured scope.", 577 "type": "string", 578 "const": "core:app:allow-remove-data-store", 579 "markdownDescription": "Enables the remove_data_store command without any pre-configured scope." 580 }, 581 { 582 + "description": "Enables the remove_listener command without any pre-configured scope.", 583 + "type": "string", 584 + "const": "core:app:allow-remove-listener", 585 + "markdownDescription": "Enables the remove_listener command without any pre-configured scope." 586 + }, 587 + { 588 "description": "Enables the set_app_theme command without any pre-configured scope.", 589 "type": "string", 590 "const": "core:app:allow-set-app-theme", ··· 651 "markdownDescription": "Denies the name command without any pre-configured scope." 652 }, 653 { 654 + "description": "Denies the register_listener command without any pre-configured scope.", 655 + "type": "string", 656 + "const": "core:app:deny-register-listener", 657 + "markdownDescription": "Denies the register_listener command without any pre-configured scope." 658 + }, 659 + { 660 "description": "Denies the remove_data_store command without any pre-configured scope.", 661 "type": "string", 662 "const": "core:app:deny-remove-data-store", 663 "markdownDescription": "Denies the remove_data_store command without any pre-configured scope." 664 + }, 665 + { 666 + "description": "Denies the remove_listener command without any pre-configured scope.", 667 + "type": "string", 668 + "const": "core:app:deny-remove-listener", 669 + "markdownDescription": "Denies the remove_listener command without any pre-configured scope." 670 }, 671 { 672 "description": "Denies the set_app_theme command without any pre-configured scope.", ··· 1851 "markdownDescription": "Enables the set_focus command without any pre-configured scope." 1852 }, 1853 { 1854 + "description": "Enables the set_focusable command without any pre-configured scope.", 1855 + "type": "string", 1856 + "const": "core:window:allow-set-focusable", 1857 + "markdownDescription": "Enables the set_focusable command without any pre-configured scope." 1858 + }, 1859 + { 1860 "description": "Enables the set_fullscreen command without any pre-configured scope.", 1861 "type": "string", 1862 "const": "core:window:allow-set-fullscreen", ··· 1927 "type": "string", 1928 "const": "core:window:allow-set-shadow", 1929 "markdownDescription": "Enables the set_shadow command without any pre-configured scope." 1930 + }, 1931 + { 1932 + "description": "Enables the set_simple_fullscreen command without any pre-configured scope.", 1933 + "type": "string", 1934 + "const": "core:window:allow-set-simple-fullscreen", 1935 + "markdownDescription": "Enables the set_simple_fullscreen command without any pre-configured scope." 1936 }, 1937 { 1938 "description": "Enables the set_size command without any pre-configured scope.", ··· 2307 "markdownDescription": "Denies the set_focus command without any pre-configured scope." 2308 }, 2309 { 2310 + "description": "Denies the set_focusable command without any pre-configured scope.", 2311 + "type": "string", 2312 + "const": "core:window:deny-set-focusable", 2313 + "markdownDescription": "Denies the set_focusable command without any pre-configured scope." 2314 + }, 2315 + { 2316 "description": "Denies the set_fullscreen command without any pre-configured scope.", 2317 "type": "string", 2318 "const": "core:window:deny-set-fullscreen", ··· 2383 "type": "string", 2384 "const": "core:window:deny-set-shadow", 2385 "markdownDescription": "Denies the set_shadow command without any pre-configured scope." 2386 + }, 2387 + { 2388 + "description": "Denies the set_simple_fullscreen command without any pre-configured scope.", 2389 + "type": "string", 2390 + "const": "core:window:deny-set-simple-fullscreen", 2391 + "markdownDescription": "Denies the set_simple_fullscreen command without any pre-configured scope." 2392 }, 2393 { 2394 "description": "Denies the set_size command without any pre-configured scope.",
+3 -1
src-tauri/src/frontend_calls/load_photos.rs
··· 16 let base_dir = cache.get("photo-path".into()).unwrap(); 17 18 thread::spawn(move || { 19 - 20 let mut photos: Vec<path::PathBuf> = Vec::new(); 21 let mut size: usize = 0; 22 23 for folder in fs::read_dir(&base_dir).unwrap() { 24 let f = folder.unwrap(); 25 26 if f.metadata().unwrap().is_dir() { 27 for photo in fs::read_dir(f.path()).unwrap() {
··· 16 let base_dir = cache.get("photo-path".into()).unwrap(); 17 18 thread::spawn(move || { 19 let mut photos: Vec<path::PathBuf> = Vec::new(); 20 let mut size: usize = 0; 21 22 + let re = Regex::new(r"^[0-9]{4}-[0-9]{2}$").unwrap(); 23 + 24 for folder in fs::read_dir(&base_dir).unwrap() { 25 let f = folder.unwrap(); 26 + if !re.is_match(f.file_name().to_str().unwrap()){ continue; } 27 28 if f.metadata().unwrap().is_dir() { 29 for photo in fs::read_dir(f.path()).unwrap() {