diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-04-10 12:40:50 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-04-10 12:40:50 +0900 |
| commit | d3fe02fb3e8dd7bfc45c246d54d45acccd5959c7 (patch) | |
| tree | 4cd72e5e5868e89ef3dd83ada99495da2bd7cd85 /src/client/components/sidebar.vue | |
| parent | Fix punycode deprecation warning (#7426) (diff) | |
| download | sharkey-d3fe02fb3e8dd7bfc45c246d54d45acccd5959c7.tar.gz sharkey-d3fe02fb3e8dd7bfc45c246d54d45acccd5959c7.tar.bz2 sharkey-d3fe02fb3e8dd7bfc45c246d54d45acccd5959c7.zip | |
Default UI redesign (#7429)
* wip
* wip
* wip
* wip
* Update default.sidebar.vue
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* wip
* Update sticky-sidebar.ts
* wip
* wip
* Update messaging-room.form.vue
* Update timeline.vue
Diffstat (limited to 'src/client/components/sidebar.vue')
| -rw-r--r-- | src/client/components/sidebar.vue | 458 |
1 files changed, 0 insertions, 458 deletions
diff --git a/src/client/components/sidebar.vue b/src/client/components/sidebar.vue deleted file mode 100644 index 61439781b4..0000000000 --- a/src/client/components/sidebar.vue +++ /dev/null @@ -1,458 +0,0 @@ -<template> -<div class="mvcprjjd"> - <transition name="nav-back"> - <div class="nav-back _modalBg" - v-if="showing" - @click="showing = false" - @touchstart.passive="showing = false" - ></div> - </transition> - - <transition name="nav"> - <nav class="nav" :class="{ iconOnly, hidden }" v-show="showing"> - <div> - <button class="item _button account" @click="openAccountMenu"> - <MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/> - </button> - <MkA class="item index" active-class="active" to="/" exact> - <Fa :icon="faHome" fixed-width/><span class="text">{{ $ts.timeline }}</span> - </MkA> - <template v-for="item in menu"> - <div v-if="item === '-'" class="divider"></div> - <component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'MkA' : 'button'" class="item _button" :class="item" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to"> - <Fa :icon="menuDef[item].icon" fixed-width/><span class="text">{{ $ts[menuDef[item].title] }}</span> - <i v-if="menuDef[item].indicated"><Fa :icon="faCircle"/></i> - </component> - </template> - <div class="divider"></div> - <button class="item _button" :class="{ active: $route.path === '/instance' || $route.path.startsWith('/instance/') }" v-if="$i.isAdmin || $i.isModerator" @click="oepnInstanceMenu"> - <Fa :icon="faServer" fixed-width/><span class="text">{{ $ts.instance }}</span> - </button> - <button class="item _button" @click="more"> - <Fa :icon="faEllipsisH" fixed-width/><span class="text">{{ $ts.more }}</span> - <i v-if="otherNavItemIndicated"><Fa :icon="faCircle"/></i> - </button> - <MkA class="item" active-class="active" to="/settings"> - <Fa :icon="faCog" fixed-width/><span class="text">{{ $ts.settings }}</span> - </MkA> - <button class="item _button post" @click="post"> - <Fa :icon="faPencilAlt" fixed-width/><span class="text">{{ $ts.note }}</span> - </button> - </div> - </nav> - </transition> -</div> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faInfoCircle, faQuestionCircle, faProjectDiagram, faStream, faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; -import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons'; -import { host } from '@client/config'; -import { search } from '@client/scripts/search'; -import * as os from '@client/os'; -import { sidebarDef } from '@client/sidebar'; -import { getAccounts, addAccount, login } from '@client/account'; - -export default defineComponent({ - props: { - defaultHidden: { - type: Boolean, - required: false, - default: false, - } - }, - - data() { - return { - host: host, - showing: false, - accounts: [], - connection: null, - menuDef: sidebarDef, - iconOnly: false, - hidden: this.defaultHidden, - faGripVertical, faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faProjectDiagram - }; - }, - - computed: { - menu(): string[] { - return this.$store.state.menu; - }, - - otherNavItemIndicated(): boolean { - for (const def in this.menuDef) { - if (this.menu.includes(def)) continue; - if (this.menuDef[def].indicated) return true; - } - return false; - }, - }, - - watch: { - $route(to, from) { - this.showing = false; - }, - - '$store.reactiveState.sidebarDisplay.value'() { - this.calcViewState(); - }, - - iconOnly() { - this.$nextTick(() => { - this.$emit('change-view-mode'); - }); - }, - - hidden() { - this.$nextTick(() => { - this.$emit('change-view-mode'); - }); - } - }, - - created() { - window.addEventListener('resize', this.calcViewState); - this.calcViewState(); - }, - - methods: { - calcViewState() { - this.iconOnly = (window.innerWidth <= 1279) || (this.$store.state.sidebarDisplay === 'icon'); - if (!this.defaultHidden) { - this.hidden = (window.innerWidth <= 650); - } - }, - - show() { - this.showing = true; - }, - - post() { - os.post(); - }, - - search() { - search(); - }, - - async openAccountMenu(ev) { - const storedAccounts = getAccounts().filter(x => x.id !== this.$i.id); - const accountsPromise = os.api('users/show', { userIds: storedAccounts.map(x => x.id) }); - - const accountItemPromises = storedAccounts.map(a => new Promise(res => { - accountsPromise.then(accounts => { - const account = accounts.find(x => x.id === a.id); - if (account == null) return res(null); - res({ - type: 'user', - user: account, - action: () => { this.switchAccount(account); } - }); - }); - })); - - os.modalMenu([...[{ - type: 'link', - text: this.$ts.profile, - to: `/@${ this.$i.username }`, - avatar: this.$i, - }, null, ...accountItemPromises, { - icon: faPlus, - text: this.$ts.addAcount, - action: () => { - os.modalMenu([{ - text: this.$ts.existingAcount, - action: () => { this.addAcount(); }, - }, { - text: this.$ts.createAccount, - action: () => { this.createAccount(); }, - }], ev.currentTarget || ev.target); - }, - }]], ev.currentTarget || ev.target, { - align: 'left' - }); - }, - - oepnInstanceMenu(ev) { - os.modalMenu([{ - type: 'link', - text: this.$ts.dashboard, - to: '/instance', - icon: faTachometerAlt, - }, null, this.$i.isAdmin ? { - type: 'link', - text: this.$ts.settings, - to: '/instance/settings', - icon: faCog, - } : undefined, { - type: 'link', - text: this.$ts.customEmojis, - to: '/instance/emojis', - icon: faLaugh, - }, { - type: 'link', - text: this.$ts.users, - to: '/instance/users', - icon: faUsers, - }, { - type: 'link', - text: this.$ts.files, - to: '/instance/files', - icon: faCloud, - }, { - type: 'link', - text: this.$ts.jobQueue, - to: '/instance/queue', - icon: faExchangeAlt, - }, { - type: 'link', - text: this.$ts.federation, - to: '/instance/federation', - icon: faGlobe, - }, { - type: 'link', - text: this.$ts.relays, - to: '/instance/relays', - icon: faProjectDiagram, - }, { - type: 'link', - text: this.$ts.announcements, - to: '/instance/announcements', - icon: faBroadcastTower, - }, { - type: 'link', - text: this.$ts.abuseReports, - to: '/instance/abuses', - icon: faExclamationCircle, - }, { - type: 'link', - text: this.$ts.logs, - to: '/instance/logs', - icon: faStream, - }], ev.currentTarget || ev.target); - }, - - more(ev) { - os.popup(import('./launch-pad.vue'), {}, { - }, 'closed'); - }, - - addAcount() { - os.popup(import('./signin-dialog.vue'), {}, { - done: res => { - addAccount(res.id, res.i); - os.success(); - }, - }, 'closed'); - }, - - createAccount() { - os.popup(import('./signup-dialog.vue'), {}, { - done: res => { - addAccount(res.id, res.i); - this.switchAccountWithToken(res.i); - }, - }, 'closed'); - }, - - switchAccount(account: any) { - const storedAccounts = getAccounts(); - const token = storedAccounts.find(x => x.id === account.id).token; - this.switchAccountWithToken(token); - }, - - switchAccountWithToken(token: string) { - login(token); - }, - } -}); -</script> - -<style lang="scss" scoped> -.nav-enter-active, -.nav-leave-active { - opacity: 1; - transform: translateX(0); - transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1); -} -.nav-enter-from, -.nav-leave-active { - opacity: 0; - transform: translateX(-240px); -} - -.nav-back-enter-active, -.nav-back-leave-active { - opacity: 1; - transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1); -} -.nav-back-enter-from, -.nav-back-leave-active { - opacity: 0; -} - -.mvcprjjd { - $ui-font-size: 1em; // TODO: どこかに集約したい - $nav-width: 250px; - $nav-icon-only-width: 86px; - - > .nav-back { - z-index: 1001; - } - - > .nav { - $avatar-size: 32px; - $avatar-margin: 8px; - - flex: 0 0 $nav-width; - width: $nav-width; - box-sizing: border-box; - - &.iconOnly { - flex: 0 0 $nav-icon-only-width; - width: $nav-icon-only-width; - - &:not(.hidden) { - > div { - width: $nav-icon-only-width; - - > .divider { - margin: 8px auto; - width: calc(100% - 32px); - } - - > .item { - padding-left: 0; - width: 100%; - text-align: center; - font-size: $ui-font-size * 1.1; - line-height: 3.7rem; - - > [data-icon], - > .avatar { - margin-right: 0; - } - - > i { - left: 10px; - } - - > .text { - display: none; - } - - &:first-child { - margin-bottom: 8px; - } - - &:last-child { - margin-top: 8px; - } - } - } - } - } - - &.hidden { - position: fixed; - top: 0; - left: 0; - z-index: 1001; - } - - &:not(.hidden) { - display: block !important; - } - - > div { - position: fixed; - top: 0; - left: 0; - z-index: 1001; - width: $nav-width; - // ほんとは単に 100vh と書きたいところだが... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ - height: calc(var(--vh, 1vh) * 100); - box-sizing: border-box; - overflow: auto; - background: var(--navBg); - - > .divider { - margin: 16px 0; - border-top: solid 1px var(--divider); - } - - > .item { - position: relative; - display: block; - padding-left: 24px; - font-size: $ui-font-size; - line-height: 3rem; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - width: 100%; - text-align: left; - box-sizing: border-box; - color: var(--navFg); - - > [data-icon] { - width: 32px; - } - - > [data-icon], - > .avatar { - margin-right: $avatar-margin; - } - - > .avatar { - width: $avatar-size; - height: $avatar-size; - vertical-align: middle; - } - - > i { - position: absolute; - top: 0; - left: 20px; - color: var(--navIndicator); - font-size: 8px; - animation: blink 1s infinite; - } - - &:hover { - text-decoration: none; - color: var(--navHoverFg); - } - - &.active { - color: var(--navActive); - } - - &:first-child, &:last-child { - position: sticky; - z-index: 1; - padding-top: 8px; - padding-bottom: 8px; - background: var(--X14); - -webkit-backdrop-filter: blur(8px); - backdrop-filter: blur(8px); - } - - &:first-child { - top: 0; - margin-bottom: 16px; - border-bottom: solid 1px var(--divider); - } - - &:last-child { - bottom: 0; - margin-top: 16px; - border-top: solid 1px var(--divider); - } - } - } - } -} -</style> |