···11#!/bin/bash
2233-VERSION=0.2.5
33+VERSION=0.2.6
4455# Linux builds
66NO_STRIP=true pnpm tauri build
+2-1
changelog
···106106v0.2.6:
107107 - Fixed photos not being loaded if they're too low resolution
108108 - Added close to tray toggle
109109- - Fixed "Open in folder" not selecting files on linux109109+ - Fixed "Open in folder" not selecting files on linux
110110+ - Remove all sync stuff
-1
src-tauri/src/frontend_calls/mod.rs
···1010pub mod open_folder;
1111pub mod open_url;
1212pub mod start_with_win;
1313-pub mod sync_photos;
1413pub mod copy_image;
-11
src-tauri/src/frontend_calls/sync_photos.rs
···11-use crate::photosync;
22-use crate::util::get_photo_path::get_photo_path;
33-use std::thread;
44-55-// On requested sync the photos to the cloud
66-#[tauri::command]
77-pub fn sync_photos(token: String, window: tauri::Window) {
88- thread::spawn(move || {
99- photosync::sync_photos(token, get_photo_path(), window);
1010- });
1111-}
···11-use regex::Regex;
22-use reqwest;
33-use serde::Serialize;
44-use serde_json::{Error, Value};
55-use std::{fs, io::Write, path, time::Duration};
66-use tauri::Emitter;
77-88-#[derive(Clone, Serialize)]
99-struct PhotoUploadMeta {
1010- photos_uploading: usize,
1111- photos_total: usize,
1212-}
1313-1414-pub fn sync_photos(token: String, path: path::PathBuf, window: tauri::Window) {
1515- let sync_lock_path = dirs::config_dir()
1616- .unwrap()
1717- .join("PhazeDev/VRChatPhotoManager/.sync_lock");
1818-1919- match fs::metadata(&sync_lock_path) {
2020- Ok(_) => {
2121- return;
2222- }
2323- Err(_) => {}
2424- }
2525-2626- fs::write(&sync_lock_path, "Currently Syncing").unwrap();
2727-2828- match fs::metadata(&path) {
2929- Ok(_) => {}
3030- Err(_) => {
3131- fs::create_dir(&path).unwrap();
3232- }
3333- };
3434-3535- let mut photos: Vec<String> = Vec::new();
3636-3737- for folder in fs::read_dir(&path).unwrap() {
3838- let f = folder.unwrap();
3939-4040- if f.metadata().unwrap().is_dir() {
4141- match fs::read_dir(f.path()) {
4242- Ok(dir) => {
4343- for photo in dir {
4444- let p = photo.unwrap();
4545-4646- 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();
4747- let re2 = Regex::new(
4848- 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").unwrap();
4949-5050- if re1.is_match(p.file_name().to_str().unwrap())
5151- || re2.is_match(p.file_name().to_str().unwrap())
5252- {
5353- photos.push(p.file_name().into_string().unwrap());
5454- }
5555- }
5656- }
5757- Err(_) => {}
5858- }
5959- }
6060- }
6161-6262- let body = reqwest::blocking::get(format!(
6363- "https://photos-cdn.phazed.xyz/api/v1/photos/exists?token={}",
6464- &token
6565- ))
6666- .unwrap()
6767- .text()
6868- .unwrap();
6969-7070- let body: Value = serde_json::from_str(&body).unwrap();
7171-7272- let mut photos_to_upload: Vec<String> = Vec::new();
7373- let uploaded_photos = body["files"].as_array().unwrap();
7474-7575- let photos_len = photos.len();
7676-7777- for photo in &photos {
7878- let mut found_photo = false;
7979-8080- for uploaded_photo in uploaded_photos {
8181- if photo == uploaded_photo.as_str().unwrap() {
8282- found_photo = true;
8383- break;
8484- }
8585- }
8686-8787- if !found_photo {
8888- photos_to_upload.push(photo.clone());
8989- }
9090- }
9191-9292- window
9393- .emit(
9494- "photos-upload-meta",
9595- PhotoUploadMeta {
9696- photos_uploading: photos_to_upload.len(),
9797- photos_total: photos_len,
9898- },
9999- )
100100- .unwrap();
101101-102102- let mut photos_left = photos_to_upload.len();
103103-104104- let client = reqwest::blocking::Client::new();
105105-106106- loop {
107107- match photos_to_upload.pop() {
108108- Some(photo) => {
109109- let folder_name = photo.clone().replace("VRChat_", "");
110110- let mut folder_name = folder_name.split("-");
111111- let folder_name = format!(
112112- "{}-{}",
113113- folder_name.nth(0).unwrap(),
114114- folder_name.nth(0).unwrap()
115115- );
116116-117117- let full_path = format!("{}\\{}\\{}", path.to_str().unwrap(), folder_name, photo);
118118- let file = fs::File::open(full_path);
119119-120120- match file {
121121- Ok(file) => {
122122- let res = client
123123- .put(format!(
124124- "https://photos-cdn.phazed.xyz/api/v1/photos?token={}",
125125- &token
126126- ))
127127- .header("Content-Type", "image/png")
128128- .header("filename", photo)
129129- .body(file)
130130- .timeout(Duration::from_secs(120))
131131- .send()
132132- .unwrap()
133133- .text()
134134- .unwrap();
135135-136136- let res: Result<Value, Error> = serde_json::from_str(&res);
137137-138138- match res {
139139- Ok(res) => {
140140- if !res["ok"].as_bool().unwrap() {
141141- println!("Failed to upload: {}", res["error"].as_str().unwrap());
142142-143143- window
144144- .emit("sync-failed", res["error"].as_str().unwrap())
145145- .unwrap();
146146-147147- break;
148148- }
149149- }
150150- Err(err) => {
151151- dbg!(err);
152152- }
153153- }
154154- }
155155- Err(_) => {}
156156- }
157157-158158- photos_left -= 1;
159159- window
160160- .emit(
161161- "photos-upload-meta",
162162- PhotoUploadMeta {
163163- photos_uploading: photos_left,
164164- photos_total: photos_len,
165165- },
166166- )
167167- .unwrap();
168168- }
169169- None => {
170170- break;
171171- }
172172- }
173173- }
174174-175175- println!("Finished Uploading.");
176176- let mut photos_to_download: Vec<String> = Vec::new();
177177-178178- for photo in uploaded_photos {
179179- let mut found_photo = false;
180180- let photo = photo.as_str().unwrap().to_string();
181181-182182- for uploaded_photo in &photos {
183183- if &photo == uploaded_photo {
184184- found_photo = true;
185185- break;
186186- }
187187- }
188188-189189- if !found_photo {
190190- photos_to_download.push(photo);
191191- }
192192- }
193193-194194- photos_to_download.reverse();
195195-196196- let photos_len = photos_to_download.len();
197197- let mut photos_left = photos_to_download.len();
198198-199199- loop {
200200- match photos_to_download.pop() {
201201- Some(photo) => {
202202- let folder_name = photo.clone().replace("VRChat_", "");
203203- let mut folder_name = folder_name.split("-");
204204- let folder_name = format!(
205205- "{}-{}",
206206- folder_name.nth(0).unwrap(),
207207- folder_name.nth(0).unwrap()
208208- );
209209-210210- let full_path = format!("{}/{}/{}", path.to_str().unwrap(), folder_name, photo);
211211-212212- let res = client
213213- .get(format!(
214214- "https://photos-cdn.phazed.xyz/api/v1/photos?token={}&photo={}",
215215- &token, &photo
216216- ))
217217- .timeout(Duration::from_secs(120))
218218- .send()
219219- .unwrap()
220220- .bytes();
221221-222222- match res {
223223- Ok(res) => {
224224- let folder_path = format!("{}/{}", path.to_str().unwrap(), folder_name);
225225- match fs::metadata(&folder_path) {
226226- Ok(_) => {}
227227- Err(_) => {
228228- fs::create_dir(folder_path).unwrap();
229229- }
230230- }
231231-232232- let mut file = fs::File::create(full_path).unwrap();
233233- file.write_all(&res).unwrap();
234234- }
235235- Err(err) => {
236236- dbg!(err);
237237- }
238238- }
239239-240240- photos_left -= 1;
241241- window
242242- .emit(
243243- "photos-download-meta",
244244- PhotoUploadMeta {
245245- photos_uploading: photos_left,
246246- photos_total: photos_len,
247247- },
248248- )
249249- .unwrap();
250250- }
251251- None => {
252252- break;
253253- }
254254- }
255255- }
256256-257257- println!("Finished Downloading.");
258258-259259- fs::remove_file(&sync_lock_path).unwrap();
260260- window.emit("sync-finished", "h").unwrap();
261261-}
-6
src-tauri/src/util/handle_uri_proto.rs
···3333 return;
3434 }
35353636- // TODO: Only accept files that are in the vrchat photos folder
3737- // Slightly more complex than originally thought, need to find a way to cache the VRC photos path
3838- // since i need to be able to load lots of photos very quickly. This shouldn't be a security issue
3939- // because tauri should only let the frontend of VRCPhotoManager read files throught this. Only
4040- // becomes a potential issue if the frontend gets modified or there's an issue with tauri.
4141-4236 #[cfg(windows)]
4337 let path = uri.path().split_at(1).1;
4438