feat(client): 通知ページで通知の種類によるフィルタ

This commit is contained in:
syuilo 2021-10-09 13:12:41 +09:00
parent abc45ded9b
commit 8006e7a34d
3 changed files with 42 additions and 8 deletions

View file

@ -15,6 +15,7 @@
- クライアント: アニメーションを減らす設定をメニューのアニメーションにも適用するように - クライアント: アニメーションを減らす設定をメニューのアニメーションにも適用するように
- クライアント: MFM関数構文のサジェストを実装 - クライアント: MFM関数構文のサジェストを実装
- クライアント: 未読の通知のみ表示する機能 - クライアント: 未読の通知のみ表示する機能
- クライアント: 通知ページで通知の種類によるフィルタ
- ActivityPub: HTML -> MFMの変換を強化 - ActivityPub: HTML -> MFMの変換を強化
- API: i/notifications に unreadOnly オプションを追加 - API: i/notifications に unreadOnly オプションを追加
- API: ap系のエンドポイントをログイン必須化+レートリミット追加 - API: ap系のエンドポイントをログイン必須化+レートリミット追加

View file

@ -27,7 +27,7 @@
<MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/> <MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/>
<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span> <span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span>
</button> </button>
<button v-else @click="clicked(item.action, $event)" :tabindex="i" class="_button item" :class="{ danger: item.danger }"> <button v-else @click="clicked(item.action, $event)" :tabindex="i" class="_button item" :class="{ danger: item.danger, active: item.active }" :disabled="item.active">
<i v-if="item.icon" class="fa-fw" :class="item.icon"></i> <i v-if="item.icon" class="fa-fw" :class="item.icon"></i>
<MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/> <MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/>
<span>{{ item.text }}</span> <span>{{ item.text }}</span>
@ -175,6 +175,10 @@ export default defineComponent({
border-radius: 6px; border-radius: 6px;
} }
> * {
position: relative;
}
&.danger { &.danger {
color: #ff2a2a; color: #ff2a2a;
@ -195,7 +199,16 @@ export default defineComponent({
} }
} }
&:hover { &.active {
color: var(--fgOnAccent);
opacity: 1;
&:before {
background: var(--accent);
}
}
&:not(:disabled):hover {
color: var(--accent); color: var(--accent);
text-decoration: none; text-decoration: none;
@ -204,11 +217,6 @@ export default defineComponent({
} }
} }
&:active {
//color: var(--fgOnAccent);
//background: var(--accentDarken);
}
&:not(:active):focus-visible { &:not(:active):focus-visible {
box-shadow: 0 0 0 2px var(--focus) inset; box-shadow: 0 0 0 2px var(--focus) inset;
} }

View file

@ -2,7 +2,7 @@
<div> <div>
<MkHeader :info="header"/> <MkHeader :info="header"/>
<div class="clupoqwt" v-size="{ min: [800] }"> <div class="clupoqwt" v-size="{ min: [800] }">
<XNotifications class="notifications" @before="before" @after="after" :unread-only="tab === 'unread'"/> <XNotifications class="notifications" @before="before" @after="after" :include-types="includeTypes" :unread-only="tab === 'unread'"/>
</div> </div>
</div> </div>
</template> </template>
@ -13,6 +13,7 @@ import Progress from '@client/scripts/loading';
import XNotifications from '@client/components/notifications.vue'; import XNotifications from '@client/components/notifications.vue';
import * as os from '@client/os'; import * as os from '@client/os';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';
import { notificationTypes } from '@/types';
export default defineComponent({ export default defineComponent({
components: { components: {
@ -27,11 +28,17 @@ export default defineComponent({
bg: 'var(--bg)', bg: 'var(--bg)',
}, },
tab: 'all', tab: 'all',
includeTypes: null,
header: computed(() => ({ header: computed(() => ({
title: this.$ts.notifications, title: this.$ts.notifications,
icon: 'fas fa-bell', icon: 'fas fa-bell',
bg: 'var(--bg)', bg: 'var(--bg)',
actions: [{ actions: [{
text: this.$ts.filter,
icon: 'fas fa-filter',
highlighted: this.includeTypes != null,
handler: this.setFilter,
}, {
text: this.$ts.markAllAsRead, text: this.$ts.markAllAsRead,
icon: 'fas fa-check', icon: 'fas fa-check',
handler: () => { handler: () => {
@ -58,6 +65,24 @@ export default defineComponent({
after() { after() {
Progress.done(); Progress.done();
},
setFilter(ev) {
const typeItems = notificationTypes.map(t => ({
text: this.$t(`_notification._types.${t}`),
active: this.includeTypes && this.includeTypes.includes(t),
action: () => {
this.includeTypes = [t];
}
}));
const items = this.includeTypes != null ? [{
icon: 'fas fa-times',
text: this.$ts.clear,
action: () => {
this.includeTypes = null;
}
}, null, ...typeItems] : typeItems;
os.popupMenu(items, ev.currentTarget || ev.target);
} }
} }
}); });