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;