This commit is contained in:
NoriDev 2023-06-19 16:44:56 +09:00
parent 5ff28f08a9
commit eba092e319
9 changed files with 30 additions and 141 deletions

View file

@ -51,24 +51,16 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
userId: { type: 'string', format: 'misskey:id' },
groupId: { type: 'string', format: 'misskey:id' },
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
sinceId: { type: 'string', format: 'misskey:id' }, sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' }, untilId: { type: 'string', format: 'misskey:id' },
markAsRead: { type: 'boolean', default: true }, markAsRead: { type: 'boolean', default: true },
}, },
anyOf: [ anyOf: [
{ { required: ['userId'] },
properties: { { required: ['groupId'] },
userId: { type: 'string', format: 'misskey:id' },
},
required: ['userId'],
},
{
properties: {
groupId: { type: 'string', format: 'misskey:id' },
},
required: ['groupId'],
},
], ],
} as const; } as const;

View file

@ -75,22 +75,14 @@ export const meta = {
export const paramDef = { export const paramDef = {
type: 'object', type: 'object',
properties: { properties: {
userId: { type: 'string', format: 'misskey:id' },
groupId: { type: 'string', format: 'misskey:id' },
text: { type: 'string', nullable: true, maxLength: 3000 }, text: { type: 'string', nullable: true, maxLength: 3000 },
fileId: { type: 'string', format: 'misskey:id' }, fileId: { type: 'string', format: 'misskey:id' },
}, },
anyOf: [ anyOf: [
{ { required: ['userId'] },
properties: { { required: ['groupId'] },
userId: { type: 'string', format: 'misskey:id' },
},
required: ['userId'],
},
{
properties: {
groupId: { type: 'string', format: 'misskey:id' },
},
required: ['groupId'],
},
], ],
} as const; } as const;

View file

@ -12,6 +12,7 @@ class MediaTimelineChannel extends Channel {
public readonly chName = 'mediaTimeline'; public readonly chName = 'mediaTimeline';
public static shouldShare = true; public static shouldShare = true;
public static requireCredential = false; public static requireCredential = false;
private withReplies: boolean;
constructor( constructor(
private metaService: MetaService, private metaService: MetaService,
@ -30,6 +31,8 @@ class MediaTimelineChannel extends Channel {
const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null); const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null);
if (!policies.ltlAvailable) return; if (!policies.ltlAvailable) return;
this.withReplies = params.withReplies as boolean;
// Subscribe events // Subscribe events
this.subscriber.on('notesStream', this.onNote); this.subscriber.on('notesStream', this.onNote);
} }
@ -54,7 +57,7 @@ class MediaTimelineChannel extends Channel {
} }
// 関係ない返信は除外 // 関係ない返信は除外
if (note.reply && this.user && !this.user.showTimelineReplies) { if (note.reply && this.user && !this.withReplies) {
const reply = note.reply; const reply = note.reply;
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
if (reply.userId !== this.user.id && note.userId !== this.user.id && reply.userId !== note.userId) return; if (reply.userId !== this.user.id && note.userId !== this.user.id && reply.userId !== note.userId) return;

View file

@ -1,104 +0,0 @@
<template>
<MkPagination ref="pagingComponent" :pagination="pagination">
<template #empty>
<div class="_fullinfo">
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
<div>{{ i18n.ts.noNotifications }}</div>
</div>
</template>
<template #default="{ items: notifications }">
<XList v-slot="{ item: notification }" class="elsfgstc" :items="notifications" :no-gap="false">
<XNote v-if="['reply', 'quote', 'mention'].includes(notification.type)" :key="notification.id" :note="notification.note" class="_panel"/>
<XNotification v-else :key="notification.id" :notification="notification" :with-time="true" :full="true" class="_panel notification"/>
</XList>
</template>
</MkPagination>
</template>
<script lang="ts" setup>
import { defineComponent, markRaw, onUnmounted, onMounted, computed, ref } from 'vue';
import { notificationTypes } from 'cherrypick-js';
import MkPagination, { Paging } from '@/components/MkPagination.vue';
import XNotification from '@/components/MkNotification.vue';
import XList from '@/components/MkDateSeparatedList.vue';
import XNote from '@/components/MkNote.vue';
import * as os from '@/os';
import { stream } from '@/stream';
import { $i } from '@/account';
import { i18n } from '@/i18n';
const props = defineProps<{
includeTypes?: typeof notificationTypes[number][];
unreadOnly?: boolean;
}>();
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
const pagination: Paging = {
endpoint: 'i/notifications' as const,
limit: 10,
params: computed(() => ({
includeTypes: props.includeTypes ?? undefined,
excludeTypes: props.includeTypes ? undefined : $i.mutingNotificationTypes,
unreadOnly: props.unreadOnly,
})),
};
const onNotification = (notification) => {
const isMuted = props.includeTypes ? !props.includeTypes.includes(notification.type) : $i.mutingNotificationTypes.includes(notification.type);
if (isMuted || document.visibilityState === 'visible') {
stream.send('readNotification', {
id: notification.id,
});
}
if (!isMuted) {
pagingComponent.value.prepend({
...notification,
isRead: document.visibilityState === 'visible',
});
}
};
let connection;
onMounted(() => {
connection = stream.useChannel('main');
connection.on('notification', onNotification);
connection.on('readAllNotifications', () => {
if (pagingComponent.value) {
for (const item of pagingComponent.value.queue) {
item.isRead = true;
}
for (const item of pagingComponent.value.items) {
item.isRead = true;
}
}
});
connection.on('readNotifications', notificationIds => {
if (pagingComponent.value) {
for (let i = 0; i < pagingComponent.value.queue.length; i++) {
if (notificationIds.includes(pagingComponent.value.queue[i].id)) {
pagingComponent.value.queue[i].isRead = true;
}
}
for (let i = 0; i < (pagingComponent.value.items || []).length; i++) {
if (notificationIds.includes(pagingComponent.value.items[i].id)) {
pagingComponent.value.items[i].isRead = true;
}
}
}
});
});
onUnmounted(() => {
if (connection) connection.dispose();
});
</script>
<style lang="scss" scoped>
.elsfgstc {
//background: var(--panel);
}
</style>

View file

@ -218,9 +218,9 @@ export default function(props: {
} }
case 'ruby': { case 'ruby': {
let rb, rt, tokens; let rb, rt, tokens;
token.children.forEach((t) => { if (t.type == 'text') { t.props.text = t.props.text.trim(); } }); token.children.forEach((t) => { if (t.type === 'text') { t.props.text = t.props.text.trim(); } });
const children = token.children.filter((t) => t.type != 'text' || t.props.text != ''); const children = token.children.filter((t) => t.type !== 'text' || t.props.text !== '');
if (children.length == 1 && children[0].type == 'text') { if (children.length === 1 && children[0].type === 'text') {
tokens = children[0].props.text.split(' '); tokens = children[0].props.text.split(' ');
rb = [tokens[0]]; rb = [tokens[0]];
rt = [tokens.slice(1).join(' ')]; rt = [tokens.slice(1).join(' ')];

View file

@ -206,6 +206,7 @@ import * as os from '@/os';
import { definePageMetadata } from '@/scripts/page-metadata'; import { definePageMetadata } from '@/scripts/page-metadata';
import { claimAchievement, claimedAchievements } from '@/scripts/achievements'; import { claimAchievement, claimedAchievements } from '@/scripts/achievements';
import { $i } from '@/account'; import { $i } from '@/account';
import { instance } from '@/instance';
const patronsWithIconWithCherryPick = [{ const patronsWithIconWithCherryPick = [{
name: 'Inger 잉어', name: 'Inger 잉어',
@ -353,6 +354,12 @@ const patronsWithMisskey = [
]; ];
let isKokonect = false; let isKokonect = false;
const instanceList = [
'http://localhost:3000',
'https://kokonect.link',
'https://beta.kokonect.link',
'https://universe.noridev.moe',
];
let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure')); let thereIsTreasure = $ref($i && !claimedAchievements.includes('foundTreasure'));
@ -361,8 +368,7 @@ let easterEggEmojis = $ref([]);
let easterEggEngine = $ref(null); let easterEggEngine = $ref(null);
const containerEl = $shallowRef<HTMLElement>(); const containerEl = $shallowRef<HTMLElement>();
const meta = await os.api('meta', { detail: true }); if (instanceList.includes(<string>instance.uri)) isKokonect = true;
if (meta.uri == 'https://kokonect.link' || 'http://localhost:3000') isKokonect = true;
function iconLoaded() { function iconLoaded() {
const emojis = defaultStore.state.reactions; const emojis = defaultStore.state.reactions;

View file

@ -198,7 +198,7 @@ function clear() {
} }
function saveDraft() { function saveDraft() {
const drafts = JSON.parse(miLocalStorage.getItem('message_drafts') || '{}'); const drafts = JSON.parse(miLocalStorage.getItem('message_drafts') ?? '{}');
drafts[draftKey] = { drafts[draftKey] = {
updatedAt: new Date(), updatedAt: new Date(),
@ -213,7 +213,7 @@ function saveDraft() {
} }
function deleteDraft() { function deleteDraft() {
const drafts = JSON.parse(miLocalStorage.getItem('message_drafts') || '{}'); const drafts = JSON.parse(miLocalStorage.getItem('message_drafts') ?? '{}');
delete drafts[draftKey]; delete drafts[draftKey];
@ -221,7 +221,7 @@ function deleteDraft() {
} }
async function insertEmoji(ev: MouseEvent) { async function insertEmoji(ev: MouseEvent) {
os.openEmojiPicker(ev.currentTarget ?? ev.target, {}, textEl); await os.openEmojiPicker(ev.currentTarget ?? ev.target, {}, textEl);
} }
onMounted(() => { onMounted(() => {
@ -232,7 +232,7 @@ onMounted(() => {
//new Autocomplete(textEl, this, { model: 'text' }); //new Autocomplete(textEl, this, { model: 'text' });
// 稿 // 稿
const draft = JSON.parse(miLocalStorage.getItem('message_drafts') || '{}')[draftKey]; const draft = JSON.parse(miLocalStorage.getItem('message_drafts') ?? '{}')[draftKey];
if (draft) { if (draft) {
text = draft.data.text; text = draft.data.text;
file = draft.data.file; file = draft.data.file;

View file

@ -112,7 +112,7 @@ async function addItem(ev: MouseEvent) {
}]; }];
}, },
}, },
], ev.target || ev.currentTarget); ], ev.currentTarget ?? ev.target );
} }
function removeItem(index: number) { function removeItem(index: number) {

View file

@ -10,8 +10,8 @@ export async function editNickname(user: User) {
placeholder: user.name || user.username, placeholder: user.name || user.username,
default: defaultStore.state.nicknameMap[user.id] ?? null, default: defaultStore.state.nicknameMap[user.id] ?? null,
}); });
if (canceled) return if (canceled) return;
const newMap = {...defaultStore.state.nicknameMap}; const newMap = { ...defaultStore.state.nicknameMap };
if (result) { if (result) {
newMap[user.id] = result; newMap[user.id] = result;
} else { } else {