A photo manager for VRChat.
1import { invoke } from '@tauri-apps/api/core';
2import { emit } from '@tauri-apps/api/event';
3import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
4import anime from 'animejs';
5import { Show, onMount } from 'solid-js';
6
7const appWindow = getCurrentWebviewWindow();
8
9let NavBar = () => {
10 let dropdownVisible = false;
11 let inAnimation = false;
12 let dropdown: HTMLElement;
13
14 onMount(() => {
15 anime.set(dropdown, { opacity: 0, translateX: -10 });
16 dropdown.style.display = 'none';
17 })
18
19 let setDropdownVisibility = ( visible: boolean ) => {
20 if(inAnimation)return;
21
22 if(dropdownVisible !== visible){
23 dropdownVisible = visible;
24 inAnimation = true;
25
26 if(visible){
27 dropdown.style.display = 'block';
28
29 anime({
30 targets: dropdown,
31 opacity: 1,
32 translateX: 0,
33 easing: 'easeInOutQuad',
34 duration: 250,
35 complete: () => {
36 inAnimation = false;
37 }
38 })
39 } else{
40 anime({
41 targets: dropdown,
42 opacity: 0,
43 translateX: -10,
44 easing: 'easeInOutQuad',
45 duration: 250,
46 complete: () => {
47 inAnimation = false;
48 dropdown.style.display = 'none';
49 }
50 })
51 }
52 }
53 }
54
55 window.CloseAllPopups.push(() => setDropdownVisibility(false));
56
57 return (
58 <>
59 <div class="navbar" data-tauri-drag-region>
60 <div class="tabs" data-tauri-drag-region>
61 <div class="nav-tab" onClick={() => {
62 anime(
63 {
64 targets: '.settings',
65 opacity: 0,
66 translateX: '500px',
67 easing: 'easeInOutQuad',
68 duration: 250,
69 complete: () => {
70 anime.set('.settings', { display: 'none' });
71 }
72 })
73 }}>Photos</div>
74 </div>
75 <div class="nav-tab" style={{ width: '200px', "text-align": 'center', background: 'transparent' }} data-tauri-drag-region>
76 <Show when={window.SyncManager.IsSyncing()}>
77 <Show when={ window.SyncManager.SyncError() == "" } fallback={ "Error: " + window.SyncManager.SyncError() }>
78 <div style={{ width: '100%', "text-align": 'center', 'font-size': '14px' }}>
79 { window.SyncManager.SyncType() }ing: { window.SyncManager.SyncPhotoTransfers () } / { window.SyncManager.SyncPhotoTotal() }<br />
80 <div style={{ width: '80%', height: '2px', margin: 'auto', "margin-top": '5px', background: '#111' }}>
81 <div style={{ height: '2px', width: (window.SyncManager.SyncPhotoTransfers() / window.SyncManager.SyncPhotoTotal()) * 100 + '%', background: '#00ccff' }}></div>
82 </div>
83 </div>
84 </Show>
85 </Show>
86 </div>
87 <div class="account" onClick={() => setDropdownVisibility(!dropdownVisible)}>
88 <Show when={window.AccountManager.hasAccount()}>
89 <div class="user-pfp" style={{ background:
90 `url('https://cdn.phazed.xyz/id/avatars/${window.AccountManager.Profile()?.id}/${window.AccountManager.Profile()?.avatar}.png')` }}></div>
91 </Show>
92 <div class="icon">
93 <img draggable="false" width="24" height="24" src="/icon/caret-down-solid.svg"></img>
94 </div>
95 </div>
96 <div class="control-lights">
97 <div class="light" onClick={() => appWindow.minimize()}>
98 <img draggable="false" width="24" height="24" src="/icon/minus-solid.svg"></img>
99 </div>
100 <div class="light" onClick={() => appWindow.toggleMaximize()}>
101 <img draggable="false" width="24" height="24" src="/icon/square-regular.svg"></img>
102 </div>
103 <div class="light" onClick={() => { appWindow.hide(); emit('hide-window'); } }>
104 <img draggable="false" width="24" height="24" src="/icon/x-solid.svg"></img>
105 </div>
106 </div>
107 </div>
108
109 <div class="dropdown" ref={( el ) => dropdown = el}>
110 <div class="dropdown-button" onClick={async () => {
111 anime.set('.settings', { display: 'block' });
112 anime({
113 targets: '.settings',
114 opacity: 1,
115 translateX: '0px',
116 easing: 'easeInOutQuad',
117 duration: 250
118 })
119
120 setDropdownVisibility(false);
121 }}>Settings</div>
122
123 <Show when={!window.AccountManager.hasAccount()} fallback={
124 <div class="dropdown-button" onClick={async () => {
125 window.AccountManager.logout()
126 .then(data => {
127 console.log(data);
128 setDropdownVisibility(false);
129 })
130 .catch(e => {
131 console.error(e);
132
133 invoke('set_config_value_string', { key: 'token', value: '' });
134 window.location.reload();
135
136 setDropdownVisibility(false);
137 })
138 }}>Sign Out</div>
139 }>
140 <div class="dropdown-button" onClick={() => {
141 window.AccountManager.login();
142 setDropdownVisibility(false);
143 }}>Sign In</div>
144 </Show>
145 </div>
146 </>
147 )
148}
149
150export default NavBar;