summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components/SkFollowingRecentNotes.vue
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2024-11-01 16:52:31 -0400
committerHazelnoot <acomputerdog@gmail.com>2024-11-20 22:22:29 -0500
commitca94959fff3f202c90166db8868a7613c424fe0b (patch)
tree6379866df378b69be44adf7689156c2ed1b1ee5a /packages/frontend/src/components/SkFollowingRecentNotes.vue
parentmerge: Bump develop version (!766) (diff)
downloadsharkey-ca94959fff3f202c90166db8868a7613c424fe0b.tar.gz
sharkey-ca94959fff3f202c90166db8868a7613c424fe0b.tar.bz2
sharkey-ca94959fff3f202c90166db8868a7613c424fe0b.zip
factor out Following Feed list into SkFollowingRecentNotes.vue
Diffstat (limited to 'packages/frontend/src/components/SkFollowingRecentNotes.vue')
-rw-r--r--packages/frontend/src/components/SkFollowingRecentNotes.vue122
1 files changed, 122 insertions, 0 deletions
diff --git a/packages/frontend/src/components/SkFollowingRecentNotes.vue b/packages/frontend/src/components/SkFollowingRecentNotes.vue
new file mode 100644
index 0000000000..35fa83812f
--- /dev/null
+++ b/packages/frontend/src/components/SkFollowingRecentNotes.vue
@@ -0,0 +1,122 @@
+<!--
+SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+<MkPullToRefresh :refresher="() => reload()">
+ <MkPagination ref="latestNotesPaging" :pagination="latestNotesPagination" @init="onListReady">
+ <template #empty>
+ <div class="_fullinfo">
+ <img :src="infoImageUrl" class="_ghost" :alt="i18n.ts.noNotes" aria-hidden="true"/>
+ <div>{{ i18n.ts.noNotes }}</div>
+ </div>
+ </template>
+
+ <template #default="{ items: notes }">
+ <MkDateSeparatedList v-slot="{ item: note }" :items="notes" :class="$style.panel" :noGap="true">
+ <SkFollowingFeedEntry v-if="!isHardMuted(note)" :isMuted="isSoftMuted(note)" :note="note" @select="u => selectUser(u.id)"/>
+ </MkDateSeparatedList>
+ </template>
+ </MkPagination>
+</MkPullToRefresh>
+</template>
+
+<script setup lang="ts">
+import * as Misskey from 'misskey-js';
+import { computed, shallowRef } from 'vue';
+import { infoImageUrl } from '@/instance.js';
+import { i18n } from '@/i18n.js';
+import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
+import MkPagination, { Paging } from '@/components/MkPagination.vue';
+import SkFollowingFeedEntry from '@/components/SkFollowingFeedEntry.vue';
+import { $i } from '@/account.js';
+import { checkWordMute } from '@/scripts/check-word-mute.js';
+import { FollowingFeedTab } from '@/scripts/following-feed-utils.js';
+import MkPullToRefresh from '@/components/MkPullToRefresh.vue';
+
+const props = defineProps<{
+ userList: FollowingFeedTab;
+ withNonPublic: boolean;
+ withQuotes: boolean;
+ withReplies: boolean;
+ withBots: boolean;
+ onlyFiles: boolean;
+}>();
+
+const emit = defineEmits<{
+ (event: 'loaded', initialUserId?: string): void;
+ (event: 'userSelected', userId: string): void;
+}>();
+
+defineExpose({ reload });
+
+async function reload() {
+ await latestNotesPaging.value?.reload();
+}
+
+function selectUser(userId: string) {
+ emit('userSelected', userId);
+}
+
+async function onListReady(): Promise<void> {
+ // This looks complicated, but it's really just a trick to get the first user ID from the pagination.
+ const initialUserId = latestNotesPaging.value?.items.size
+ ? latestNotesPaging.value.items.values().next().value?.userId
+ : undefined;
+
+ emit('loaded', initialUserId);
+}
+
+const latestNotesPagination: Paging<'notes/following'> = {
+ endpoint: 'notes/following' as const,
+ limit: 20,
+ params: computed(() => ({
+ list: props.userList,
+ filesOnly: props.onlyFiles,
+ includeNonPublic: props.withNonPublic,
+ includeReplies: props.withReplies,
+ includeQuotes: props.withQuotes,
+ includeBots: props.withBots,
+ })),
+};
+
+const latestNotesPaging = shallowRef<InstanceType<typeof MkPagination>>();
+
+function isSoftMuted(note: Misskey.entities.Note): boolean {
+ return isMuted(note, $i?.mutedWords);
+}
+
+function isHardMuted(note: Misskey.entities.Note): boolean {
+ return isMuted(note, $i?.hardMutedWords);
+}
+
+// Match the typing used by Misskey
+type Mutes = (string | string[])[] | null | undefined;
+
+// Adapted from MkNote.ts
+function isMuted(note: Misskey.entities.Note, mutes: Mutes): boolean {
+ return checkMute(note, mutes)
+ || checkMute(note.reply, mutes)
+ || checkMute(note.renote, mutes);
+}
+
+// Adapted from check-word-mute.ts
+function checkMute(note: Misskey.entities.Note | undefined | null, mutes: Mutes): boolean {
+ if (!note) {
+ return false;
+ }
+
+ if (!mutes || mutes.length < 1) {
+ return false;
+ }
+
+ return checkWordMute(note, $i, mutes);
+}
+</script>
+
+<style module lang="scss">
+.panel {
+ background: var(--panel);
+}
+</style>