Migrate user menu

This commit is contained in:
wvffle 2022-08-05 17:14:17 +00:00 committed by Georg Krause
parent 07abe66af1
commit b3a08c8688
6 changed files with 138 additions and 846 deletions

View File

@ -20,12 +20,9 @@
"dependencies": { "dependencies": {
"@sentry/tracing": "^7.7.0", "@sentry/tracing": "^7.7.0",
"@sentry/vue": "^7.7.0", "@sentry/vue": "^7.7.0",
"@tiptap/starter-kit": "^2.0.0-beta.191",
"@tiptap/vue-3": "^2.0.0-beta.96",
"@vue/runtime-core": "3.2.37", "@vue/runtime-core": "3.2.37",
"@vueuse/core": "8.9.4", "@vueuse/core": "8.9.4",
"@vueuse/integrations": "8.9.4", "@vueuse/integrations": "8.9.4",
"add": "^2.0.6",
"axios": "0.27.2", "axios": "0.27.2",
"axios-auth-refresh": "3.3.3", "axios-auth-refresh": "3.3.3",
"diff": "5.1.0", "diff": "5.1.0",
@ -35,27 +32,21 @@
"howler": "2.2.3", "howler": "2.2.3",
"js-logger": "1.6.1", "js-logger": "1.6.1",
"lodash-es": "4.17.21", "lodash-es": "4.17.21",
"mavon-editor": "^3.0.0-beta",
"moment": "2.29.4", "moment": "2.29.4",
"qs": "6.11.0", "qs": "6.11.0",
"register-service-worker": "1.7.2",
"sanitize-html": "2.7.1",
"sass": "1.54.0", "sass": "1.54.0",
"showdown": "2.1.0", "showdown": "2.1.0",
"text-clipper": "2.2.0", "text-clipper": "2.2.0",
"tiptap-markdown": "^0.5.0",
"transliteration": "2.3.5", "transliteration": "2.3.5",
"universal-cookie": "^4.0.4", "universal-cookie": "^4.0.4",
"vue": "3.2.37", "vue": "3.2.37",
"vue-gettext": "2.1.12", "vue-gettext": "2.1.12",
"vue-plyr": "7.0.0", "vue-plyr": "7.0.0",
"vue-router": "4.1.2", "vue-router": "4.1.2",
"vue-tsc": "0.39.0",
"vue-upload-component": "3.1.2", "vue-upload-component": "3.1.2",
"vue-virtual-scroller": "^2.0.0-alpha.1", "vue-virtual-scroller": "^2.0.0-alpha.1",
"vue3-gettext": "2.3.0", "vue3-gettext": "2.3.0",
"vue3-lazyload": "0.3.5", "vue3-lazyload": "0.3.5",
"vue3-virtual-scroll-list": "0.2.0",
"vuedraggable": "4.1.0", "vuedraggable": "4.1.0",
"vuex": "4.0.2", "vuex": "4.0.2",
"vuex-persistedstate": "4.1.0", "vuex-persistedstate": "4.1.0",
@ -91,7 +82,6 @@
"eslint-plugin-vue": "9.3.0", "eslint-plugin-vue": "9.3.0",
"jest-cli": "28.1.3", "jest-cli": "28.1.3",
"moxios": "0.4.0", "moxios": "0.4.0",
"sentry-vite-plugin": "^1.0.4",
"sinon": "14.0.0", "sinon": "14.0.0",
"ts-jest": "28.0.7", "ts-jest": "28.0.7",
"typescript": "4.7.4", "typescript": "4.7.4",
@ -99,6 +89,7 @@
"vite-plugin-pwa": "0.12.3", "vite-plugin-pwa": "0.12.3",
"vite-plugin-vue-inspector": "1.0.1", "vite-plugin-vue-inspector": "1.0.1",
"vue-jest": "3.0.7", "vue-jest": "3.0.7",
"vue-tsc": "0.39.4",
"workbox-core": "6.5.3", "workbox-core": "6.5.3",
"workbox-precaching": "6.5.3", "workbox-precaching": "6.5.3",
"workbox-routing": "6.5.3", "workbox-routing": "6.5.3",

View File

@ -1,3 +1,39 @@
<script setup lang="ts">
import { useGettext } from 'vue3-gettext'
import useThemeList from '~/composables/useThemeList'
import useTheme from '~/composables/useTheme'
import { computed } from 'vue'
interface Emits {
(e: 'show:shortcuts-modal'): void
}
const emit = defineEmits<Emits>()
const { $pgettext } = useGettext()
const themes = useThemeList()
const theme = useTheme()
const labels = computed(() => ({
profile: $pgettext('*/*/*/Noun', 'Profile'),
settings: $pgettext('*/*/*/Noun', 'Settings'),
logout: $pgettext('Sidebar/Login/List item.Link/Verb', 'Log out'),
about: $pgettext('Sidebar/About/List item.Link', 'About'),
shortcuts: $pgettext('*/*/*/Noun', 'Keyboard shortcuts'),
support: $pgettext('Sidebar/*/Listitem.Link', 'Help'),
forum: $pgettext('Sidebar/*/Listitem.Link', 'Forum'),
docs: $pgettext('Sidebar/*/Listitem.Link', 'Documentation'),
language: $pgettext('Footer/Settings/Dropdown.Label/Short, Verb', 'Change language'),
theme: $pgettext('Footer/Settings/Dropdown.Label/Short, Verb', 'Change theme'),
chat: $pgettext('Sidebar/*/Listitem.Link', 'Chat room'),
git: $pgettext('Footer/*/List item.Link', 'Issue tracker'),
login: $pgettext('*/*/Button.Label/Verb', 'Log in'),
signup: $pgettext('*/*/Button.Label/Verb', 'Sign up'),
notifications: $pgettext('*/Notifications/*', 'Notifications')
}))
</script>
<template> <template>
<div class="ui menu"> <div class="ui menu">
<div class="ui scrolling dropdown item"> <div class="ui scrolling dropdown item">
@ -52,6 +88,13 @@
:to="{name: 'notifications'}" :to="{name: 'notifications'}"
> >
<i class="bell icon" /> <i class="bell icon" />
<div
v-if="$store.state.ui.notifications.inbox > 0"
:title="labels.notifications"
:class="['ui', 'circular', 'mini', 'right floated', 'accent', 'label']"
>
{{ $store.state.ui.notifications.inbox }}
</div>
{{ labels.notifications }} {{ labels.notifications }}
</router-link> </router-link>
<router-link <router-link
@ -105,7 +148,7 @@
<a <a
href="" href=""
class="item" class="item"
@click.prevent="showShortcuts" @click.prevent="emit('show:shortcuts-modal')"
> >
<i class="keyboard icon" /> <i class="keyboard icon" />
{{ labels.shortcuts }} {{ labels.shortcuts }}
@ -150,49 +193,3 @@
</template> </template>
</div> </div>
</template> </template>
<script>
import { mapGetters } from 'vuex'
import useThemeList from '~/composables/useThemeList'
import useTheme from '~/composables/useTheme'
export default {
setup () {
return {
theme: useTheme(),
themes: useThemeList()
}
},
computed: {
labels () {
return {
profile: this.$pgettext('*/*/*/Noun', 'Profile'),
settings: this.$pgettext('*/*/*/Noun', 'Settings'),
logout: this.$pgettext('Sidebar/Login/List item.Link/Verb', 'Log out'),
about: this.$pgettext('Sidebar/About/List item.Link', 'About'),
shortcuts: this.$pgettext('*/*/*/Noun', 'Keyboard shortcuts'),
support: this.$pgettext('Sidebar/*/Listitem.Link', 'Help'),
forum: this.$pgettext('Sidebar/*/Listitem.Link', 'Forum'),
docs: this.$pgettext('Sidebar/*/Listitem.Link', 'Documentation'),
language: this.$pgettext('Footer/Settings/Dropdown.Label/Short, Verb', 'Change language'),
theme: this.$pgettext('Footer/Settings/Dropdown.Label/Short, Verb', 'Change theme'),
chat: this.$pgettext('Sidebar/*/Listitem.Link', 'Chat room'),
git: this.$pgettext('Footer/*/List item.Link', 'Issue tracker'),
login: this.$pgettext('*/*/Button.Label/Verb', 'Log in'),
signup: this.$pgettext('*/*/Button.Label/Verb', 'Sign up'),
notifications: this.$pgettext('*/Notifications/*', 'Notifications')
}
},
...mapGetters({
additionalNotifications: 'ui/additionalNotifications'
})
},
methods: {
showShortcuts () {
this.$emit('show:shortcuts-modal')
console.log(this.$store.getters['ui/windowSize'])
}
}
}
</script>

View File

@ -101,7 +101,7 @@ const loadSound = (track: Track): Sound => {
onplay () { onplay () {
const [otherId] = (this as any)._getSoundIds() const [otherId] = (this as any)._getSoundIds()
const [currentId] = (currentSound.value?.howl as any)._getSoundIds() ?? [] const [currentId] = (currentSound.value?.howl as any)?._getSoundIds() ?? []
if (otherId !== currentId) { if (otherId !== currentId) {
return (this as any).stop() return (this as any).stop()

View File

@ -1,10 +1,12 @@
import type { InitModule } from '~/types' import type { InitModule } from '~/types'
import type { RootState } from '~/store'
import type { Router } from 'vue-router' import type { Router } from 'vue-router'
import type { App } from 'vue' import type { Store } from 'vuex'
import { watchEffect, type App } from 'vue'
const COOKIE = 'allow-tracing' const COOKIE = 'allow-tracing'
const initSentry = async (app: App, router: Router) => { const initSentry = async (app: App, router: Router, store: Store<RootState>) => {
const [{ default: useLogger }, { BrowserTracing }, Sentry] = await Promise.all([ const [{ default: useLogger }, { BrowserTracing }, Sentry] = await Promise.all([
import('~/composables/useLogger'), import('~/composables/useLogger'),
import('@sentry/tracing'), import('@sentry/tracing'),
@ -16,7 +18,7 @@ const initSentry = async (app: App, router: Router) => {
Sentry.init({ Sentry.init({
app, app,
dsn: import.meta.env.VUE_SENTRY_DSN, dsn: import.meta.env.FUNKWHALE_SENTRY_DSN,
logErrors: true, logErrors: true,
trackComponents: true, trackComponents: true,
integrations: [ integrations: [
@ -35,10 +37,33 @@ const initSentry = async (app: App, router: Router) => {
'Image failed to load!' 'Image failed to load!'
] ]
}) })
watchEffect(() => {
const url = store.getters['instance/domain']
Sentry.setTag('instance', url)
})
const setUser = (user: { username: string, [key: string]: any } | null) => {
Sentry.setUser(user)
Sentry.setContext('user', user)
}
watchEffect(() => {
if (store.state.auth.authenticated) {
return setUser({
username: store.state.auth.username,
canPublish: store.state.auth.availablePermissions.library,
canModerate: store.state.auth.availablePermissions.moderation,
isAdmin: store.state.auth.availablePermissions.settings
})
}
setUser(null)
})
} }
export const install: InitModule = async ({ app, router, store }) => { export const install: InitModule = async ({ app, router, store }) => {
if (import.meta.env.VUE_SENTRY_DSN) { if (import.meta.env.FUNKWHALE_SENTRY_DSN) {
const [{ useCookies }, { gettext: { $pgettext } }] = await Promise.all([ const [{ useCookies }, { gettext: { $pgettext } }] = await Promise.all([
import('@vueuse/integrations/useCookies'), import('@vueuse/integrations/useCookies'),
import('~/init/locale') import('~/init/locale')
@ -49,11 +74,11 @@ export const install: InitModule = async ({ app, router, store }) => {
const allowed = get(COOKIE) const allowed = get(COOKIE)
if (allowed === 'yes') { if (allowed === 'yes') {
return initSentry(app, router) return initSentry(app, router, store)
} }
if (allowed === undefined) { if (allowed === undefined) {
const { hostname, origin } = new URL(import.meta.env.VUE_SENTRY_DSN) const { hostname, origin } = new URL(import.meta.env.FUNKWHALE_SENTRY_DSN)
return store.commit('ui/addMessage', { return store.commit('ui/addMessage', {
content: hostname === 'am.funkwhale.audio' content: hostname === 'am.funkwhale.audio'
? $pgettext( ? $pgettext(
@ -76,7 +101,7 @@ export const install: InitModule = async ({ app, router, store }) => {
class: 'primary', class: 'primary',
click: () => { click: () => {
set(COOKIE, 'yes') set(COOKIE, 'yes')
return initSentry(app, router) return initSentry(app, router, store)
} }
}, },
{ {

View File

@ -1,5 +1,4 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import Sentry from 'sentry-vite-plugin'
import Vue from '@vitejs/plugin-vue' import Vue from '@vitejs/plugin-vue'
import Inspector from 'vite-plugin-vue-inspector' import Inspector from 'vite-plugin-vue-inspector'
import { VitePWA } from 'vite-plugin-pwa' import { VitePWA } from 'vite-plugin-pwa'
@ -9,23 +8,8 @@ const port = +(process.env.VUE_PORT ?? 8080)
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({ export default defineConfig(({ mode }) => ({
envPrefix: 'VUE_', envPrefix: ['VUE_', 'FUNKWHALE_SENTRY_'],
plugins: [ plugins: [
// https://github.com/huyanhai/sentry-vite-plugin
Sentry({
url: process.env.VUE_SENTRY_DSN?.split(/(\/|@)/)[6],
include: './dist',
ignore: ['node_modules', 'vite.config.js'],
cleanSourceMap: false,
dryRun: !process.env.VUE_SENTRY_DSN/* || !!process.env.GITPOD_WORKSPACE_ID */,
setCommits: {
auto: true
},
deploy: {
env: mode
}
}),
// https://github.com/vitejs/vite/tree/main/packages/plugin-vue // https://github.com/vitejs/vite/tree/main/packages/plugin-vue
Vue(), Vue(),

File diff suppressed because it is too large Load Diff