+5
-1
changelog
+5
-1
changelog
+1
-1
src-tauri/Cargo.lock
+1
-1
src-tauri/Cargo.lock
+1
-1
src-tauri/Cargo.toml
+1
-1
src-tauri/Cargo.toml
+21
-3
src-tauri/src/frontend_calls/load_photo_meta.rs
+21
-3
src-tauri/src/frontend_calls/load_photo_meta.rs
···
20
20
let mut buffer = Vec::new();
21
21
22
22
let _out = file.read_to_end(&mut buffer);
23
-
window
24
-
.emit("photo_meta_loaded", PNGImage::new(buffer, photo))
25
-
.unwrap();
23
+
let png = PNGImage::new(buffer, photo.clone());
24
+
25
+
if png.is_err(){
26
+
println!("Failed to load: {} => {}", base_dir, png.unwrap_err());
27
+
28
+
window.emit("photo_meta_loaded", PNGImage {
29
+
width: 1920,
30
+
height: 1080,
31
+
bit_depth: 0,
32
+
colour_type: 0,
33
+
compression_method: 0,
34
+
filter_method: 0,
35
+
interlace_method: 0,
36
+
metadata: "".into(),
37
+
error: true,
38
+
path: photo
39
+
}).unwrap();
40
+
} else{
41
+
println!("Loaded: {}", base_dir);
42
+
window.emit("photo_meta_loaded", png.unwrap()).unwrap();
43
+
}
26
44
}
27
45
Err(_) => {
28
46
println!("Cannot read image file: {:?}", base_dir);
+8
-24
src-tauri/src/pngmeta.rs
+8
-24
src-tauri/src/pngmeta.rs
···
1
-
use serde::ser::{Serialize, SerializeStruct, Serializer};
2
1
use std::str;
3
2
4
-
#[derive(Clone)]
3
+
use serde::Serialize;
4
+
5
+
#[derive(Clone, Debug, Serialize)]
5
6
pub struct PNGImage {
6
7
pub width: u32,
7
8
pub height: u32,
···
12
13
pub interlace_method: u8,
13
14
pub metadata: String,
14
15
pub path: String,
16
+
pub error: bool
15
17
}
16
18
17
19
impl PNGImage {
18
-
pub fn new(buff: Vec<u8>, path: String) -> PNGImage {
20
+
pub fn new(buff: Vec<u8>, path: String) -> Result<PNGImage, &'static str> {
19
21
if buff[0] != 0x89
20
22
|| buff[1] != 0x50
21
23
|| buff[2] != 0x4E
···
26
28
|| buff[7] != 0x0A
27
29
{
28
30
dbg!(path);
29
-
panic!("Image is not a PNG file");
31
+
return Err("Image is not a PNG file");
30
32
}
31
33
32
34
let mut img = PNGImage {
···
39
41
interlace_method: 0,
40
42
metadata: "".to_string(),
41
43
path: path,
44
+
error: false
42
45
};
43
46
44
47
img.read_png_chunk(8, buff);
45
-
img
48
+
Ok(img)
46
49
}
47
50
48
51
fn read_png_chunk(&mut self, start_byte: usize, buff: Vec<u8>) {
···
82
85
}
83
86
}
84
87
}
85
-
86
-
impl Serialize for PNGImage {
87
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
88
-
where
89
-
S: Serializer,
90
-
{
91
-
let mut s = serializer.serialize_struct("PNGImage", 7)?;
92
-
s.serialize_field("width", &self.width)?;
93
-
s.serialize_field("height", &self.height)?;
94
-
s.serialize_field("bit_depth", &self.bit_depth)?;
95
-
s.serialize_field("colour_type", &self.colour_type)?;
96
-
s.serialize_field("compression_method", &self.compression_method)?;
97
-
s.serialize_field("filter_method", &self.filter_method)?;
98
-
s.serialize_field("interlace_method", &self.interlace_method)?;
99
-
s.serialize_field("metadata", &self.metadata)?;
100
-
s.serialize_field("path", &self.path)?;
101
-
s.end()
102
-
}
103
-
}
+11
-1
src/Components/Managers/PhotoListRenderingManager.tsx
+11
-1
src/Components/Managers/PhotoListRenderingManager.tsx
···
127
127
// ctx.strokeStyle = '#f00';
128
128
// ctx.strokeRect((rowXPos - row.Width / 2) + canvas.width / 2, currentY - scroll, photo.scaledWidth!, row.Height);
129
129
130
-
if(!photo.loaded)
130
+
if(photo.error){
131
+
ctx.fillStyle = '#fff';
132
+
ctx.textAlign = 'center';
133
+
ctx.textBaseline = 'middle';
134
+
135
+
photo.x = (rowXPos - row.Width / 2) + canvas.width / 2;
136
+
photo.y = currentY - scroll;
137
+
138
+
ctx.font = '18px Rubik'
139
+
ctx.fillText('Error loading image.', photo.x + photo.scaledWidth! / 2, photo.y + photo.scaledHeight! / 2);
140
+
} else if(!photo.loaded)
131
141
// If the photo is not loaded, start a new task and load it in that task
132
142
setTimeout(() => photo.loadImage(), 1);
133
143
else{
+3
-1
src/Components/Managers/PhotoManager.tsx
+3
-1
src/Components/Managers/PhotoManager.tsx
···
112
112
// we don't need to store metadata of those photos as they inherit this
113
113
// data from the main photo.
114
114
115
+
photo.error = data.error;
115
116
this._lastLoaded = photo.index;
116
117
117
118
if(this._onLoadedMeta[photo.index]){
···
129
130
130
131
photo.metadata = data.metadata.split('\u0000').filter(x => x !== '')[1];
131
132
this._amountLoaded++;
132
-
133
+
134
+
photo.loadingMeta = false;
133
135
photo.metaLoaded = true;
134
136
photo.onMetaLoaded();
135
137
+11
-4
src/Components/PhotoList.tsx
+11
-4
src/Components/PhotoList.tsx
···
162
162
onMount(() => {
163
163
// Update Stuff
164
164
fetch('https://api.github.com/repos/phaze-the-dumb/VRChat-Photo-Manager/releases/latest')
165
-
.then(data => data.json())
166
-
.then(async data => {
167
-
let currentVersion = await invoke('get_version');
168
-
setUpdateAvailable(data.tag_name !== currentVersion);
165
+
.then(data => {
166
+
if(data.status !== 200)return;
167
+
168
+
data.json().then(async data => {
169
+
let currentVersion = await invoke('get_version');
170
+
setUpdateAvailable(data.tag_name !== currentVersion);
171
+
})
172
+
})
173
+
.catch(e => {
174
+
console.error(e);
175
+
setUpdateAvailable(false);
169
176
})
170
177
171
178
// Other Stuff
+9
-4
src/Components/Structs/Photo.ts
+9
-4
src/Components/Structs/Photo.ts
···
6
6
export class Photo{
7
7
path: string;
8
8
loaded: boolean = false;
9
+
loadingMeta: boolean = false;
9
10
loading: boolean = false;
10
11
metaLoaded: boolean = false;
11
12
image?: HTMLCanvasElement;
···
14
15
height?: number;
15
16
loadingRotate: number = 0;
16
17
metadata: any;
18
+
19
+
error: boolean = false;
17
20
18
21
frames: number = 0;
19
22
shown: boolean = false;
···
90
93
}
91
94
92
95
loadMeta(){
96
+
this.loadingMeta = true;
93
97
invoke('load_photo_meta', { photo: this.path });
94
98
}
95
99
96
100
loadImage(){
97
-
if(this.loading || this.loaded || imagesLoading >= Vars.MAX_IMAGE_LOAD)return;
98
-
99
-
// this.loadMeta();
101
+
if(this.loadingMeta || this.loading || this.loaded || imagesLoading >= Vars.MAX_IMAGE_LOAD)return;
100
102
if(!this.metaLoaded)return this.loadMeta();
101
103
102
104
this.loading = true;
103
-
104
105
imagesLoading++;
105
106
106
107
this.image = document.createElement('canvas');
···
120
121
this.loading = false;
121
122
122
123
imagesLoading--;
124
+
}
125
+
126
+
this.imageEl.onerror = () => {
127
+
console.log('Cannot load image');
123
128
}
124
129
}
125
130
}