wip
This commit is contained in:
parent
a1f346a549
commit
8a7264835e
3 changed files with 73 additions and 113 deletions
|
@ -271,6 +271,7 @@ onDeactivated(() => {
|
|||
defineExpose({
|
||||
items,
|
||||
backed,
|
||||
more,
|
||||
reload,
|
||||
fetchMoreAhead,
|
||||
prepend,
|
||||
|
|
|
@ -35,45 +35,39 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { } from 'vue';
|
||||
import * as mfm from 'mfm-js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm';
|
||||
import MkUrlPreview from '@/components/url-preview.vue';
|
||||
import * as os from '@/os';
|
||||
import { $i } from '@/account';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkUrlPreview
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
required: true
|
||||
},
|
||||
isGroup: {
|
||||
required: false
|
||||
const props = defineProps<{
|
||||
message: Misskey.entities.MessagingMessage;
|
||||
isGroup?: boolean;
|
||||
connection?: Misskey.ChannelConnection<Misskey.Channels['messaging']>;
|
||||
}>();
|
||||
|
||||
const isMe = $computed(() => props.message.userId === $i?.id);
|
||||
const urls = $computed(() => props.message.text ? extractUrlFromMfm(mfm.parse(props.message.text)) : []);
|
||||
|
||||
if (props.connection) {
|
||||
props.connection?.on('read', (x) => {
|
||||
if (!props.isGroup) {
|
||||
props.message.isRead = true;
|
||||
} else {
|
||||
props.message.reads = [...props.message.reads, x.userId];
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isMe(): boolean {
|
||||
return this.message.userId === this.$i.id;
|
||||
},
|
||||
urls(): string[] {
|
||||
if (this.message.text) {
|
||||
return extractUrlFromMfm(mfm.parse(this.message.text));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
del() {
|
||||
os.api('messaging/messages/delete', {
|
||||
messageId: this.message.id
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function del() {
|
||||
os.api('messaging/messages/delete', {
|
||||
messageId: props.message.id
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -6,15 +6,18 @@
|
|||
>
|
||||
<div class="_content mk-messaging-room">
|
||||
<div class="body">
|
||||
<MkPagination v-if="pagination" ref="pagingComponent" :pagination="pagination">
|
||||
<template #empty>
|
||||
<i class="fas fa-info-circle"></i>{{ $ts.noMessagesYet }}</p>
|
||||
</template>
|
||||
|
||||
<template #defalut="{ items: messages }">
|
||||
<XList v-slot="{ item: message }" class="messages" :items="messages" direction="up" reversed>
|
||||
<XMessage :key="message.id" :message="message" :is-group="group != null"/>
|
||||
</XList>
|
||||
</template>
|
||||
</MkPagination>
|
||||
<MkLoading v-if="fetching"/>
|
||||
<p v-if="!fetching && messages.length == 0" class="empty"><i class="fas fa-info-circle"></i>{{ $ts.noMessagesYet }}</p>
|
||||
<p v-if="!fetching && messages.length > 0 && !existMoreMessages" class="no-history"><i class="fas fa-flag"></i>{{ $ts.noMoreHistory }}</p>
|
||||
<button v-show="existMoreMessages" ref="loadMore" class="more _button" :class="{ fetching: fetchingMoreMessages }" :disabled="fetchingMoreMessages" @click="fetchMoreMessages">
|
||||
<template v-if="fetchingMoreMessages"><i class="fas fa-spinner fa-pulse fa-fw"></i></template>{{ fetchingMoreMessages ? $ts.loading : $ts.loadMore }}
|
||||
</button>
|
||||
<XList v-slot="{ item: message }" class="messages" :items="messages" direction="up" reversed>
|
||||
<XMessage :key="message.id" :message="message" :is-group="group != null"/>
|
||||
</XList>
|
||||
</div>
|
||||
<footer>
|
||||
<div v-if="typers.length > 0" class="typers">
|
||||
|
@ -39,7 +42,9 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, watch, onMounted, nextTick, onBeforeUnmount } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import XList from '@/components/date-separated-list.vue';
|
||||
import MkPagination from '@/components/ui/pagination.vue';
|
||||
import { Paging } from '@/components/ui/pagination.vue';
|
||||
import XMessage from './messaging-room.message.vue';
|
||||
import XForm from './messaging-room.form.vue';
|
||||
import * as Acct from 'misskey-js/built/acct';
|
||||
|
@ -52,33 +57,42 @@ import * as symbols from '@/symbols';
|
|||
import { i18n } from '@/i18n';
|
||||
import { defaultStore } from '@/store';
|
||||
import { $i } from '@/account';
|
||||
import { router } from '@/router';
|
||||
|
||||
const props = defineProps<{
|
||||
userAcct?: 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 form = $ref<InstanceType<typeof XForm>>();
|
||||
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], () => {
|
||||
if (connection) connection.dispose();
|
||||
|
@ -94,7 +108,6 @@ async function fetch() {
|
|||
});
|
||||
|
||||
connection?.on('message', onMessage);
|
||||
connection?.on('read', onRead);
|
||||
connection?.on('deleted', onDeleted);
|
||||
connection?.on('typers', typers => {
|
||||
typers = typers.filter(u => u.id !== $i.id);
|
||||
|
@ -102,7 +115,7 @@ async function fetch() {
|
|||
|
||||
document.addEventListener('visibilitychange', onVisibilitychange);
|
||||
|
||||
fetchMessages().then(() => {
|
||||
pagingComponent.fetchMoreAhead().then(() => {
|
||||
scrollToBottom();
|
||||
|
||||
// もっと見るの交差検知を発火させないためにfetchは
|
||||
|
@ -149,33 +162,10 @@ function onDrop(e: DragEvent): void {
|
|||
//#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() {
|
||||
fetchingMoreMessages = true;
|
||||
fetchMessages().then(() => {
|
||||
fetchingMoreMessages = false;
|
||||
fetching = true;
|
||||
pagingComponent.fetchMoreAhead().then(() => {
|
||||
fetching = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -184,7 +174,7 @@ function onMessage(message) {
|
|||
|
||||
const _isBottom = isBottom(rootEl, 64);
|
||||
|
||||
messages.push(message);
|
||||
pagingComponent.append(message);
|
||||
if (message.userId != $i.id && !document.hidden) {
|
||||
connection?.send('read', {
|
||||
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) {
|
||||
const msg = messages.find(m => m.id === id);
|
||||
if (msg) {
|
||||
|
|
Loading…
Reference in a new issue