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}