mirror of
https://github.com/thelounge/thelounge.git
synced 2024-06-09 17:22:25 +02:00
ef651e3e46
- Which provides transaction/rollback wrapper (I heard talk on IRC that we do everything transactional... we didn't do anything transactional) - Is synchronous, so we can test the state of the DB beforehand (instead of after we already told everyone it's ok, like wtf why did we even check for schema version when we don't do anything about mismatches??!) - much much faster - provides more functionality we might use in the future, you never know ¯\_(ツ)_/¯ - fewer bugs (according to better-sqlite3 team) Also read: https://github.com/JoshuaWise/better-sqlite3#why-should-i-use-this-instead-of-node-sqlite3 https://github.com/JoshuaWise/better-sqlite3/issues/262#issuecomment-490536241
247 lines
5.6 KiB
Vue
247 lines
5.6 KiB
Vue
<template>
|
|
<div id="chat-container" class="window">
|
|
<div
|
|
id="chat"
|
|
:class="{
|
|
'colored-nicks': $store.state.settings.coloredNicks,
|
|
'time-seconds': $store.state.settings.showSeconds,
|
|
'time-12h': $store.state.settings.use12hClock,
|
|
}"
|
|
>
|
|
<div
|
|
class="chat-view"
|
|
data-type="search-results"
|
|
aria-label="Search results"
|
|
role="tabpanel"
|
|
>
|
|
<div class="header">
|
|
<SidebarToggle />
|
|
<span class="title"
|
|
>Searching in <span class="channel-name">{{ channel.name }}</span> for</span
|
|
>
|
|
<span class="topic">{{ $route.query.q }}</span>
|
|
<MessageSearchForm :network="network" :channel="channel" />
|
|
<button
|
|
class="close"
|
|
aria-label="Close search window"
|
|
title="Close search window"
|
|
@click="closeSearch"
|
|
/>
|
|
</div>
|
|
<div class="chat-content">
|
|
<div ref="chat" class="chat" tabindex="-1">
|
|
<div v-show="moreResultsAvailable" class="show-more">
|
|
<button
|
|
ref="loadMoreButton"
|
|
:disabled="
|
|
$store.state.messageSearchInProgress ||
|
|
!$store.state.isConnected
|
|
"
|
|
class="btn"
|
|
@click="onShowMoreClick"
|
|
>
|
|
<span v-if="$store.state.messageSearchInProgress">Loading…</span>
|
|
<span v-else>Show older messages</span>
|
|
</button>
|
|
</div>
|
|
|
|
<div
|
|
v-if="$store.state.messageSearchInProgress && !offset"
|
|
class="search-status"
|
|
>
|
|
Searching…
|
|
</div>
|
|
<div v-else-if="!messages.length && !offset" class="search-status">
|
|
No results found.
|
|
</div>
|
|
<div
|
|
v-else
|
|
class="messages"
|
|
role="log"
|
|
aria-live="polite"
|
|
aria-relevant="additions"
|
|
>
|
|
<template v-for="(message, id) in messages">
|
|
<div :key="message.id" class="result" @:click="jump(message, id)">
|
|
<DateMarker
|
|
v-if="shouldDisplayDateMarker(message, id)"
|
|
:key="message.date"
|
|
:message="message"
|
|
/>
|
|
<Message
|
|
:key="message.id"
|
|
:channel="channel"
|
|
:network="network"
|
|
:message="message"
|
|
:data-id="message.id"
|
|
/>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style>
|
|
.channel-name {
|
|
font-weight: 700;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
import socket from "../../js/socket";
|
|
|
|
import SidebarToggle from "../SidebarToggle.vue";
|
|
import Message from "../Message.vue";
|
|
import MessageSearchForm from "../MessageSearchForm.vue";
|
|
import DateMarker from "../DateMarker.vue";
|
|
|
|
export default {
|
|
name: "SearchResults",
|
|
components: {
|
|
SidebarToggle,
|
|
Message,
|
|
DateMarker,
|
|
MessageSearchForm,
|
|
},
|
|
data() {
|
|
return {
|
|
offset: 0,
|
|
moreResultsAvailable: false,
|
|
oldScrollTop: 0,
|
|
oldChatHeight: 0,
|
|
};
|
|
},
|
|
computed: {
|
|
search() {
|
|
return this.$store.state.messageSearchResults;
|
|
},
|
|
messages() {
|
|
if (!this.search) {
|
|
return [];
|
|
}
|
|
|
|
return this.search.results.slice();
|
|
},
|
|
chan() {
|
|
const chanId = parseInt(this.$route.params.id, 10);
|
|
return this.$store.getters.findChannel(chanId);
|
|
},
|
|
network() {
|
|
if (!this.chan) {
|
|
return null;
|
|
}
|
|
|
|
return this.chan.network;
|
|
},
|
|
channel() {
|
|
if (!this.chan) {
|
|
return null;
|
|
}
|
|
|
|
return this.chan.channel;
|
|
},
|
|
},
|
|
watch: {
|
|
"$route.params.id"() {
|
|
this.doSearch();
|
|
this.setActiveChannel();
|
|
},
|
|
"$route.query.q"() {
|
|
this.doSearch();
|
|
this.setActiveChannel();
|
|
},
|
|
messages() {
|
|
this.moreResultsAvailable = this.messages.length && !(this.messages.length % 100);
|
|
|
|
if (!this.offset) {
|
|
this.jumpToBottom();
|
|
} else {
|
|
this.$nextTick(() => {
|
|
const currentChatHeight = this.$refs.chat.scrollHeight;
|
|
this.$refs.chat.scrollTop =
|
|
this.oldScrollTop + currentChatHeight - this.oldChatHeight;
|
|
});
|
|
}
|
|
},
|
|
},
|
|
mounted() {
|
|
this.setActiveChannel();
|
|
this.doSearch();
|
|
this.$root.$on("re-search", this.doSearch); // Enable MessageSearchForm to search for the same query again
|
|
},
|
|
beforeDestroy() {
|
|
this.$root.$off("re-search");
|
|
},
|
|
methods: {
|
|
setActiveChannel() {
|
|
this.$store.commit("activeChannel", this.chan);
|
|
},
|
|
closeSearch() {
|
|
this.$root.switchToChannel(this.channel);
|
|
},
|
|
shouldDisplayDateMarker(message, id) {
|
|
const previousMessage = this.messages[id - 1];
|
|
|
|
if (!previousMessage) {
|
|
return true;
|
|
}
|
|
|
|
return new Date(previousMessage.time).getDay() !== new Date(message.time).getDay();
|
|
},
|
|
doSearch() {
|
|
this.offset = 0;
|
|
this.$store.commit("messageSearchInProgress", true);
|
|
|
|
if (!this.offset) {
|
|
this.$store.commit("messageSearchResults", null); // Only reset if not getting offset
|
|
}
|
|
|
|
socket.emit("search", {
|
|
networkUuid: this.network.uuid,
|
|
channelName: this.channel.name,
|
|
searchTerm: this.$route.query.q,
|
|
offset: this.offset,
|
|
});
|
|
},
|
|
onShowMoreClick() {
|
|
this.offset += 100;
|
|
this.$store.commit("messageSearchInProgress", true);
|
|
|
|
this.oldScrollTop = this.$refs.chat.scrollTop;
|
|
this.oldChatHeight = this.$refs.chat.scrollHeight;
|
|
|
|
socket.emit("search", {
|
|
networkUuid: this.network.uuid,
|
|
channelName: this.channel.name,
|
|
searchTerm: this.$route.query.q,
|
|
offset: this.offset + 1,
|
|
});
|
|
},
|
|
jumpToBottom() {
|
|
this.$nextTick(() => {
|
|
const el = this.$refs.chat;
|
|
el.scrollTop = el.scrollHeight;
|
|
});
|
|
},
|
|
jump(message, id) {
|
|
// TODO: Implement jumping to messages!
|
|
// This is difficult because it means client will need to handle a potentially nonlinear message set
|
|
// (loading IntersectionObserver both before AND after the messages)
|
|
this.$router.push({
|
|
name: "MessageList",
|
|
params: {
|
|
id: this.chan.id,
|
|
},
|
|
query: {
|
|
focused: id,
|
|
},
|
|
});
|
|
},
|
|
},
|
|
};
|
|
</script>
|