add @babel/plugin-transform-runtime, fix scrolling on chan switch/history loading

This commit is contained in:
Max Leiter 2022-05-30 21:10:11 -07:00
parent 027ab3bbfc
commit a1659e1c02
No known key found for this signature in database
GPG key ID: A3512F2F2F17EBDA
24 changed files with 147 additions and 148 deletions

View file

@ -5,5 +5,6 @@ module.exports = {
"@babel/preset-typescript", // ? babel-preset-typescript-vue should be a drop-in replacement for @babel/typescript with vue support "@babel/preset-typescript", // ? babel-preset-typescript-vue should be a drop-in replacement for @babel/typescript with vue support
// "@vue/babel-preset-jsx", // "@vue/babel-preset-jsx",
], ],
plugins: ["@babel/plugin-transform-runtime"],
targets: "> 0.25%, not dead", targets: "> 0.25%, not dead",
}; };

View file

@ -105,7 +105,6 @@
:network="network" :network="network"
:channel="channel" :channel="channel"
:focused="focused" :focused="focused"
@scrolled-to-bottom="onScrolledToBottom"
/> />
</div> </div>
</div> </div>
@ -175,10 +174,6 @@ export default defineComponent({
return undefined; return undefined;
}); });
const onScrolledToBottom = (data: boolean) => {
props.channel.scrolledToBottom = data;
};
const channelChanged = () => { const channelChanged = () => {
// Triggered when active channel is set or changed // Triggered when active channel is set or changed
emit("channel-changed", props.channel); emit("channel-changed", props.channel);
@ -234,21 +229,15 @@ export default defineComponent({
}); });
}; };
watch( watch(props.channel, () => {
() => props.channel, channelChanged();
() => { });
channelChanged();
}
);
const editTopicRef = ref(props.channel.editTopic); const editTopicRef = ref(props.channel.editTopic);
watch(editTopicRef, (newTopic) => { watch(editTopicRef, (newTopic) => {
if (newTopic) { if (newTopic) {
nextTick(() => { void nextTick(() => {
topicInput.value?.focus(); topicInput.value?.focus();
}).catch((e) => {
// eslint-disable-next-line no-console
console.error(e);
}); });
} }
}); });
@ -257,10 +246,8 @@ export default defineComponent({
channelChanged(); channelChanged();
if (props.channel.editTopic) { if (props.channel.editTopic) {
nextTick(() => { void nextTick(() => {
topicInput.value?.focus(); topicInput.value?.focus();
}).catch(() => {
// no-op
}); });
} }
}); });
@ -271,7 +258,6 @@ export default defineComponent({
topicInput, topicInput,
specialComponent, specialComponent,
editTopicRef, editTopicRef,
onScrolledToBottom,
hideUserVisibleError, hideUserVisibleError,
editTopic, editTopic,
saveTopic, saveTopic,

View file

@ -102,7 +102,7 @@ export default defineComponent({
const autocompletionRef = ref<ReturnType<typeof autocompletion>>(); const autocompletionRef = ref<ReturnType<typeof autocompletion>>();
const setInputSize = () => { const setInputSize = () => {
nextTick(() => { void nextTick(() => {
if (!input.value) { if (!input.value) {
return; return;
} }
@ -120,8 +120,6 @@ export default defineComponent({
input.value.style.height = `${ input.value.style.height = `${
Math.ceil(input.value.scrollHeight / lineHeight) * lineHeight Math.ceil(input.value.scrollHeight / lineHeight) * lineHeight
}px`; }px`;
}).catch(() => {
// no-op
}); });
}; };

View file

@ -175,11 +175,9 @@ export default defineComponent({
const scrollToActiveUser = () => { const scrollToActiveUser = () => {
// Scroll the list if needed after the active class is applied // Scroll the list if needed after the active class is applied
nextTick(() => { void nextTick(() => {
const el = userlist.value?.querySelector(".active"); const el = userlist.value?.querySelector(".active");
el?.scrollIntoView({block: "nearest", inline: "nearest"}); el?.scrollIntoView({block: "nearest", inline: "nearest"});
}).catch(() => {
// no-op
}); });
}; };

View file

@ -9,7 +9,14 @@
<script lang="ts"> <script lang="ts">
import dayjs from "dayjs"; import dayjs from "dayjs";
import calendar from "dayjs/plugin/calendar"; import calendar from "dayjs/plugin/calendar";
import {computed, defineComponent, onBeforeUnmount, onMounted, PropType} from "vue"; import {
computed,
defineComponent,
getCurrentInstance,
onBeforeUnmount,
onMounted,
PropType,
} from "vue";
import eventbus from "../js/eventbus"; import eventbus from "../js/eventbus";
import {ClientMessage} from "../js/types"; import {ClientMessage} from "../js/types";
@ -33,8 +40,8 @@ export default defineComponent({
const dayChange = () => { const dayChange = () => {
// TODO: this is nasty. and maybe doesnt work? // TODO: this is nasty. and maybe doesnt work?
// const instance = Vue.getCurrentInstance(); const instance = getCurrentInstance();
// instance?.proxy?.$forceUpdate(); instance?.proxy?.$forceUpdate();
if (hoursPassed() >= 48) { if (hoursPassed() >= 48) {
eventbus.off("daychange", dayChange); eventbus.off("daychange", dayChange);

View file

@ -179,12 +179,9 @@ export default defineComponent({
return messages.filter((message) => !message.channel?.channel.muted); return messages.filter((message) => !message.channel?.channel.muted);
}); });
watch( watch(store.state.mentions, () => {
() => store.state.mentions, isLoading.value = false;
() => { });
isLoading.value = false;
}
);
const messageTime = (time: string) => { const messageTime = (time: string) => {
return dayjs(time).fromNow(); return dayjs(time).fromNow();

View file

@ -120,7 +120,7 @@ export default defineComponent({
message: {type: Object as PropType<ClientMessage>, required: true}, message: {type: Object as PropType<ClientMessage>, required: true},
channel: {type: Object as PropType<ClientChan>, required: false}, channel: {type: Object as PropType<ClientChan>, required: false},
network: {type: Object as PropType<ClientNetwork>, required: true}, network: {type: Object as PropType<ClientNetwork>, required: true},
keepScrollPosition: Function, keepScrollPosition: Function as PropType<() => void>,
isPreviousSource: Boolean, isPreviousSource: Boolean,
focused: Boolean, focused: Boolean,
}, },

View file

@ -66,7 +66,6 @@ import Message from "./Message.vue";
import MessageCondensed from "./MessageCondensed.vue"; import MessageCondensed from "./MessageCondensed.vue";
import DateMarker from "./DateMarker.vue"; import DateMarker from "./DateMarker.vue";
import { import {
defineExpose,
computed, computed,
defineComponent, defineComponent,
nextTick, nextTick,
@ -104,7 +103,6 @@ export default defineComponent({
channel: {type: Object as PropType<ClientChan>, required: true}, channel: {type: Object as PropType<ClientChan>, required: true},
focused: String, focused: String,
}, },
emits: ["scrolled-to-bottom"],
setup(props, {emit}) { setup(props, {emit}) {
const store = useStore(); const store = useStore();
@ -117,7 +115,7 @@ export default defineComponent({
const jumpToBottom = () => { const jumpToBottom = () => {
skipNextScrollEvent.value = true; skipNextScrollEvent.value = true;
emit("scrolled-to-bottom", true); props.channel.scrolledToBottom = true;
const el = chat.value; const el = chat.value;
@ -173,8 +171,9 @@ export default defineComponent({
} }
jumpToBottom(); jumpToBottom();
}).catch(() => { }).catch((e) => {
// no-op // eslint-disable-next-line no-console
console.error("Error in new IntersectionObserver", e);
}); });
const condensedMessages = computed(() => { const condensedMessages = computed(() => {
@ -293,7 +292,9 @@ export default defineComponent({
} }
}; };
const keepScrollPosition = () => { const keepScrollPosition = async () => {
console.log("keepScrollPosition");
// If we are already waiting for the next tick to force scroll position, // If we are already waiting for the next tick to force scroll position,
// we have no reason to perform more checks and set it again in the next tick // we have no reason to perform more checks and set it again in the next tick
if (isWaitingForNextTick.value) { if (isWaitingForNextTick.value) {
@ -306,40 +307,44 @@ export default defineComponent({
return; return;
} }
console.log(el);
if (!props.channel.scrolledToBottom) { if (!props.channel.scrolledToBottom) {
if (props.channel.historyLoading) { if (props.channel.historyLoading) {
const heightOld = el.scrollHeight - el.scrollTop; const heightOld = el.scrollHeight - el.scrollTop;
isWaitingForNextTick.value = true; isWaitingForNextTick.value = true;
nextTick(() => { await nextTick();
isWaitingForNextTick.value = false;
skipNextScrollEvent.value = true; isWaitingForNextTick.value = false;
el.scrollTop = el.scrollHeight - heightOld; skipNextScrollEvent.value = true;
}).catch(() => {
// no-op console.log("old top", heightOld);
}); el.scrollTop = el.scrollHeight - heightOld;
console.log("new top", el.scrollTop);
} }
return; return;
} }
isWaitingForNextTick.value = true; isWaitingForNextTick.value = true;
nextTick(() => { await nextTick();
isWaitingForNextTick.value = false; isWaitingForNextTick.value = false;
jumpToBottom();
}).catch(() => { console.log("HERE");
// no-op jumpToBottom();
});
}; };
const onLinkPreviewToggle = (preview: ClientLinkPreview, message: ClientMessage) => { const onLinkPreviewToggle = async (preview: ClientLinkPreview, message: ClientMessage) => {
keepScrollPosition(); await keepScrollPosition();
// Tell the server we're toggling so it remembers at page reload // Tell the server we're toggling so it remembers at page reload
socket.emit("msg:preview:toggle", { socket.emit("msg:preview:toggle", {
target: props.channel.id, target: props.channel.id,
msgId: message.id, msgId: message.id,
// TODO: type
// @ts-ignore
link: preview.link, link: preview.link,
shown: preview.shown, shown: preview.shown,
}); });
@ -359,7 +364,7 @@ export default defineComponent({
return; return;
} }
emit("scrolled-to-bottom", el.scrollHeight - el.scrollTop - el.offsetHeight <= 30); props.channel.scrolledToBottom = el.scrollHeight - el.scrollTop - el.offsetHeight <= 30;
}; };
const handleResize = () => { const handleResize = () => {
@ -374,19 +379,17 @@ export default defineComponent({
eventbus.on("resize", handleResize); eventbus.on("resize", handleResize);
nextTick(() => { void nextTick(() => {
if (historyObserver.value && loadMoreButton.value) { if (historyObserver.value && loadMoreButton.value) {
historyObserver.value.observe(loadMoreButton.value); historyObserver.value.observe(loadMoreButton.value);
} }
}).catch(() => {
// no-op
}); });
}); });
watch( watch(
() => props.channel.id, () => props.channel.id,
() => { () => {
emit("scrolled-to-bottom", true); props.channel.scrolledToBottom = true;
// Re-add the intersection observer to trigger the check again on channel switch // Re-add the intersection observer to trigger the check again on channel switch
// Otherwise if last channel had the button visible, switching to a new channel won't trigger the history // Otherwise if last channel had the button visible, switching to a new channel won't trigger the history
@ -399,20 +402,19 @@ export default defineComponent({
watch( watch(
() => props.channel.messages, () => props.channel.messages,
() => { async () => {
keepScrollPosition(); await keepScrollPosition();
},
{
deep: true,
} }
); );
watch( watch(
() => props.channel.pendingMessage, () => props.channel.pendingMessage,
() => { async () => {
nextTick(() => { // Keep the scroll stuck when input gets resized while typing
// Keep the scroll stuck when input gets resized while typing await keepScrollPosition();
keepScrollPosition();
}).catch(() => {
// no-op
});
} }
); );

View file

@ -475,10 +475,8 @@ export default defineComponent({
watch(displayPasswordField, (newValue) => { watch(displayPasswordField, (newValue) => {
if (newValue) { if (newValue) {
nextTick(() => { void nextTick(() => {
publicPassword.value?.focus(); publicPassword.value?.focus();
}).catch(() => {
// no-op
}); });
} }
}); });
@ -502,10 +500,8 @@ export default defineComponent({
watch( watch(
() => props.defaults?.commands, () => props.defaults?.commands,
() => { () => {
nextTick(() => { void nextTick(() => {
resizeCommandsInput(); resizeCommandsInput();
}).catch((e) => {
// no-op
}); });
} }
); );

View file

@ -383,10 +383,8 @@ export default defineComponent({
sidebarWasClosed.value = store.state.sidebarOpen ? false : true; sidebarWasClosed.value = store.state.sidebarOpen ? false : true;
store.commit("sidebarOpen", true); store.commit("sidebarOpen", true);
nextTick(() => { void nextTick(() => {
searchInput.value?.focus(); searchInput.value?.focus();
}).catch(() => {
// no-op
}); });
}; };
@ -432,14 +430,12 @@ export default defineComponent({
const scrollToActive = () => { const scrollToActive = () => {
// Scroll the list if needed after the active class is applied // Scroll the list if needed after the active class is applied
nextTick(() => { void nextTick(() => {
const el = networklist.value?.querySelector(".channel-list-item.active"); const el = networklist.value?.querySelector(".channel-list-item.active");
if (el) { if (el) {
el.scrollIntoView({block: "nearest", inline: "nearest"}); el.scrollIntoView({block: "nearest", inline: "nearest"});
} }
}).catch(() => {
// no-op
}); });
}; };

View file

@ -265,13 +265,10 @@ export default defineComponent({
} }
); );
watch( watch(route.query, () => {
() => route.query, doSearch();
() => { setActiveChannel();
doSearch(); });
setActiveChannel();
}
);
watch(messages, () => { watch(messages, () => {
moreResultsAvailable.value = !!( moreResultsAvailable.value = !!(
@ -281,7 +278,7 @@ export default defineComponent({
if (!offset.value) { if (!offset.value) {
jumpToBottom(); jumpToBottom();
} else { } else {
nextTick(() => { void nextTick(() => {
if (!chatRef) { if (!chatRef) {
return; return;
} }
@ -289,9 +286,6 @@ export default defineComponent({
const currentChatHeight = chatRef.scrollHeight; const currentChatHeight = chatRef.scrollHeight;
chatRef.scrollTop = chatRef.scrollTop =
oldScrollTop.value + currentChatHeight - oldChatHeight.value; oldScrollTop.value + currentChatHeight - oldChatHeight.value;
}).catch((e) => {
// eslint-disable-next-line no-console
console.error("Failed to scroll to bottom", e);
}); });
} }
}); });

View file

@ -172,27 +172,26 @@ router.afterEach((to) => {
} }
}); });
function navigate(routeName: string, params: any = {}) { async function navigate(routeName: string, params: any = {}) {
if (router.currentRoute.value.name) { if (router.currentRoute.value.name) {
// eslint-disable-next-line @typescript-eslint/no-empty-function await router.push({name: routeName, params});
router.push({name: routeName, params}).catch(() => {});
} else { } else {
// If current route is null, replace the history entry // If current route is null, replace the history entry
// This prevents invalid entries from lingering in history, // This prevents invalid entries from lingering in history,
// and then the route guard preventing proper navigation // and then the route guard preventing proper navigation
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
router.replace({name: routeName, params}).catch(() => {}); await router.replace({name: routeName, params}).catch(() => {});
} }
} }
function switchToChannel(channel: ClientChan) { function switchToChannel(channel: ClientChan) {
return navigate("RoutedChat", {id: channel.id}); return void navigate("RoutedChat", {id: channel.id});
} }
if ("serviceWorker" in navigator) { if ("serviceWorker" in navigator) {
navigator.serviceWorker.addEventListener("message", (event) => { navigator.serviceWorker.addEventListener("message", (event) => {
if (event.data && event.data.type === "open") { if (event.data && event.data.type === "open") {
const id = parseInt(event.data.channel.substr(5), 10); // remove "chan-" prefix const id = parseInt(event.data.channel.substring(5), 10); // remove "chan-" prefix
const channelTarget = store.getters.findChannel(id); const channelTarget = store.getters.findChannel(id);

View file

@ -30,7 +30,10 @@ socket.on("init", function (data) {
if (!handleQueryParams()) { if (!handleQueryParams()) {
// If we are on an unknown route or still on SignIn component // If we are on an unknown route or still on SignIn component
// then we can open last known channel on server, or Connect window if none // then we can open last known channel on server, or Connect window if none
if (!router.currentRoute.name || router.currentRoute.name === "SignIn") { if (
!router.currentRoute.value.name ||
router.currentRoute.value.name === "SignIn"
) {
const channel = store.getters.findChannel(data.active); const channel = store.getters.findChannel(data.active);
if (channel) { if (channel) {

View file

@ -2,8 +2,9 @@ import {nextTick} from "vue";
import socket from "../socket"; import socket from "../socket";
import {store} from "../store"; import {store} from "../store";
import {ClientMessage} from "../types";
socket.on("more", function (data) { socket.on("more", async (data) => {
const channel = store.getters.findChannel(data.chan)?.channel; const channel = store.getters.findChannel(data.chan)?.channel;
if (!channel) { if (!channel) {
@ -15,13 +16,12 @@ socket.on("more", function (data) {
.filter((m) => m.self && m.text && m.type === "message") .filter((m) => m.self && m.text && m.type === "message")
.map((m) => m.text) .map((m) => m.text)
.reverse() .reverse()
.slice(null, 100 - channel.inputHistory.length) .slice(undefined, 100 - channel.inputHistory.length)
); );
channel.moreHistoryAvailable = channel.moreHistoryAvailable =
data.totalMessages > channel.messages.length + data.messages.length; data.totalMessages > channel.messages.length + data.messages.length;
channel.messages.unshift(...data.messages); channel.messages.unshift(...(data.messages as ClientMessage[]));
nextTick(() => { await nextTick();
channel.historyLoading = false; channel.historyLoading = false;
});
}); });

View file

@ -78,6 +78,7 @@
"devDependencies": { "devDependencies": {
"@babel/core": "7.17.10", "@babel/core": "7.17.10",
"@babel/plugin-syntax-jsx": "7.16.7", "@babel/plugin-syntax-jsx": "7.16.7",
"@babel/plugin-transform-runtime": "7.18.2",
"@babel/plugin-transform-typescript": "7.16.8", "@babel/plugin-transform-typescript": "7.16.8",
"@babel/preset-env": "7.17.10", "@babel/preset-env": "7.17.10",
"@babel/preset-typescript": "7.16.7", "@babel/preset-typescript": "7.16.7",

View file

@ -146,10 +146,6 @@ class Client {
for (const messageStorage of client.messageStorage) { for (const messageStorage of client.messageStorage) {
messageStorage.enable(); messageStorage.enable();
} }
console.log(
"Message storage: " + client.messageStorage.map((m) => m.isEnabled).join(", ")
);
} }
if (!_.isPlainObject(client.config.sessions)) { if (!_.isPlainObject(client.config.sessions)) {

View file

@ -306,7 +306,9 @@ class Chan {
requestZncPlayback(this, network, from); requestZncPlayback(this, network, from);
} }
}) })
.catch((err) => log.error(`Failed to load messages for ${client.name}: ${err}`)); .catch((err: Error) =>
log.error(`Failed to load messages for ${client.name}: ${err.toString()}`)
);
} }
isLoggable() { isLoggable() {
return this.type === ChanType.CHANNEL || this.type === ChanType.QUERY; return this.type === ChanType.CHANNEL || this.type === ChanType.QUERY;

View file

@ -30,8 +30,6 @@ const toExport = {
initialized: false, initialized: false,
// TODO: fix typing // TODO: fix typing
async initialize() { async initialize() {
log.info("Auth initializing", toExport.initialized);
if (toExport.initialized) { if (toExport.initialized) {
return; return;
} }
@ -40,8 +38,6 @@ const toExport = {
const resolvedPlugins = await Promise.all(plugins); const resolvedPlugins = await Promise.all(plugins);
for (const {default: plugin} of resolvedPlugins) { for (const {default: plugin} of resolvedPlugins) {
log.info("Auth plugin", plugin.moduleName, "enabled", plugin.isEnabled().toString());
if (plugin.isEnabled()) { if (plugin.isEnabled()) {
toExport.initialized = true; toExport.initialized = true;

View file

@ -18,8 +18,8 @@ function ldapAuthCommon(
tlsOptions: config.ldap.tlsOptions, tlsOptions: config.ldap.tlsOptions,
}); });
ldapclient.on("error", function (err) { ldapclient.on("error", function (err: Error) {
log.error(`Unable to connect to LDAP server: ${err}`); log.error(`Unable to connect to LDAP server: ${err.toString()}`);
callback(false); callback(false);
}); });
@ -27,7 +27,7 @@ function ldapAuthCommon(
ldapclient.unbind(); ldapclient.unbind();
if (err) { if (err) {
log.error(`LDAP bind failed: ${err}`); log.error(`LDAP bind failed: ${err.toString()}`);
callback(false); callback(false);
} else { } else {
callback(true); callback(true);
@ -43,7 +43,7 @@ function simpleLdapAuth(user: string, password: string, callback: (success: bool
const config = Config.values; const config = Config.values;
const userDN = user.replace(/([,\\/#+<>;"= ])/g, "\\$1"); const userDN = user.replace(/([,\\/#+<>;"= ])/g, "\\$1");
const bindDN = `${config.ldap.primaryKey}=${userDN},${config.ldap.baseDN}`; const bindDN = `${config.ldap.primaryKey}=${userDN},${config.ldap.baseDN || ""}`;
log.info(`Auth against LDAP ${config.ldap.url} with provided bindDN ${bindDN}`); log.info(`Auth against LDAP ${config.ldap.url} with provided bindDN ${bindDN}`);
@ -73,8 +73,8 @@ function advancedLdapAuth(user: string, password: string, callback: (success: bo
attributes: ["dn"], attributes: ["dn"],
} as SearchOptions; } as SearchOptions;
ldapclient.on("error", function (err) { ldapclient.on("error", function (err: Error) {
log.error(`Unable to connect to LDAP server: ${err}`); log.error(`Unable to connect to LDAP server: ${err.toString()}`);
callback(false); callback(false);
}); });
@ -99,15 +99,15 @@ function advancedLdapAuth(user: string, password: string, callback: (success: bo
res.on("searchEntry", function (entry) { res.on("searchEntry", function (entry) {
found = true; found = true;
const bindDN = entry.objectName; const bindDN = entry.objectName;
log.info(`Auth against LDAP ${config.ldap.url} with found bindDN ${bindDN}`); log.info(`Auth against LDAP ${config.ldap.url} with found bindDN ${bindDN || ""}`);
ldapclient.unbind(); ldapclient.unbind();
// TODO: Fix type ! // TODO: Fix type !
ldapAuthCommon(user, bindDN!, password, callback); ldapAuthCommon(user, bindDN!, password, callback);
}); });
res.on("error", function (err3) { res.on("error", function (err3: Error) {
log.error(`LDAP error: ${err3}`); log.error(`LDAP error: ${err3.toString()}`);
callback(false); callback(false);
}); });
@ -116,7 +116,9 @@ function advancedLdapAuth(user: string, password: string, callback: (success: bo
if (!found) { if (!found) {
log.warn( log.warn(
`LDAP Search did not find anything for: ${userDN} (${result?.status})` `LDAP Search did not find anything for: ${userDN} (${
result?.status.toString() || "unknown"
})`
); );
callback(false); callback(false);
} }
@ -138,7 +140,7 @@ const ldapAuth: AuthHandler = (manager, client, user, password, callback) => {
callback(valid); callback(valid);
} }
let auth; let auth: typeof simpleLdapAuth | typeof advancedLdapAuth;
if ("baseDN" in Config.values.ldap) { if ("baseDN" in Config.values.ldap) {
auth = simpleLdapAuth; auth = simpleLdapAuth;
@ -164,8 +166,8 @@ function advancedLdapLoadUsers(users: string[], callbackLoadUser) {
const base = config.ldap.searchDN.base; const base = config.ldap.searchDN.base;
ldapclient.on("error", function (err) { ldapclient.on("error", function (err: Error) {
log.error(`Unable to connect to LDAP server: ${err}`); log.error(`Unable to connect to LDAP server: ${err.toString()}`);
}); });
ldapclient.bind(config.ldap.searchDN.rootDN, config.ldap.searchDN.rootPassword, function (err) { ldapclient.bind(config.ldap.searchDN.rootDN, config.ldap.searchDN.rootPassword, function (err) {
@ -185,7 +187,7 @@ function advancedLdapLoadUsers(users: string[], callbackLoadUser) {
ldapclient.search(base, searchOptions, function (err2, res) { ldapclient.search(base, searchOptions, function (err2, res) {
if (err2) { if (err2) {
log.error(`LDAP search error: ${err2}`); log.error(`LDAP search error: ${err2?.toString()}`);
return true; return true;
} }
@ -200,7 +202,7 @@ function advancedLdapLoadUsers(users: string[], callbackLoadUser) {
}); });
res.on("error", function (err3) { res.on("error", function (err3) {
log.error(`LDAP error: ${err3}`); log.error(`LDAP error: ${err3.toString()}`);
}); });
res.on("end", function () { res.on("end", function () {

View file

@ -27,9 +27,9 @@ export type LinkPreview = {
thumb: string; thumb: string;
size: number; size: number;
link: string; // Send original matched link to the client link: string; // Send original matched link to the client
shown: boolean | null; shown?: boolean;
error: undefined | string; error?: string;
message: undefined | string; message?: string;
media: string; media: string;
mediaType: string; mediaType: string;
@ -65,7 +65,7 @@ export default function (client: Client, chan: Chan, msg: Msg, cleanText: string
thumb: "", thumb: "",
size: -1, size: -1,
link: link.link, // Send original matched link to the client link: link.link, // Send original matched link to the client
shown: null, shown: undefined,
error: undefined, error: undefined,
message: undefined, message: undefined,
media: "", media: "",

View file

@ -3,7 +3,8 @@ import LinkPrefetch from "./link";
import cleanIrcMessage from "../../../client/js/helpers/ircmessageparser/cleanIrcMessage"; import cleanIrcMessage from "../../../client/js/helpers/ircmessageparser/cleanIrcMessage";
import Helper from "../../helper"; import Helper from "../../helper";
import {IrcEventHandler} from "../../client"; import {IrcEventHandler} from "../../client";
import {ChanType} from "../../models/chan"; import Chan, {ChanType} from "../../models/chan";
import User from "../../models/user";
const nickRegExp = /(?:\x03[0-9]{1,2}(?:,[0-9]{1,2})?)?([\w[\]\\`^{|}-]+)/g; const nickRegExp = /(?:\x03[0-9]{1,2}(?:,[0-9]{1,2})?)?([\w[\]\\`^{|}-]+)/g;
@ -12,28 +13,39 @@ export default <IrcEventHandler>function (irc, network) {
irc.on("notice", function (data) { irc.on("notice", function (data) {
data.type = MessageType.NOTICE as any; data.type = MessageType.NOTICE as any;
handleMessage(data); handleMessage(data as any);
}); });
irc.on("action", function (data) { irc.on("action", function (data) {
data.type = MessageType.ACTION; data.type = MessageType.ACTION;
handleMessage(data); handleMessage(data as any);
}); });
irc.on("privmsg", function (data) { irc.on("privmsg", function (data) {
data.type = MessageType.MESSAGE; data.type = MessageType.MESSAGE;
handleMessage(data); handleMessage(data as any);
}); });
irc.on("wallops", function (data) { irc.on("wallops", function (data) {
data.from_server = true; data.from_server = true;
data.type = MessageType.WALLOPS; data.type = MessageType.WALLOPS;
handleMessage(data); handleMessage(data as any);
}); });
function handleMessage(data: any) { function handleMessage(data: {
let chan; nick: string;
let from; from_server: boolean;
hostname: string;
ident: string;
target: string;
type: MessageType;
time: number;
text: string;
message: string;
group?: string;
}) {
let chan: Chan | undefined;
let from: User;
let highlight = false; let highlight = false;
let showInActive = false; let showInActive = false;
const self = data.nick === irc.user.nick; const self = data.nick === irc.user.nick;
@ -108,7 +120,7 @@ export default <IrcEventHandler>function (irc, network) {
// msg is constructed down here because `from` is being copied in the constructor // msg is constructed down here because `from` is being copied in the constructor
const msg = new Msg({ const msg = new Msg({
type: data.type, type: data.type,
time: data.time, time: data.time as any,
text: data.message, text: data.message,
self: self, self: self,
from: from, from: from,

View file

@ -51,9 +51,6 @@ class SqliteMessageStorage implements ISqliteMessageStorage {
const logsPath = Config.getUserLogsPath(); const logsPath = Config.getUserLogsPath();
const sqlitePath = path.join(logsPath, `${this.client.name}.sqlite3`); const sqlitePath = path.join(logsPath, `${this.client.name}.sqlite3`);
log.info("Logs path", logsPath);
log.info("Sqlite path", sqlitePath);
try { try {
fs.mkdirSync(logsPath, {recursive: true}); fs.mkdirSync(logsPath, {recursive: true});
} catch (e: any) { } catch (e: any) {

View file

@ -107,11 +107,13 @@ interface ClientToServerEvents {
"msg:preview:toggle": ({ "msg:preview:toggle": ({
target, target,
messageIds, messageIds,
msgId,
shown, shown,
}: { }: {
target: number; target: number;
messageIds: number[]; messageIds?: number[];
shown: boolean; msgId?: number;
shown?: boolean;
}) => void; }) => void;
"network:get": (uuid: string) => void; "network:get": (uuid: string) => void;
@ -133,6 +135,8 @@ interface ClientToServerEvents {
}) => void; }) => void;
} }
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface InterServerEvents {} interface InterServerEvents {}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface SocketData {} interface SocketData {}

View file

@ -821,6 +821,18 @@
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7"
"@babel/plugin-transform-runtime@7.18.2":
version "7.18.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz#04637de1e45ae8847ff14b9beead09c33d34374d"
integrity sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg==
dependencies:
"@babel/helper-module-imports" "^7.16.7"
"@babel/helper-plugin-utils" "^7.17.12"
babel-plugin-polyfill-corejs2 "^0.3.0"
babel-plugin-polyfill-corejs3 "^0.5.0"
babel-plugin-polyfill-regenerator "^0.3.0"
semver "^6.3.0"
"@babel/plugin-transform-shorthand-properties@^7.16.7": "@babel/plugin-transform-shorthand-properties@^7.16.7":
version "7.16.7" version "7.16.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a"