This commit is contained in:
tamaina 2022-01-27 18:58:41 +09:00
parent a1f346a549
commit 8a7264835e
3 changed files with 73 additions and 113 deletions

View File

@ -271,6 +271,7 @@ onDeactivated(() => {
defineExpose({ defineExpose({
items, items,
backed, backed,
more,
reload, reload,
fetchMoreAhead, fetchMoreAhead,
prepend, prepend,

View File

@ -35,45 +35,39 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { } from 'vue';
import * as mfm from 'mfm-js'; import * as mfm from 'mfm-js';
import * as Misskey from 'misskey-js';
import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm'; import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm';
import MkUrlPreview from '@/components/url-preview.vue'; import MkUrlPreview from '@/components/url-preview.vue';
import * as os from '@/os'; import * as os from '@/os';
import { $i } from '@/account';
export default defineComponent({ const props = defineProps<{
components: { message: Misskey.entities.MessagingMessage;
MkUrlPreview isGroup?: boolean;
}, connection?: Misskey.ChannelConnection<Misskey.Channels['messaging']>;
props: { }>();
message: {
required: true const isMe = $computed(() => props.message.userId === $i?.id);
}, const urls = $computed(() => props.message.text ? extractUrlFromMfm(mfm.parse(props.message.text)) : []);
isGroup: {
required: false if (props.connection) {
} props.connection?.on('read', (x) => {
}, if (!props.isGroup) {
computed: { props.message.isRead = true;
isMe(): boolean {
return this.message.userId === this.$i.id;
},
urls(): string[] {
if (this.message.text) {
return extractUrlFromMfm(mfm.parse(this.message.text));
} else { } else {
return []; props.message.reads = [...props.message.reads, x.userId];
} }
}
},
methods: {
del() {
os.api('messaging/messages/delete', {
messageId: this.message.id
}); });
} }
}
}); function del() {
os.api('messaging/messages/delete', {
messageId: props.message.id
});
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -6,15 +6,18 @@
> >
<div class="_content mk-messaging-room"> <div class="_content mk-messaging-room">
<div class="body"> <div class="body">
<MkLoading v-if="fetching"/> <MkPagination v-if="pagination" ref="pagingComponent" :pagination="pagination">
<p v-if="!fetching && messages.length == 0" class="empty"><i class="fas fa-info-circle"></i>{{ $ts.noMessagesYet }}</p> <template #empty>
<p v-if="!fetching && messages.length > 0 && !existMoreMessages" class="no-history"><i class="fas fa-flag"></i>{{ $ts.noMoreHistory }}</p> <i class="fas fa-info-circle"></i>{{ $ts.noMessagesYet }}</p>
<button v-show="existMoreMessages" ref="loadMore" class="more _button" :class="{ fetching: fetchingMoreMessages }" :disabled="fetchingMoreMessages" @click="fetchMoreMessages"> </template>
<template v-if="fetchingMoreMessages"><i class="fas fa-spinner fa-pulse fa-fw"></i></template>{{ fetchingMoreMessages ? $ts.loading : $ts.loadMore }}
</button> <template #defalut="{ items: messages }">
<XList v-slot="{ item: message }" class="messages" :items="messages" direction="up" reversed> <XList v-slot="{ item: message }" class="messages" :items="messages" direction="up" reversed>
<XMessage :key="message.id" :message="message" :is-group="group != null"/> <XMessage :key="message.id" :message="message" :is-group="group != null"/>
</XList> </XList>
</template>
</MkPagination>
<MkLoading v-if="fetching"/>
</div> </div>
<footer> <footer>
<div v-if="typers.length > 0" class="typers"> <div v-if="typers.length > 0" class="typers">
@ -39,7 +42,9 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, watch, onMounted, nextTick, onBeforeUnmount } from 'vue'; import { computed, watch, onMounted, nextTick, onBeforeUnmount } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import XList from '@/components/date-separated-list.vue';
import MkPagination from '@/components/ui/pagination.vue'; import MkPagination from '@/components/ui/pagination.vue';
import { Paging } from '@/components/ui/pagination.vue';
import XMessage from './messaging-room.message.vue'; import XMessage from './messaging-room.message.vue';
import XForm from './messaging-room.form.vue'; import XForm from './messaging-room.form.vue';
import * as Acct from 'misskey-js/built/acct'; import * as Acct from 'misskey-js/built/acct';
@ -52,33 +57,42 @@ import * as symbols from '@/symbols';
import { i18n } from '@/i18n'; import { i18n } from '@/i18n';
import { defaultStore } from '@/store'; import { defaultStore } from '@/store';
import { $i } from '@/account'; import { $i } from '@/account';
import { router } from '@/router';
const props = defineProps<{ const props = defineProps<{
userAcct?: string; userAcct?: string;
groupId?: string; groupId?: string;
}>(); }>();
let fetching = $ref(true);
let user: Misskey.entities.UserDetailed | null = $ref(null);
let group: Misskey.entities.UserGroup | null = $ref(null);
let fetchingMoreMessages = $ref(false);
let messages = $ref<Misskey.entities.MessagingMessage[]>([]);
let existMoreMessages = $ref(false);
let connection: Misskey.ChannelConnection<Misskey.Channels['messaging']> | null = $ref(null);
let showIndicator = $ref(false);
let timer: number | null = $ref(null);
const ilObserver = new IntersectionObserver(
(entries) => entries.some((entry) => entry.isIntersecting)
&& !fetching
&& !fetchingMoreMessages
&& existMoreMessages
&& fetchMoreMessages()
);
let rootEl = $ref<Element>(); let rootEl = $ref<Element>();
let form = $ref<InstanceType<typeof XForm>>(); let form = $ref<InstanceType<typeof XForm>>();
let loadMore = $ref<HTMLDivElement>(); let loadMore = $ref<HTMLDivElement>();
let pagingComponent = $ref<InstanceType<typeof MkPagination>>();
let fetching = $ref(true);
let user: Misskey.entities.UserDetailed | null = $ref(null);
let group: Misskey.entities.UserGroup | null = $ref(null);
let connection: Misskey.ChannelConnection<Misskey.Channels['messaging']> | null = $ref(null);
let showIndicator = $ref(false);
let timer: number | null = $ref(null);
let pagination: Paging = $computed(() => {
return {
endpoint: 'messaging/messages',
limit: pagingComponent?.more ? 20 : 10,
params: {
userId: user ? user.id : undefined,
groupId: group ? group.id : undefined,
},
reversed: true,
};
});
const ilObserver = new IntersectionObserver(
(entries) => entries.some((entry) => entry.isIntersecting)
&& !fetching
&& pagingComponent?.more
&& fetchMoreMessages()
);
watch([() => props.userAcct, () => props.groupId], () => { watch([() => props.userAcct, () => props.groupId], () => {
if (connection) connection.dispose(); if (connection) connection.dispose();
@ -94,7 +108,6 @@ async function fetch() {
}); });
connection?.on('message', onMessage); connection?.on('message', onMessage);
connection?.on('read', onRead);
connection?.on('deleted', onDeleted); connection?.on('deleted', onDeleted);
connection?.on('typers', typers => { connection?.on('typers', typers => {
typers = typers.filter(u => u.id !== $i.id); typers = typers.filter(u => u.id !== $i.id);
@ -102,7 +115,7 @@ async function fetch() {
document.addEventListener('visibilitychange', onVisibilitychange); document.addEventListener('visibilitychange', onVisibilitychange);
fetchMessages().then(() => { pagingComponent.fetchMoreAhead().then(() => {
scrollToBottom(); scrollToBottom();
// fetch // fetch
@ -149,33 +162,10 @@ function onDrop(e: DragEvent): void {
//#endregion //#endregion
} }
function fetchMessages() {
return new Promise<void>((resolve, reject) => {
const max = existMoreMessages ? 20 : 10;
os.api('messaging/messages', {
userId: user ? user.id : undefined,
groupId: group ? group.id : undefined,
limit: max + 1,
untilId: existMoreMessages ? messages[0].id : undefined
}).then(messages => {
if (messages.length == max + 1) {
existMoreMessages = true;
messages.pop();
} else {
existMoreMessages = false;
}
messages.unshift.apply(messages, messages.reverse());
resolve();
});
});
}
function fetchMoreMessages() { function fetchMoreMessages() {
fetchingMoreMessages = true; fetching = true;
fetchMessages().then(() => { pagingComponent.fetchMoreAhead().then(() => {
fetchingMoreMessages = false; fetching = false;
}); });
} }
@ -184,7 +174,7 @@ function onMessage(message) {
const _isBottom = isBottom(rootEl, 64); const _isBottom = isBottom(rootEl, 64);
messages.push(message); pagingComponent.append(message);
if (message.userId != $i.id && !document.hidden) { if (message.userId != $i.id && !document.hidden) {
connection?.send('read', { connection?.send('read', {
id: message.id id: message.id
@ -202,31 +192,6 @@ function onMessage(message) {
} }
} }
function onRead(x) {
if (user) {
if (!Array.isArray(x)) x = [x];
for (const id of x) {
if (messages.some(x => x.id == id)) {
const exist = messages.map(x => x.id).indexOf(id);
messages[exist] = {
...messages[exist],
isRead: true,
};
}
}
} else if (group) {
for (const id of x.ids) {
if (messages.some(x => x.id == id)) {
const exist = messages.map(x => x.id).indexOf(id);
messages[exist] = {
...messages[exist],
reads: [...messages[exist].reads, x.userId]
};
}
}
}
}
function onDeleted(id) { function onDeleted(id) {
const msg = messages.find(m => m.id === id); const msg = messages.find(m => m.id === id);
if (msg) { if (msg) {