ability to pin items in navigation menu, initial draft version
This commit is contained in:
parent
732733f115
commit
6df9913354
@ -756,6 +756,9 @@ option {
|
||||
padding: 0 0.3em;
|
||||
}
|
||||
}
|
||||
.veryfaint {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.login-hint {
|
||||
text-align: center;
|
||||
|
@ -31,6 +31,66 @@ library.add(
|
||||
faList
|
||||
)
|
||||
|
||||
export const TIMELINES = {
|
||||
home: {
|
||||
route: 'friends',
|
||||
anonRoute: 'public-timeline',
|
||||
icon: 'home',
|
||||
label: 'nav.home_timeline',
|
||||
criteria: ['!private']
|
||||
},
|
||||
public: {
|
||||
route: 'public-timeline',
|
||||
anon: true,
|
||||
icon: 'users',
|
||||
label: 'nav.public_tl',
|
||||
criteria: ['!private']
|
||||
},
|
||||
twkn: {
|
||||
route: 'public-external-timeline',
|
||||
anon: true,
|
||||
icon: 'globe',
|
||||
label: 'nav.twkn',
|
||||
criteria: ['!private', 'federating']
|
||||
},
|
||||
bookmarks: {
|
||||
route: 'bookmarks',
|
||||
icon: 'bookmark',
|
||||
label: 'nav.bookmarks'
|
||||
},
|
||||
dms: {
|
||||
route: 'dms',
|
||||
icon: 'envelope',
|
||||
label: 'nav.dms'
|
||||
}
|
||||
}
|
||||
export const ROOT_ITEMS = {
|
||||
interactions: {
|
||||
route: 'interactions',
|
||||
icon: 'bell',
|
||||
label: 'nav.interactions'
|
||||
},
|
||||
chats: {
|
||||
route: 'chats',
|
||||
icon: 'comments',
|
||||
label: 'nav.chats',
|
||||
badgeGetter: 'unreadChatCount'
|
||||
},
|
||||
friendRequests: {
|
||||
route: 'friend-requests',
|
||||
icon: 'user-plus',
|
||||
label: 'nav.friend_requests',
|
||||
criteria: ['lockedUser'],
|
||||
badgeGetter: 'followRequestCount'
|
||||
},
|
||||
about: {
|
||||
route: 'about',
|
||||
anon: true,
|
||||
icon: 'info-circle',
|
||||
label: 'nav.about'
|
||||
}
|
||||
}
|
||||
|
||||
const NavPanel = {
|
||||
created () {
|
||||
if (this.currentUser && this.currentUser.locked) {
|
||||
@ -43,8 +103,11 @@ const NavPanel = {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
collapsed: false,
|
||||
showTimelines: false,
|
||||
showLists: false
|
||||
showLists: false,
|
||||
timelinesList: Object.entries(TIMELINES).map(([k, v]) => ({ ...v, name: k })),
|
||||
rootList: Object.entries(ROOT_ITEMS).map(([k, v]) => ({ ...v, name: k }))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -53,19 +116,57 @@ const NavPanel = {
|
||||
},
|
||||
toggleLists () {
|
||||
this.showLists = !this.showLists
|
||||
},
|
||||
toggleCollapse () {
|
||||
this.collapsed = !this.collapsed
|
||||
},
|
||||
isPinned (item) {
|
||||
return this.pinnedItems.has(item)
|
||||
},
|
||||
togglePin (item) {
|
||||
if (this.isPinned(item)) {
|
||||
this.$store.commit('removeCollectionPreference', { path: 'collections.pinnedNavItems', value: item })
|
||||
} else {
|
||||
this.$store.commit('addCollectionPreference', { path: 'collections.pinnedNavItems', value: item })
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
listsNavigation () {
|
||||
return this.$store.getters.mergedConfig.listsNavigation
|
||||
},
|
||||
...mapState({
|
||||
currentUser: state => state.users.currentUser,
|
||||
followRequestCount: state => state.api.followRequests.length,
|
||||
privateMode: state => state.instance.private,
|
||||
federating: state => state.instance.federating,
|
||||
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable
|
||||
pleromaChatMessagesAvailable: state => state.instance.pleromaChatMessagesAvailable,
|
||||
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems)
|
||||
}),
|
||||
rootItems () {
|
||||
return Object
|
||||
.entries({ ...ROOT_ITEMS })
|
||||
.map(([k, v]) => ({ ...v, name: k }))
|
||||
.filter(({ criteria, anon, anonRoute }) => {
|
||||
const set = new Set(criteria || [])
|
||||
if (!this.federating && set.has('federating')) return false
|
||||
if (this.private && set.has('!private')) return false
|
||||
if (!this.currentUser && !(anon || anonRoute)) return false
|
||||
if ((!this.currentUser || !this.currentUser.locked) && set.has('lockedUser')) return false
|
||||
return true
|
||||
})
|
||||
},
|
||||
pinnedList () {
|
||||
return Object
|
||||
.entries({ ...TIMELINES, ...ROOT_ITEMS })
|
||||
.filter(([k]) => this.pinnedItems.has(k))
|
||||
.map(([k, v]) => ({ ...v, name: k }))
|
||||
.filter(({ criteria, anon, anonRoute }) => {
|
||||
const set = new Set(criteria || [])
|
||||
if (!this.federating && set.has('federating')) return false
|
||||
if (this.private && set.has('!private')) return false
|
||||
if (!this.currentUser && !(anon || anonRoute)) return false
|
||||
if (this.currentUser && !this.currentUser.locked && set.has('locked')) return false
|
||||
return true
|
||||
})
|
||||
},
|
||||
...mapGetters(['unreadChatCount'])
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,33 @@
|
||||
<template>
|
||||
<div class="NavPanel">
|
||||
<div class="panel panel-default">
|
||||
<ul>
|
||||
<div class="panel-heading">
|
||||
<span>
|
||||
<span v-for="item in pinnedList" :key="item.name" class="pinned-item">
|
||||
<router-link
|
||||
:to="{ name: (currentUser || item.anon) ? item.route : item.anonRoute, params: { username: currentUser.screen_name } }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
:icon="item.icon"
|
||||
/>
|
||||
</router-link>
|
||||
</span>
|
||||
</span>
|
||||
<div class="spacer"/>
|
||||
<button
|
||||
class="button-unstyled"
|
||||
@click="toggleCollapse"
|
||||
>
|
||||
<FAIcon
|
||||
class="timelines-chevron"
|
||||
fixed-width
|
||||
:icon="collapsed ? 'chevron-down' : 'chevron-up'"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<ul class="panel-body" v-if="!collapsed">
|
||||
<li v-if="currentUser || !privateMode">
|
||||
<button
|
||||
class="button-unstyled menu-item"
|
||||
@ -22,29 +48,34 @@
|
||||
v-show="showTimelines"
|
||||
class="timelines-background"
|
||||
>
|
||||
<TimelineMenuContent class="timelines" />
|
||||
<TimelineMenuContent class="timelines" :content="timelinesList" />
|
||||
</div>
|
||||
</li>
|
||||
<li v-if="currentUser && listsNavigation">
|
||||
<li v-if="currentUser">
|
||||
<button
|
||||
class="button-unstyled menu-item"
|
||||
@click="toggleLists"
|
||||
>
|
||||
<router-link
|
||||
:to="{ name: 'lists' }"
|
||||
@click.stop
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110"
|
||||
icon="list"
|
||||
/>{{ $t("nav.lists") }}
|
||||
</router-link>
|
||||
<FAIcon
|
||||
class="timelines-chevron"
|
||||
fixed-width
|
||||
:icon="showLists ? 'chevron-up' : 'chevron-down'"
|
||||
/>
|
||||
<router-link
|
||||
:to="{ name: 'lists' }"
|
||||
@click.stop
|
||||
>
|
||||
<FAIcon
|
||||
class="timelines-chevron"
|
||||
fixed-width
|
||||
icon="wrench"
|
||||
/>
|
||||
</router-link>
|
||||
</button>
|
||||
<div
|
||||
v-show="showLists"
|
||||
@ -53,83 +84,31 @@
|
||||
<ListsMenuContent class="timelines" />
|
||||
</div>
|
||||
</li>
|
||||
<li v-if="currentUser && !listsNavigation">
|
||||
<li v-for="item in rootItems" :key="item.name">
|
||||
<router-link
|
||||
:to="{ name: 'lists' }"
|
||||
@click.stop
|
||||
class="menu-item"
|
||||
:to="{ name: (currentUser || item.anon) ? item.route : item.anonRoute, params: { username: currentUser.screen_name } }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
:icon="item.icon"
|
||||
/>{{ $t(item.label) }}
|
||||
<button
|
||||
class="button-unstyled menu-item"
|
||||
@click="toggleLists"
|
||||
>
|
||||
type="button"
|
||||
class="button-unstyled"
|
||||
@click.stop.prevent="togglePin(item.name)"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110"
|
||||
icon="list"
|
||||
/>{{ $t("nav.lists") }}
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
:class="{ 'veryfaint': !isPinned(item.name) }"
|
||||
:transform="!isPinned(item.name) ? 'rotate-45' : ''"
|
||||
icon="thumbtack"
|
||||
/>
|
||||
</button>
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="currentUser">
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'interactions', params: { username: currentUser.screen_name } }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110"
|
||||
icon="bell"
|
||||
/>{{ $t("nav.interactions") }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="currentUser && pleromaChatMessagesAvailable">
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'chats', params: { username: currentUser.screen_name } }"
|
||||
>
|
||||
<div
|
||||
v-if="unreadChatCount"
|
||||
class="badge badge-notification"
|
||||
>
|
||||
{{ unreadChatCount }}
|
||||
</div>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110"
|
||||
icon="comments"
|
||||
/>{{ $t("nav.chats") }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="currentUser && currentUser.locked">
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'friend-requests' }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110"
|
||||
icon="user-plus"
|
||||
/>{{ $t("nav.friend_requests") }}
|
||||
<span
|
||||
v-if="followRequestCount > 0"
|
||||
class="badge badge-notification"
|
||||
>
|
||||
{{ followRequestCount }}
|
||||
</span>
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'about' }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110"
|
||||
icon="info-circle"
|
||||
/>{{ $t("nav.about") }}
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -246,5 +225,12 @@
|
||||
right: 0.6rem;
|
||||
top: 1.25em;
|
||||
}
|
||||
|
||||
.pinned-item {
|
||||
.router-link-exact-active .svg-inline--fa {
|
||||
color: $fallback--text;
|
||||
color: var(--selectedMenuText, $fallback--text);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -124,11 +124,6 @@
|
||||
{{ $t('settings.hide_shoutbox') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<BooleanSetting path="listsNavigation">
|
||||
{{ $t('settings.lists_navigation') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
<li>
|
||||
<h3>{{ $t('settings.columns') }}</h3>
|
||||
</li>
|
||||
|
@ -10,7 +10,7 @@
|
||||
@close="() => isOpen = false"
|
||||
>
|
||||
<template #content>
|
||||
<TimelineMenuContent />
|
||||
<TimelineMenuContent :content="timelinesList" />
|
||||
</template>
|
||||
<template #trigger>
|
||||
<span class="button-unstyled title timeline-menu-title">
|
||||
|
@ -17,12 +17,35 @@ library.add(
|
||||
)
|
||||
|
||||
const TimelineMenuContent = {
|
||||
props: ['content'],
|
||||
methods: {
|
||||
isPinned (item) {
|
||||
return this.pinnedItems.has(item)
|
||||
},
|
||||
togglePin (item) {
|
||||
if (this.isPinned(item)) {
|
||||
this.$store.commit('removeCollectionPreference', { path: 'collections.pinnedNavItems', value: item })
|
||||
} else {
|
||||
this.$store.commit('addCollectionPreference', { path: 'collections.pinnedNavItems', value: item })
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
currentUser: state => state.users.currentUser,
|
||||
privateMode: state => state.instance.private,
|
||||
federating: state => state.instance.federating
|
||||
})
|
||||
federating: state => state.instance.federating,
|
||||
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems)
|
||||
}),
|
||||
list () {
|
||||
return (this.content || []).filter(({ criteria, anon, anonRoute }) => {
|
||||
const set = new Set(criteria || [])
|
||||
if (!this.federating && set.has('federating')) return false
|
||||
if (this.private && set.has('!private')) return false
|
||||
if (!this.currentUser && !(anon || anonRoute)) return false
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,63 +1,28 @@
|
||||
<template>
|
||||
<ul>
|
||||
<li v-if="currentUser">
|
||||
<li v-for="item in list" :key="item.name">
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'friends' }"
|
||||
:to="{ name: (currentUser || item.anon) ? item.route : item.anonRoute, params: { username: currentUser.screen_name } }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
icon="home"
|
||||
/>{{ $t("nav.home_timeline") }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="currentUser || !privateMode">
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'public-timeline' }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
icon="users"
|
||||
/>{{ $t("nav.public_tl") }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="federating && (currentUser || !privateMode)">
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'public-external-timeline' }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
icon="globe"
|
||||
/>{{ $t("nav.twkn") }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="currentUser">
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'bookmarks'}"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
icon="bookmark"
|
||||
/>{{ $t("nav.bookmarks") }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li v-if="currentUser">
|
||||
<router-link
|
||||
class="menu-item"
|
||||
:to="{ name: 'dms', params: { username: currentUser.screen_name } }"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
icon="envelope"
|
||||
/>{{ $t("nav.dms") }}
|
||||
:icon="item.icon"
|
||||
/>{{ $t(item.label) }}
|
||||
<button
|
||||
type="button"
|
||||
class="button-unstyled"
|
||||
@click.stop.prevent="togglePin(item.name)"
|
||||
>
|
||||
<FAIcon
|
||||
fixed-width
|
||||
class="fa-scale-110 fa-old-padding "
|
||||
:class="{ 'veryfaint': !isPinned(item.name) }"
|
||||
:transform="!isPinned(item.name) ? 'rotate-45' : ''"
|
||||
icon="thumbtack"
|
||||
/>
|
||||
</button>
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -87,7 +87,6 @@ export const defaultState = {
|
||||
sidebarColumnWidth: '25rem',
|
||||
contentColumnWidth: '45rem',
|
||||
notifsColumnWidth: '25rem',
|
||||
listsNavigation: false,
|
||||
greentext: undefined, // instance default
|
||||
useAtIcon: undefined, // instance default
|
||||
mentionLinkDisplay: undefined, // instance default
|
||||
|
@ -23,6 +23,9 @@ export const defaultState = {
|
||||
_journal: [],
|
||||
simple: {
|
||||
dontShowUpdateNotifs: false
|
||||
},
|
||||
collections: {
|
||||
pinnedNavItems: ['home', 'dms', 'chats', 'about']
|
||||
}
|
||||
},
|
||||
// raw data
|
||||
@ -274,8 +277,8 @@ export const mutations = {
|
||||
|
||||
totalFlags = _resetFlags(totalFlags)
|
||||
|
||||
recent.flagStorage = totalFlags
|
||||
recent.prefsStorage = totalPrefs
|
||||
recent.flagStorage = { ...flagsTemplate, ...totalFlags }
|
||||
recent.prefsStorage = { ...defaultState.prefsStorage, ...totalPrefs }
|
||||
|
||||
state.dirty = dirty || needsUpload
|
||||
state.cache = recent
|
||||
@ -320,7 +323,7 @@ export const mutations = {
|
||||
return
|
||||
}
|
||||
const collection = new Set(get(state.prefsStorage, path))
|
||||
collection.remove(value)
|
||||
collection.delete(value)
|
||||
set(state.prefsStorage, path, collection)
|
||||
state.prefsStorage._journal = [
|
||||
...state.prefsStorage._journal,
|
||||
|
Loading…
Reference in New Issue
Block a user