<!-- SPDX-FileCopyrightText: syuilo and misskey-project SPDX-License-Identifier: AGPL-3.0-only --> <template> <MkContainer :showHeader="widgetProps.showHeader" :style="`height: ${widgetProps.height}px;`" :scrollable="true" data-cy-mkw-timeline class="mkw-timeline"> <template #icon> <i v-if="isBasicTimeline(widgetProps.src)" :class="basicTimelineIconClass(widgetProps.src)"></i> <i v-else-if="widgetProps.src === 'list'" class="ti ti-list"></i> <i v-else-if="widgetProps.src === 'antenna'" class="ti ti-antenna"></i> </template> <template #header> <button class="_button" @click="choose"> <span>{{ widgetProps.src === 'list' ? widgetProps.list.name : widgetProps.src === 'antenna' ? widgetProps.antenna.name : i18n.ts._timelines[widgetProps.src] }}</span> <i :class="menuOpened ? 'ti ti-chevron-up' : 'ti ti-chevron-down'" style="margin-left: 8px;"></i> </button> </template> <div v-if="isBasicTimeline(widgetProps.src) && !isAvailableBasicTimeline(serverMetadata, widgetProps.src)" :class="$style.disabled"> <p :class="$style.disabledTitle"> <i class="ti ti-minus"></i> {{ i18n.ts._disabledTimeline.title }} </p> <p :class="$style.disabledDescription">{{ i18n.ts._disabledTimeline.description }}</p> </div> <div v-else> <MkTimeline :key="widgetProps.src === 'list' ? `list:${widgetProps.list.id}` : widgetProps.src === 'antenna' ? `antenna:${widgetProps.antenna.id}` : widgetProps.src" :src="widgetProps.src" :list="widgetProps.list ? widgetProps.list.id : null" :antenna="widgetProps.antenna ? widgetProps.antenna.id : null"/> </div> </MkContainer> </template> <script lang="ts" setup> import { inject, ref } from 'vue'; import { useWidgetPropsManager, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js'; import { GetFormResultType } from '@/scripts/form.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import MkContainer from '@/components/MkContainer.vue'; import MkTimeline from '@/components/MkTimeline.vue'; import { i18n } from '@/i18n.js'; import { availableBasicTimelines, isAvailableBasicTimeline, isBasicTimeline, basicTimelineIconClass } from '@/timelines.js'; const name = 'timeline'; const widgetPropsDef = { showHeader: { type: 'boolean' as const, default: true, }, height: { type: 'number' as const, default: 300, }, src: { type: 'string' as const, default: 'home', hidden: true, }, antenna: { type: 'object' as const, default: null, hidden: true, }, list: { type: 'object' as const, default: null, hidden: true, }, }; type WidgetProps = GetFormResultType<typeof widgetPropsDef>; const props = defineProps<WidgetComponentProps<WidgetProps>>(); const emit = defineEmits<WidgetComponentEmits<WidgetProps>>(); const { widgetProps, configure, save } = useWidgetPropsManager(name, widgetPropsDef, props, emit, ); import { DI } from '@/di.js'; const serverMetadata = inject(DI.serverMetadata); const menuOpened = ref(false); const setSrc = (src) => { widgetProps.src = src; save(); }; const choose = async (ev) => { menuOpened.value = true; const [antennas, lists] = await Promise.all([ misskeyApi('antennas/list'), misskeyApi('users/lists/list'), ]); const antennaItems = antennas.map(antenna => ({ text: antenna.name, icon: 'ti ti-antenna', action: () => { widgetProps.antenna = antenna; setSrc('antenna'); }, })); const listItems = lists.map(list => ({ text: list.name, icon: 'ti ti-list', action: () => { widgetProps.list = list; setSrc('list'); }, })); os.popupMenu([...availableBasicTimelines(serverMetadata).map(tl => ({ text: i18n.ts._timelines[tl], icon: basicTimelineIconClass(tl), action: () => { setSrc(tl); }, })), antennaItems.length > 0 ? { type: 'divider' } : undefined, ...antennaItems, listItems.length > 0 ? { type: 'divider' } : undefined, ...listItems], ev.currentTarget ?? ev.target).then(() => { menuOpened.value = false; }); }; defineExpose<WidgetComponentExpose>({ name, configure, id: props.widget ? props.widget.id : null, }); </script> <style lang="scss" module> .disabled { text-align: center; } .disabledTitle { margin: 16px; } .disabledDescription { font-size: 90%; } </style>