kopia lustrzana https://github.com/elk-zone/elk
				
				
				
			
		
			
				
	
	
		
			136 wiersze
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			136 wiersze
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Vue
		
	
	
| <script setup lang="ts">
 | |
| import type { NavButtonName } from '~/composables/settings'
 | |
| import { STORAGE_KEY_BOTTOM_NAV_BUTTONS } from '~/constants'
 | |
| 
 | |
| interface NavButton {
 | |
|   name: NavButtonName
 | |
|   label: string
 | |
|   icon: string
 | |
| }
 | |
| 
 | |
| const availableNavButtons: NavButton[] = [
 | |
|   { name: 'home', label: 'nav.home', icon: 'i-ri:home-5-line' },
 | |
|   { name: 'search', label: 'nav.search', icon: 'i-ri:search-line' },
 | |
|   { name: 'notification', label: 'nav.notifications', icon: 'i-ri:notification-4-line' },
 | |
|   { name: 'mention', label: 'nav.conversations', icon: 'i-ri:at-line' },
 | |
|   { name: 'explore', label: 'nav.explore', icon: 'i-ri:compass-3-line' },
 | |
|   { name: 'local', label: 'nav.local', icon: 'i-ri:group-2-line' },
 | |
|   { name: 'federated', label: 'nav.federated', icon: 'i-ri:earth-line' },
 | |
|   { name: 'moreMenu', label: 'nav.more_menu', icon: 'i-ri:more-fill' },
 | |
| ] as const
 | |
| 
 | |
| const defaultSelectedNavButtonNames = computed<NavButtonName[]>(() =>
 | |
|   currentUser.value
 | |
|     ? ['home', 'search', 'notification', 'mention', 'moreMenu']
 | |
|     : ['explore', 'local', 'federated', 'moreMenu'],
 | |
| )
 | |
| const navButtonNamesSetting = useLocalStorage<NavButtonName[]>(STORAGE_KEY_BOTTOM_NAV_BUTTONS, defaultSelectedNavButtonNames.value)
 | |
| const selectedNavButtonNames = ref<NavButtonName[]>([])
 | |
| 
 | |
| const selectedNavButtons = computed<NavButton[]>(() =>
 | |
|   selectedNavButtonNames.value.map(name =>
 | |
|     availableNavButtons.find(navButton => navButton.name === name)!,
 | |
|   ),
 | |
| )
 | |
| 
 | |
| const canSave = computed(() =>
 | |
|   selectedNavButtonNames.value.length > 0
 | |
|   && selectedNavButtonNames.value.includes('moreMenu')
 | |
|   && JSON.stringify(selectedNavButtonNames.value) !== JSON.stringify(navButtonNamesSetting.value),
 | |
| )
 | |
| 
 | |
| function isAdded(name: NavButtonName) {
 | |
|   return selectedNavButtonNames.value.includes(name)
 | |
| }
 | |
| 
 | |
| function append(navButtonName: NavButtonName) {
 | |
|   const maxButtonNumber = 5
 | |
|   if (selectedNavButtonNames.value.length < maxButtonNumber)
 | |
|     selectedNavButtonNames.value = [...selectedNavButtonNames.value, navButtonName]
 | |
| }
 | |
| 
 | |
| function remove(navButtonName: NavButtonName) {
 | |
|   selectedNavButtonNames.value = selectedNavButtonNames.value.filter(name => name !== navButtonName)
 | |
| }
 | |
| 
 | |
| function clear() {
 | |
|   selectedNavButtonNames.value = []
 | |
| }
 | |
| 
 | |
| function reset() {
 | |
|   selectedNavButtonNames.value = defaultSelectedNavButtonNames.value
 | |
| }
 | |
| 
 | |
| function save() {
 | |
|   navButtonNamesSetting.value = selectedNavButtonNames.value
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <section space-y-2>
 | |
|     <h2 id="interface-bn" font-medium>
 | |
|       {{ $t('settings.interface.bottom_nav') }}
 | |
|     </h2>
 | |
|     <form aria-labelledby="interface-bn" aria-describedby="interface-bn-desc" @submit.prevent="save">
 | |
|       <p id="interface-bn-desc" pb-2>
 | |
|         {{ $t('settings.interface.bottom_nav_instructions') }}
 | |
|       </p>
 | |
|       <!-- preview -->
 | |
|       <div aria-hidden="true" flex="~ gap4 wrap" items-center select-settings h-14 p0>
 | |
|         <nav
 | |
|           v-for="availableNavButton in selectedNavButtons" :key="availableNavButton.name"
 | |
|           flex="~ 1" items-center justify-center text-xl
 | |
|           scrollbar-hide overscroll-none
 | |
|         >
 | |
|           <button btn-base :class="availableNavButton.icon" mx-4 tabindex="-1" />
 | |
|         </nav>
 | |
|       </div>
 | |
| 
 | |
|       <!-- button selection -->
 | |
|       <div flex="~ gap4 wrap" py4>
 | |
|         <button
 | |
|           v-for="{ name, label, icon } in availableNavButtons"
 | |
|           :key="name"
 | |
|           btn-text flex="~ gap-2" items-center p2 border="~ base rounded" bg-base ws-nowrap
 | |
|           :class="isAdded(name) ? 'text-secondary hover:text-second bg-auto' : ''"
 | |
|           type="button"
 | |
|           role="switch"
 | |
|           :aria-checked="isAdded(name)"
 | |
|           @click="isAdded(name) ? remove(name) : append(name)"
 | |
|         >
 | |
|           <span :class="icon" />
 | |
|           {{ label ? $t(label) : 'More menu' }}
 | |
|         </button>
 | |
|       </div>
 | |
| 
 | |
|       <div flex="~ col" gap-y-4 gap-x-2 py-1 sm="~ justify-end flex-row">
 | |
|         <button
 | |
|           btn-outline font-bold py2 full-w sm-wa flex="~ gap2 center"
 | |
|           type="button"
 | |
|           :disabled="selectedNavButtonNames.length === 0"
 | |
|           :class="selectedNavButtonNames.length === 0 ? 'border-none' : undefined"
 | |
|           @click="clear"
 | |
|         >
 | |
|           <span aria-hidden="true" class="block i-ri:delete-bin-line" />
 | |
|           {{ $t('action.clear') }}
 | |
|         </button>
 | |
|         <button
 | |
|           btn-outline font-bold py2 full-w sm-wa flex="~ gap2 center"
 | |
|           type="reset"
 | |
|           @click="reset"
 | |
|         >
 | |
|           <span aria-hidden="true" class="block i-ri:repeat-line" />
 | |
|           {{ $t('action.reset') }}
 | |
|         </button>
 | |
|         <button
 | |
|           btn-solid font-bold py2 full-w sm-wa flex="~ gap2 center"
 | |
|           :disabled="!canSave"
 | |
|         >
 | |
|           <span aria-hidden="true" i-ri:save-2-fill />
 | |
|           {{ $t('action.save') }}
 | |
|         </button>
 | |
|       </div>
 | |
|     </form>
 | |
|   </section>
 | |
| </template>
 |