(friendly) Responding to the new header design

This commit is contained in:
NoriDev 2023-05-14 14:29:28 +09:00
parent fc8573a9e7
commit de0beaf59b
6 changed files with 88 additions and 40 deletions

View file

@ -9,7 +9,15 @@
이 문서는 CherryPick의 변경 사항만 포함합니다. 전체 변경 사항을 확인하려면, [CHANGELOG.md](CHANGELOG.md) 문서를 참고하십시오.
## 13.5.5-cp-3.1.0 (2023/02/10)
## 13.x.x-cp-3.x.x (unreleased)
### Improvements
- 클라이언트: (friendly) 모바일에서 스크롤 시 각종 요소들의 유동적인 높이 조절을 변경된 헤더 디자인에 대응
### Bugfixes
---
## 13.5.6-cp-3.1.0 (2023/02/10)
이 버전부터 Misskey v13을 대응합니다.
### Improvements

View file

@ -1,6 +1,6 @@
<template>
<div class="ssazuxis">
<header class="_button" :style="{ background: bg }" @click="showBody = !showBody">
<header :class="{ reduceAnimation: !defaultStore.state.animation, showEl: showEl && isMobile && mainRouter().currentRoute.value.name === 'explore' }" class="_button" :style="{ background: bg }" @click="showBody = !showBody">
<div class="title"><div><slot name="header"></slot></div></div>
<div class="divider"></div>
<button class="_button">
@ -26,7 +26,11 @@
import { defineComponent } from 'vue';
import tinycolor from 'tinycolor2';
import { miLocalStorage } from '@/local-storage';
import { mainRouter } from '@/router';
import { defaultStore } from '@/store';
import { eventBus } from '@/scripts/cherrypick/eventBus';
const MOBILE_THRESHOLD = 500;
const miLocalStoragePrefix = 'ui:folder:' as const;
@ -48,6 +52,10 @@ export default defineComponent({
defaultStore,
bg: null,
showBody: (this.persistKey && miLocalStorage.getItem(`${miLocalStoragePrefix}${this.persistKey}`)) ? (miLocalStorage.getItem(`${miLocalStoragePrefix}${this.persistKey}`) === 't') : this.expanded,
showEl: false,
isMobile: window.innerWidth <= MOBILE_THRESHOLD,
isFriendly: miLocalStorage.getItem('ui') === 'friendly',
isAllowHideHeader: mainRouter.currentRoute.value.name === 'index' || mainRouter.currentRoute.value.name === 'explore' || mainRouter.currentRoute.value.name === 'my-notifications' || mainRouter.currentRoute.value.name === 'my-favorites',
};
},
watch: {
@ -71,8 +79,15 @@ export default defineComponent({
const bg = tinycolor(rawBg.startsWith('var(') ? getComputedStyle(document.documentElement).getPropertyValue(rawBg.slice(4, -1)) : rawBg);
bg.setAlpha(0.85);
this.bg = bg.toRgbString();
eventBus.on('showEl', (showEl_receive: boolean) => {
this.showEl = showEl_receive;
});
},
methods: {
mainRouter() {
return mainRouter
},
toggleContent(show: boolean) {
this.showBody = show;
},
@ -122,6 +137,7 @@ export default defineComponent({
top: var(--stickyTop, 0px);
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(20px));
transition: opacity 0.5s, transform 0.5s;
> .title {
display: grid;
@ -137,6 +153,14 @@ export default defineComponent({
background: var(--divider);
}
&.reduceAnimation {
transition: opacity 0s, transform 0s;
}
&.showEl {
transform: translateY(-50.55px);
}
> button {
padding: 12px 0 12px 16px;
}

View file

@ -42,7 +42,7 @@
</div>
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
<MkAvatar :class="[$style.avatar, {[$style.showEl]: showEl}]" :user="appearNote.user" link preview/>
<MkAvatar :class="[$style.avatar, { [$style.showEl]: showEl && mainRouter.currentRoute.value.name === 'index', [$style.showElTab]: showEl && mainRouter.currentRoute.value.name !== 'index' }]" :user="appearNote.user" link preview/>
<div :class="$style.main">
<MkNoteHeader :class="$style.header" :note="appearNote" :mini="true"/>
<MkInstanceTicker v-if="showTicker" :class="$style.ticker" :instance="appearNote.user.instance"/>
@ -167,6 +167,7 @@ import { MenuItem } from '@/types/menu';
import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/scripts/show-moved-dialog';
import { eventBus } from '@/scripts/cherrypick/eventBus';
import { mainRouter } from '@/router';
let showEl = $ref(false);
@ -854,6 +855,10 @@ function showReactions(): void {
&.showEl {
top: 14px;
}
&.showElTab {
top: 54px;
}
}
}

View file

@ -1,6 +1,6 @@
<template>
<div v-if="show" ref="el" :class="[$style.root]" :style="{ background: bg }">
<div :class="[$style.upper, { [$style.slim]: narrow, [$style.thin]: thin_, [$style.reduceAnimation]: !defaultStore.state.animation, [$style.showEl]: showEl && isMobile && isAllowHideHeader }]">
<div :class="[$style.upper, { [$style.slim]: narrow, [$style.thin]: thin_ }]">
<div v-if="!thin_ && narrow && props.displayMyAvatar && $i && !isFriendly" class="_button" :class="$style.buttonsLeft" @click="openAccountMenu">
<MkAvatar :class="$style.avatar" :user="$i"/>
</div>
@ -45,12 +45,9 @@ import { injectPageMetadata } from '@/scripts/page-metadata';
import { $i, openAccountMenu as openAccountMenu_ } from '@/account';
import { miLocalStorage } from '@/local-storage';
import { deviceKind } from '@/scripts/device-kind';
import { mainRouter } from '@/router';
import { defaultStore } from '@/store';
import { eventBus } from '@/scripts/cherrypick/eventBus';
const isFriendly = ref(miLocalStorage.getItem('ui') === 'friendly');
const isAllowHideHeader = ref(mainRouter.currentRoute.value.name === 'index' || mainRouter.currentRoute.value.name === 'explore' || mainRouter.currentRoute.value.name === 'my-notifications' || mainRouter.currentRoute.value.name === 'my-favorites');
const MOBILE_THRESHOLD = 500;
@ -59,9 +56,6 @@ window.addEventListener('resize', () => {
isMobile.value = deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD;
});
let showEl = $ref(false);
let lastScrollPosition = $ref(0);
const props = withDefaults(defineProps<{
tabs?: Tab[];
tab?: string;
@ -138,10 +132,6 @@ onMounted(() => {
});
ro.observe(el.parentElement as HTMLElement);
}
eventBus.on('showEl', (showEl_receive) => {
showEl = showEl_receive;
});
});
onUnmounted(() => {
@ -156,6 +146,11 @@ onUnmounted(() => {
backdrop-filter: var(--blur, blur(15px));
border-bottom: solid 0.5px var(--divider);
width: 100%;
transition: opacity 0.5s, transform 0.5s;
&.reduceAnimation {
transition: opacity 0s, transform 0s;
}
}
.upper,
@ -169,7 +164,6 @@ onUnmounted(() => {
display: flex;
gap: var(--margin);
height: var(--height);
transition: opacity 0.5s, transform 0.5s;
.tabs:first-child {
margin-left: auto;
@ -201,14 +195,6 @@ onUnmounted(() => {
max-width: 100%;
}
}
&.reduceAnimation {
transition: opacity 0s, transform 0s;
}
&.showEl {
transform: translateY(-50.55px);
}
}
.lower {

View file

@ -1,6 +1,6 @@
<template>
<div ref="rootEl">
<div ref="headerEl">
<div :class="[$style.root, {[$style.reduceAnimation]: !defaultStore.state.animation, [$style.showEl]: showEl && isMobile && isAllowHideHeader && mainRouter.currentRoute.value.name !== 'index', [$style.showElTl]: showEl && isMobile && isAllowHideHeader && mainRouter.currentRoute.value.name === 'index' }]" ref="headerEl">
<slot name="header"></slot>
</div>
<div ref="bodyEl" :data-sticky-container-header-height="headerHeight">
@ -15,6 +15,23 @@
<script lang="ts" setup>
import { onMounted, onUnmounted, provide, inject, Ref, ref, watch } from 'vue';
import { CURRENT_STICKY_BOTTOM, CURRENT_STICKY_TOP } from '@/const';
import { miLocalStorage } from '@/local-storage';
import { deviceKind } from '@/scripts/device-kind';
import { mainRouter } from '@/router';
import { defaultStore } from '@/store';
import { eventBus } from '@/scripts/cherrypick/eventBus';
const isFriendly = ref(miLocalStorage.getItem('ui') === 'friendly');
const isAllowHideHeader = ref(mainRouter.currentRoute.value.name === 'index' || mainRouter.currentRoute.value.name === 'explore' || mainRouter.currentRoute.value.name === 'my-notifications' || mainRouter.currentRoute.value.name === 'my-favorites');
const MOBILE_THRESHOLD = 500;
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);
window.addEventListener('resize', () => {
isMobile.value = deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD;
});
let showEl = $ref(false);
const rootEl = $shallowRef<HTMLElement>();
const headerEl = $shallowRef<HTMLElement>();
@ -78,6 +95,10 @@ onMounted(() => {
observer.observe(headerEl);
observer.observe(footerEl);
eventBus.on('showEl', (showEl_receive) => {
showEl = showEl_receive;
});
});
onUnmounted(() => {
@ -86,5 +107,19 @@ onUnmounted(() => {
</script>
<style lang="scss" module>
.root {
transition: opacity 0.5s, transform 0.5s;
&.reduceAnimation {
transition: opacity 0s, transform 0s;
}
&.showEl {
transform: translateY(-50.55px);
}
&.showElTl {
transform: translateY(-90.55px);
}
}
</style>

View file

@ -8,7 +8,7 @@
:enter-from-class="defaultStore.state.animation ? $style.transition_new_enterFrom : ''"
:leave-to-class="defaultStore.state.animation ? $style.transition_new_leaveTo : ''"
>
<div v-if="queue > 0 && defaultStore.state.newNoteRecivedNotificationBehavior === 'default'" :class="[$style.new, {[$style.reduceAnimation]: !defaultStore.state.animation, [$style.showEl]: showEl && isMobile }]"><button class="_buttonPrimary" @click="top()"><i class="ti ti-arrow-up"></i>{{ i18n.ts.newNoteRecived }}</button></div>
<div v-if="queue > 0 && defaultStore.state.newNoteRecivedNotificationBehavior === 'default'" :class="[$style.new, {[$style.reduceAnimation]: !defaultStore.state.animation }]"><button class="_buttonPrimary" @click="top()"><i class="ti ti-arrow-up"></i>{{ i18n.ts.newNoteRecived }}</button></div>
</transition>
<transition
:enter-active-class="defaultStore.state.animation ? $style.transition_new_enterActive : ''"
@ -16,7 +16,7 @@
:enter-from-class="defaultStore.state.animation ? $style.transition_new_enterFrom : ''"
:leave-to-class="defaultStore.state.animation ? $style.transition_new_leaveTo : ''"
>
<div v-if="queue > 0 && defaultStore.state.newNoteRecivedNotificationBehavior === 'count'" :class="[$style.new, {[$style.reduceAnimation]: !defaultStore.state.animation, [$style.showEl]: showEl && isMobile }]"><button class="_buttonPrimary" @click="top()"><i class="ti ti-arrow-up"></i><I18n :src="i18n.ts.newNoteRecivedCount" text-tag="span"><template #n>{{ queue }}</template></I18n></button></div>
<div v-if="queue > 0 && defaultStore.state.newNoteRecivedNotificationBehavior === 'count'" :class="[$style.new, {[$style.reduceAnimation]: !defaultStore.state.animation }]"><button class="_buttonPrimary" @click="top()"><i class="ti ti-arrow-up"></i><I18n :src="i18n.ts.newNoteRecivedCount" text-tag="span"><template #n>{{ queue }}</template></I18n></button></div>
</transition>
</template>
<MkSpacer :content-max="800">
@ -50,9 +50,12 @@ import { instance } from '@/instance';
import { $i } from '@/account';
import { definePageMetadata } from '@/scripts/page-metadata';
import { eventBus } from '@/scripts/cherrypick/eventBus';
import { miLocalStorage } from '@/local-storage';
import { deviceKind } from '@/scripts/device-kind';
provide('shouldOmitHeaderTitle', true);
const isFriendly = ref(miLocalStorage.getItem('ui') === 'friendly');
if (!isFriendly.value) provide('shouldOmitHeaderTitle', true);
const MOBILE_THRESHOLD = 500;
@ -61,8 +64,6 @@ window.addEventListener('resize', () => {
isMobile.value = deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD;
});
let showEl = $ref(false);
const XTutorial = defineAsyncComponent(() => import('./timeline.tutorial.vue'));
const isLocalTimelineAvailable = ($i == null && instance.policies.ltlAvailable) || ($i != null && $i.policies.ltlAvailable);
@ -206,12 +207,6 @@ definePageMetadata(computed(() => ({
title: i18n.ts.timeline,
icon: src === 'local' ? 'ti ti-planet' : src === 'social' ? 'ti ti-rocket' : src === 'global' ? 'ti ti-whirl' : 'ti ti-home',
})));
onMounted(() => {
eventBus.on('showEl', (showEl_receive) => {
showEl = showEl_receive;
});
});
</script>
<style lang="scss" module>
@ -230,7 +225,6 @@ onMounted(() => {
z-index: 1000;
width: 100%;
transition: opacity 0.5s, transform 0.5s;
margin: calc(-0.675em - 8px) 0;
&:first-child {
margin-top: calc(-0.675em - 8px - var(--margin));
@ -240,10 +234,6 @@ onMounted(() => {
transition: opacity 0s, transform 0s;
}
&.showEl {
transform: translateY(-50px);
}
> button {
display: block;
margin: var(--margin) auto 0 auto;