+3
-1
changelog
+3
-1
changelog
+3
-1
src-tauri/src/frontend_calls/load_photos.rs
+3
-1
src-tauri/src/frontend_calls/load_photos.rs
···
36
let name = name.to_str().unwrap();
37
38
let re1_match = // This is the current format used by VRChat
39
-
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}.png").unwrap().is_match(name);
40
41
let re2_match = // This is the format VRCX uses if you enable renaming photos
42
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}_wrld_[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}.png").unwrap().is_match(name);
···
36
let name = name.to_str().unwrap();
37
38
let re1_match = // This is the current format used by VRChat
39
+
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}.png").unwrap().is_match(name) ||
40
+
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}_Player.png").unwrap().is_match(name) ||
41
+
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}_Environment.png").unwrap().is_match(name);
42
43
let re2_match = // This is the format VRCX uses if you enable renaming photos
44
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}_wrld_[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}.png").unwrap().is_match(name);
+8
-6
src-tauri/src/main.rs
+8
-6
src-tauri/src/main.rs
···
98
let path = event.paths.first().unwrap();
99
let name = path.file_name().unwrap().to_str().unwrap().to_owned();
100
101
-
let re1 = Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{4}x[0-9]{4}.png").unwrap();
102
-
let re2 = Regex::new(r"(?m)/VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{4}x[0-9]{4}_wrld_[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}.png/gm").unwrap();
103
104
-
if
105
-
re1.is_match(&name) ||
106
-
re2.is_match(&name)
107
-
{
108
sender.send((2, path.strip_prefix(get_photo_path()).unwrap().to_str().unwrap().to_owned())).unwrap();
109
}
110
},
···
98
let path = event.paths.first().unwrap();
99
let name = path.file_name().unwrap().to_str().unwrap().to_owned();
100
101
+
let re1_match = // This is the current format used by VRChat
102
+
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}.png").unwrap().is_match(&name) ||
103
+
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}_Player.png").unwrap().is_match(&name) ||
104
+
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}_Environment.png").unwrap().is_match(&name);
105
106
+
let re2_match = // This is the format VRCX uses if you enable renaming photos
107
+
Regex::new(r"(?m)VRChat_[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}.[0-9]{3}_[0-9]{3,4}x[0-9]{3,4}_wrld_[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}.png").unwrap().is_match(&name);
108
+
109
+
if re1_match || re2_match{
110
sender.send((2, path.strip_prefix(get_photo_path()).unwrap().to_str().unwrap().to_owned())).unwrap();
111
}
112
},
+10
-11
src/Components/Managers/PhotoManager.tsx
+10
-11
src/Components/Managers/PhotoManager.tsx
···
61
})
62
63
this.Photos = MergeSort(this.Photos);
64
65
console.log(this.Photos.length + ' Photos found.');
66
if(this.Photos.length === 0 || photoPaths.length > Vars.MAX_PHOTOS_BULK_LOAD){
···
116
117
photo.onMetaLoaded = () => this.ReloadFilters();
118
photo.loadMeta();
119
-
120
-
if(!window.SyncManager.IsSyncing()){
121
-
window.SyncManager.TriggerSync();
122
-
}
123
})
124
-
125
listen('photo_remove', ( event: any ) => {
126
this.Photos = this.Photos.filter(x => x.path !== event.payload);
127
-
this.FilteredPhotos = this.FilteredPhotos.filter(x => x.path !== event.payload);
128
-
129
if(event.payload === window.PhotoViewerManager.CurrentPhoto()?.path)
130
window.PhotoViewerManager.Close()
131
···
168
public ReloadFilters(){
169
this.FilteredPhotos = [];
170
171
switch(this._filterType){
172
case FilterType.USER:
173
-
if(this._filter === '')return this.FilteredPhotos = this.Photos;
174
-
175
this.Photos.map(p => {
176
if(p.metadata){
177
try{
···
187
})
188
break;
189
case FilterType.WORLD:
190
-
if(this._filter === '')return this.FilteredPhotos = this.Photos;
191
-
192
this.Photos.map(p => {
193
if(p.metadata){
194
try{
···
61
})
62
63
this.Photos = MergeSort(this.Photos);
64
+
console.log(this.Photos);
65
66
console.log(this.Photos.length + ' Photos found.');
67
if(this.Photos.length === 0 || photoPaths.length > Vars.MAX_PHOTOS_BULK_LOAD){
···
117
118
photo.onMetaLoaded = () => this.ReloadFilters();
119
photo.loadMeta();
120
})
121
+
122
listen('photo_remove', ( event: any ) => {
123
this.Photos = this.Photos.filter(x => x.path !== event.payload);
124
+
125
if(event.payload === window.PhotoViewerManager.CurrentPhoto()?.path)
126
window.PhotoViewerManager.Close()
127
···
164
public ReloadFilters(){
165
this.FilteredPhotos = [];
166
167
+
if(this._filter === ''){
168
+
this.FilteredPhotos = this.Photos;
169
+
window.PhotoListRenderingManager.ComputeLayout();
170
+
171
+
return;
172
+
}
173
+
174
switch(this._filterType){
175
case FilterType.USER:
176
this.Photos.map(p => {
177
if(p.metadata){
178
try{
···
188
})
189
break;
190
case FilterType.WORLD:
191
this.Photos.map(p => {
192
if(p.metadata){
193
try{
+5
-1
src/Components/PhotoViewer.tsx
+5
-1
src/Components/PhotoViewer.tsx
···
272
let id = doc.getElementsByTagName('xmp:Author')[0]!.innerHTML;
273
274
authorProfileButton!.style.display = 'flex';
275
-
authorProfileButton!.onclick = () =>
276
invoke('open_url', { url: 'https://vrchat.com/home/user/' + id });
277
} catch(e){
278
console.error(e);
279
console.log('Couldn\'t decode metadata')
···
286
}
287
} else{
288
trayButton.style.display = 'none';
289
closeTray();
290
}
291
}
···
272
let id = doc.getElementsByTagName('xmp:Author')[0]!.innerHTML;
273
274
authorProfileButton!.style.display = 'flex';
275
+
authorProfileButton!.onclick = () => {
276
+
console.log(id);
277
invoke('open_url', { url: 'https://vrchat.com/home/user/' + id });
278
+
}
279
} catch(e){
280
console.error(e);
281
console.log('Couldn\'t decode metadata')
···
288
}
289
} else{
290
trayButton.style.display = 'none';
291
+
authorProfileButton!.style.display = 'none';
292
+
293
closeTray();
294
}
295
}
+11
src/Components/Structs/Photo.ts
+11
src/Components/Structs/Photo.ts
···
43
else
44
this.dateString = split[1];
45
46
let splitDateString = this.dateString.split('-');
47
48
this.date = new Date();
49
50
this.date.setFullYear(parseInt(splitDateString[0]));
51
this.date.setMonth(parseInt(splitDateString[1]));
52
this.date.setDate(parseInt(splitDateString[2]));
53
54
let resSplit = split[3].split('x');
55
···
43
else
44
this.dateString = split[1];
45
46
+
let timeString;
47
+
if(this.legacy)
48
+
timeString = split[3];
49
+
else
50
+
timeString = split[2];
51
+
52
let splitDateString = this.dateString.split('-');
53
+
let splitTimeString = timeString.split('-');
54
55
this.date = new Date();
56
57
this.date.setFullYear(parseInt(splitDateString[0]));
58
this.date.setMonth(parseInt(splitDateString[1]));
59
this.date.setDate(parseInt(splitDateString[2]));
60
+
61
+
this.date.setHours(parseInt(splitTimeString[0]));
62
+
this.date.setMinutes(parseInt(splitTimeString[1]));
63
+
this.date.setSeconds(parseInt(splitTimeString[2]));
64
65
let resSplit = split[3].split('x');
66