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;