Merge branch 'develop' into img-max
This commit is contained in:
32
packages/frontend/src/components/MkAccountMoved.vue
Normal file
32
packages/frontend/src/components/MkAccountMoved.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div :class="$style.root">
|
||||
<i class="ti ti-plane-departure" style="margin-right: 8px;"></i>
|
||||
{{ i18n.ts.accountMoved }}
|
||||
<MkMention :class="$style.link" :username="acct" :host="host ?? localHost"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MkMention from './MkMention.vue';
|
||||
import { i18n } from '@/i18n';
|
||||
import { host as localHost } from '@/config';
|
||||
|
||||
defineProps<{
|
||||
acct: string;
|
||||
host: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
padding: 16px;
|
||||
font-size: 90%;
|
||||
background: var(--infoWarnBg);
|
||||
color: var(--error);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
.link {
|
||||
margin-left: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -17,8 +17,8 @@
|
||||
<MkInput v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder || undefined" :autocomplete="input.autocomplete" @keydown="onInputKeydown">
|
||||
<template v-if="input.type === 'password'" #prefix><i class="ti ti-lock"></i></template>
|
||||
<template #caption>
|
||||
<span v-if="okButtonDisabled && disabledReason === 'charactersExceeded'" v-text="i18n.t('_dialog.charactersExceeded', { current: (inputValue as string).length, max: input.maxLength ?? 'NaN' })" />
|
||||
<span v-else-if="okButtonDisabled && disabledReason === 'charactersBelow'" v-text="i18n.t('_dialog.charactersBelow', { current: (inputValue as string).length, min: input.minLength ?? 'NaN' })" />
|
||||
<span v-if="okButtonDisabled && disabledReason === 'charactersExceeded'" v-text="i18n.t('_dialog.charactersExceeded', { current: (inputValue as string).length, max: input.maxLength ?? 'NaN' })"/>
|
||||
<span v-else-if="okButtonDisabled && disabledReason === 'charactersBelow'" v-text="i18n.t('_dialog.charactersBelow', { current: (inputValue as string).length, min: input.minLength ?? 'NaN' })"/>
|
||||
</template>
|
||||
</MkInput>
|
||||
<MkSelect v-if="select" v-model="selectedValue" autofocus>
|
||||
@@ -32,11 +32,11 @@
|
||||
</template>
|
||||
</MkSelect>
|
||||
<div v-if="(showOkButton || showCancelButton) && !actions" :class="$style.buttons">
|
||||
<MkButton v-if="showOkButton" inline primary :autofocus="!input && !select" :disabled="okButtonDisabled" @click="ok">{{ okText ?? ((showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt) }}</MkButton>
|
||||
<MkButton v-if="showCancelButton || input || select" inline @click="cancel">{{ cancelText ?? i18n.ts.cancel }}</MkButton>
|
||||
<MkButton v-if="showOkButton" inline primary rounded :autofocus="!input && !select" :disabled="okButtonDisabled" @click="ok">{{ okText ?? ((showCancelButton || input || select) ? i18n.ts.ok : i18n.ts.gotIt) }}</MkButton>
|
||||
<MkButton v-if="showCancelButton || input || select" inline rounded @click="cancel">{{ cancelText ?? i18n.ts.cancel }}</MkButton>
|
||||
</div>
|
||||
<div v-if="actions" :class="$style.buttons">
|
||||
<MkButton v-for="action in actions" :key="action.text" inline :primary="action.primary" :danger="action.danger" @click="() => { action.callback(); modal?.close(); }">{{ action.text }}</MkButton>
|
||||
<MkButton v-for="action in actions" :key="action.text" inline rounded :primary="action.primary" :danger="action.danger" @click="() => { action.callback(); modal?.close(); }">{{ action.text }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</MkModal>
|
||||
|
||||
@@ -439,6 +439,7 @@ defineExpose({
|
||||
|
||||
&.asDrawer {
|
||||
width: 100% !important;
|
||||
padding: 12px 0 max(env(safe-area-inset-bottom, 0px), 12px) 0;
|
||||
|
||||
> .emojis {
|
||||
::v-deep(section) {
|
||||
|
||||
@@ -11,15 +11,21 @@
|
||||
<div :class="$style.body" class="_shadow" @mousedown="onBodyMousedown" @keydown="onKeydown">
|
||||
<div :class="[$style.header, { [$style.mini]: mini }]" @contextmenu.prevent.stop="onContextmenu">
|
||||
<span :class="$style.headerLeft">
|
||||
<button v-for="button in buttonsLeft" v-tooltip="button.title" class="_button" :class="[$style.headerButton, { [$style.highlighted]: button.highlighted }]" @click="button.onClick"><i :class="button.icon"></i></button>
|
||||
<template v-if="!minimized">
|
||||
<button v-for="button in buttonsLeft" v-tooltip="button.title" class="_button" :class="[$style.headerButton, { [$style.highlighted]: button.highlighted }]" @click="button.onClick"><i :class="button.icon"></i></button>
|
||||
</template>
|
||||
</span>
|
||||
<span :class="$style.headerTitle" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown">
|
||||
<slot name="header"></slot>
|
||||
</span>
|
||||
<span :class="$style.headerRight">
|
||||
<button v-for="button in buttonsRight" v-tooltip="button.title" class="_button" :class="[$style.headerButton, { [$style.highlighted]: button.highlighted }]" @click="button.onClick"><i :class="button.icon"></i></button>
|
||||
<template v-if="!minimized">
|
||||
<button v-for="button in buttonsRight" v-tooltip="button.title" class="_button" :class="[$style.headerButton, { [$style.highlighted]: button.highlighted }]" @click="button.onClick"><i :class="button.icon"></i></button>
|
||||
</template>
|
||||
<button v-if="canResize && minimized" v-tooltip="i18n.ts.windowRestore" class="_button" :class="$style.headerButton" @click="unMinimize()"><i class="ti ti-maximize"></i></button>
|
||||
<button v-else-if="canResize && !maximized" v-tooltip="i18n.ts.windowMinimize" class="_button" :class="$style.headerButton" @click="minimize()"><i class="ti ti-minimize"></i></button>
|
||||
<button v-if="canResize && maximized" v-tooltip="i18n.ts.windowRestore" class="_button" :class="$style.headerButton" @click="unMaximize()"><i class="ti ti-picture-in-picture"></i></button>
|
||||
<button v-else-if="canResize && !maximized" v-tooltip="i18n.ts.windowMaximize" class="_button" :class="$style.headerButton" @click="maximize()"><i class="ti ti-rectangle"></i></button>
|
||||
<button v-else-if="canResize && !maximized && !minimized" v-tooltip="i18n.ts.windowMaximize" class="_button" :class="$style.headerButton" @click="maximize()"><i class="ti ti-rectangle"></i></button>
|
||||
<button v-if="closeButton" v-tooltip="i18n.ts.close" class="_button" :class="$style.headerButton" @click="close()"><i class="ti ti-x"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
@@ -27,7 +33,7 @@
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="canResize">
|
||||
<template v-if="canResize && !minimized">
|
||||
<div :class="$style.handleTop" @mousedown.prevent="onTopHandleMousedown"></div>
|
||||
<div :class="$style.handleRight" @mousedown.prevent="onRightHandleMousedown"></div>
|
||||
<div :class="$style.handleBottom" @mousedown.prevent="onBottomHandleMousedown"></div>
|
||||
@@ -100,10 +106,11 @@ let rootEl = $shallowRef<HTMLElement | null>();
|
||||
let showing = $ref(true);
|
||||
let beforeClickedAt = 0;
|
||||
let maximized = $ref(false);
|
||||
let unMaximizedTop = '';
|
||||
let unMaximizedLeft = '';
|
||||
let unMaximizedWidth = '';
|
||||
let unMaximizedHeight = '';
|
||||
let minimized = $ref(false);
|
||||
let unResizedTop = '';
|
||||
let unResizedLeft = '';
|
||||
let unResizedWidth = '';
|
||||
let unResizedHeight = '';
|
||||
|
||||
function close() {
|
||||
showing = false;
|
||||
@@ -132,10 +139,10 @@ function top() {
|
||||
|
||||
function maximize() {
|
||||
maximized = true;
|
||||
unMaximizedTop = rootEl.style.top;
|
||||
unMaximizedLeft = rootEl.style.left;
|
||||
unMaximizedWidth = rootEl.style.width;
|
||||
unMaximizedHeight = rootEl.style.height;
|
||||
unResizedTop = rootEl.style.top;
|
||||
unResizedLeft = rootEl.style.left;
|
||||
unResizedWidth = rootEl.style.width;
|
||||
unResizedHeight = rootEl.style.height;
|
||||
rootEl.style.top = '0';
|
||||
rootEl.style.left = '0';
|
||||
rootEl.style.width = '100%';
|
||||
@@ -144,10 +151,35 @@ function maximize() {
|
||||
|
||||
function unMaximize() {
|
||||
maximized = false;
|
||||
rootEl.style.top = unMaximizedTop;
|
||||
rootEl.style.left = unMaximizedLeft;
|
||||
rootEl.style.width = unMaximizedWidth;
|
||||
rootEl.style.height = unMaximizedHeight;
|
||||
rootEl.style.top = unResizedTop;
|
||||
rootEl.style.left = unResizedLeft;
|
||||
rootEl.style.width = unResizedWidth;
|
||||
rootEl.style.height = unResizedHeight;
|
||||
}
|
||||
|
||||
function minimize() {
|
||||
minimized = true;
|
||||
unResizedWidth = rootEl.style.width;
|
||||
unResizedHeight = rootEl.style.height;
|
||||
rootEl.style.width = minWidth + 'px';
|
||||
rootEl.style.height = props.mini ? '32px' : '39px';
|
||||
}
|
||||
|
||||
function unMinimize() {
|
||||
const main = rootEl;
|
||||
if (main == null) return;
|
||||
|
||||
minimized = false;
|
||||
rootEl.style.width = unResizedWidth;
|
||||
rootEl.style.height = unResizedHeight;
|
||||
const browserWidth = window.innerWidth;
|
||||
const browserHeight = window.innerHeight;
|
||||
const windowWidth = main.offsetWidth;
|
||||
const windowHeight = main.offsetHeight;
|
||||
|
||||
const position = main.getBoundingClientRect();
|
||||
if (position.top + windowHeight > browserHeight) main.style.top = browserHeight - windowHeight + 'px';
|
||||
if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px';
|
||||
}
|
||||
|
||||
function onBodyMousedown() {
|
||||
@@ -155,7 +187,11 @@ function onBodyMousedown() {
|
||||
}
|
||||
|
||||
function onDblClick() {
|
||||
maximize();
|
||||
if (minimized) {
|
||||
unMinimize();
|
||||
} else {
|
||||
maximize();
|
||||
}
|
||||
}
|
||||
|
||||
function onHeaderMousedown(evt: MouseEvent) {
|
||||
@@ -187,7 +223,7 @@ function onHeaderMousedown(evt: MouseEvent) {
|
||||
|
||||
const clickX = evt.touches && evt.touches.length > 0 ? evt.touches[0].clientX : evt.clientX;
|
||||
const clickY = evt.touches && evt.touches.length > 0 ? evt.touches[0].clientY : evt.clientY;
|
||||
const moveBaseX = beforeMaximized ? parseInt(unMaximizedWidth, 10) / 2 : clickX - position.left; // TODO: parseIntやめる
|
||||
const moveBaseX = beforeMaximized ? parseInt(unResizedWidth, 10) / 2 : clickX - position.left; // TODO: parseIntやめる
|
||||
const moveBaseY = beforeMaximized ? 20 : clickY - position.top;
|
||||
const browserWidth = window.innerWidth;
|
||||
const browserHeight = window.innerHeight;
|
||||
|
||||
@@ -22,7 +22,7 @@ export const Default = {
|
||||
};
|
||||
},
|
||||
},
|
||||
template: '<MkA v-bind="props">Text</MkA>',
|
||||
template: '<MkA v-bind="props">Misskey</MkA>',
|
||||
};
|
||||
},
|
||||
async play({ canvasElement }) {
|
||||
|
||||
@@ -4,12 +4,16 @@
|
||||
<MkUserOnlineIndicator v-if="indicator" :class="$style.indicator" :user="user"/>
|
||||
<div v-if="user.isCat" :class="[$style.ears, { [$style.mask]: useBlurEffect }]">
|
||||
<div :class="$style.earLeft">
|
||||
<div v-if="useBlurEffect" :class="$style.layer">
|
||||
<div v-if="false" :class="$style.layer">
|
||||
<div :class="$style.plot" :style="{ backgroundImage: `url(${JSON.stringify(url)})` }"/>
|
||||
<div :class="$style.plot" :style="{ backgroundImage: `url(${JSON.stringify(url)})` }"/>
|
||||
<div :class="$style.plot" :style="{ backgroundImage: `url(${JSON.stringify(url)})` }"/>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="$style.earRight">
|
||||
<div v-if="useBlurEffect" :class="$style.layer">
|
||||
<div v-if="false" :class="$style.layer">
|
||||
<div :class="$style.plot" :style="{ backgroundImage: `url(${JSON.stringify(url)})` }"/>
|
||||
<div :class="$style.plot" :style="{ backgroundImage: `url(${JSON.stringify(url)})` }"/>
|
||||
<div :class="$style.plot" :style="{ backgroundImage: `url(${JSON.stringify(url)})` }"/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -195,11 +199,21 @@ watch(() => props.user.avatarBlurhash, () => {
|
||||
|
||||
> .plot {
|
||||
contain: strict;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
clip-path: path('M0 0H1V1H0z');
|
||||
transform: scale(32767);
|
||||
transform-origin: 0 0;
|
||||
opacity: 0.5;
|
||||
|
||||
&:first-child {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
opacity: calc(1 / 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,6 +235,14 @@ watch(() => props.user.avatarBlurhash, () => {
|
||||
|
||||
> .plot {
|
||||
background-position: 20% 10%; /* ~= 37.5deg */
|
||||
|
||||
&:first-child {
|
||||
background-position-x: 21%;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
background-position-y: 11%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,7 +263,16 @@ watch(() => props.user.avatarBlurhash, () => {
|
||||
-38.5857864376%); /* 40 - 2 * sqrt(2) */
|
||||
|
||||
> .plot {
|
||||
position: absolute;
|
||||
background-position: 80% 10%; /* ~= 37.5deg */
|
||||
|
||||
&:first-child {
|
||||
background-position-x: 79%;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
background-position-y: 11%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { waitFor } from '@storybook/testing-library';
|
||||
import { StoryObj } from '@storybook/vue3';
|
||||
import MkPageHeader from './MkPageHeader.vue';
|
||||
export const Empty = {
|
||||
@@ -22,16 +23,16 @@ export const Empty = {
|
||||
template: '<MkPageHeader v-bind="props" />',
|
||||
};
|
||||
},
|
||||
async play() {
|
||||
const wait = new Promise((resolve) => setTimeout(resolve, 800));
|
||||
await waitFor(async () => await wait);
|
||||
},
|
||||
args: {
|
||||
static: true,
|
||||
tabs: [],
|
||||
},
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
chromatic: {
|
||||
/* This component has animations that are implemented with JavaScript. So it's unstable to take a snapshot. */
|
||||
disableSnapshot: true,
|
||||
},
|
||||
},
|
||||
} satisfies StoryObj<typeof MkPageHeader>;
|
||||
export const OneTab = {
|
||||
|
||||
Reference in New Issue
Block a user