Merge branch 'develop' into mkjs-n

This commit is contained in:
tamaina 2023-05-21 12:11:22 +00:00
commit 361ab296c7
36 changed files with 255 additions and 304 deletions

View file

@ -86,7 +86,11 @@ jobs:
if [ "$CHROMATIC_PARAMETER" = " --skip" ]; then
echo "skip=true" >> $GITHUB_OUTPUT
fi
pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static $(echo "$CHROMATIC_PARAMETER")
BRANCH="${{ github.event.pull_request.head.user.login }}:${{ github.event.pull_request.head.ref }}"
if [ "$BRANCH" = "misskey-dev:${{ github.event.pull_request.head.ref }}" ]; then
BRANCH="${{ github.event.pull_request.head.ref }}"
fi
pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name $BRANCH $(echo "$CHROMATIC_PARAMETER")
env:
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
- name: Notify that Chromatic detects changes

View file

@ -27,6 +27,8 @@
- リアクションの取り消し/変更時に確認ダイアログを出すように
- 開発者モードを追加
- AiScriptを0.13.3に更新
- Deck UIを使用している場合、`/`以外にアクセスした際にZen UIで表示するように
- メインカラムを設置していない場合の問題を解決
- Fix: URLプレビューで情報が取得できなかった際の挙動を修正
- Fix: Safari、Firefoxでの新規登録時、パスワードマネージャーにメールアドレスが登録されていた挙動を修正
- fix:ロールタイムラインが無効でも投稿が流れてしまう問題の修正

View file

@ -1,6 +1,6 @@
{
"name": "misskey",
"version": "13.13.0-beta.2",
"version": "13.13.0-beta.3",
"codename": "nasubi",
"repository": {
"type": "git",

View file

@ -35,17 +35,18 @@
"@swc/core-win32-x64-msvc": "1.3.56",
"@tensorflow/tfjs": "4.4.0",
"@tensorflow/tfjs-node": "4.4.0",
"slacc-android-arm-eabi": "0.0.7",
"slacc-android-arm64": "0.0.7",
"slacc-darwin-arm64": "0.0.7",
"slacc-darwin-universal": "0.0.7",
"slacc-darwin-x64": "0.0.7",
"slacc-linux-arm-gnueabihf": "0.0.7",
"slacc-linux-arm64-gnu": "0.0.7",
"slacc-linux-arm64-musl": "0.0.7",
"slacc-linux-x64-gnu": "0.0.7",
"slacc-win32-arm64-msvc": "0.0.7",
"slacc-win32-x64-msvc": "0.0.7"
"slacc-android-arm-eabi": "0.0.9",
"slacc-android-arm64": "0.0.9",
"slacc-darwin-arm64": "0.0.9",
"slacc-darwin-universal": "0.0.9",
"slacc-darwin-x64": "0.0.9",
"slacc-freebsd-x64": "0.0.9",
"slacc-linux-arm-gnueabihf": "0.0.9",
"slacc-linux-arm64-gnu": "0.0.9",
"slacc-linux-arm64-musl": "0.0.9",
"slacc-linux-x64-gnu": "0.0.9",
"slacc-win32-arm64-msvc": "0.0.9",
"slacc-win32-x64-msvc": "0.0.9"
},
"dependencies": {
"@aws-sdk/client-s3": "3.321.1",

View file

@ -25,7 +25,6 @@ html
meta(name='referrer' content='origin')
meta(name='theme-color' content= themeColor || '#86b300')
meta(name='theme-color-orig' content= themeColor || '#86b300')
meta(property='twitter:card' content='summary')
meta(property='og:site_name' content= instanceName || 'Misskey')
meta(name='viewport' content='width=device-width, initial-scale=1')
link(rel='icon' href= icon || '/favicon.ico')
@ -59,6 +58,7 @@ html
meta(property='og:title' content= title || 'Misskey')
meta(property='og:description' content= desc || '✨🌎✨ A interplanetary communication platform ✨🚀✨')
meta(property='og:image' content= img)
meta(property='twitter:card' content='summary')
style
include ../style.css

View file

@ -16,3 +16,4 @@ block og
meta(property='og:description' content= channel.description)
meta(property='og:url' content= url)
meta(property='og:image' content= channel.bannerUrl)
meta(property='twitter:card' content='summary')

View file

@ -17,6 +17,7 @@ block og
meta(property='og:description' content= clip.description)
meta(property='og:url' content= url)
meta(property='og:image' content= avatarUrl)
meta(property='twitter:card' content='summary')
block meta
if profile.noCrawle

View file

@ -17,6 +17,7 @@ block og
meta(property='og:description' content= flash.summary)
meta(property='og:url' content= url)
meta(property='og:image' content= avatarUrl)
meta(property='twitter:card' content='summary')
block meta
if profile.noCrawle

View file

@ -17,6 +17,7 @@ block og
meta(property='og:description' content= post.description)
meta(property='og:url' content= url)
meta(property='og:image' content= post.files[0].thumbnailUrl)
meta(property='twitter:card' content='summary_large_image')
block meta
if user.host || profile.noCrawle

View file

@ -5,6 +5,8 @@ block vars
- const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`;
- const url = `${config.url}/notes/${note.id}`;
- const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null;
- const image = (note.files || []).find(file => file.type.startsWith('image/') && !file.type.isSensitive)
- const video = (note.files || []).find(file => file.type.startsWith('video/') && !file.type.isSensitive)
block title
= `${title} | ${instanceName}`
@ -17,7 +19,19 @@ block og
meta(property='og:title' content= title)
meta(property='og:description' content= summary)
meta(property='og:url' content= url)
meta(property='og:image' content= avatarUrl)
if video
meta(property='og:video:url' content= video.url)
meta(property='og:video:secure_url' content= video.url)
meta(property='og:video:type' content= video.type)
// FIXME: add width and height
// FIXME: add embed player for Twitter
if image
meta(property='twitter:card' content='summary_large_image')
meta(property='og:image' content= image.url)
else
meta(property='twitter:card' content='summary')
meta(property='og:image' content= avatarUrl)
block meta
if user.host || isRenote || profile.noCrawle

View file

@ -17,6 +17,7 @@ block og
meta(property='og:description' content= page.summary)
meta(property='og:url' content= url)
meta(property='og:image' content= page.eyeCatchingImage ? page.eyeCatchingImage.thumbnailUrl : avatarUrl)
meta(property='twitter:card' content= page.eyeCatchingImage ? 'summary_large_image' : 'summary')
block meta
if profile.noCrawle

View file

@ -16,6 +16,7 @@ block og
meta(property='og:description' content= profile.description)
meta(property='og:url' content= url)
meta(property='og:image' content= avatarUrl)
meta(property='twitter:card' content='summary')
block meta
if user.host || profile.noCrawle

View file

@ -397,6 +397,7 @@ function toStories(component: string): string {
Promise.all([
glob('src/components/global/*.vue'),
glob('src/components/Mk{A,B}*.vue'),
glob('src/components/MkDigitalClock.vue'),
glob('src/components/MkGalleryPostPreview.vue'),
glob('src/components/MkSignupServerRules.vue'),
glob('src/components/MkUserSetupDialog.vue'),

View file

@ -16,7 +16,7 @@ import { initializeSw } from '@/scripts/initialize-sw';
export async function mainBoot() {
const { isClientUpdated } = await common(() => createApp(
new URLSearchParams(window.location.search).has('zen') ? defineAsyncComponent(() => import('@/ui/zen.vue')) :
new URLSearchParams(window.location.search).has('zen') || (ui === 'deck' && location.pathname !== '/') ? defineAsyncComponent(() => import('@/ui/zen.vue')) :
!$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) :
ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) :
ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) :

View file

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { StoryObj } from '@storybook/vue3';
import isChromatic from 'chromatic/isChromatic';
import MkAnalogClock from './MkAnalogClock.vue';
import isChromatic from 'chromatic';
export const Default = {
render(args) {
return {

View file

@ -39,6 +39,7 @@
-->
<line
ref="sLine"
:class="[$style.s, { [$style.animate]: !disableSAnimate && sAnimation !== 'none', [$style.elastic]: sAnimation === 'elastic', [$style.easeOut]: sAnimation === 'easeOut' }]"
:x1="5 - (0 * (sHandLengthRatio * handsTailLength))"
:y1="5 + (1 * (sHandLengthRatio * handsTailLength))"
@ -73,9 +74,10 @@
</template>
<script lang="ts" setup>
import { computed, onMounted, onBeforeUnmount } from 'vue';
import { computed, onMounted, onBeforeUnmount, ref } from 'vue';
import tinycolor from 'tinycolor2';
import { globalEvents } from '@/events.js';
import { defaultIdlingRenderScheduler } from '@/scripts/idle-render.js';
// https://stackoverflow.com/questions/1878907/how-can-i-find-the-difference-between-two-angles
const angleDiff = (a: number, b: number) => {
@ -145,6 +147,7 @@ let mAngle = $ref<number>(0);
let sAngle = $ref<number>(0);
let disableSAnimate = $ref(false);
let sOneRound = false;
const sLine = ref<SVGPathElement>();
function tick() {
const now = props.now();
@ -160,17 +163,21 @@ function tick() {
}
hAngle = Math.PI * (h % (props.twentyfour ? 24 : 12) + (m + s / 60) / 60) / (props.twentyfour ? 12 : 6);
mAngle = Math.PI * (m + s / 60) / 30;
if (sOneRound) { // (59->0)
if (sOneRound && sLine.value) { // (59->0)
sAngle = Math.PI * 60 / 30;
window.setTimeout(() => {
defaultIdlingRenderScheduler.delete(tick);
sLine.value.addEventListener('transitionend', () => {
disableSAnimate = true;
window.setTimeout(() => {
requestAnimationFrame(() => {
sAngle = 0;
window.setTimeout(() => {
requestAnimationFrame(() => {
disableSAnimate = false;
}, 100);
}, 100);
}, 700);
if (enabled) {
defaultIdlingRenderScheduler.add(tick);
}
});
});
}, { once: true });
} else {
sAngle = Math.PI * s / 30;
}
@ -194,20 +201,13 @@ function calcColors() {
calcColors();
onMounted(() => {
const update = () => {
if (enabled) {
tick();
window.setTimeout(update, 1000);
}
};
update();
defaultIdlingRenderScheduler.add(tick);
globalEvents.on('themeChanged', calcColors);
});
onBeforeUnmount(() => {
enabled = false;
defaultIdlingRenderScheduler.delete(tick);
globalEvents.off('themeChanged', calcColors);
});
</script>

View file

@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { StoryObj } from '@storybook/vue3';
import isChromatic from 'chromatic/isChromatic';
import MkDigitalClock from './MkDigitalClock.vue';
export const Default = {
render(args) {
return {
components: {
MkDigitalClock,
},
setup() {
return {
args,
};
},
computed: {
props() {
return {
...this.args,
};
},
},
template: '<MkDigitalClock v-bind="props" />',
};
},
args: {
now: isChromatic() ? () => new Date('2023-01-01T10:10:30') : undefined,
},
parameters: {
layout: 'centered',
},
} satisfies StoryObj<typeof MkDigitalClock>;

View file

@ -11,19 +11,21 @@
</template>
<script lang="ts" setup>
import { onUnmounted, ref, watch } from 'vue';
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { defaultIdlingRenderScheduler } from '@/scripts/idle-render.js';
const props = withDefaults(defineProps<{
showS?: boolean;
showMs?: boolean;
offset?: number;
now?: () => Date;
}>(), {
showS: true,
showMs: false,
offset: 0 - new Date().getTimezoneOffset(),
now: () => new Date(),
});
let intervalId;
const hh = ref('');
const mm = ref('');
const ss = ref('');
@ -39,9 +41,9 @@ watch(showColon, (v) => {
}
});
const tick = () => {
const now = new Date();
now.setMinutes(now.getMinutes() + (new Date().getTimezoneOffset() + props.offset));
const tick = (): void => {
const now = props.now();
now.setMinutes(now.getMinutes() + now.getTimezoneOffset() + props.offset);
hh.value = now.getHours().toString().padStart(2, '0');
mm.value = now.getMinutes().toString().padStart(2, '0');
ss.value = now.getSeconds().toString().padStart(2, '0');
@ -52,13 +54,12 @@ const tick = () => {
tick();
watch(() => props.showMs, () => {
if (intervalId) window.clearInterval(intervalId);
intervalId = window.setInterval(tick, props.showMs ? 10 : 1000);
}, { immediate: true });
onMounted(() => {
defaultIdlingRenderScheduler.add(tick);
});
onUnmounted(() => {
window.clearInterval(intervalId);
defaultIdlingRenderScheduler.delete(tick);
});
</script>

View file

@ -58,7 +58,6 @@ function tick() {
if (props.mode === 'relative' || props.mode === 'detail') {
tick();
onUnmounted(() => {
window.clearTimeout(tickId);
});

View file

@ -3,7 +3,7 @@
<MkStickyContainer>
<template #header><XHeader :actions="headerActions"/></template>
<MkSpacer :contentMax="900">
<div>
<div class="_gaps">
<div>
<MkInput v-model="host" :debounce="true" class="">
<template #prefix><i class="ti ti-search"></i></template>

View file

@ -3,29 +3,27 @@
<MkStickyContainer>
<template #header><XHeader :actions="headerActions"/></template>
<MkSpacer :contentMax="900">
<div>
<div>
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<MkSelect v-model="origin" style="margin: 0; flex: 1;">
<template #label>{{ i18n.ts.instance }}</template>
<option value="combined">{{ i18n.ts.all }}</option>
<option value="local">{{ i18n.ts.local }}</option>
<option value="remote">{{ i18n.ts.remote }}</option>
</MkSelect>
<MkInput v-model="searchHost" :debounce="true" type="search" style="margin: 0; flex: 1;" :disabled="pagination.params.origin === 'local'">
<template #label>{{ i18n.ts.host }}</template>
</MkInput>
</div>
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap; padding-top: 1.2em;">
<MkInput v-model="userId" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>User ID</template>
</MkInput>
<MkInput v-model="type" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>MIME type</template>
</MkInput>
</div>
<MkFileListForAdmin :pagination="pagination" :viewMode="viewMode"/>
<div class="_gaps">
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<MkSelect v-model="origin" style="margin: 0; flex: 1;">
<template #label>{{ i18n.ts.instance }}</template>
<option value="combined">{{ i18n.ts.all }}</option>
<option value="local">{{ i18n.ts.local }}</option>
<option value="remote">{{ i18n.ts.remote }}</option>
</MkSelect>
<MkInput v-model="searchHost" :debounce="true" type="search" style="margin: 0; flex: 1;" :disabled="pagination.params.origin === 'local'">
<template #label>{{ i18n.ts.host }}</template>
</MkInput>
</div>
<div class="inputs" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
<MkInput v-model="userId" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>User ID</template>
</MkInput>
<MkInput v-model="type" :debounce="true" type="search" style="margin: 0; flex: 1;">
<template #label>MIME type</template>
</MkInput>
</div>
<MkFileListForAdmin :pagination="pagination" :viewMode="viewMode"/>
</div>
</MkSpacer>
</MkStickyContainer>

View file

@ -0,0 +1,38 @@
class IdlingRenderScheduler {
#renderers: Set<FrameRequestCallback>;
#rafId: number;
#ricId: number;
constructor() {
this.#renderers = new Set();
this.#rafId = 0;
this.#ricId = requestIdleCallback((deadline) => this.#schedule(deadline));
}
#schedule(deadline: IdleDeadline): void {
if (deadline.timeRemaining()) {
this.#rafId = requestAnimationFrame((time) => {
for (const renderer of this.#renderers) {
renderer(time);
}
});
}
this.#ricId = requestIdleCallback((arg) => this.#schedule(arg));
}
add(renderer: FrameRequestCallback): void {
this.#renderers.add(renderer);
}
delete(renderer: FrameRequestCallback): void {
this.#renderers.delete(renderer);
}
dispose(): void {
this.#renderers.clear();
cancelAnimationFrame(this.#rafId);
cancelIdleCallback(this.#ricId);
}
}
export const defaultIdlingRenderScheduler = new IdlingRenderScheduler();

View file

@ -4,27 +4,23 @@
<div :class="$style.main">
<XStatusBars/>
<div ref="columnsEl" :class="[$style.columns, deckStore.reactiveState.columnAlign.value, { [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu">
<template v-for="ids in layout">
<!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section
v-if="ids.length > 1"
:class="$style.folder"
:style="columns.filter(c => ids.includes(c.id)).some(c => c.flexible) ? { flex: 1, minWidth: '350px' } : { width: Math.max(...columns.filter(c => ids.includes(c.id)).map(c => c.width)) + 'px' }"
>
<DeckColumnCore v-for="id in ids" :ref="id" :key="id" :column="columns.find(c => c.id === id)" :isStacked="true" @parentFocus="moveFocus(id, $event)"/>
</section>
<DeckColumnCore
v-else
:ref="ids[0]"
:key="ids[0]"
<div ref="columnsEl" :class="[$style.sections, deckStore.reactiveState.columnAlign.value, { [$style.snapScroll]: snapScroll }]" @contextmenu.self.prevent="onContextmenu">
<!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section
v-for="ids in layout"
:class="$style.section"
:style="columns.filter(c => ids.includes(c.id)).some(c => c.flexible) ? { flex: 1, minWidth: '350px' } : { width: Math.max(...columns.filter(c => ids.includes(c.id)).map(c => c.width)) + 'px' }"
>
<component
:is="columnComponents[columns.find(c => c.id === id)!.type] ?? XTlColumn"
v-for="id in ids"
:ref="id"
:key="id"
:class="$style.column"
:column="columns.find(c => c.id === ids[0])"
:isStacked="false"
:style="columns.find(c => c.id === ids[0])!.flexible ? { flex: 1, minWidth: '350px' } : { width: columns.find(c => c.id === ids[0])!.width + 'px' }"
@parentFocus="moveFocus(ids[0], $event)"
:column="columns.find(c => c.id === id)"
:isStacked="ids.length > 1"
/>
</template>
</section>
<div v-if="layout.length === 0" class="_panel" :class="$style.onboarding">
<div>{{ i18n.ts._deck.introduction }}</div>
<MkButton primary style="margin: 1em auto;" @click="addColumn">{{ i18n.ts._deck.addColumn }}</MkButton>
@ -87,7 +83,6 @@ import { computed, defineAsyncComponent, ref, watch } from 'vue';
import { v4 as uuid } from 'uuid';
import XCommon from './_common_/common.vue';
import { deckStore, addColumn as addColumnToStore, loadDeck, getProfiles, deleteProfile as deleteProfile_ } from './deck/deck-store';
import DeckColumnCore from '@/ui/deck/column-core.vue';
import XSidebar from '@/ui/_common_/navbar.vue';
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue';
import MkButton from '@/components/MkButton.vue';
@ -100,8 +95,31 @@ import { mainRouter } from '@/router';
import { unisonReload } from '@/scripts/unison-reload';
import { deviceKind } from '@/scripts/device-kind';
import { defaultStore } from '@/store';
import XMainColumn from '@/ui/deck/main-column.vue';
import XTlColumn from '@/ui/deck/tl-column.vue';
import XAntennaColumn from '@/ui/deck/antenna-column.vue';
import XListColumn from '@/ui/deck/list-column.vue';
import XChannelColumn from '@/ui/deck/channel-column.vue';
import XNotificationsColumn from '@/ui/deck/notifications-column.vue';
import XWidgetsColumn from '@/ui/deck/widgets-column.vue';
import XMentionsColumn from '@/ui/deck/mentions-column.vue';
import XDirectColumn from '@/ui/deck/direct-column.vue';
import XRoleTimelineColumn from '@/ui/deck/role-timeline-column.vue';
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
const columnComponents = {
main: XMainColumn,
widgets: XWidgetsColumn,
notifications: XNotificationsColumn,
tl: XTlColumn,
list: XListColumn,
channel: XChannelColumn,
antenna: XAntennaColumn,
mentions: XMentionsColumn,
direct: XDirectColumn,
roleTimeline: XRoleTimelineColumn,
};
mainRouter.navHook = (path, flag): boolean => {
if (flag === 'forcePage') return false;
const noMainColumn = !deckStore.state.columns.some(x => x.type === 'main');
@ -187,11 +205,8 @@ window.addEventListener('wheel', (ev) => {
columnsEl.scrollLeft += ev.deltaY;
}
});
loadDeck();
function moveFocus(id: string, direction: 'up' | 'down' | 'left' | 'right') {
// TODO??
}
loadDeck();
function changeProfile(ev: MouseEvent) {
const items = ref([{
@ -286,18 +301,18 @@ async function deleteProfile() {
flex-direction: column;
}
.columns {
.sections {
flex: 1;
display: flex;
overflow-x: auto;
overflow-y: clip;
&.center {
> .column:first-of-type {
> .section:first-of-type {
margin-left: auto;
}
> .column:last-of-type {
> .section:last-of-type {
margin-right: auto;
}
}
@ -307,7 +322,9 @@ async function deleteProfile() {
}
}
.column {
.section {
display: flex;
flex-direction: column;
scroll-snap-align: start;
flex-shrink: 0;
border-right: solid var(--deckDividerThickness) var(--deckDivider);
@ -315,14 +332,8 @@ async function deleteProfile() {
&:first-of-type {
border-left: solid var(--deckDividerThickness) var(--deckDivider);
}
}
.folder {
composes: column;
display: flex;
flex-direction: column;
> *:not(:last-of-type) {
> .column:not(:last-of-type) {
border-bottom: solid var(--deckDividerThickness) var(--deckDivider);
}
}

View file

@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i class="ti ti-antenna"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
@ -23,7 +23,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();

View file

@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i class="ti ti-device-tv"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
@ -29,7 +29,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();

View file

@ -1,38 +0,0 @@
<template>
<!-- TODO: リファクタの余地がありそう -->
<div v-if="!column">たぶん見えちゃいけないやつ</div>
<XMainColumn v-else-if="column.type === 'main'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XWidgetsColumn v-else-if="column.type === 'widgets'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XNotificationsColumn v-else-if="column.type === 'notifications'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XTlColumn v-else-if="column.type === 'tl'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XListColumn v-else-if="column.type === 'list'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XChannelColumn v-else-if="column.type === 'channel'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XAntennaColumn v-else-if="column.type === 'antenna'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XMentionsColumn v-else-if="column.type === 'mentions'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XDirectColumn v-else-if="column.type === 'direct'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
<XRoleTimelineColumn v-else-if="column.type === 'roleTimeline'" :column="column" :isStacked="isStacked" @parentFocus="emit('parent-focus', $event)"/>
</template>
<script lang="ts" setup>
import { } from 'vue';
import XMainColumn from './main-column.vue';
import XTlColumn from './tl-column.vue';
import XAntennaColumn from './antenna-column.vue';
import XListColumn from './list-column.vue';
import XChannelColumn from './channel-column.vue';
import XNotificationsColumn from './notifications-column.vue';
import XWidgetsColumn from './widgets-column.vue';
import XMentionsColumn from './mentions-column.vue';
import XDirectColumn from './direct-column.vue';
import XRoleTimelineColumn from './role-timeline-column.vue';
import { Column } from './deck-store';
defineProps<{
column?: Column;
isStacked: boolean;
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
</script>

View file

@ -1,7 +1,5 @@
<template>
<!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section
v-hotkey="keymap"
<div
:class="[$style.root, { [$style.paged]: isMainColumn, [$style.naked]: naked, [$style.active]: active, [$style.isStacked]: isStacked, [$style.draghover]: draghover, [$style.dragging]: dragging, [$style.dropready]: dropready }]"
@dragover.prevent.stop="onDragover"
@dragleave="onDragleave"
@ -22,10 +20,10 @@
<span :class="$style.title"><slot name="header"></slot></span>
<button v-tooltip="i18n.ts.settings" :class="$style.menu" class="_button" @click.stop="showSettingsMenu"><i class="ti ti-dots"></i></button>
</header>
<div v-show="active" ref="body" :class="$style.body">
<div v-if="active" ref="body" :class="$style.body">
<slot></slot>
</div>
</section>
</div>
</template>
<script lang="ts" setup>
@ -49,12 +47,7 @@ const props = withDefaults(defineProps<{
naked: false,
});
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
(ev: 'change-active-state', v: boolean): void;
}>();
let body = $shallowRef<HTMLDivElement>();
let body = $shallowRef<HTMLDivElement | null>();
let dragging = $ref(false);
watch($$(dragging), v => os.deckGlobalEvents.emit(v ? 'column.dragStart' : 'column.dragEnd'));
@ -64,14 +57,6 @@ let dropready = $ref(false);
const isMainColumn = $computed(() => props.column.type === 'main');
const active = $computed(() => props.column.active !== false);
watch($$(active), v => emit('change-active-state', v));
const keymap = $computed(() => ({
'shift+up': () => emit('parent-focus', 'up'),
'shift+down': () => emit('parent-focus', 'down'),
'shift+left': () => emit('parent-focus', 'left'),
'shift+right': () => emit('parent-focus', 'right'),
}));
onMounted(() => {
os.deckGlobalEvents.on('column.dragStart', onOtherDragStart);
@ -190,10 +175,12 @@ function onContextmenu(ev: MouseEvent) {
}
function goTop() {
body.scrollTo({
top: 0,
behavior: 'smooth',
});
if (body) {
body.scrollTo({
top: 0,
behavior: 'smooth',
});
}
}
function onDragstart(ev) {

View file

@ -1,5 +1,5 @@
<template>
<XColumn :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :column="column" :isStacked="isStacked">
<template #header><i class="ti ti-mail" style="margin-right: 8px;"></i>{{ column.name }}</template>
<MkNotes :pagination="pagination"/>
@ -18,7 +18,6 @@ defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
const pagination = {

View file

@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i class="ti ti-list"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
@ -23,7 +23,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();

View file

@ -1,5 +1,5 @@
<template>
<XColumn v-if="deckStore.state.alwaysShowMainColumn || mainRouter.currentRoute.value.name !== 'index'" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn v-if="deckStore.state.alwaysShowMainColumn || mainRouter.currentRoute.value.name !== 'index'" :column="column" :isStacked="isStacked">
<template #header>
<template v-if="pageMetadata?.value">
<i :class="pageMetadata?.value.icon"></i>
@ -26,7 +26,6 @@ defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let pageMetadata = $ref<null | ComputedRef<PageMetadata>>();

View file

@ -1,5 +1,5 @@
<template>
<XColumn :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :column="column" :isStacked="isStacked">
<template #header><i class="ti ti-at" style="margin-right: 8px;"></i>{{ column.name }}</template>
<MkNotes :pagination="pagination"/>
@ -18,7 +18,6 @@ defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
const pagination = {

View file

@ -1,5 +1,5 @@
<template>
<XColumn :column="column" :isStacked="isStacked" :menu="menu" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :column="column" :isStacked="isStacked" :menu="menu">
<template #header><i class="ti ti-bell" style="margin-right: 8px;"></i>{{ column.name }}</template>
<XNotifications :includeTypes="column.includingTypes"/>
@ -20,7 +20,6 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
function func() {

View file

@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i class="ti ti-badge"></i><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
@ -23,7 +23,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let timeline = $shallowRef<InstanceType<typeof MkTimeline>>();

View file

@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :column="column" :isStacked="isStacked">
<template #header>
<i v-if="column.tl === 'home'" class="ti ti-home"></i>
<i v-else-if="column.tl === 'local'" class="ti ti-planet"></i>
@ -36,7 +36,6 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'loaded'): void;
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let disabled = $ref(false);

View file

@ -1,5 +1,5 @@
<template>
<XColumn :menu="menu" :naked="true" :column="column" :isStacked="isStacked" @parentFocus="$event => emit('parent-focus', $event)">
<XColumn :menu="menu" :naked="true" :column="column" :isStacked="isStacked">
<template #header><i class="ti ti-apps" style="margin-right: 8px;"></i>{{ column.name }}</template>
<div :class="$style.root">
@ -22,7 +22,6 @@ const props = defineProps<{
}>();
const emit = defineEmits<{
(ev: 'parent-focus', direction: 'up' | 'down' | 'left' | 'right'): void;
}>();
let edit = $ref(false);

View file

@ -438,38 +438,41 @@ importers:
specifier: 4.4.0
version: 4.4.0(seedrandom@3.0.5)
slacc-android-arm-eabi:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-android-arm64:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-darwin-arm64:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-darwin-universal:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-darwin-x64:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-freebsd-x64:
specifier: 0.0.9
version: 0.0.9
slacc-linux-arm-gnueabihf:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-linux-arm64-gnu:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-linux-arm64-musl:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-linux-x64-gnu:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-win32-arm64-msvc:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
slacc-win32-x64-msvc:
specifier: 0.0.7
version: 0.0.7
specifier: 0.0.9
version: 0.0.9
devDependencies:
'@jest/globals':
specifier: 29.5.0
@ -17902,15 +17905,6 @@ packages:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
dev: true
/slacc-android-arm-eabi@0.0.7:
resolution: {integrity: sha512-6TikZlR1jsQscxwphhrf0U4xbsRy6zKJ0zmEULopTzbohgo5OLdZ7L3tQazkYlaaFe3YjGnVLW3FfGhhrajVog==}
engines: {node: '>= 10'}
cpu: [arm]
os: [android]
requiresBuild: true
dev: false
optional: true
/slacc-android-arm-eabi@0.0.9:
resolution: {integrity: sha512-T5P5kJ5UwW3UMoPXqqHh9TpCnuCJDCoivoiuONDXrYPYKF8sKDPMVVg1x/KU9/m7e562x9vAMBrIyqFFbEW0Jw==}
engines: {node: '>= 10'}
@ -17920,15 +17914,6 @@ packages:
dev: false
optional: true
/slacc-android-arm64@0.0.7:
resolution: {integrity: sha512-aol/9Rg0Hfqu81hpK+HXcx9sGYu4qqYU+djBCgLtb8I6ZMdWUdE0dp8ACBoTOmYn34hYGcUu4FlJUZ8r7Utucg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: false
optional: true
/slacc-android-arm64@0.0.9:
resolution: {integrity: sha512-bcKB3ukcI5wWJa2clK/5cy6a4TKp51DRkdRuFgKLG05gBj1jbH+7+8iBPojljeY28LC2frmwVHGj3vDmkFUeYg==}
engines: {node: '>= 10'}
@ -17938,15 +17923,6 @@ packages:
dev: false
optional: true
/slacc-darwin-arm64@0.0.7:
resolution: {integrity: sha512-PkV7rO/c9AImNYDacP+kxtOjVuxjy06IIOAxbWerIWvoeqsCNRtiF/dh+OqIACRFBuHIDe0oAyUCEMGUTnzjyQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/slacc-darwin-arm64@0.0.9:
resolution: {integrity: sha512-EspX0Hj6t0Afxbsyc6rY9mTOUQQrPVtWPwwNRaljGRorPyRDDefrU1OnJXRcwcIp0oCZrRrivRYlO7lai63EMw==}
engines: {node: '>= 10'}
@ -17956,14 +17932,6 @@ packages:
dev: false
optional: true
/slacc-darwin-universal@0.0.7:
resolution: {integrity: sha512-Y9zXpL40m4Yq3dE5vdnAgfmn0Fxc0Bf0ixC9TSl96gKeIZEd6drkjfpHFdsIDNImzOksIAUo0HHiDdbEfE7zdQ==}
engines: {node: '>= 10'}
os: [darwin]
requiresBuild: true
dev: false
optional: true
/slacc-darwin-universal@0.0.9:
resolution: {integrity: sha512-oQySg+9MPyKI9rwwwhmSZQkPks2/rq3k1P5HKwUgnaFZDvDtS/hpDycB3BxSDqWdD5kVA8PLCVa8pt9T5KyKfg==}
engines: {node: '>= 10'}
@ -17972,15 +17940,6 @@ packages:
dev: false
optional: true
/slacc-darwin-x64@0.0.7:
resolution: {integrity: sha512-yKaGjX2YJl1QHe4NgqQVsY83jees3hjFxEUPoKpuZEQzWbMNn0XSyceFRGXIk1oDqiKU40UcsdcCedjYjSEd0Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: false
optional: true
/slacc-darwin-x64@0.0.9:
resolution: {integrity: sha512-9Xp7mVKKF2QvDiIZOBgwsDdL/+95KBiFTdbo+XtH6YKoh6zNw0aPpkA3JojsdSMYdGHUrxl8b7avhzI0USqeEg==}
engines: {node: '>= 10'}
@ -17999,15 +17958,6 @@ packages:
dev: false
optional: true
/slacc-linux-arm-gnueabihf@0.0.7:
resolution: {integrity: sha512-pdWMdQeX6uA9JfSoWo9EHH0yRiwXKMbaKoS9gflDSyt/hjeR3Qx/KK7Wihd7HeXx7njlNdpr9ycTRmm5NgapQQ==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: false
optional: true
/slacc-linux-arm-gnueabihf@0.0.9:
resolution: {integrity: sha512-nhP6+jgd30sq+zFxFW7fGhnPwCfCCU0l1JKk3ORGFMl7wH7ippTDd1xGapKq7N+zgdgURbyj83P3wWb2gcRZ1w==}
engines: {node: '>= 10'}
@ -18017,15 +17967,6 @@ packages:
dev: false
optional: true
/slacc-linux-arm64-gnu@0.0.7:
resolution: {integrity: sha512-hz9TK/w6fxeNZXyFzuLq5cJD/XRyJbo6BaIdW+VrKKnb9nkLnWlqDQtdtJk7Fw7zHjdY3Uqufjwm0iT6qBVpUQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/slacc-linux-arm64-gnu@0.0.9:
resolution: {integrity: sha512-x7v0rDe0KNVe1Hl6/XCtkCpqdT283pyVaUmk+af0AnoesNRjYEK8DBc8i53N4nhotionHzPIZfu5gPAFkf6RhA==}
engines: {node: '>= 10'}
@ -18035,15 +17976,6 @@ packages:
dev: false
optional: true
/slacc-linux-arm64-musl@0.0.7:
resolution: {integrity: sha512-wCDAYL7e+lh3XL7g87Ui/Bb2Ap9GcBqeJuj2yHIx6MYC8ontwFSXhqRTmd2zmPLmZA5Nc11aKGN11YNu0Pnwlw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/slacc-linux-arm64-musl@0.0.9:
resolution: {integrity: sha512-jyq/ylITHIXTQX5ZqAbi7Mn5SdRgYJi+uEoUCi5UhoXb9LjpNzhkFuY29Je3IkVIIV7AEcAxIlvjdymXdzcF5w==}
engines: {node: '>= 10'}
@ -18053,15 +17985,6 @@ packages:
dev: false
optional: true
/slacc-linux-x64-gnu@0.0.7:
resolution: {integrity: sha512-E5+2cveizpfHXCk/Hu5VfslWFeDVw47nywODiJ8CsofT2l5ITfYPMFEBXm9ORY25mGBTgsO6lJYiF9Hz4FlS9Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: false
optional: true
/slacc-linux-x64-gnu@0.0.9:
resolution: {integrity: sha512-Xs/F81H7cKhlIBigFID6CJlgjy0NeDUGV1CI1MI5mSVHsVI8dUO8zXWETjo6o8krJPgfjT5Jd4tAgvUFct5hng==}
engines: {node: '>= 10'}
@ -18071,15 +17994,6 @@ packages:
dev: false
optional: true
/slacc-win32-arm64-msvc@0.0.7:
resolution: {integrity: sha512-3a+qnkZbP+Pr5RZuzd0Vi1uCal137QiJajRAWT4r7qwu+Zidd50x2oikQ4rAegqZVTm8qTwVmWA+WmH8WHI7iw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: false
optional: true
/slacc-win32-arm64-msvc@0.0.9:
resolution: {integrity: sha512-C+H0VkKbEEnRbcXRIG5rIaXlg7IZw3o1BbvqA71B8ouQRCu/dNRuH9EQsOYXWltndY42zZi8IupNIwydTUg+Mg==}
engines: {node: '>= 10'}
@ -18089,15 +18003,6 @@ packages:
dev: false
optional: true
/slacc-win32-x64-msvc@0.0.7:
resolution: {integrity: sha512-ydFdZ7wEXQPsw2Tg+yG9uJdCGTehyPtrWBVUMa7fojr3j1gbtThXS2l9Ad/6fYYi2VwdaYPLWbwV3GYElPGL8g==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: false
optional: true
/slacc-win32-x64-msvc@0.0.9:
resolution: {integrity: sha512-bElMnBbeMatCtVp2/+hBS6Z+846nQImEul9nBEr4gfezHotOM6MqR6PI7UQQzGhozpgwiDg2l1ub1MdOIgYizg==}
engines: {node: '>= 10'}