1
0
mirror of https://github.com/hotomoe/hotomoe synced 2024-12-15 07:08:23 +09:00

Imorive client

This commit is contained in:
syuilo 2021-08-05 22:43:14 +09:00
parent 62ccb53c24
commit f6f96ae5bf
8 changed files with 126 additions and 103 deletions

View File

@ -2,12 +2,9 @@
<MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> <MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')">
<div class="hrmcaedk _popup _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }"> <div class="hrmcaedk _popup _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }">
<div class="header" @contextmenu="onContextmenu"> <div class="header" @contextmenu="onContextmenu">
<button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button>
<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
<span class="title"> <span class="title">
<XHeader :info="pageInfo" :with-back="false"/> <XHeader :info="pageInfo" :back-button="history.length > 0" @back="back()" :close-button="true" @close="$refs.modal.close()"/>
</span> </span>
<button class="_button" @click="$refs.modal.close()"><i class="fas fa-times"></i></button>
</div> </div>
<div class="body _flat_"> <div class="body _flat_">
<keep-alive> <keep-alive>
@ -177,35 +174,19 @@ export default defineComponent({
flex-shrink: 0; flex-shrink: 0;
box-shadow: 0px 1px var(--divider); box-shadow: 0px 1px var(--divider);
> button {
height: $height;
width: $height;
@media (max-width: 500px) {
height: $height-narrow;
width: $height-narrow;
}
}
> .title { > .title {
flex: 1; flex: 1;
line-height: $height; height: $height;
padding-left: 32px;
font-weight: bold; font-weight: bold;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
pointer-events: none;
@media (max-width: 500px) { @media (max-width: 500px) {
line-height: $height-narrow; height: $height-narrow;
padding-left: 16px; padding-left: 16px;
} }
} }
> button + .title {
padding-left: 0;
}
} }
> .body { > .body {

View File

@ -3,16 +3,12 @@
:initial-width="500" :initial-width="500"
:initial-height="500" :initial-height="500"
:can-resize="true" :can-resize="true"
:close-right="true" :close-button="false"
:contextmenu="contextmenu" :contextmenu="contextmenu"
@closed="$emit('closed')" @closed="$emit('closed')"
> >
<template #header> <template #header>
<XHeader :info="pageInfo" :with-back="false"/> <XHeader :info="pageInfo" :back-button="history.length > 0" @back="back()" :close-button="true" @close="close()"/>
</template>
<template #buttons>
<button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button>
<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
</template> </template>
<div class="yrolvcoq _flat_"> <div class="yrolvcoq _flat_">
<component :is="component" v-bind="props" :ref="changePage"/> <component :is="component" v-bind="props" :ref="changePage"/>
@ -139,6 +135,10 @@ export default defineComponent({
this.navigate(this.history.pop(), false); this.navigate(this.history.pop(), false);
}, },
close() {
this.$refs.window.close();
},
expand() { expand() {
this.$router.push(this.path); this.$router.push(this.path);
this.$refs.window.close(); this.$refs.window.close();
@ -155,6 +155,5 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.yrolvcoq { .yrolvcoq {
min-height: 100%; min-height: 100%;
background: var(--bg);
} }
</style> </style>

View File

@ -3,15 +3,11 @@
<div class="ebkgocck" :class="{ front }" v-if="showing"> <div class="ebkgocck" :class="{ front }" v-if="showing">
<div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown"> <div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown">
<div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu"> <div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu">
<slot v-if="closeRight" name="buttons"><button class="_button" style="pointer-events: none;"></button></slot> <button v-if="closeButton" class="_button" @click="close()"><i class="fas fa-times"></i></button>
<button v-else class="_button" @click="close()"><i class="fas fa-times"></i></button>
<span class="title" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown"> <span class="title" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown">
<slot name="header"></slot> <slot name="header"></slot>
</span> </span>
<button v-if="closeRight" class="_button" @click="close()"><i class="fas fa-times"></i></button>
<slot v-else name="buttons"><button class="_button" style="pointer-events: none;"></button></slot>
</div> </div>
<div class="body" v-if="padding"> <div class="body" v-if="padding">
<div class="_section"> <div class="_section">
@ -86,10 +82,10 @@ export default defineComponent({
required: false, required: false,
default: false, default: false,
}, },
closeRight: { closeButton: {
type: Boolean, type: Boolean,
required: false, required: false,
default: false, default: true,
}, },
mini: { mini: {
type: Boolean, type: Boolean,

View File

@ -1,8 +1,8 @@
<template> <template>
<div class="cmuxhskf _root" v-hotkey.global="keymap"> <div class="cmuxhskf _root" v-hotkey.global="keymap">
<XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block"/> <XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block _isolated"/>
<XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/> <XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block _isolated" fixed/>
<div class="tabs _block"> <div class="tabs">
<div class="left"> <div class="left">
<button class="_button tab" @click="() => { src = 'home'; saveSrc(); }" :class="{ active: src === 'home' }" v-tooltip="$ts._timelines.home"><i class="fas fa-home"></i></button> <button class="_button tab" @click="() => { src = 'home'; saveSrc(); }" :class="{ active: src === 'home' }" v-tooltip="$ts._timelines.home"><i class="fas fa-home"></i></button>
<button class="_button tab" @click="() => { src = 'local'; saveSrc(); }" :class="{ active: src === 'local' }" v-tooltip="$ts._timelines.local" v-if="isLocalTimelineAvailable"><i class="fas fa-comments"></i></button> <button class="_button tab" @click="() => { src = 'local'; saveSrc(); }" :class="{ active: src === 'local' }" v-tooltip="$ts._timelines.local" v-if="isLocalTimelineAvailable"><i class="fas fa-comments"></i></button>
@ -20,7 +20,6 @@
</div> </div>
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div> <div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
<XTimeline ref="tl" <XTimeline ref="tl"
class="_gap"
:key="src === 'list' ? `list:${list.id}` : src === 'antenna' ? `antenna:${antenna.id}` : src === 'channel' ? `channel:${channel.id}` : src" :key="src === 'list' ? `list:${list.id}` : src === 'antenna' ? `antenna:${antenna.id}` : src === 'channel' ? `channel:${channel.id}` : src"
:src="src" :src="src"
:list="list ? list.id : null" :list="list ? list.id : null"
@ -62,6 +61,7 @@ export default defineComponent({
queue: 0, queue: 0,
[symbols.PAGE_INFO]: computed(() => ({ [symbols.PAGE_INFO]: computed(() => ({
title: this.$ts.timeline, title: this.$ts.timeline,
subtitle: this.src === 'local' ? this.$ts._timelines.local : this.src === 'social' ? this.$ts._timelines.social : this.src === 'global' ? this.$ts._timelines.global : this.$ts._timelines.home,
icon: this.src === 'local' ? 'fas fa-comments' : this.src === 'social' ? 'fas fa-share-alt' : this.src === 'global' ? 'fas fa-globe' : 'fas fa-home', icon: this.src === 'local' ? 'fas fa-comments' : this.src === 'social' ? 'fas fa-share-alt' : this.src === 'global' ? 'fas fa-globe' : 'fas fa-home',
actions: [{ actions: [{
icon: 'fas fa-calendar-alt', icon: 'fas fa-calendar-alt',
@ -211,6 +211,8 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.cmuxhskf { .cmuxhskf {
background: var(--bg);
> .new { > .new {
position: sticky; position: sticky;
top: calc(var(--stickyTop, 0px) + 16px); top: calc(var(--stickyTop, 0px) + 16px);

View File

@ -1,22 +1,29 @@
<template> <template>
<div class="fdidabkb" :class="{ center }" :style="`--height:${height};`" :key="key"> <div class="fdidabkb" :class="{ center }" :style="`--height:${height};`" :key="key">
<transition :name="$store.state.animation ? 'header' : ''" mode="out-in" appear> <transition :name="$store.state.animation ? 'header' : ''" mode="out-in" appear>
<button class="_button back" v-if="withBack && canBack" @click.stop="back()" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button> <div class="buttons left" v-if="backButton">
<button class="_button button back" @click.stop="$emit('back')" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button>
</div>
</transition> </transition>
<template v-if="info"> <template v-if="info">
<div class="titleContainer"> <div class="titleContainer">
<i v-if="info.icon" class="icon" :class="info.icon"></i>
<MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/>
<div class="title"> <div class="title">
<i v-if="info.icon" class="icon" :class="info.icon"></i> <MkUserName v-if="info.userName" :user="info.userName" :nowrap="false" class="title"/>
<MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/> <div v-else-if="info.title" class="title">{{ info.title }}</div>
<MkUserName v-if="info.userName" :user="info.userName" :nowrap="false" class="text"/> <div class="subtitle" v-if="info.subtitle">
<span v-else-if="info.title" class="text">{{ info.title }}</span> {{ info.subtitle }}
</div>
</div> </div>
</div> </div>
<div class="buttons"> <div class="buttons right">
<template v-if="info.actions && showActions"> <template v-if="info.actions && showActions">
<button v-for="action in info.actions" class="_button button" @click.stop="action.handler" v-tooltip="action.text"><i :class="action.icon"></i></button> <button v-for="action in info.actions" class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" v-tooltip="action.text"><i :class="action.icon"></i></button>
</template> </template>
<button v-if="showMenu" class="_button button" @click.stop="menu"><i class="fas fa-ellipsis-h"></i></button> <button v-if="shouldShowMenu" class="_button button" @click.stop="showMenu" v-tooltip="$ts.menu"><i class="fas fa-ellipsis-h"></i></button>
<button v-if="closeButton" class="_button button" @click.stop="$emit('close')" v-tooltip="$ts.close"><i class="fas fa-times"></i></button>
</div> </div>
</template> </template>
</div> </div>
@ -32,10 +39,18 @@ export default defineComponent({
info: { info: {
required: true required: true
}, },
withBack: { menu: {
required: false
},
backButton: {
type: Boolean, type: Boolean,
required: false, required: false,
default: true, default: false,
},
closeButton: {
type: Boolean,
required: false,
default: false,
}, },
center: { center: {
type: Boolean, type: Boolean,
@ -46,7 +61,6 @@ export default defineComponent({
data() { data() {
return { return {
canBack: false,
showActions: false, showActions: false,
height: 0, height: 0,
key: 0, key: 0,
@ -54,10 +68,11 @@ export default defineComponent({
}, },
computed: { computed: {
showMenu() { shouldShowMenu() {
if (this.info.actions != null && !this.showActions) return true; if (this.info.actions != null && !this.showActions) return true;
if (this.info.menu != null) return true; if (this.info.menu != null) return true;
if (this.info.share != null) return true; if (this.info.share != null) return true;
if (this.menu != null) return true;
return false; return false;
} }
}, },
@ -66,13 +81,6 @@ export default defineComponent({
info() { info() {
this.key++; this.key++;
}, },
$route: {
handler(to, from) {
this.canBack = (window.history.length > 0 && !['index'].includes(to.name));
},
immediate: true
},
}, },
mounted() { mounted() {
@ -85,10 +93,6 @@ export default defineComponent({
}, },
methods: { methods: {
back() {
if (this.canBack) this.$router.back();
},
share() { share() {
navigator.share({ navigator.share({
url: url + this.info.path, url: url + this.info.path,
@ -96,7 +100,7 @@ export default defineComponent({
}); });
}, },
menu(ev) { showMenu(ev) {
let menu = this.info.menu ? this.info.menu() : []; let menu = this.info.menu ? this.info.menu() : [];
if (!this.showActions && this.info.actions) { if (!this.showActions && this.info.actions) {
menu = [...this.info.actions.map(x => ({ menu = [...this.info.actions.map(x => ({
@ -113,6 +117,10 @@ export default defineComponent({
action: this.share action: this.share
}); });
} }
if (this.menu) {
if (menu.length > 0) menu.push(null);
menu = menu.concat(this.menu);
}
modalMenu(menu, ev.currentTarget || ev.target); modalMenu(menu, ev.currentTarget || ev.target);
} }
} }
@ -121,62 +129,92 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.fdidabkb { .fdidabkb {
display: flex;
&.center { &.center {
text-align: center; text-align: center;
> .titleContainer { > .titleContainer {
margin: 0 auto; margin: 0 auto;
} }
}
> .back { > .buttons {
position: absolute; &.right {
z-index: 1; margin-left: 0;
top: 0; }
left: 0; }
height: var(--height);
width: var(--height);
} }
> .buttons { > .buttons {
position: absolute; --margin: 8px;
z-index: 1; display: flex;
top: 0; align-items: center;
right: 0; height: var(--height);
margin: 0 var(--margin);
&.right {
margin-left: auto;
}
&:empty {
width: var(--height);
}
> .button { > .button {
height: var(--height); display: flex;
width: var(--height); align-items: center;
justify-content: center;
height: calc(var(--height) - (var(--margin) * 2));
width: calc(var(--height) - (var(--margin) * 2));
box-sizing: border-box;
position: relative;
border-radius: 5px;
&:hover {
background: rgba(0, 0, 0, 0.05);
}
&.highlighted {
color: var(--accent);
}
} }
} }
> .titleContainer { > .titleContainer {
display: flex;
align-items: center;
overflow: auto; overflow: auto;
white-space: nowrap; white-space: nowrap;
width: calc(100% - (var(--height) * 2)); text-align: left;
> .avatar {
$size: 32px;
display: inline-block;
width: $size;
height: $size;
vertical-align: bottom;
margin: 0 8px;
pointer-events: none;
}
> .icon {
margin-right: 8px;
}
> .title { > .title {
display: inline-block; min-width: 0;
vertical-align: bottom;
white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 0 16px; white-space: nowrap;
position: relative; line-height: 1.1;
height: var(--height);
> .icon + .text { > .subtitle {
margin-left: 8px; opacity: 0.6;
} font-size: 0.8em;
font-weight: normal;
> .avatar { white-space: nowrap;
$size: 32px; overflow: hidden;
display: inline-block; text-overflow: ellipsis;
width: $size;
height: $size;
vertical-align: bottom;
margin: calc((var(--height) - #{$size}) / 2) 8px calc((var(--height) - #{$size}) / 2) 0;
pointer-events: none;
} }
} }
} }

View File

@ -1,7 +1,7 @@
<template> <template>
<XColumn v-if="deckStore.state.alwaysShowMainColumn || $route.name !== 'index'" :column="column" :is-stacked="isStacked"> <XColumn v-if="deckStore.state.alwaysShowMainColumn || $route.name !== 'index'" :column="column" :is-stacked="isStacked">
<template #header> <template #header>
<XHeader :info="pageInfo"/> <XHeader :info="pageInfo" :back-button="true" @back="back()"/>
</template> </template>
<router-view v-slot="{ Component }" class="_flat_"> <router-view v-slot="{ Component }" class="_flat_">
@ -56,6 +56,10 @@ export default defineComponent({
} }
}, },
back() {
history.back();
},
onContextmenu(e) { onContextmenu(e) {
const isLink = (el: HTMLElement) => { const isLink = (el: HTMLElement) => {
if (el.tagName === 'A') return true; if (el.tagName === 'A') return true;

View File

@ -4,7 +4,7 @@
<header class="header" @contextmenu.prevent.stop="onContextmenu"> <header class="header" @contextmenu.prevent.stop="onContextmenu">
<button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button> <button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button>
<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button> <button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
<XHeader class="title" :info="pageInfo" :with-back="false"/> <XHeader class="title" :info="pageInfo" :back-button="false"/>
<button class="_button" @click="close()"><i class="fas fa-times"></i></button> <button class="_button" @click="close()"><i class="fas fa-times"></i></button>
</header> </header>
<component :is="component" v-bind="props" :ref="changePage"/> <component :is="component" v-bind="props" :ref="changePage"/>

View File

@ -14,7 +14,7 @@
<main class="main _panel" @contextmenu.stop="onContextmenu"> <main class="main _panel" @contextmenu.stop="onContextmenu">
<header class="header" @click="onHeaderClick"> <header class="header" @click="onHeaderClick">
<XHeader :info="pageInfo"/> <XHeader :info="pageInfo" :back-button="true" @back="back()"/>
</header> </header>
<div class="content" :class="{ _flat_: !fullView }"> <div class="content" :class="{ _flat_: !fullView }">
<router-view v-slot="{ Component }"> <router-view v-slot="{ Component }">
@ -157,6 +157,10 @@ export default defineComponent({
window.scroll({ top: 0, behavior: 'smooth' }); window.scroll({ top: 0, behavior: 'smooth' });
}, },
back() {
history.back();
},
showDrawerNav() { showDrawerNav() {
this.$refs.drawerNav.show(); this.$refs.drawerNav.show();
}, },
@ -287,7 +291,7 @@ export default defineComponent({
min-width: 0; min-width: 0;
width: 750px; width: 750px;
margin: 0 16px 0 0; margin: 0 16px 0 0;
background: var(--bg); background: var(--panel);
border-radius: 0; border-radius: 0;
--margin: 12px; --margin: 12px;
@ -296,14 +300,13 @@ export default defineComponent({
z-index: 1000; z-index: 1000;
top: var(--globalHeaderHeight, 0px); top: var(--globalHeaderHeight, 0px);
height: $header-height; height: $header-height;
line-height: $header-height;
-webkit-backdrop-filter: blur(32px); -webkit-backdrop-filter: blur(32px);
backdrop-filter: blur(32px); backdrop-filter: blur(32px);
background-color: var(--header); background-color: var(--header);
border-bottom: solid 0.5px var(--divider);
} }
> .content { > .content {
background: var(--bg);
--stickyTop: calc(var(--globalHeaderHeight, 0px) + #{$header-height}); --stickyTop: calc(var(--globalHeaderHeight, 0px) + #{$header-height});
} }