This commit is contained in:
syuilo 2023-08-13 10:58:17 +09:00
parent 6634727d83
commit ad752a8931
7 changed files with 49 additions and 17 deletions

2
locales/index.d.ts vendored
View File

@ -1101,6 +1101,8 @@ export interface Locale {
"dialog": string;
"icon": string;
"forYou": string;
"currentAnnouncements": string;
"pastAnnouncements": string;
"_announcement": {
"forExistingUsers": string;
"forExistingUsersDescription": string;

View File

@ -1098,6 +1098,8 @@ iHaveReadXCarefullyAndAgree: "「{x}」の内容をよく読み、同意しま
dialog: "ダイアログ"
icon: "アイコン"
forYou: "あなたへ"
currentAnnouncements: "現在のお知らせ"
pastAnnouncements: "過去のお知らせ"
_announcement:
forExistingUsers: "既存ユーザーのみ"

View File

@ -33,6 +33,7 @@ export const paramDef = {
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
isActive: { type: 'boolean', default: true },
},
required: [],
} as const;
@ -52,7 +53,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
) {
super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.announcementsRepository.createQueryBuilder('announcement'), ps.sinceId, ps.untilId)
.where('announcement.isActive = true')
.where('announcement.isActive = :isActive', { isActive: ps.isActive })
.andWhere(new Brackets(qb => {
if (me) qb.orWhere('announcement.userId = :meId', { meId: me.id });
qb.orWhere('announcement.userId IS NULL');

View File

@ -12,10 +12,15 @@ SPDX-License-Identifier: AGPL-3.0-only
:class="$style.input"
@keydown.enter="toggle"
>
<XButton :checked="checked" :disabled="disabled" @toggle="toggle" />
<XButton :checked="checked" :disabled="disabled" @toggle="toggle"/>
<span :class="$style.body">
<!-- TODO: 無名slotの方は廃止 -->
<span :class="$style.label" @click="toggle"><slot name="label"></slot><slot></slot></span>
<span :class="$style.label">
<span @click="toggle">
<slot name="label"></slot><slot></slot>
</span>
<span v-if="helpText" v-tooltip:dialog="helpText" class="_button _help" :class="$style.help"><i class="ti ti-help-circle"></i></span>
</span>
<p :class="$style.caption"><slot name="caption"></slot></p>
</span>
</div>
@ -28,6 +33,7 @@ import XButton from '@/components/MkSwitch.button.vue';
const props = defineProps<{
modelValue: boolean | Ref<boolean>;
disabled?: boolean;
helpText?: string;
}>();
const emit = defineEmits<{
@ -38,10 +44,6 @@ const checked = toRefs(props).modelValue;
const toggle = () => {
if (props.disabled) return;
emit('update:modelValue', !checked.value);
if (!checked.value) {
}
};
</script>
@ -98,4 +100,10 @@ const toggle = () => {
display: none;
}
}
.help {
margin-left: 0.5em;
font-size: 85%;
vertical-align: top;
}
</style>

View File

@ -32,13 +32,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<option value="banner">{{ i18n.ts.banner }}</option>
<option value="dialog">{{ i18n.ts.dialog }}</option>
</MkRadios>
<MkSwitch v-model="announcement.forExistingUsers">
<MkSwitch v-model="announcement.forExistingUsers" :helpText="i18n.ts._announcement.forExistingUsersDescription">
{{ i18n.ts._announcement.forExistingUsers }}
<template #caption>{{ i18n.ts._announcement.forExistingUsersDescription }}</template>
</MkSwitch>
<MkSwitch v-model="announcement.needConfirmationToRead">
<MkSwitch v-model="announcement.needConfirmationToRead" :helpText="i18n.ts._announcement.needConfirmationToReadDescription">
{{ i18n.ts._announcement.needConfirmationToRead }}
<template #caption>{{ i18n.ts._announcement.needConfirmationToReadDescription }}</template>
</MkSwitch>
<p v-if="announcement.reads">{{ i18n.t('nUsersRead', { n: announcement.reads }) }}</p>
<div class="buttons _buttons">

View File

@ -5,9 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkStickyContainer>
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :contentMax="800">
<MkPagination ref="paginationEl" v-slot="{items}" :pagination="pagination" class="_gaps_m">
<MkPagination ref="paginationEl" :key="tab" v-slot="{items}" :pagination="tab === 'current' ? paginationCurrent : paginationPast" class="_gaps_m">
<section v-for="announcement in items" :key="announcement.id" class="_panel" :class="$style.announcement">
<div v-if="announcement.forYou" :class="$style.forYou"><i class="ti ti-pin"></i> {{ i18n.ts.forYou }}</div>
<div :class="$style.header">
@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkTime :time="announcement.updatedAt ?? announcement.createdAt" mode="detail"/>
</div>
</div>
<div v-if="$i && !announcement.isRead" :class="$style.footer">
<div v-if="tab !== 'past' && $i && !announcement.isRead" :class="$style.footer">
<MkButton primary @click="read(announcement.id)"><i class="ti ti-check"></i> {{ i18n.ts.gotIt }}</MkButton>
</div>
</section>
@ -45,13 +45,26 @@ import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata';
import { $i, updateAccount } from '@/account';
const pagination = {
const paginationCurrent = {
endpoint: 'announcements' as const,
limit: 10,
params: {
isActive: true,
},
};
const paginationPast = {
endpoint: 'announcements' as const,
limit: 10,
params: {
isActive: false,
},
};
const paginationEl = ref<InstanceType<typeof MkPagination>>();
const tab = ref('current');
function read(id: string) {
if (!paginationEl.value) return;
paginationEl.value.updateItem(id, announcement => {
@ -66,7 +79,15 @@ function read(id: string) {
const headerActions = $computed(() => []);
const headerTabs = $computed(() => []);
const headerTabs = $computed(() => [{
key: 'current',
title: i18n.ts.currentAnnouncements,
icon: 'ti ti-flare',
}, {
key: 'past',
title: i18n.ts.pastAnnouncements,
icon: 'ti ti-point',
}]);
definePageMetadata({
title: i18n.ts.announcements,

View File

@ -86,7 +86,7 @@ const tagUsersPagination = $computed(() => ({
endpoint: 'hashtags/users' as const,
limit: 30,
params: {
tag: this.tag,
tag: props.tag,
origin: 'combined',
sort: '+follower',
},