Merge pull request #3365 from h3poteto/iss-3301/global-header

refs #3301 Rewrite GlobalHeader with composition API
This commit is contained in:
AkiraFukushima 2022-05-22 17:48:34 +09:00 committed by GitHub
commit 5fd66348a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 41 deletions

View File

@ -2,7 +2,7 @@
<div id="global_header"> <div id="global_header">
<el-menu <el-menu
v-if="!hide" v-if="!hide"
:default-active="activeRoute()" :default-active="activeRoute"
class="el-menu-vertical account-menu" class="el-menu-vertical account-menu"
:collapse="true" :collapse="true"
:router="true" :router="true"
@ -14,7 +14,7 @@
<el-menu-item <el-menu-item
:index="`/${account._id}/`" :index="`/${account._id}/`"
:route="{ path: `/${account._id}/home` }" :route="{ path: `/${account._id}/home` }"
v-for="(account, index) in accounts" v-for="(account, _index) in accounts"
v-bind:key="account._id" v-bind:key="account._id"
role="menuitem" role="menuitem"
> >
@ -34,56 +34,69 @@
</div> </div>
</template> </template>
<script> <script lang="ts">
import { mapState } from 'vuex' import { defineComponent, computed, onMounted } from 'vue'
import FailoverImg from '~/src/renderer/components/atoms/FailoverImg' import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { useI18next } from 'vue3-i18next'
import { useStore } from '@/store'
import FailoverImg from '@/components/atoms/FailoverImg.vue'
import { StreamingError } from '~/src/errors/streamingError' import { StreamingError } from '~/src/errors/streamingError'
import { ACTION_TYPES } from '@/store/GlobalHeader'
export default { export default defineComponent({
components: { components: {
FailoverImg FailoverImg
}, },
name: 'global-header', name: 'global-header',
computed: { setup() {
...mapState('GlobalHeader', { const space = 'GlobalHeader'
accounts: state => state.accounts, const store = useStore()
hide: state => state.hide const route = useRoute()
}), const router = useRouter()
...mapState({ const i18n = useI18next()
themeColor: state => state.App.theme.global_header_color
const accounts = computed(() => store.state.GlobalHeader.accounts)
const hide = computed(() => store.state.GlobalHeader.hide)
const themeColor = computed(() => store.state.App.theme.global_header_color)
const activeRoute = computed(() => `/${route.path.split('/')[1]}/`)
onMounted(() => {
initialize()
}) })
},
created() { const initialize = async () => {
this.initialize() await store
}, .dispatch(`${space}/initLoad`)
methods: {
activeRoute() {
return `/${this.$route.path.split('/')[1]}/`
},
async initialize() {
await this.$store
.dispatch('GlobalHeader/initLoad')
.then(accounts => { .then(accounts => {
this.$store.dispatch('GlobalHeader/startStreamings').catch(err => { store.dispatch(`${space}/${ACTION_TYPES.START_STREAMINGS}`).catch(err => {
if (err instanceof StreamingError) { if (err instanceof StreamingError) {
this.$message({ ElMessage({
message: this.$t('message.start_all_streamings_error', { message: i18n.t('message.start_all_streamings_error', {
domain: err.domain domain: err.domain
}), }),
type: 'error' type: 'error'
}) })
} }
}) })
if (this.$route.params.id === undefined) { if (route.params.id === undefined) {
this.$router.push({ path: `/${accounts[0]._id}/home` }) router.push({ path: `/${accounts[0]._id}/home` })
} }
}) })
.catch(_ => { .catch(_ => {
return this.$router.push({ path: '/login' }) return router.push({ path: '/login' })
}) })
} }
return {
accounts,
hide,
themeColor,
activeRoute
} }
} },
methods: {}
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -3,7 +3,7 @@
* @param element a target dom element * @param element a target dom element
* @param point scroll target point of the element * @param point scroll target point of the element
**/ **/
export default function scrollTop(element, point = 0) { export default function scrollTop(element: HTMLElement, point: number = 0) {
const start = element.scrollTop const start = element.scrollTop
const range = start - point const range = start - point
// Progress of scroll: 0 ~ 100 // Progress of scroll: 0 ~ 100
@ -32,26 +32,28 @@ export default function scrollTop(element, point = 0) {
/** /**
* easeOut * easeOut
**/ **/
const easeOut = function (p) { const easeOut = function (p: number) {
return p * (2 - p) return p * (2 - p)
} }
export class ScrollPosition { export class ScrollPosition {
node = null private node: HTMLElement | null = null
previousScrollHeightMinusTop = 0 private previousScrollHeightMinusTop: number = 0
constructor(node) { constructor(node: HTMLElement) {
this.node = node this.node = node
this.previousScrollHeightMinusTop = 0 this.previousScrollHeightMinusTop = 0
} }
prepare() { prepare() {
this.previousScrollHeightMinusTop = if (this.node) {
this.node.scrollHeight - this.node.scrollTop this.previousScrollHeightMinusTop = this.node.scrollHeight - this.node.scrollTop
}
} }
restore() { restore() {
this.node.scrollTop = if (this.node) {
this.node.scrollHeight - this.previousScrollHeightMinusTop this.node.scrollTop = this.node.scrollHeight - this.previousScrollHeightMinusTop
}
} }
} }

View File

@ -37,6 +37,20 @@ const mutations: MutationTree<GlobalHeaderState> = {
} }
} }
export const ACTION_TYPES = {
INIT_LOAD: 'initLoad',
START_STREAMINGS: 'startStreamings',
LIST_ACCOUNTS: 'listAccounts',
REFRESH_ACCOUNTS: 'refreshAccounts',
WATCH_SHORTCUT_EVENTS: 'watchShortcutEvents',
REMOVE_SHORTCUT_EVENTS: 'removeShortcutEvents',
LOAD_HIDE: 'loadHide',
SWITCH_HIDE: 'switchHide',
START_USER_STREAMINGS: 'startUserStreamings',
STOP_USER_STREAMINGS: 'stopUserStreamings',
BIND_NOTIFICATION: 'bindNotification'
}
const actions: ActionTree<GlobalHeaderState, RootState> = { const actions: ActionTree<GlobalHeaderState, RootState> = {
initLoad: async ({ dispatch }): Promise<Array<LocalAccount>> => { initLoad: async ({ dispatch }): Promise<Array<LocalAccount>> => {
// Ignore error // Ignore error