logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: 77127e2a588abb5bf329506ff7e006021b086e90
parent 04f8c2d29d0e9c5e0341b067e5e783b90c95064b
Author: Henry Jameson <me@hjkos.com>
Date:   Thu, 11 Aug 2022 21:00:27 +0300

you can now pin lists

Diffstat:

Msrc/App.scss15++++++++++++---
Msrc/components/lists_menu/lists_menu_content.js32+++++++++++++++-----------------
Msrc/components/lists_menu/lists_menu_content.vue16+++-------------
Msrc/components/nav_panel/nav_panel.js123+++++++++++++++++++++++--------------------------------------------------------
Msrc/components/nav_panel/nav_panel.vue56++++++++++++++++++--------------------------------------
Msrc/components/timeline/timeline.js1+
Msrc/components/timeline/timeline.vue2+-
Msrc/components/timeline_menu/timeline_menu.js16+++++++++++++---
Msrc/components/timeline_menu/timeline_menu.vue8+++++---
Dsrc/components/timeline_menu/timeline_menu_content.js52----------------------------------------------------
Dsrc/components/timeline_menu/timeline_menu_content.vue31-------------------------------
11 files changed, 103 insertions(+), 249 deletions(-)

diff --git a/src/App.scss b/src/App.scss @@ -117,8 +117,15 @@ h4 { margin: 0; } +.iconLetter { + display: inline-block; + text-align: center; + font-weight: 1000; +} + i[class*=icon-], -.svg-inline--fa { +.svg-inline--fa, +.iconLetter { color: $fallback--icon; color: var(--icon, $fallback--icon); } @@ -746,13 +753,15 @@ option { } .fa-scale-110 { - &.svg-inline--fa { + &.svg-inline--fa, + &.iconLetter { font-size: 1.1em; } } .fa-old-padding { - &.svg-inline--fa { + &.svg-inline--fa, + &.iconLetter { padding: 0 0.3em; } } diff --git a/src/components/lists_menu/lists_menu_content.js b/src/components/lists_menu/lists_menu_content.js @@ -1,28 +1,26 @@ import { mapState } from 'vuex' -import { library } from '@fortawesome/fontawesome-svg-core' -import { - faUsers, - faGlobe, - faBookmark, - faEnvelope, - faHome -} from '@fortawesome/free-solid-svg-icons' +import NavigationEntry from 'src/components/navigation/navigation_entry.vue' -library.add( - faUsers, - faGlobe, - faBookmark, - faEnvelope, - faHome -) +export const getListEntries = state => state.lists.allLists.map(list => ({ + name: 'list-' + list.id, + routeObject: { name: 'lists-timeline', params: { id: list.id } }, + labelRaw: list.title, + iconLetter: list.title[0] +})) -const ListsMenuContent = { +export const ListsMenuContent = { + props: [ + 'showPin' + ], created () { this.$store.dispatch('startFetchingLists') }, + components: { + NavigationEntry + }, computed: { ...mapState({ - lists: state => state.lists.allLists, + lists: getListEntries, currentUser: state => state.users.currentUser, privateMode: state => state.instance.private, federating: state => state.instance.federating diff --git a/src/components/lists_menu/lists_menu_content.vue b/src/components/lists_menu/lists_menu_content.vue @@ -1,17 +1,7 @@ <template> - <ul> - <li - v-for="list in lists.slice().reverse()" - :key="list.id" - > - <router-link - class="menu-item" - :to="{ name: 'lists-timeline', params: { id: list.id } }" - > - {{ list.title }} - </router-link> - </li> - </ul> +<ul> + <NavigationEntry v-for="item in lists" :key="item.name" :show-pin="showPin" :item="item" /> +</ul> </template> <script src="./lists_menu_content.js"></script> diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js @@ -1,6 +1,8 @@ -import TimelineMenuContent from '../timeline_menu/timeline_menu_content.vue' -import ListsMenuContent from '../lists_menu/lists_menu_content.vue' +import { getListEntries, ListsMenuContent } from '../lists_menu/lists_menu_content.vue' import { mapState, mapGetters } from 'vuex' +import { TIMELINES, ROOT_ITEMS } from 'src/components/navigation/navigation.js' +import { filterNavigation } from 'src/components/navigation/filter.js' +import NavigationEntry from 'src/components/navigation/navigation_entry.vue' import { library } from '@fortawesome/fontawesome-svg-core' import { @@ -30,67 +32,6 @@ library.add( faStream, 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) { @@ -98,8 +39,8 @@ const NavPanel = { } }, components: { - TimelineMenuContent, - ListsMenuContent + ListsMenuContent, + NavigationEntry }, data () { return { @@ -134,6 +75,7 @@ const NavPanel = { }, computed: { ...mapState({ + lists: getListEntries, currentUser: state => state.users.currentUser, followRequestCount: state => state.api.followRequests.length, privateMode: state => state.instance.private, @@ -143,31 +85,36 @@ const NavPanel = { collapsed: state => state.serverSideStorage.prefsStorage.simple.collapseNav }), 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 - }) + return filterNavigation( + Object + .entries({ ...ROOT_ITEMS }) + .map(([k, v]) => ({ ...v, name: k })), + { + isFederating: this.federating, + isPrivate: this.private, + currentUser: this.currentUser + } + ) }, 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 - }) + return filterNavigation( + [ + ...Object + .entries({ + ...TIMELINES, + ...ROOT_ITEMS + }) + .filter(([k]) => this.pinnedItems.has(k)) + .map(([k, v]) => ({ ...v, name: k })), + ...this.lists.filter((k) => this.pinnedItems.has(k.name)) + + ], + { + isFederating: this.federating, + isPrivate: this.private, + currentUser: this.currentUser + } + ) }, ...mapGetters(['unreadChatCount']) } diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue @@ -5,13 +5,18 @@ <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 } }" + :to="item.routeObject || { name: (currentUser || item.anon) ? item.route : item.anonRoute, params: { username: currentUser.screen_name } }" > <FAIcon + v-if="item.icon" fixed-width - class="fa-scale-110 fa-old-padding " + class="fa-scale-110 fa-old-padding" :icon="item.icon" /> + <span + v-if="item.iconLetter" + class="iconLetter fa-scale-110 fa-old-padding" + >{{ item.iconLetter }}</span> </router-link> </span> </span> @@ -48,7 +53,9 @@ v-show="showTimelines" class="timelines-background" > - <TimelineMenuContent class="timelines" :content="timelinesList" /> + <ul class="timelines"> + <NavigationEntry v-for="item in timelinesList" :key="item.name" :show-pin="true" :item="item" /> + </ul> </div> </li> <li v-if="currentUser"> @@ -81,34 +88,10 @@ v-show="showLists" class="timelines-background" > - <ListsMenuContent class="timelines" /> + <ListsMenuContent :showPin="true" class="timelines" /> </div> </li> - <li v-for="item in rootItems" :key="item.name"> - <router-link - 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 - 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> + <NavigationEntry v-for="item in rootItems" :key="item.name" :show-pin="true" :item="item" /> </ul> </div> </div> @@ -220,16 +203,13 @@ margin-right: 0.8em; } - .badge { - position: absolute; - right: 0.6rem; - top: 1.25em; - } - .pinned-item { - .router-link-exact-active .svg-inline--fa { - color: $fallback--text; - color: var(--selectedMenuText, $fallback--text); + .router-link-active { + & .svg-inline--fa, + & .iconLetter { + color: $fallback--text; + color: var(--selectedMenuText, $fallback--text); + } } } } diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js @@ -28,6 +28,7 @@ const Timeline = { 'footerSlipgate' // reference to an element where we should put our footer ], data () { + console.log(this.timelineName) return { paused: false, unfocused: false, diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue @@ -1,7 +1,7 @@ <template> <div :class="['Timeline', classes.root]"> <div :class="classes.header"> - <TimelineMenu v-if="!embedded" /> + <TimelineMenu v-if="!embedded" :timeline-name="timelineName"/> <button v-if="showLoadButton" class="button-default loadmore-button" diff --git a/src/components/timeline_menu/timeline_menu.js b/src/components/timeline_menu/timeline_menu.js @@ -1,6 +1,8 @@ import Popover from '../popover/popover.vue' -import TimelineMenuContent from './timeline_menu_content.vue' +import NavigationEntry from 'src/components/navigation/navigation_entry.vue' +import { ListsMenuContent } from '../lists_menu/lists_menu_content.vue' import { library } from '@fortawesome/fontawesome-svg-core' +import { TIMELINES } from 'src/components/navigation/navigation.js' import { faChevronDown } from '@fortawesome/free-solid-svg-icons' @@ -22,11 +24,13 @@ export const timelineNames = () => { const TimelineMenu = { components: { Popover, - TimelineMenuContent + NavigationEntry, + ListsMenuContent }, data () { return { - isOpen: false + isOpen: false, + timelinesList: Object.entries(TIMELINES).map(([k, v]) => ({ ...v, name: k })) } }, created () { @@ -34,6 +38,12 @@ const TimelineMenu = { this.$store.dispatch('setLastTimeline', this.$route.name) } }, + computed: { + useListsMenu () { + const route = this.$route.name + return route === 'lists-timeline' + } + }, methods: { openMenu () { // $nextTick is too fast, animation won't play back but diff --git a/src/components/timeline_menu/timeline_menu.vue b/src/components/timeline_menu/timeline_menu.vue @@ -10,7 +10,10 @@ @close="() => isOpen = false" > <template #content> - <TimelineMenuContent :content="timelinesList" /> + <ListsMenuContent v-if="useListsMenu" :showPin="false" class="timelines" /> + <ul v-else> + <NavigationEntry v-for="item in timelinesList" :key="item.name" :show-pin="false" :item="item" /> + </ul> </template> <template #trigger> <span class="button-unstyled title timeline-menu-title"> @@ -138,8 +141,7 @@ background-color: $fallback--lightBg; background-color: var(--selectedMenu, $fallback--lightBg); color: $fallback--text; - color: var(--selectedMenuText, $fallback--text); - --faint: var(--selectedMenuFaintText, $fallback--faint); + color: var(--selectedMenuText, $fallback--text); --faint: var(--selectedMenuFaintText, $fallback--faint); --faintLink: var(--selectedMenuFaintLink, $fallback--faint); --lightText: var(--selectedMenuLightText, $fallback--lightText); --icon: var(--selectedMenuIcon, $fallback--icon); diff --git a/src/components/timeline_menu/timeline_menu_content.js b/src/components/timeline_menu/timeline_menu_content.js @@ -1,52 +0,0 @@ -import { mapState } from 'vuex' -import { library } from '@fortawesome/fontawesome-svg-core' -import { - faUsers, - faGlobe, - faBookmark, - faEnvelope, - faHome -} from '@fortawesome/free-solid-svg-icons' - -library.add( - faUsers, - faGlobe, - faBookmark, - faEnvelope, - faHome -) - -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, - 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 - }) - } - } -} - -export default TimelineMenuContent diff --git a/src/components/timeline_menu/timeline_menu_content.vue b/src/components/timeline_menu/timeline_menu_content.vue @@ -1,31 +0,0 @@ -<template> - <ul> - <li v-for="item in list" :key="item.name"> - <router-link - 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 - 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> -</template> - -<script src="./timeline_menu_content.js"></script>