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…
	
	Add table
		Add a link
		
	
		Reference in a new issue