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