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:
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>