[ts-migrate][client] Init tsconfig.json file

Co-authored-by: ts-migrate <>
This commit is contained in:
Max Leiter 2022-05-02 21:09:44 -07:00
parent a77c00b2d6
commit a3674b8261
No known key found for this signature in database
GPG key ID: A3512F2F2F17EBDA
10 changed files with 76 additions and 14 deletions

View file

@ -1,8 +1,10 @@
"use strict";
import {ParsedStyle} from "./parseStyle";
// Return true if any section of "a" or "b" parts (defined by their start/end
// markers) intersect each other, false otherwise.
function anyIntersection(a, b) {
function anyIntersection(a: ParsedStyle, b: ParsedStyle) {
return (
(a.start <= b.start && b.start < a.end) ||
(a.start < b.end && b.end <= a.end) ||

View file

@ -3,4 +3,4 @@
const matchFormatting =
/\x02|\x1D|\x1F|\x16|\x0F|\x11|\x1E|\x03(?:[0-9]{1,2}(?:,[0-9]{1,2})?)?|\x04(?:[0-9a-f]{6}(?:,[0-9a-f]{6})?)?/gi;
module.exports = (message) => message.replace(matchFormatting, "").trim();
export default (message: string) => message.replace(matchFormatting, "").trim();

View file

@ -1,15 +1,17 @@
"use strict";
import {ParsedStyle} from "./parseStyle";
// Create plain text entries corresponding to areas of the text that match no
// existing entries. Returns an empty array if all parts of the text have been
// parsed into recognizable entries already.
function fill(existingEntries, text) {
function fill(existingEntries: ParsedStyle[], text: string) {
let position = 0;
// Fill inner parts of the text. For example, if text is `foobarbaz` and both
// `foo` and `baz` have matched into an entry, this will return a dummy entry
// corresponding to `bar`.
const result = existingEntries.reduce((acc, textSegment) => {
const result = existingEntries.reduce((acc: Omit<ParsedStyle, "text">[], textSegment) => {
if (textSegment.start > position) {
acc.push({
start: position,

View file

@ -11,6 +11,21 @@ const UNDERLINE = "\x1f";
const STRIKETHROUGH = "\x1e";
const MONOSPACE = "\x11";
export type ParsedStyle = {
bold?: boolean;
textColor?: string;
bgColor?: string;
hexColor?: string;
hexBgColor?: string;
italic?: boolean;
underline?: boolean;
strikethrough?: boolean;
monospace?: boolean;
text: string;
start: number;
end: number;
};
// Color code matcher, with format `XX,YY` where both `XX` and `YY` are
// integers, `XX` is the text color and `YY` is an optional background color.
const colorRx = /^(\d{1,2})(?:,(\d{1,2}))?/;
@ -26,8 +41,8 @@ const controlCodesRx = /[\u0000-\u0009\u000B-\u001F]/g;
// similarly styled section of the text. Each object carries the `text`, style
// information (`bold`, `textColor`, `bgcolor`, `italic`,
// `underline`, `strikethrough`, `monospace`), and `start`/`end` cursors.
function parseStyle(text) {
const result = [];
function parseStyle(text: string) {
const result: ParsedStyle[] = [];
let start = 0;
let position = 0;
@ -213,12 +228,12 @@ const properties = [
"monospace",
];
function prepare(text) {
function prepare(text: string) {
return (
parseStyle(text)
// This optimizes fragments by combining them together when all their values
// for the properties defined above are equal.
.reduce((prev, curr) => {
.reduce((prev: ParsedStyle[], curr) => {
if (prev.length) {
const lastEntry = prev[prev.length - 1];

View file

@ -1,8 +1,10 @@
import storage from "./localStorage";
import socket from "./socket";
import {config, createState} from "./settings";
import {Store} from "vuex";
import {State} from "./store";
export function createSettingsStore(store) {
export function createSettingsStore(store: Store<State>) {
return {
namespaced: true,
state: assignStoredSettings(createState(), loadFromLocalStorage()),
@ -72,7 +74,7 @@ function loadFromLocalStorage() {
let storedSettings;
try {
storedSettings = JSON.parse(storage.get("settings"));
storedSettings = JSON.parse(storage.get("settings") || "{}");
} catch (e) {
storage.remove("settings");
}

View file

@ -19,7 +19,44 @@ function detectDesktopNotificationState() {
return "blocked";
}
const store = new Vuex.Store({
export type State = {
appLoaded: boolean;
activeChannel: {
network: Network;
channel: Channel;
} | null;
currentUserVisibleError: string | null;
desktopNotificationState: "granted" | "blocked" | "nohttps" | "unsupported";
isAutoCompleting: boolean;
isConnected: boolean;
networks: Network[];
// TODO: type
mentions: any[];
hasServiceWorker: boolean;
pushNotificationState: string;
serverConfiguration: null;
sessions: [];
sidebarOpen: boolean;
sidebarDragging: boolean;
userlistOpen: boolean;
versionData: null | {
latest: {
version: string;
prerelease: boolean;
};
};
versionStatus: "loading" | "new-version" | "new-packages" | "up-to-date" | "error";
versionDataExpired: boolean;
serverHasSettings: boolean;
messageSearchResults: {
results: any[];
} | null;
messageSearchInProgress: boolean;
searchEnabled: boolean;
};
export type SettingsState = {};
const store = new Vuex.Store<Omit<State, "settings">>({
state: {
appLoaded: false,
activeChannel: null,
@ -124,8 +161,12 @@ const store = new Vuex.Store({
state.messageSearchResults = value;
},
addMessageSearchResults(state, value) {
// Append the search results and add networks and channels to new messages
value.results = [...state.messageSearchResults.results, ...value.results];
if (state.messageSearchResults!.results) {
// Append the search results and add networks and channels to new messages
value.results = [...state.messageSearchResults!.results, ...value.results];
} else {
value.results = value.results;
}
state.messageSearchResults = value;
},
@ -139,7 +180,7 @@ const store = new Vuex.Store({
getters: {
findChannelOnCurrentNetwork: (state) => (name) => {
name = name.toLowerCase();
return state.activeChannel.network.channels.find((c) => c.name.toLowerCase() === name);
return state.activeChannel?.network.channels.find((c) => c.name.toLowerCase() === name);
},
findChannelOnNetwork: (state) => (networkUuid, channelName) => {
for (const network of state.networks) {