init
This commit is contained in:
@@ -17,7 +17,7 @@ const userStore = useUserStore();
|
||||
const {renderMarkdown} = useMarkdown()
|
||||
|
||||
const messageContainer = ref<HTMLElement | null>(null);
|
||||
const {messages, loading, loadingBefore, loadingAfter} = storeToRefs(messageStore);
|
||||
const {messages, loading, loadingBefore, loadingAfter, hasMoreAfter, isAtBottom} = storeToRefs(messageStore);
|
||||
const newMessage = ref('');
|
||||
|
||||
const SCROLL_LOAD_THRESHOLD = 120;
|
||||
@@ -26,6 +26,10 @@ const paginationLock = ref<'before' | 'after' | null>(null);
|
||||
const paginationLockScrollTop = ref(0);
|
||||
const lastScrollTop = ref(0);
|
||||
|
||||
const showRecentMessagesButton = computed(() =>
|
||||
!loading.value && (hasMoreAfter.value || !isAtBottom.value),
|
||||
);
|
||||
|
||||
interface ScrollAnchor {
|
||||
id: string;
|
||||
top: number;
|
||||
@@ -36,6 +40,8 @@ const scrollToBottom = async () => {
|
||||
if (messageContainer.value) {
|
||||
messageContainer.value.scrollTop = messageContainer.value.scrollHeight;
|
||||
messageStore.setAtBottom(true);
|
||||
paginationLock.value = null;
|
||||
lastScrollTop.value = messageContainer.value.scrollTop;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -153,6 +159,12 @@ const sendMessage = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const returnToRecentMessages = async () => {
|
||||
paginationLock.value = null;
|
||||
await messageStore.fetchMessages(channelId.value);
|
||||
await scrollToBottom();
|
||||
};
|
||||
|
||||
// Only explicit initial loads and realtime messages received while at the
|
||||
// bottom request an automatic scroll. Pagination restores its own anchor.
|
||||
watch(messages, async () => {
|
||||
@@ -169,7 +181,7 @@ watch(channelId, async (newChannelId) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-container class="pa-0 fill-height d-flex flex-column" fluid>
|
||||
<v-container class="pa-0 fill-height d-flex flex-column channel-layout" fluid>
|
||||
<div
|
||||
ref="messageContainer"
|
||||
class="flex-grow-1 overflow-y-auto w-100 message-container"
|
||||
@@ -211,6 +223,22 @@ watch(channelId, async (newChannelId) => {
|
||||
<v-progress-linear v-if="loadingAfter" color="primary" indeterminate />
|
||||
</div>
|
||||
|
||||
<div v-if="showRecentMessagesButton" class="recent-messages-button">
|
||||
<v-tooltip location="top" text="Revenir aux messages récents">
|
||||
<template #activator="{ props: tooltipProps }">
|
||||
<v-btn
|
||||
v-bind="tooltipProps"
|
||||
aria-label="Revenir aux messages récents"
|
||||
color="primary"
|
||||
elevation="4"
|
||||
icon="mdi-arrow-down-bold"
|
||||
:loading="loading"
|
||||
@click="returnToRecentMessages"
|
||||
/>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
</div>
|
||||
|
||||
<v-sheet class="pa-4 flex-shrink-0" width="100%">
|
||||
<v-textarea
|
||||
v-model="newMessage"
|
||||
@@ -244,6 +272,17 @@ watch(channelId, async (newChannelId) => {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.channel-layout {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.recent-messages-button {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 92px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.markdown-content :deep(p) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
pub use sea_orm_migration::prelude::*;
|
||||
|
||||
mod m20220101_000001_create_table;
|
||||
mod m20260808_000002_add_message_channel_id_id_index;
|
||||
|
||||
pub struct Migrator;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigratorTrait for Migrator {
|
||||
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
|
||||
vec![
|
||||
Box::new(m20220101_000001_create_table::Migration),
|
||||
Box::new(m20260808_000002_add_message_channel_id_id_index::Migration),
|
||||
]
|
||||
vec![Box::new(m20220101_000001_create_table::Migration)]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,6 +505,12 @@ impl MigrationTrait for Migration {
|
||||
.to(Alias::new("message"), Alias::new("id"))
|
||||
.on_delete(ForeignKeyAction::SetNull),
|
||||
)
|
||||
.index(
|
||||
Index::create()
|
||||
.name("idx_message_channel_id_id")
|
||||
.col(Alias::new("channel_id"))
|
||||
.col(Alias::new("id")),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.create_index(
|
||||
Index::create()
|
||||
.name("idx_message_channel_id_id")
|
||||
.table(Alias::new("message"))
|
||||
.col(Alias::new("channel_id"))
|
||||
.col(Alias::new("id"))
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.drop_index(
|
||||
Index::drop()
|
||||
.name("idx_message_channel_id_id")
|
||||
.table(Alias::new("message"))
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate test messages directly in the project's SQLite database."""
|
||||
|
||||
# python3 scripts/generate_messages.py \
|
||||
# --db oxspeak.db \
|
||||
# --channel-id 672e7757-b7df-401b-8e47-8c62e1fb9d7d \
|
||||
# --user-id d327a80b-83d4-4a53-9c0b-140f60cc0caa \
|
||||
# --count 1000 \
|
||||
# --min-words 10 \
|
||||
# --max-words 500
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
|
||||
Reference in New Issue
Block a user