A photo manager for VRChat.
1import { invoke } from "@tauri-apps/api/core";
2import { Vars } from "./Vars";
3
4let imagesLoading = 0;
5
6export class Photo{
7 path: string;
8 loaded: boolean = false;
9 loadingMeta: boolean = false;
10 loading: boolean = false;
11 metaLoaded: boolean = false;
12 image?: HTMLCanvasElement;
13 imageEl?: HTMLImageElement;
14 width?: number;
15 height?: number;
16 loadingRotate: number = 0;
17 metadata: any;
18
19 error: boolean = false;
20
21 frames: number = 0;
22 shown: boolean = false;
23
24 x: number = 0;
25 y: number = 0;
26 scaledWidth?: number;
27 scaledHeight?: number;
28
29 dateString: string;
30 date: Date;
31
32 legacy: boolean = false;
33 index: number = 0;
34
35 splitPath: string[];
36
37 playerLayer: Photo | null = null;
38 environmentLayer: Photo | null = null;
39 isMultiLayer = false;
40
41 public onMetaLoaded: () => void = () => {};
42
43 constructor( path: string, isLegacy: boolean = false, i: number ){
44 this.path = path;
45 this.legacy = isLegacy;
46 this.index = i;
47
48 let split = this.path.split('_');
49 this.splitPath = split;
50
51 if(this.legacy)
52 this.dateString = split[2];
53 else
54 this.dateString = split[1];
55
56 let timeString;
57 if(this.legacy)
58 timeString = split[3];
59 else
60 timeString = split[2];
61
62 let splitDateString = this.dateString.split('-');
63 let splitTimeString = timeString.split('-');
64
65 this.date = new Date();
66
67 this.date.setFullYear(parseInt(splitDateString[0]));
68 this.date.setMonth(parseInt(splitDateString[1]));
69 this.date.setDate(parseInt(splitDateString[2]));
70
71 this.date.setHours(parseInt(splitTimeString[0]));
72 this.date.setMinutes(parseInt(splitTimeString[1]));
73 this.date.setSeconds(parseInt(splitTimeString[2]));
74
75 let resSplit;
76 if(this.legacy)
77 resSplit = split[0].split('x')
78 else
79 resSplit = split[3].split('x')
80
81 // let width = parseInt(resSplit[0]);
82 // let height = parseInt(resSplit[1]);
83
84 // if(!isNaN(width) || !isNaN(height)){
85 // this.width = width;
86 // this.height = height;
87
88 // let scale = Vars.PHOTO_HEIGHT / this.height;
89
90 // this.scaledWidth = this.width * scale;
91 // this.scaledHeight = Vars.PHOTO_HEIGHT;
92 // }
93 }
94
95 loadMeta(){
96 this.loadingMeta = true;
97 invoke('load_photo_meta', { photo: this.path });
98 }
99
100 loadImage(){
101 if(this.loadingMeta || this.loading || this.loaded || imagesLoading >= Vars.MAX_IMAGE_LOAD)return;
102 if(!this.metaLoaded)return this.loadMeta();
103
104 this.loading = true;
105 imagesLoading++;
106
107 this.image = document.createElement('canvas');
108
109 this.imageEl = document.createElement('img');
110 this.imageEl.crossOrigin = 'anonymous';
111
112 this.imageEl.src = (window.OS === "windows" ? "http://photo.localhost/" : "photo://localhost/") + this.path + "?downscale";
113
114 this.imageEl.onload = () => {
115 this.image!.width = this.scaledWidth!;
116 this.image!.height = this.scaledHeight!;
117
118 this.image!.getContext('2d')!.drawImage(this.imageEl!, 0, 0, this.scaledWidth!, this.scaledHeight!);
119
120 this.loaded = true;
121 this.loading = false;
122
123 imagesLoading--;
124 }
125
126 this.imageEl.onerror = () => {
127 console.log('Cannot load image');
128 }
129 }
130}