+5
-1
changelog
+5
-1
changelog
···
47
47
48
48
v0.2.1:
49
49
- Fixed app using GPU while minimised, might use a tiny bit, but should be much better than before
50
-
- Fixed a load a bugs todo with
50
+
- Fixed a load a bugs todo with (something? apparently i forgot to write this bit...)
51
+
52
+
v0.2.2:
53
+
- Use more linux friendly directories
54
+
- Move away from localstorage and use the .config file
+2
-2
src-tauri/src/frontend_calls/change_final_path.rs
+2
-2
src-tauri/src/frontend_calls/change_final_path.rs
···
2
2
3
3
#[tauri::command]
4
4
pub fn change_final_path(new_path: &str) {
5
-
let config_path = dirs::home_dir()
5
+
let config_path = dirs::config_dir()
6
6
.unwrap()
7
-
.join("AppData\\Roaming\\PhazeDev\\VRChatPhotoManager\\.photos_path");
7
+
.join("PhazeDev\\VRChatPhotoManager\\.photos_path");
8
8
9
9
fs::write(&config_path, new_path.as_bytes()).unwrap();
10
10
+56
src-tauri/src/frontend_calls/config.rs
+56
src-tauri/src/frontend_calls/config.rs
···
1
+
use std::{ fs, path::PathBuf };
2
+
3
+
use serde_json::Value;
4
+
5
+
pub fn get_config_path() -> PathBuf{
6
+
let path = dirs::config_dir()
7
+
.unwrap()
8
+
.join("PhazeDev\\VRChatPhotoManager\\.config");
9
+
10
+
match fs::metadata(&path){
11
+
Ok(_) => {}
12
+
Err(_) => {
13
+
fs::write(&path, b"{}").unwrap();
14
+
}
15
+
}
16
+
17
+
path
18
+
}
19
+
20
+
#[tauri::command]
21
+
pub fn set_config_value_string( key: String, value: String ){
22
+
let path = get_config_path();
23
+
24
+
let mut config: Value = serde_json::from_str(&fs::read_to_string(&path).unwrap()).unwrap();
25
+
config[key] = Value::from(value);
26
+
27
+
fs::write(path, config.to_string()).unwrap();
28
+
}
29
+
30
+
#[tauri::command]
31
+
pub fn get_config_value_string( key: String ) -> Option<String>{
32
+
let config: Value = serde_json::from_str(&fs::read_to_string(get_config_path()).unwrap()).unwrap();
33
+
let string = config[key].as_str();
34
+
35
+
if string.is_some(){
36
+
Some(string.unwrap().to_owned())
37
+
} else{
38
+
None
39
+
}
40
+
}
41
+
42
+
#[tauri::command]
43
+
pub fn set_config_value_int( key: String, value: i64 ){
44
+
let path = get_config_path();
45
+
46
+
let mut config: Value = serde_json::from_str(&fs::read_to_string(&path).unwrap()).unwrap();
47
+
config[key] = Value::from(value);
48
+
49
+
fs::write(path, config.to_string()).unwrap();
50
+
}
51
+
52
+
#[tauri::command]
53
+
pub fn get_config_value_int( key: String ) -> Option<i64>{
54
+
let config: Value = serde_json::from_str(&fs::read_to_string(get_config_path()).unwrap()).unwrap();
55
+
config[key].as_i64()
56
+
}
+2
-1
src-tauri/src/frontend_calls/mod.rs
+2
-1
src-tauri/src/frontend_calls/mod.rs
+2
-2
src-tauri/src/frontend_calls/relaunch.rs
+2
-2
src-tauri/src/frontend_calls/relaunch.rs
···
2
2
3
3
#[tauri::command]
4
4
pub fn relaunch() {
5
-
let container_folder = dirs::home_dir()
5
+
let container_folder = dirs::config_dir()
6
6
.unwrap()
7
-
.join("AppData\\Roaming\\PhazeDev\\VRChatPhotoManager");
7
+
.join("PhazeDev\\VRChatPhotoManager");
8
8
9
9
let mut cmd = Command::new(&container_folder.join("./vrchat-photo-manager.exe"));
10
10
cmd.current_dir(container_folder);
+20
-16
src-tauri/src/frontend_calls/start_with_win.rs
+20
-16
src-tauri/src/frontend_calls/start_with_win.rs
···
5
5
// create and delete the shortcut from the startup folder
6
6
#[tauri::command]
7
7
pub fn start_with_win(start: bool) {
8
-
thread::spawn(move || {
9
-
if start {
10
-
let target = dirs::home_dir()
11
-
.unwrap()
12
-
.join("AppData\\Roaming\\PhazeDev\\VRChatPhotoManager\\vrchat-photo-manager.exe");
8
+
if cfg!(windows) {
9
+
thread::spawn(move || {
10
+
if start {
11
+
let target = dirs::config_dir()
12
+
.unwrap()
13
+
.join("PhazeDev\\VRChatPhotoManager\\vrchat-photo-manager.exe");
13
14
14
-
match fs::metadata(&target) {
15
-
Ok(_) => {
16
-
let lnk = dirs::home_dir().unwrap().join("AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\VRChat Photo Manager.lnk");
15
+
match fs::metadata(&target) {
16
+
Ok(_) => {
17
+
let lnk = dirs::home_dir().unwrap().join("AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\VRChat Photo Manager.lnk");
17
18
18
-
let sl = ShellLink::new(target).unwrap();
19
-
sl.create_lnk(lnk).unwrap();
19
+
let sl = ShellLink::new(target).unwrap();
20
+
sl.create_lnk(lnk).unwrap();
21
+
}
22
+
Err(_) => {}
20
23
}
21
-
Err(_) => {}
24
+
} else {
25
+
let lnk = dirs::home_dir().unwrap().join("AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\VRChat Photo Manager.lnk");
26
+
fs::remove_file(lnk).unwrap();
22
27
}
23
-
} else {
24
-
let lnk = dirs::home_dir().unwrap().join("AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\VRChat Photo Manager.lnk");
25
-
fs::remove_file(lnk).unwrap();
26
-
}
27
-
});
28
+
});
29
+
} else {
30
+
panic!("Cannot start with windows... on not windows...");
31
+
}
28
32
}
+9
-5
src-tauri/src/main.rs
+9
-5
src-tauri/src/main.rs
···
21
21
tauri_plugin_deep_link::prepare("uk.phaz.vrcpm");
22
22
23
23
// Double check the app has an install directory
24
-
let container_folder = dirs::home_dir()
24
+
let container_folder = dirs::config_dir()
25
25
.unwrap()
26
-
.join("AppData\\Roaming\\PhazeDev\\VRChatPhotoManager");
26
+
.join("PhazeDev\\VRChatPhotoManager");
27
27
28
28
match fs::metadata(&container_folder) {
29
29
Ok(meta) => {
···
36
36
}
37
37
}
38
38
39
-
let sync_lock_path = dirs::home_dir()
39
+
let sync_lock_path = dirs::config_dir()
40
40
.unwrap()
41
-
.join("AppData\\Roaming\\PhazeDev\\VRChatPhotoManager\\.sync_lock");
41
+
.join("PhazeDev\\VRChatPhotoManager\\.sync_lock");
42
42
43
43
match fs::metadata(&sync_lock_path) {
44
44
Ok(_) => {
···
159
159
change_final_path::change_final_path,
160
160
sync_photos::sync_photos,
161
161
util::get_version::get_version,
162
-
relaunch::relaunch
162
+
relaunch::relaunch,
163
+
config::set_config_value_string,
164
+
config::get_config_value_string,
165
+
config::set_config_value_int,
166
+
config::get_config_value_int
163
167
])
164
168
.run(tauri::generate_context!())
165
169
.expect("error while running tauri application");
+2
-2
src-tauri/src/photosync.rs
+2
-2
src-tauri/src/photosync.rs
···
12
12
}
13
13
14
14
pub fn sync_photos(token: String, path: path::PathBuf, window: tauri::Window) {
15
-
let sync_lock_path = dirs::home_dir()
15
+
let sync_lock_path = dirs::config_dir()
16
16
.unwrap()
17
-
.join("AppData\\Roaming\\PhazeDev\\VRChatPhotoManager\\.sync_lock");
17
+
.join("PhazeDev\\VRChatPhotoManager\\.sync_lock");
18
18
19
19
match fs::metadata(&sync_lock_path) {
20
20
Ok(_) => {
+2
-2
src-tauri/src/util/get_photo_path.rs
+2
-2
src-tauri/src/util/get_photo_path.rs
···
1
1
use std::{ fs, path };
2
2
3
3
pub fn get_photo_path() -> path::PathBuf {
4
-
let config_path = dirs::home_dir()
4
+
let config_path = dirs::config_dir()
5
5
.unwrap()
6
-
.join("AppData\\Roaming\\PhazeDev\\VRChatPhotoManager\\.photos_path");
6
+
.join("PhazeDev\\VRChatPhotoManager\\.photos_path");
7
7
8
8
match fs::read_to_string(config_path) {
9
9
Ok(path) => {
+30
-26
src/Components/App.tsx
+30
-26
src/Components/App.tsx
···
12
12
// TODO: Clean up frontend files, split up into smaller files PLEASE
13
13
14
14
function App() {
15
-
if(!localStorage.getItem('start-in-bg')){
16
-
invoke('close_splashscreen')
17
-
}
15
+
invoke('get_config_value_string', { key: 'start-in-bg' })
16
+
.then(str => {
17
+
if(str === "false")invoke('close_splashscreen')
18
+
})
18
19
19
20
let [ loggedIn, setLoggedIn ] = createSignal({ loggedIn: false, username: '', avatar: '', id: '', serverVersion: '0.0' });
20
21
let [ storageInfo, setStorageInfo ] = createSignal({ storage: 0, used: 0, sync: false });
···
37
38
confirmationBoxCallback = cb;
38
39
}
39
40
40
-
if(localStorage.getItem('token')){
41
-
fetch('https://photos.phazed.xyz/api/v1/account?token='+localStorage.getItem('token'))
42
-
.then(data => data.json())
43
-
.then(data => {
44
-
if(!data.ok){
45
-
return console.error(data);
46
-
}
47
-
48
-
console.log(data.data);
49
-
setLoggedIn({ loggedIn: true, username: data.user.username, avatar: data.user.avatar, id: data.user._id, serverVersion: data.user.serverVersion });
50
-
setStorageInfo({ storage: data.user.storage, used: data.user.used, sync: data.user.settings.enableSync });
51
-
52
-
if(!isPhotosSyncing() && data.user.settings.enableSync){
53
-
setIsPhotosSyncing(true);
54
-
invoke('sync_photos', { token: localStorage.getItem('token') });
55
-
}
56
-
})
57
-
.catch(e => {
58
-
console.error(e);
59
-
})
60
-
}
41
+
invoke('get_config_value_string', { key: 'token' })
42
+
.then(token => {
43
+
if(token){
44
+
fetch('https://photos.phazed.xyz/api/v1/account?token='+token)
45
+
.then(data => data.json())
46
+
.then(data => {
47
+
if(!data.ok){
48
+
return console.error(data);
49
+
}
50
+
51
+
console.log(data.data);
52
+
setLoggedIn({ loggedIn: true, username: data.user.username, avatar: data.user.avatar, id: data.user._id, serverVersion: data.user.serverVersion });
53
+
setStorageInfo({ storage: data.user.storage, used: data.user.used, sync: data.user.settings.enableSync });
54
+
55
+
if(!isPhotosSyncing() && data.user.settings.enableSync){
56
+
setIsPhotosSyncing(true);
57
+
invoke('sync_photos', { token: token });
58
+
}
59
+
})
60
+
.catch(e => {
61
+
console.error(e);
62
+
})
63
+
}
64
+
})
61
65
62
66
setTimeout(() => {
63
67
setLoadingType('none');
···
124
128
}
125
129
126
130
console.log(data);
127
-
localStorage.setItem('token', token);
131
+
invoke('set_config_value_string', { key: 'token', value: token });
128
132
129
133
setLoadingType('none');
130
134
setLoggedIn({ loggedIn: true, username: data.user.username, avatar: data.user.avatar, id: data.user._id, serverVersion: data.user.serverVersion });
···
132
136
133
137
if(!isPhotosSyncing() && data.user.settings.enableSync){
134
138
setIsPhotosSyncing(true);
135
-
invoke('sync_photos', { token: localStorage.getItem('token') });
139
+
invoke('sync_photos', { token: token });
136
140
}
137
141
})
138
142
.catch(e => {
+2
-2
src/Components/PhotoList.tsx
+2
-2
src/Components/PhotoList.tsx
···
423
423
}
424
424
})
425
425
426
-
listen('photo_create', ( event: any ) => {
426
+
listen('photo_create', async ( event: any ) => {
427
427
let photo = new Photo(event.payload);
428
428
429
429
photos.splice(0, 0, photo);
···
431
431
432
432
if(!props.isPhotosSyncing() && props.storageInfo().sync){
433
433
props.setIsPhotosSyncing(true);
434
-
invoke('sync_photos', { token: localStorage.getItem('token') });
434
+
invoke('sync_photos', { token: (await invoke('get_config_value_string', { key: 'token' })) });
435
435
}
436
436
})
437
437
+4
-4
src/Components/PhotoViewer.tsx
+4
-4
src/Components/PhotoViewer.tsx
···
31
31
}
32
32
}
33
33
34
-
let worldCache: WorldCache[] = JSON.parse(localStorage.getItem('worldCache') || "[]");
34
+
let worldCache: WorldCache[] = JSON.parse(await invoke('get_config_value_string', { key: 'worldcache' }) || "[]");
35
35
36
36
let PhotoViewer = ( props: PhotoViewerProps ) => {
37
37
let viewer: HTMLElement;
···
430
430
}
431
431
432
432
worldCache.push(worldData);
433
-
localStorage.setItem("worldCache", JSON.stringify(worldCache));
433
+
invoke('set_config_value_string', { key: 'worldcache', value: worldCache });
434
434
435
435
loadWorldData(worldData);
436
436
})
···
534
534
<div class="viewer-button"
535
535
onMouseOver={( el ) => anime({ targets: el.currentTarget, width: '40px', height: '40px', 'margin-left': '15px', 'margin-right': '15px', 'margin-top': '-10px' })}
536
536
onMouseLeave={( el ) => anime({ targets: el.currentTarget, width: '30px', height: '30px', 'margin-left': '20px', 'margin-right': '20px', 'margin-top': '0px' })}
537
-
onClick={() => props.setConfirmationBox("Are you sure you want to delete this photo?", () => { invoke("delete_photo", {
537
+
onClick={() => props.setConfirmationBox("Are you sure you want to delete this photo?", async () => { invoke("delete_photo", {
538
538
path: props.currentPhotoView().path,
539
-
token: localStorage.getItem("token") || "none",
539
+
token: (await invoke('get_config_value_string', { key: 'token' })) || "none",
540
540
isSyncing: props.loggedIn().loggedIn ? props.storageInfo().sync : false
541
541
});
542
542
})}>
+20
-20
src/Components/SettingsMenu.tsx
+20
-20
src/Components/SettingsMenu.tsx
···
43
43
}
44
44
}
45
45
46
-
onMount(() => {
47
-
if(localStorage.getItem('transparent')){
48
-
localStorage.setItem('transparent', 'true');
46
+
onMount(async () => {
47
+
if(await invoke('get_config_value_string', { key: 'transparent' }) === "true"){
48
+
invoke('set_config_value_string', { key: 'transparent', value: 'true' });
49
49
50
50
anime({ targets: document.body, background: 'rgba(0, 0, 0, 0.5)', easing: 'linear', duration: 100 });
51
51
anime({ targets: '.settings', background: 'rgba(0, 0, 0, 0.5)', easing: 'linear', duration: 100 });
52
52
} else{
53
-
localStorage.removeItem('transparent')
53
+
invoke('set_config_value_string', { key: 'transparent', value: 'false' });
54
54
55
55
anime({ targets: document.body, background: 'rgba(0, 0, 0, 1)', easing: 'linear', duration: 100 });
56
56
anime({ targets: '.settings', background: 'rgba(0, 0, 0, 0)', easing: 'linear', duration: 100 });
···
191
191
window.removeEventListener('keyup', closeWithKey);
192
192
})
193
193
194
-
let refreshAccount = () => {
195
-
fetch('https://photos.phazed.xyz/api/v1/account?token='+localStorage.getItem('token')!)
194
+
let refreshAccount = async () => {
195
+
fetch('https://photos.phazed.xyz/api/v1/account?token='+(await invoke('get_config_value_string', { key: 'token' }))!)
196
196
.then(data => data.json())
197
197
.then(data => {
198
198
if(!data.ok){
···
217
217
<p>{ props.photoCount() } Photos ({ bytesToFormatted(props.photoSize(), 0) })</p>
218
218
219
219
<div class="selector">
220
-
<input type="checkbox" id="start-in-bg-check" ref={( el ) => {
221
-
el.checked = localStorage.getItem('start-in-bg') ? true : false;
220
+
<input type="checkbox" id="start-in-bg-check" ref={async ( el ) => {
221
+
el.checked = await invoke('get_config_value_string', { key: 'start-in-bg' }) === "true" ? true : false;
222
222
}} onChange={( el ) => {
223
223
if(el.target.checked){
224
-
localStorage.setItem('start-in-bg', 'true');
224
+
invoke('set_config_value_string', { key: 'start-in-bg', value: 'true' });
225
225
} else{
226
-
localStorage.removeItem('start-in-bg')
226
+
invoke('set_config_value_string', { key: 'start-in-bg', value: 'false' });
227
227
}
228
228
}} />
229
229
Start in background
···
238
238
</div>
239
239
240
240
<div class="selector">
241
-
<input type="checkbox" id="start-with-win-check" ref={( el ) => {
242
-
el.checked = localStorage.getItem('start-with-win') ? true : false;
241
+
<input type="checkbox" id="start-with-win-check" ref={async ( el ) => {
242
+
el.checked = await invoke('get_config_value_string', { key: 'start-with-win' }) === "true" ? true : false;
243
243
}} onChange={( el ) => {
244
244
if(el.target.checked){
245
-
localStorage.setItem('start-with-win', 'true');
245
+
invoke('set_config_value_string', { key: 'start-with-win', value: 'true' });
246
246
invoke("start_with_win", { start: true });
247
247
} else{
248
-
localStorage.removeItem('start-with-win')
248
+
invoke('set_config_value_string', { key: 'start-with-win', value: 'false' });
249
249
invoke("start_with_win", { start: false });
250
250
}
251
251
}} />
···
261
261
</div>
262
262
263
263
<div class="selector">
264
-
<input type="checkbox" id="transparent-check" ref={( el ) => {
265
-
el.checked = localStorage.getItem('transparent') ? true : false;
264
+
<input type="checkbox" id="transparent-check" ref={async ( el ) => {
265
+
el.checked = await invoke('get_config_value_string', { key: 'transparent' }) === "true" ? true : false;
266
266
}} onChange={( el ) => {
267
267
if(el.target.checked){
268
-
localStorage.setItem('transparent', 'true');
268
+
invoke('set_config_value_string', { key: 'transparent', value: 'true' });
269
269
270
270
anime({ targets: document.body, background: 'rgba(0, 0, 0, 0.5)', easing: 'linear', duration: 100 });
271
271
anime({ targets: '.settings', background: 'rgba(0, 0, 0, 0.5)', easing: 'linear', duration: 100 });
272
272
} else{
273
-
localStorage.removeItem('transparent')
273
+
invoke('set_config_value_string', { key: 'transparent', value: 'false' });
274
274
275
275
anime({ targets: document.body, background: 'rgba(0, 0, 0, 1)', easing: 'linear', duration: 100 });
276
276
anime({ targets: '.settings', background: 'rgba(0, 0, 0, 0)', easing: 'linear', duration: 100 });
···
390
390
391
391
<div class="account-notice" style={{ display: 'flex' }}>
392
392
<Show when={!deletingPhotos()} fallback={ "We are deleting your photos, please leave this window open while we delete them." }>
393
-
<div class="button-danger" onClick={() => props.setConfirmationBox("You are about to delete all your photos from the cloud, and disable syncing. This will NOT delete any local files.", () => {
393
+
<div class="button-danger" onClick={() => props.setConfirmationBox("You are about to delete all your photos from the cloud, and disable syncing. This will NOT delete any local files.", async () => {
394
394
props.setStorageInfo({ used: 0, storage: 0, sync: false });
395
395
setDeletingPhotos(true);
396
396
397
397
fetch('https://photos-cdn.phazed.xyz/api/v1/allphotos', {
398
398
method: 'DELETE',
399
-
headers: { auth: localStorage.getItem("token")! }
399
+
headers: { auth: (await invoke('get_config_value_string', { key: 'token' }))! }
400
400
})
401
401
.then(data => data.json())
402
402
.then(data => {