Merge remote-tracking branch 'origin/develop' into migrate/vuex-to-pinia

This commit is contained in:
Henry Jameson 2025-01-30 18:08:05 +02:00
commit 58e18d48df
489 changed files with 31167 additions and 9871 deletions

View file

@ -1,4 +1,4 @@
export const filterNavigation = (list = [], { hasChats, hasAnnouncements, isFederating, isPrivate, currentUser }) => {
export const filterNavigation = (list = [], { hasChats, hasAnnouncements, isFederating, isPrivate, currentUser, supportsBookmarkFolders }) => {
return list.filter(({ criteria, anon, anonRoute }) => {
const set = new Set(criteria || [])
if (!isFederating && set.has('federating')) return false
@ -7,6 +7,7 @@ export const filterNavigation = (list = [], { hasChats, hasAnnouncements, isFede
if ((!currentUser || !currentUser.locked) && set.has('lockedUser')) return false
if (!hasChats && set.has('chats')) return false
if (!hasAnnouncements && set.has('announcements')) return false
if (supportsBookmarkFolders && set.has('!supportsBookmarkFolders')) return false
return true
})
}
@ -17,3 +18,12 @@ export const getListEntries = store => store.allLists.map(list => ({
labelRaw: list.title,
iconLetter: list.title[0]
}))
export const getBookmarkFolderEntries = state => state.bookmarkFolders.allFolders.map(folder => ({
name: 'bookmark-folder-' + folder.id,
routeObject: { name: 'bookmark-folder', params: { id: folder.id } },
labelRaw: folder.name,
iconEmoji: folder.emoji,
iconEmojiUrl: folder.emoji_url,
iconLetter: folder.name[0]
}))

View file

@ -1,11 +1,16 @@
// routes that take :username property
export const USERNAME_ROUTES = new Set([
'bookmarks',
'dms',
'interactions',
'notifications',
'chat',
'chats',
'user-profile'
'chats'
])
// routes that take :name property
export const NAME_ROUTES = new Set([
'user-profile',
'legacy-user-profile'
])
export const TIMELINES = {
@ -32,7 +37,8 @@ export const TIMELINES = {
bookmarks: {
route: 'bookmarks',
icon: 'bookmark',
label: 'nav.bookmarks'
label: 'nav.bookmarks',
criteria: ['!supportsBookmarkFolders']
},
favorites: {
routeObject: { name: 'user-profile', query: { tab: 'favorites' } },
@ -56,6 +62,7 @@ export const ROOT_ITEMS = {
route: 'chats',
icon: 'comments',
label: 'nav.chats',
badgeStyle: 'notification',
badgeGetter: 'unreadChatCount',
criteria: ['chats']
},
@ -63,6 +70,7 @@ export const ROOT_ITEMS = {
route: 'friend-requests',
icon: 'user-plus',
label: 'nav.friend_requests',
badgeStyle: 'notification',
criteria: ['lockedUser'],
badgeGetter: 'followRequestCount'
},
@ -77,8 +85,16 @@ export const ROOT_ITEMS = {
icon: 'bullhorn',
label: 'nav.announcements',
store: 'announcements',
badgeStyle: 'notification',
badgeGetter: 'unreadAnnouncementCount',
criteria: ['announcements']
},
drafts: {
route: 'drafts',
icon: 'file-pen',
label: 'nav.drafts',
badgeStyle: 'neutral',
badgeGetter: 'draftCount'
}
}
@ -94,7 +110,9 @@ export function routeTo (item, currentUser) {
}
if (USERNAME_ROUTES.has(route.name)) {
route.params = { username: currentUser.screen_name, name: currentUser.screen_name }
route.params = { username: currentUser.screen_name }
} else if (NAME_ROUTES.has(route.name)) {
route.params = { name: currentUser.screen_name }
}
return route

View file

@ -1,7 +1,6 @@
<template>
<OptionalRouterLink
v-slot="{ isActive, href, navigate } = {}"
ass="ass"
:to="routeTo"
>
<li
@ -11,7 +10,7 @@
>
<component
:is="routeTo ? 'a' : 'button'"
class="main-link button-unstyled"
class="main-link"
:href="href"
@click="navigate"
>
@ -23,11 +22,25 @@
:icon="item.icon"
/>
</span>
<img
v-if="item.iconEmojiUrl"
class="menu-icon iconEmoji iconEmoji-image"
:src="item.iconEmojiUrl"
:alt="item.iconEmoji"
:title="item.iconEmoji"
>
<span
v-if="item.iconLetter"
class="icon iconLetter fa-scale-110 menu-icon"
>{{ item.iconLetter }}
v-else-if="item.iconEmoji"
class="menu-icon iconEmoji"
>
<span>
{{ item.iconEmoji }}
</span>
</span>
<span
v-else-if="item.iconLetter"
class="icon iconLetter fa-scale-110 menu-icon"
>{{ item.iconLetter }}</span>
<span class="label">
{{ item.labelRaw || $t(item.label) }}
</span>
@ -35,7 +48,8 @@
<slot />
<div
v-if="item.badgeGetter && getters[item.badgeGetter]"
class="badge badge-notification"
class="badge"
:class="[`-${item.badgeStyle}`]"
>
{{ getters[item.badgeGetter] }}
</div>
@ -69,73 +83,63 @@
<script src="./navigation_entry.js"></script>
<style lang="scss">
@import "../../variables";
.NavigationEntry.menu-item {
--__line-height: 2.5em;
--__horizontal-gap: 0.5em;
--__vertical-gap: 0.4em;
.NavigationEntry {
display: flex;
box-sizing: border-box;
padding: var(--__vertical-gap) var(--__horizontal-gap);
display: grid;
grid-template-columns: 1fr;
grid-auto-columns: var(--__line-height);
grid-auto-flow: column;
grid-gap: var(--__horizontal-gap);
align-items: baseline;
height: 3.5em;
line-height: 3.5em;
padding: 0 1em;
width: 100%;
color: $fallback--link;
color: var(--link, $fallback--link);
.timelines-chevron {
margin-right: 0;
&[aria-expanded] {
padding-right: var(--__horizontal-gap);
}
.main-link {
flex: 1;
line-height: var(--__line-height);
box-sizing: border-box;
}
.menu-icon {
margin-right: 0.8em;
line-height: var(--__line-height);
padding: 0;
width: var(--__line-height);
margin-right: var(--__horizontal-gap);
}
.timelines-chevron,
.extra-button {
width: 3em;
line-height: var(--__line-height);
width: 100%;
padding: 0;
text-align: center;
}
&:last-child {
margin-right: -0.8em;
.badge {
justify-self: center;
}
.iconEmoji {
display: inline-block;
text-align: center;
object-fit: contain;
vertical-align: middle;
height: var(--__line-height);
width: var(--__line-height);
> span {
font-size: 1.5rem;
}
}
&:hover {
background-color: $fallback--lightBg;
background-color: var(--selectedMenu, $fallback--lightBg);
color: $fallback--link;
color: var(--selectedMenuText, $fallback--link);
--faint: var(--selectedMenuFaintText, $fallback--faint);
--faintLink: var(--selectedMenuFaintLink, $fallback--faint);
--lightText: var(--selectedMenuLightText, $fallback--lightText);
.menu-icon {
--icon: var(--text, $fallback--icon);
}
}
&.-active {
font-weight: bolder;
background-color: $fallback--lightBg;
background-color: var(--selectedMenu, $fallback--lightBg);
color: $fallback--text;
color: var(--selectedMenuText, $fallback--text);
--faint: var(--selectedMenuFaintText, $fallback--faint);
--faintLink: var(--selectedMenuFaintLink, $fallback--faint);
--lightText: var(--selectedMenuLightText, $fallback--lightText);
.menu-icon {
--icon: var(--text, $fallback--icon);
}
&:hover {
text-decoration: underline;
}
img.iconEmoji {
padding: 0.25rem;
box-sizing: border-box;
}
}
</style>

View file

@ -1,7 +1,9 @@
import { mapState } from 'vuex'
import { mapState as mapPiniaState } from 'pinia'
import { TIMELINES, ROOT_ITEMS, routeTo } from 'src/components/navigation/navigation.js'
import { getListEntries, filterNavigation } from 'src/components/navigation/filter.js'
import { getBookmarkFolderEntries, getListEntries, filterNavigation } from 'src/components/navigation/filter.js'
import StillImage from 'src/components/still-image/still-image.vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -36,6 +38,9 @@ const NavPanel = {
return routeTo(item, this.currentUser)
}
},
components: {
StillImage
},
computed: {
getters () {
return this.$store.getters
@ -44,11 +49,13 @@ const NavPanel = {
lists: getListEntries
}),
...mapState({
bookmarks: getBookmarkFolderEntries,
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,
supportsAnnouncements: state => state.announcements.supportsAnnouncements,
pinnedItems: state => new Set(state.serverSideStorage.prefsStorage.collections.pinnedNavItems)
}),
pinnedList () {
@ -60,6 +67,7 @@ const NavPanel = {
],
{
hasChats: this.pleromaChatMessagesAvailable,
hasAnnouncements: this.supportsAnnouncements,
isFederating: this.federating,
isPrivate: this.privateMode,
currentUser: this.currentUser
@ -72,6 +80,7 @@ const NavPanel = {
.filter(([k]) => this.pinnedItems.has(k))
.map(([k, v]) => ({ ...v, name: k })),
...this.lists.filter((k) => this.pinnedItems.has(k.name)),
...this.bookmarks.filter((k) => this.pinnedItems.has(k.name)),
...Object
.entries({ ...ROOT_ITEMS })
.filter(([k]) => this.pinnedItems.has(k))
@ -79,6 +88,7 @@ const NavPanel = {
],
{
hasChats: this.pleromaChatMessagesAvailable,
hasAnnouncements: this.supportsAnnouncements,
isFederating: this.federating,
isPrivate: this.privateMode,
currentUser: this.currentUser

View file

@ -3,7 +3,8 @@
<router-link
v-for="item in pinnedList"
:key="item.name"
class="pinned-item"
class="button-unstyled pinned-item"
active-class="toggled"
:to="getRouteTo(item)"
:title="item.labelRaw || $t(item.label)"
>
@ -13,12 +14,18 @@
:icon="item.icon"
/>
<span
v-if="item.iconLetter"
v-if="item.iconLetter && !item.iconEmoji"
class="iconLetter fa-scale-110 fa-old-padding"
>{{ item.iconLetter }}</span>
<StillImage
v-if="item.iconEmoji"
class="bookmark-emoji"
:src="item.iconEmojiUrl"
/>
<div
v-if="item.badgeGetter && getters[item.badgeGetter]"
class="alert-dot"
class="badge -dot"
:class="[`-${item.badgeStyle}`]"
/>
</router-link>
</span>
@ -27,23 +34,18 @@
<script src="./navigation_pins.js"></script>
<style lang="scss">
@import "../../variables";
.NavigationPins {
display: flex;
flex-wrap: wrap;
overflow: hidden;
height: 100%;
.alert-dot {
border-radius: 100%;
height: 0.5em;
width: 0.5em;
position: absolute;
right: calc(50% - 0.75em);
top: calc(50% - 0.5em);
background-color: $fallback--cRed;
background-color: var(--badgeNotification, $fallback--cRed);
&.alert-dot-notification {
background-color: var(--badgeNotification);
}
&.alert-dot-neutral {
background-color: var(--badgeNeutral);
}
.pinned-item {
@ -55,20 +57,21 @@
box-sizing: border-box;
height: 100%;
.bookmark-emoji {
height: 100%;
box-sizing: border-box;
padding: 0.5em;
}
& .bookmark-emoji,
& .svg-inline--fa,
& .iconLetter {
margin: 0;
}
&.router-link-active {
color: $fallback--text;
color: var(--panelText, $fallback--text);
&.toggled {
margin-bottom: -4px;
border-bottom: 4px solid;
& .svg-inline--fa,
& .iconLetter {
color: inherit;
}
}
}
}