summaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2020-11-29 11:25:43 +0900
committersyuilo <syuilotan@yahoo.co.jp>2020-11-29 11:25:43 +0900
commit9bf5dc67f57d4272a91fef329854d0dc5c8c7245 (patch)
treec8a662fc7a200af9612e3080694cfbe79ab764e9 /src/client
parentwip (diff)
downloadmisskey-9bf5dc67f57d4272a91fef329854d0dc5c8c7245.tar.gz
misskey-9bf5dc67f57d4272a91fef329854d0dc5c8c7245.tar.bz2
misskey-9bf5dc67f57d4272a91fef329854d0dc5c8c7245.zip
wip
Diffstat (limited to 'src/client')
-rw-r--r--src/client/pages/user/index.vue6
-rw-r--r--src/client/pages/welcome.entrance.block.vue1
-rw-r--r--src/client/scripts/get-user-menu.ts11
-rw-r--r--src/client/themes/_dark.json51
-rw-r--r--src/client/themes/_light.json51
-rw-r--r--src/client/ui/visitor/b.vue252
-rw-r--r--src/client/ui/visitor/header.vue235
7 files changed, 364 insertions, 143 deletions
diff --git a/src/client/pages/user/index.vue b/src/client/pages/user/index.vue
index fd2e2f10cb..0c816a2d22 100644
--- a/src/client/pages/user/index.vue
+++ b/src/client/pages/user/index.vue
@@ -508,12 +508,17 @@ export default defineComponent({
}
.ftskorzw.narrow {
+ max-width: 100vw;
+ box-sizing: border-box;
+ overflow: hidden;
+
> .punished {
font-size: 0.8em;
padding: 16px;
}
> .profile {
+
> .main {
position: relative;
overflow: hidden;
@@ -678,6 +683,7 @@ export default defineComponent({
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
+ margin: 0;
}
}
diff --git a/src/client/pages/welcome.entrance.block.vue b/src/client/pages/welcome.entrance.block.vue
index 0e4aefa4b0..b4f5881773 100644
--- a/src/client/pages/welcome.entrance.block.vue
+++ b/src/client/pages/welcome.entrance.block.vue
@@ -136,6 +136,7 @@ export default defineComponent({
> div {
flex: 1;
overflow: auto;
+ background: var(--bg);
}
}
</style>
diff --git a/src/client/scripts/get-user-menu.ts b/src/client/scripts/get-user-menu.ts
index c3de7313cc..a97fed9919 100644
--- a/src/client/scripts/get-user-menu.ts
+++ b/src/client/scripts/get-user-menu.ts
@@ -7,9 +7,10 @@ import getAcct from '../../misc/acct/render';
import * as os from '@/os';
import { store, userActions } from '@/store';
import { router } from '@/router';
-import { popout } from './popout';
export function getUserMenu(user) {
+ const meId = store.getters.isSignedIn ? store.state.i.id : null;
+
async function pushList() {
const t = i18n.global.t('selectList'); // なぜか後で参照すると null になるので最初にメモリに確保しておく
const lists = await os.api('users/lists/list');
@@ -130,7 +131,7 @@ export function getUserMenu(user) {
action: () => {
os.post({ specified: user });
}
- }, store.state.i.id != user.id ? {
+ }, meId != user.id ? {
type: 'link',
icon: faComments,
text: i18n.global.t('startMessaging'),
@@ -139,13 +140,13 @@ export function getUserMenu(user) {
icon: faListUl,
text: i18n.global.t('addToList'),
action: pushList
- }, store.state.i.id != user.id ? {
+ }, meId != user.id ? {
icon: faUsers,
text: i18n.global.t('inviteToGroup'),
action: inviteGroup
} : undefined] as any;
- if (store.getters.isSignedIn && store.state.i.id != user.id) {
+ if (store.getters.isSignedIn && meId != user.id) {
menu = menu.concat([null, {
icon: user.isMuted ? faEye : faEyeSlash,
text: user.isMuted ? i18n.global.t('unmute') : i18n.global.t('mute'),
@@ -175,7 +176,7 @@ export function getUserMenu(user) {
}
}
- if (store.getters.isSignedIn && store.state.i.id === user.id) {
+ if (store.getters.isSignedIn && meId === user.id) {
menu = menu.concat([null, {
icon: faPencilAlt,
text: i18n.global.t('editProfile'),
diff --git a/src/client/themes/_dark.json5 b/src/client/themes/_dark.json5
index f290586eb4..9ce8853614 100644
--- a/src/client/themes/_dark.json5
+++ b/src/client/themes/_dark.json5
@@ -76,5 +76,6 @@
X13: 'rgba(255, 255, 255, 0.15)',
X14: ':alpha<0.5<@navBg',
X15: ':alpha<0<@panel',
+ X16: ':alpha<0.7<@panel',
},
}
diff --git a/src/client/themes/_light.json5 b/src/client/themes/_light.json5
index 0a1125cab7..d08063fdaf 100644
--- a/src/client/themes/_light.json5
+++ b/src/client/themes/_light.json5
@@ -76,5 +76,6 @@
X13: 'rgba(0, 0, 0, 0.15)',
X14: ':alpha<0.5<@navBg',
X15: ':alpha<0<@panel',
+ X16: ':alpha<0.7<@panel',
},
}
diff --git a/src/client/ui/visitor/b.vue b/src/client/ui/visitor/b.vue
index 39ee4e3ed9..6c7366c6f2 100644
--- a/src/client/ui/visitor/b.vue
+++ b/src/client/ui/visitor/b.vue
@@ -4,7 +4,7 @@
<div :style="{ backgroundImage: `url(${ $store.state.instance.meta.backgroundImageUrl })` }">
<div class="fade"></div>
<h1 v-if="meta"><img class="logo" v-if="meta.logoImageUrl" :src="meta.logoImageUrl"><span v-else class="text">{{ instanceName }}</span></h1>
- <div class="about _panel" v-if="meta">
+ <div class="about" v-if="meta">
<div class="desc" v-html="meta.description || $t('introMisskey')"></div>
</div>
<div class="action">
@@ -28,14 +28,35 @@
<div class="main">
<div v-if="narrow" class="banner" :style="{ backgroundImage: `url(${ $store.state.instance.meta.bannerUrl })` }">
- <h1 v-if="meta"><img class="logo" v-if="meta.logoImageUrl" :src="meta.logoImageUrl"><span v-else class="text">{{ instanceName }}</span></h1>
+ <h1 v-if="meta">
+ <MkA to="/" class="link"><img class="logo" v-if="meta.logoImageUrl" :src="meta.logoImageUrl"><span v-else class="text">{{ instanceName }}</span></MkA>
+ </h1>
+ <template v-if="$route.path === '/'">
+ <div class="about" v-if="meta">
+ <div class="desc" v-html="meta.description || $t('introMisskey')"></div>
+ </div>
+ <div class="action">
+ <button class="_buttonPrimary" @click="signup()">{{ $t('signup') }}</button>
+ <button class="_button" @click="signin()">{{ $t('login') }}</button>
+ </div>
+ <div class="announcements panel">
+ <header>{{ $t('announcements') }}</header>
+ <MkPagination :pagination="announcements" #default="{items}" class="list">
+ <section class="item" v-for="(announcement, i) in items" :key="announcement.id">
+ <div class="title">{{ announcement.title }}</div>
+ <div class="content">
+ <Mfm :text="announcement.text"/>
+ <img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
+ </div>
+ </section>
+ </MkPagination>
+ </div>
+ </template>
</div>
- <div class="contents" ref="contents" :class="{ wallpaper }">
- <header class="header" ref="header" v-show="$route.path !== '/'">
- <XHeader :info="pageInfo"/>
- </header>
- <main ref="main">
+ <div class="contents" :class="{ wallpaper }">
+ <XHeader class="header" :info="pageInfo"/>
+ <main>
<router-view v-slot="{ Component }">
<transition :name="$store.state.device.animation ? 'page' : ''" mode="out-in" @enter="onTransition">
<component :is="Component" :ref="changePage"/>
@@ -48,6 +69,27 @@
</div>
</div>
</div>
+
+ <transition name="tray-back">
+ <div class="menu-back _modalBg"
+ v-if="showMenu"
+ @click="showMenu = false"
+ @touchstart.passive="showMenu = false"
+ ></div>
+ </transition>
+
+ <transition name="tray">
+ <div v-if="showMenu" class="menu">
+ <MkA to="/" class="link" active-class="active"><Fa :icon="faHome" class="icon"/>{{ $t('home') }}</MkA>
+ <MkA to="/explore" class="link" active-class="active"><Fa :icon="faHashtag" class="icon"/>{{ $t('explore') }}</MkA>
+ <MkA to="/featured" class="link" active-class="active"><Fa :icon="faFireAlt" class="icon"/>{{ $t('featured') }}</MkA>
+ <MkA to="/channels" class="link" active-class="active"><Fa :icon="faSatelliteDish" class="icon"/>{{ $t('channel') }}</MkA>
+ <div class="action">
+ <button class="_buttonPrimary" @click="signup()">{{ $t('signup') }}</button>
+ <button class="_button" @click="signin()">{{ $t('login') }}</button>
+ </div>
+ </div>
+ </transition>
</div>
</template>
@@ -61,7 +103,7 @@ import MkPagination from '@/components/ui/pagination.vue';
import XSigninDialog from '@/components/signin-dialog.vue';
import XSignupDialog from '@/components/signup-dialog.vue';
import MkButton from '@/components/ui/button.vue';
-import XHeader from '../_common_/header.vue';
+import XHeader from './header.vue';
const DESKTOP_THRESHOLD = 1100;
@@ -79,6 +121,7 @@ export default defineComponent({
pageKey: 0,
pageInfo: null,
meta: null,
+ showMenu: false,
narrow: window.innerWidth < 1280,
announcements: {
endpoint: 'announcements',
@@ -159,6 +202,28 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
+.tray-enter-active,
+.tray-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);
+}
+.tray-enter-from,
+.tray-leave-active {
+ opacity: 0;
+ transform: translateX(-240px);
+}
+
+.tray-back-enter-active,
+.tray-back-leave-active {
+ opacity: 1;
+ transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
+}
+.tray-back-enter-from,
+.tray-back-leave-active {
+ opacity: 0;
+}
+
.mk-app {
display: flex;
min-height: 100vh;
@@ -217,6 +282,8 @@ export default defineComponent({
padding: 24px;
text-align: center;
box-sizing: border-box;
+ text-shadow: 0 0 8px black;
+ color: #fff;
}
> .action {
@@ -272,30 +339,9 @@ export default defineComponent({
> .main {
flex: 1;
- > header {
- position: relative;
- z-index: 1;
- background: var(--panel);
- padding: 0 32px;
- text-align: left;
- overflow: auto;
- white-space: nowrap;
-
- > .link {
- display: inline-block;
- line-height: 60px;
- padding: 0 0.7em;
-
- &.MkA-active {
- box-shadow: 0 -2px 0 0 var(--accent) inset;
- }
- }
- }
-
> .banner {
position: relative;
width: 100%;
- height: 200px;
background-size: cover;
background-position: center;
@@ -311,15 +357,90 @@ export default defineComponent({
}
> h1 {
+ position: relative;
+ z-index: 2;
margin: 0;
padding: 32px;
text-align: center;
color: #fff;
text-shadow: 0 0 8px #000;
- > .logo {
- vertical-align: bottom;
- max-height: 150px;
+ > .link {
+ display: block;
+
+ > ::v-deep(.logo) {
+ vertical-align: bottom;
+ max-height: 100px;
+ }
+ }
+ }
+
+ > .panel {
+ -webkit-backdrop-filter: blur(8px);
+ backdrop-filter: blur(8px);
+ background: rgba(0, 0, 0, 0.5);
+ border-radius: var(--radius);
+
+ &, * {
+ color: #fff !important;
+ }
+ }
+
+ > .about {
+ display: block;
+ margin: 0 0 16px 0;
+ padding: 0 16px 24px 16px;
+ text-align: center;
+ box-sizing: border-box;
+ text-shadow: 0 0 8px black;
+ color: #fff;
+ }
+
+ > .action {
+ padding: 0 64px;
+
+ > button {
+ display: block;
+ width: 100%;
+ padding: 10px;
+ box-sizing: border-box;
+ text-align: center;
+ border-radius: 999px;
+
+ &._button {
+ background: var(--panel);
+ }
+
+ &:first-child {
+ margin-bottom: 16px;
+ }
+ }
+ }
+
+ > .announcements {
+ margin: 64px 64px 16px 64px;
+ text-align: left;
+
+ > header {
+ padding: 12px 16px;
+ border-bottom: solid 1px rgba(255, 255, 255, 0.5);
+ }
+
+ > .list {
+ max-height: 300px;
+ overflow: auto;
+
+ > .item {
+ padding: 12px 16px;
+
+ & + .item {
+ border-top: solid 1px rgba(255, 255, 255, 0.5);
+ }
+
+ > .title {
+ font-weight: bold;
+ }
+ }
}
}
}
@@ -328,21 +449,6 @@ export default defineComponent({
position: relative;
z-index: 1;
- > .header {
- position: sticky;
- top: 0;
- left: 0;
- z-index: 1000;
- height: 60px;
- width: 100%;
- line-height: 60px;
- text-align: center;
- -webkit-backdrop-filter: blur(32px);
- backdrop-filter: blur(32px);
- background-color: var(--header);
- border-bottom: 1px solid var(--divider);
- }
-
> .powered-by {
padding: 28px;
font-size: 14px;
@@ -357,8 +463,54 @@ export default defineComponent({
}
}
}
-}
-</style>
-<style lang="scss">
+ > .menu-back {
+ position: fixed;
+ z-index: 1001;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ }
+
+ > .menu {
+ position: fixed;
+ z-index: 1001;
+ top: 0;
+ left: 0;
+ width: 240px;
+ height: 100vh;
+ background: var(--panel);
+
+ > .link {
+ display: block;
+ padding: 16px;
+
+ > .icon {
+ margin-right: 1em;
+ }
+ }
+
+ > .action {
+ padding: 16px;
+
+ > button {
+ display: block;
+ width: 100%;
+ padding: 10px;
+ box-sizing: border-box;
+ text-align: center;
+ border-radius: 999px;
+
+ &._button {
+ background: var(--panel);
+ }
+
+ &:first-child {
+ margin-bottom: 16px;
+ }
+ }
+ }
+ }
+}
</style>
diff --git a/src/client/ui/visitor/header.vue b/src/client/ui/visitor/header.vue
index ff6fb91443..8086164637 100644
--- a/src/client/ui/visitor/header.vue
+++ b/src/client/ui/visitor/header.vue
@@ -1,31 +1,47 @@
<template>
<div class="sqxihjet">
- <div class="content">
- <MkA to="/" class="link" active-class="active">{{ $t('home') }}</MkA>
- <MkA to="/explore" class="link" active-class="active">{{ $t('explore') }}</MkA>
- <MkA to="/featured" class="link" active-class="active">{{ $t('featured') }}</MkA>
- <MkA to="/channels" class="link" active-class="active">{{ $t('channel') }}</MkA>
- <div class="page link" v-if="info">
- <div class="title">
- <Fa v-if="info.icon" :icon="info.icon" :key="info.icon" class="icon"/>
- <MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true"/>
- <span v-if="info.title" class="text">{{ info.title }}</span>
- <MkUserName v-else-if="info.userName" :user="info.userName" :nowrap="false" class="text"/>
+ <div class="wide" v-if="narrow === false">
+ <div class="content">
+ <MkA to="/" class="link" active-class="active"><Fa :icon="faHome" class="icon"/>{{ $t('home') }}</MkA>
+ <MkA to="/explore" class="link" active-class="active"><Fa :icon="faHashtag" class="icon"/>{{ $t('explore') }}</MkA>
+ <MkA to="/featured" class="link" active-class="active"><Fa :icon="faFireAlt" class="icon"/>{{ $t('featured') }}</MkA>
+ <MkA to="/channels" class="link" active-class="active"><Fa :icon="faSatelliteDish" class="icon"/>{{ $t('channel') }}</MkA>
+ <div class="page active link" v-if="info">
+ <div class="title">
+ <Fa v-if="info.icon" :icon="info.icon" :key="info.icon" class="icon"/>
+ <MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true"/>
+ <span v-if="info.title" class="text">{{ info.title }}</span>
+ <MkUserName v-else-if="info.userName" :user="info.userName" :nowrap="false" class="text"/>
+ </div>
+ <button class="_button action" v-if="info.action" @click.stop="info.action.handler"><Fa :icon="info.action.icon" :key="info.action.icon"/></button>
+ </div>
+ <div class="right">
+ <button class="_button search" @click="search()"><Fa :icon="faSearch" class="icon"/><span>{{ $t('search') }}</span></button>
+ <button class="_buttonPrimary signup" @click="signup()">{{ $t('signup') }}</button>
+ <button class="_button login" @click="signin()">{{ $t('login') }}</button>
</div>
- <button class="_button action" v-if="info.action" @click.stop="info.action.handler"><Fa :icon="info.action.icon" :key="info.action.icon"/></button>
</div>
- <div class="right">
- <button class="_button search" @click="search()"><Fa :icon="faSearch" class="icon"/><span>{{ $t('search') }}</span></button>
- <button class="_buttonPrimary signup" @click="signup()">{{ $t('signup') }}</button>
- <button class="_button login" @click="signin()">{{ $t('login') }}</button>
+ </div>
+ <div class="narrow" v-else-if="narrow === true">
+ <button class="menu _button" @click="$parent.showMenu = true">
+ <Fa :icon="faBars" class="icon"/>
+ </button>
+ <div class="title" v-if="info">
+ <Fa v-if="info.icon" :icon="info.icon" :key="info.icon" class="icon"/>
+ <MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true"/>
+ <span v-if="info.title" class="text">{{ info.title }}</span>
+ <MkUserName v-else-if="info.userName" :user="info.userName" :nowrap="false" class="text"/>
</div>
+ <button class="action _button" v-if="info && info.action" @click.stop="info.action.handler">
+ <Fa :icon="info.action.icon" :key="info.action.icon" class="icon"/>
+ </button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
-import { faSearch } from '@fortawesome/free-solid-svg-icons';
+import { faSearch, faHome, faFireAlt, faHashtag, faSatelliteDish, faBars } from '@fortawesome/free-solid-svg-icons';
import XSigninDialog from '@/components/signin-dialog.vue';
import XSignupDialog from '@/components/signup-dialog.vue';
import * as os from '@/os';
@@ -40,10 +56,16 @@ export default defineComponent({
data() {
return {
- faSearch
+ narrow: null,
+ showMenu: false,
+ faSearch, faHome, faFireAlt, faHashtag, faSatelliteDish, faBars,
};
},
+ mounted() {
+ this.narrow = this.$el.clientWidth < 1300;
+ },
+
methods: {
signin() {
os.popup(XSigninDialog, {
@@ -65,105 +87,142 @@ export default defineComponent({
<style lang="scss" scoped>
.sqxihjet {
$height: 60px;
+ position: sticky;
+ top: 0;
+ left: 0;
+ z-index: 1000;
line-height: $height;
- background: var(--panel);
+ -webkit-backdrop-filter: blur(32px);
+ backdrop-filter: blur(32px);
+ background-color: var(--X16);
- > .content {
- max-width: 1400px;
- margin: 0 auto;
- display: flex;
- align-items: center;
-
- > .link {
- display: inline-block;
- padding: 0 16px;
- line-height: $height - 4px;
- border-top: solid 2px transparent;
- border-bottom: solid 2px transparent;
-
- &.page {
- border-bottom-color: var(--accent);
- }
- }
+ > .wide {
+ > .content {
+ max-width: 1400px;
+ margin: 0 auto;
+ display: flex;
+ align-items: center;
- > .page {
- > .title {
+ > .link {
+ $line: 3px;
display: inline-block;
- vertical-align: bottom;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- position: relative;
+ padding: 0 16px;
+ line-height: $height - ($line * 2);
+ border-top: solid $line transparent;
+ border-bottom: solid $line transparent;
- > .indicator {
- position: absolute;
- top: initial;
- right: 8px;
- top: 8px;
- color: var(--indicator);
- font-size: 12px;
- animation: blink 1s infinite;
+ > .icon {
+ margin-right: 0.5em;
}
- > .icon + .text {
- margin-left: 8px;
+ &.page {
+ border-bottom-color: var(--accent);
}
+ }
- > .avatar {
- $size: 32px;
+ > .page {
+ > .title {
display: inline-block;
- width: $size;
- height: $size;
- vertical-align: middle;
- margin-right: 8px;
- pointer-events: none;
- }
+ vertical-align: bottom;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ position: relative;
- &._button {
- &:hover {
+ > .icon + .text {
+ margin-left: 8px;
+ }
+
+ > .avatar {
+ $size: 32px;
+ display: inline-block;
+ width: $size;
+ height: $size;
+ vertical-align: middle;
+ margin-right: 8px;
+ pointer-events: none;
+ }
+
+ &._button {
+ &:hover {
+ color: var(--fgHighlighted);
+ }
+ }
+
+ &.selected {
+ box-shadow: 0 -2px 0 0 var(--accent) inset;
color: var(--fgHighlighted);
}
}
- &.selected {
- box-shadow: 0 -2px 0 0 var(--accent) inset;
- color: var(--fgHighlighted);
+ > .action {
+ padding: 0 0 0 16px;
}
}
- > .action {
- padding: 0 0 0 16px;
- }
- }
+ > .right {
+ margin-left: auto;
- > .right {
- margin-left: auto;
+ > .search {
+ background: var(--bg);
+ border-radius: 999px;
+ width: 230px;
+ line-height: $height - 20px;
+ margin-right: 16px;
+ text-align: left;
- > .search {
- background: var(--bg);
- border-radius: 999px;
- width: 230px;
- line-height: $height - 20px;
- margin-right: 16px;
- text-align: left;
+ > * {
+ opacity: 0.7;
+ }
- > * {
- opacity: 0.7;
+ > .icon {
+ padding: 0 16px;
+ }
}
- > .icon {
+ > .signup {
+ border-radius: 999px;
+ padding: 0 24px;
+ line-height: $height - 20px;
+ }
+
+ > .login {
padding: 0 16px;
}
}
+ }
+ }
+
+ > .narrow {
+ display: flex;
+
+ > .menu,
+ > .action {
+ width: $height;
+ height: $height;
+ font-size: 20px;
+ }
+
+ > .title {
+ flex: 1;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ position: relative;
+ text-align: center;
- > .signup {
- border-radius: 999px;
- padding: 0 24px;
- line-height: $height - 20px;
+ > .icon + .text {
+ margin-left: 8px;
}
- > .login {
- padding: 0 16px;
+ > .avatar {
+ $size: 32px;
+ display: inline-block;
+ width: $size;
+ height: $size;
+ vertical-align: middle;
+ margin-right: 8px;
+ pointer-events: none;
}
}
}