use eslint to format ts files.
This commit is contained in:
parent
641714285a
commit
34489bfb30
14 changed files with 117 additions and 303 deletions
|
@ -57,5 +57,6 @@ module.exports = {
|
||||||
"@typescript-eslint/no-unused-vars": "error",
|
"@typescript-eslint/no-unused-vars": "error",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/ban-ts-comment": "off",
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
|
"@typescript-eslint/ban-types": "off",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
|
@ -1,5 +1,11 @@
|
||||||
{
|
{
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"typescript.tsdk": "node_modules/typescript/lib"
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||||
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
|
import { MatrixClient, MatrixEvent, NotificationCountType, Room } from 'matrix-js-sdk';
|
||||||
import renderAvatar from '../../app/atoms/avatar/render';
|
import renderAvatar from '../../app/atoms/avatar/render';
|
||||||
import { cssColorMXID } from '../../util/colorMXID';
|
import { cssColorMXID } from '../../util/colorMXID';
|
||||||
import { selectRoom } from '../action/navigation';
|
import { selectRoom } from '../action/navigation';
|
||||||
|
@ -11,7 +12,6 @@ import LogoSVG from '../../../public/res/svg/cinny.svg';
|
||||||
import LogoUnreadSVG from '../../../public/res/svg/cinny-unread.svg';
|
import LogoUnreadSVG from '../../../public/res/svg/cinny-unread.svg';
|
||||||
import LogoHighlightSVG from '../../../public/res/svg/cinny-highlight.svg';
|
import LogoHighlightSVG from '../../../public/res/svg/cinny-highlight.svg';
|
||||||
import { html, plain } from '../../util/markdown';
|
import { html, plain } from '../../util/markdown';
|
||||||
import { MatrixClient, MatrixEvent, NotificationCountType, Room } from 'matrix-js-sdk';
|
|
||||||
import RoomList from './RoomList';
|
import RoomList from './RoomList';
|
||||||
|
|
||||||
function isNotifEvent(mEvent: MatrixEvent) {
|
function isNotifEvent(mEvent: MatrixEvent) {
|
||||||
|
@ -35,14 +35,23 @@ function findMutedRule(overrideRules, roomId) {
|
||||||
|
|
||||||
class Notifications extends EventEmitter {
|
class Notifications extends EventEmitter {
|
||||||
initialized: boolean;
|
initialized: boolean;
|
||||||
|
|
||||||
favicon: string;
|
favicon: string;
|
||||||
|
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
|
||||||
roomList: RoomList;
|
roomList: RoomList;
|
||||||
|
|
||||||
roomIdToNoti: Map<string, any>;
|
roomIdToNoti: Map<string, any>;
|
||||||
|
|
||||||
roomIdToPopupNotis: Map<string, any>;
|
roomIdToPopupNotis: Map<string, any>;
|
||||||
|
|
||||||
eventIdToPopupNoti: Map<any, any>;
|
eventIdToPopupNoti: Map<any, any>;
|
||||||
|
|
||||||
_notiAudio: any;
|
_notiAudio: any;
|
||||||
|
|
||||||
_inviteAudio: any;
|
_inviteAudio: any;
|
||||||
|
|
||||||
constructor(roomList) {
|
constructor(roomList) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -333,7 +342,7 @@ class Notifications extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
_listenEvents() {
|
_listenEvents() {
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('Room.timeline', (mEvent: MatrixEvent, room: Room) => {
|
this.matrixClient.on('Room.timeline', (mEvent: MatrixEvent, room: Room) => {
|
||||||
if (mEvent.isRedaction()) this._deletePopupNoti(mEvent.event.redacts);
|
if (mEvent.isRedaction()) this._deletePopupNoti(mEvent.event.redacts);
|
||||||
|
|
||||||
|
@ -360,7 +369,7 @@ class Notifications extends EventEmitter {
|
||||||
this._displayPopupNoti(mEvent, room);
|
this._displayPopupNoti(mEvent, room);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('accountData', (mEvent: MatrixEvent, oldMEvent: MatrixEvent) => {
|
this.matrixClient.on('accountData', (mEvent: MatrixEvent, oldMEvent: MatrixEvent) => {
|
||||||
if (mEvent.getType() === 'm.push_rules') {
|
if (mEvent.getType() === 'm.push_rules') {
|
||||||
const override = mEvent?.getContent()?.global?.override;
|
const override = mEvent?.getContent()?.global?.override;
|
||||||
|
@ -397,7 +406,7 @@ class Notifications extends EventEmitter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('Room.receipt', (mEvent: MatrixEvent, room: Room) => {
|
this.matrixClient.on('Room.receipt', (mEvent: MatrixEvent, room: Room) => {
|
||||||
if (mEvent.getType() === 'm.receipt') {
|
if (mEvent.getType() === 'm.receipt') {
|
||||||
if (room.isSpaceRoom()) return;
|
if (room.isSpaceRoom()) return;
|
||||||
|
@ -411,7 +420,7 @@ class Notifications extends EventEmitter {
|
||||||
this._deletePopupRoomNotis(room.roomId);
|
this._deletePopupRoomNotis(room.roomId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('Room.myMembership', (room: Room, membership) => {
|
this.matrixClient.on('Room.myMembership', (room: Room, membership) => {
|
||||||
if (membership === 'leave' && this.hasNoti(room.roomId)) {
|
if (membership === 'leave' && this.hasNoti(room.roomId)) {
|
||||||
this.deleteNoti(room.roomId);
|
this.deleteNoti(room.roomId);
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
MatrixClient,
|
MatrixClient,
|
||||||
MatrixEvent,
|
MatrixEvent,
|
||||||
Room,
|
Room,
|
||||||
TimelineIndex,
|
|
||||||
} from 'matrix-js-sdk';
|
} from 'matrix-js-sdk';
|
||||||
import initMatrix from '../initMatrix';
|
import initMatrix from '../initMatrix';
|
||||||
import cons from './cons';
|
import cons from './cons';
|
||||||
|
@ -53,18 +52,18 @@ function addToMap(myMap: Map<string, MatrixEvent[]>, mEvent: MatrixEvent) {
|
||||||
|
|
||||||
function getFirstLinkedTimeline(timeline: EventTimeline) {
|
function getFirstLinkedTimeline(timeline: EventTimeline) {
|
||||||
let tm = timeline;
|
let tm = timeline;
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
while (tm.prevTimeline) {
|
while (tm.prevTimeline) {
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
tm = tm.prevTimeline;
|
tm = tm.prevTimeline;
|
||||||
}
|
}
|
||||||
return tm;
|
return tm;
|
||||||
}
|
}
|
||||||
function getLastLinkedTimeline(timeline: EventTimeline) {
|
function getLastLinkedTimeline(timeline: EventTimeline) {
|
||||||
let tm = timeline;
|
let tm = timeline;
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
while (tm.nextTimeline) {
|
while (tm.nextTimeline) {
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
tm = tm.nextTimeline;
|
tm = tm.nextTimeline;
|
||||||
}
|
}
|
||||||
return tm;
|
return tm;
|
||||||
|
@ -78,9 +77,9 @@ function iterateLinkedTimelines(
|
||||||
let tm = timeline;
|
let tm = timeline;
|
||||||
while (tm) {
|
while (tm) {
|
||||||
callback(tm);
|
callback(tm);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
if (backwards) tm = tm.prevTimeline;
|
if (backwards) tm = tm.prevTimeline;
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
else tm = tm.nextTimeline;
|
else tm = tm.nextTimeline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +88,7 @@ function isTimelineLinked(tm1: EventTimeline, tm2: EventTimeline) {
|
||||||
let tm = getFirstLinkedTimeline(tm1);
|
let tm = getFirstLinkedTimeline(tm1);
|
||||||
while (tm) {
|
while (tm) {
|
||||||
if (tm === tm2) return true;
|
if (tm === tm2) return true;
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
tm = tm.nextTimeline;
|
tm = tm.nextTimeline;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -97,17 +96,29 @@ function isTimelineLinked(tm1: EventTimeline, tm2: EventTimeline) {
|
||||||
|
|
||||||
class RoomTimeline extends EventEmitter {
|
class RoomTimeline extends EventEmitter {
|
||||||
timeline: any[];
|
timeline: any[];
|
||||||
|
|
||||||
editedTimeline: Map<any, any>;
|
editedTimeline: Map<any, any>;
|
||||||
|
|
||||||
reactionTimeline: Map<any, any>;
|
reactionTimeline: Map<any, any>;
|
||||||
|
|
||||||
typingMembers: Set<unknown>;
|
typingMembers: Set<unknown>;
|
||||||
|
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
|
||||||
roomId: string;
|
roomId: string;
|
||||||
|
|
||||||
room: any;
|
room: any;
|
||||||
|
|
||||||
liveTimeline;
|
liveTimeline;
|
||||||
|
|
||||||
activeTimeline: any;
|
activeTimeline: any;
|
||||||
|
|
||||||
isOngoingPagination: boolean;
|
isOngoingPagination: boolean;
|
||||||
|
|
||||||
ongoingDecryptionCount: number;
|
ongoingDecryptionCount: number;
|
||||||
|
|
||||||
initialized: boolean;
|
initialized: boolean;
|
||||||
|
|
||||||
_listenRoomTimeline: (
|
_listenRoomTimeline: (
|
||||||
event: any,
|
event: any,
|
||||||
room: any,
|
room: any,
|
||||||
|
@ -115,10 +126,15 @@ class RoomTimeline extends EventEmitter {
|
||||||
removed: any,
|
removed: any,
|
||||||
data: any
|
data: any
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
_listenDecryptEvent: (event: any) => void;
|
_listenDecryptEvent: (event: any) => void;
|
||||||
|
|
||||||
_listenRedaction: (mEvent: MatrixEvent, room: any) => void;
|
_listenRedaction: (mEvent: MatrixEvent, room: any) => void;
|
||||||
|
|
||||||
_listenTypingEvent: (event: any, member: any) => void;
|
_listenTypingEvent: (event: any, member: any) => void;
|
||||||
|
|
||||||
_listenReciptEvent: (event: any, room: any) => void;
|
_listenReciptEvent: (event: any, room: any) => void;
|
||||||
|
|
||||||
constructor(roomId: string) {
|
constructor(roomId: string) {
|
||||||
super();
|
super();
|
||||||
// These are local timelines
|
// These are local timelines
|
||||||
|
@ -141,7 +157,7 @@ class RoomTimeline extends EventEmitter {
|
||||||
setTimeout(() => this.room.loadMembersIfNeeded());
|
setTimeout(() => this.room.loadMembersIfNeeded());
|
||||||
|
|
||||||
// TODO: remove below line
|
// TODO: remove below line
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
window.selectedRoom = this;
|
window.selectedRoom = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,29 +456,29 @@ class RoomTimeline extends EventEmitter {
|
||||||
this.emit(cons.events.roomTimeline.LIVE_RECEIPT);
|
this.emit(cons.events.roomTimeline.LIVE_RECEIPT);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('Room.timeline', this._listenRoomTimeline);
|
this.matrixClient.on('Room.timeline', this._listenRoomTimeline);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('Room.redaction', this._listenRedaction);
|
this.matrixClient.on('Room.redaction', this._listenRedaction);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('Event.decrypted', this._listenDecryptEvent);
|
this.matrixClient.on('Event.decrypted', this._listenDecryptEvent);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('RoomMember.typing', this._listenTypingEvent);
|
this.matrixClient.on('RoomMember.typing', this._listenTypingEvent);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.on('Room.receipt', this._listenReciptEvent);
|
this.matrixClient.on('Room.receipt', this._listenReciptEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeInternalListeners() {
|
removeInternalListeners() {
|
||||||
if (!this.initialized) return;
|
if (!this.initialized) return;
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.removeListener('Room.timeline', this._listenRoomTimeline);
|
this.matrixClient.removeListener('Room.timeline', this._listenRoomTimeline);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.removeListener('Room.redaction', this._listenRedaction);
|
this.matrixClient.removeListener('Room.redaction', this._listenRedaction);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.removeListener('Event.decrypted', this._listenDecryptEvent);
|
this.matrixClient.removeListener('Event.decrypted', this._listenDecryptEvent);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.removeListener('RoomMember.typing', this._listenTypingEvent);
|
this.matrixClient.removeListener('RoomMember.typing', this._listenTypingEvent);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.matrixClient.removeListener('Room.receipt', this._listenReciptEvent);
|
this.matrixClient.removeListener('Room.receipt', this._listenReciptEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,15 @@ import { RoomHierarchy } from 'matrix-js-sdk/lib/room-hierarchy';
|
||||||
|
|
||||||
class RoomsHierarchy {
|
class RoomsHierarchy {
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
|
||||||
_maxDepth: number;
|
_maxDepth: number;
|
||||||
|
|
||||||
_suggestedOnly: boolean;
|
_suggestedOnly: boolean;
|
||||||
|
|
||||||
_limit: number;
|
_limit: number;
|
||||||
|
|
||||||
roomIdToHierarchy: Map<any, any>;
|
roomIdToHierarchy: Map<any, any>;
|
||||||
|
|
||||||
constructor(matrixClient: MatrixClient, limit = 20, maxDepth = 1, suggestedOnly = false) {
|
constructor(matrixClient: MatrixClient, limit = 20, maxDepth = 1, suggestedOnly = false) {
|
||||||
this.matrixClient = matrixClient;
|
this.matrixClient = matrixClient;
|
||||||
this._maxDepth = maxDepth;
|
this._maxDepth = maxDepth;
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import encrypt from 'browser-encrypt-attachment';
|
import encrypt from 'browser-encrypt-attachment';
|
||||||
import { encode } from 'blurhash';
|
import { encode } from 'blurhash';
|
||||||
|
import { IContent, MatrixClient, MatrixEvent } from 'matrix-js-sdk';
|
||||||
import { getShortcodeToEmoji } from '../../app/organisms/emoji-board/custom-emoji';
|
import { getShortcodeToEmoji } from '../../app/organisms/emoji-board/custom-emoji';
|
||||||
import { getBlobSafeMimeType } from '../../util/mimetypes';
|
import { getBlobSafeMimeType } from '../../util/mimetypes';
|
||||||
import { sanitizeText } from '../../util/sanitize';
|
import { sanitizeText } from '../../util/sanitize';
|
||||||
import cons from './cons';
|
import cons from './cons';
|
||||||
import settings from './settings';
|
import settings from './settings';
|
||||||
import { markdown, plain } from '../../util/markdown';
|
import { markdown, plain } from '../../util/markdown';
|
||||||
import { IContent, MatrixClient, MatrixEvent } from 'matrix-js-sdk';
|
|
||||||
import RoomList from './RoomList';
|
import RoomList from './RoomList';
|
||||||
|
|
||||||
const blurhashField = 'xyz.amorgan.blurhash';
|
const blurhashField = 'xyz.amorgan.blurhash';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
function encodeBlurhash(img: CanvasImageSource) {
|
function encodeBlurhash(img: CanvasImageSource) {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.width = 100;
|
canvas.width = 100;
|
||||||
|
@ -66,6 +67,7 @@ function loadVideo(videoFile: Blob) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function getVideoThumbnail(
|
function getVideoThumbnail(
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
video: CanvasImageSource,
|
video: CanvasImageSource,
|
||||||
width: number,
|
width: number,
|
||||||
height: number,
|
height: number,
|
||||||
|
@ -107,8 +109,11 @@ function getVideoThumbnail(
|
||||||
|
|
||||||
class RoomsInput extends EventEmitter {
|
class RoomsInput extends EventEmitter {
|
||||||
matrixClient: MatrixClient;
|
matrixClient: MatrixClient;
|
||||||
|
|
||||||
roomList: RoomList;
|
roomList: RoomList;
|
||||||
|
|
||||||
roomIdToInput: Map<any, any>;
|
roomIdToInput: Map<any, any>;
|
||||||
|
|
||||||
constructor(mx: MatrixClient, roomList: RoomList) {
|
constructor(mx: MatrixClient, roomList: RoomList) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -221,7 +226,7 @@ class RoomsInput extends EventEmitter {
|
||||||
const autoMarkdown = options?.autoMarkdown ?? true;
|
const autoMarkdown = options?.autoMarkdown ?? true;
|
||||||
|
|
||||||
const room = this.matrixClient.getRoom(roomId);
|
const room = this.matrixClient.getRoom(roomId);
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
const userNames = room.currentState.userIdsToDisplayNames;
|
const userNames = room.currentState.userIdsToDisplayNames;
|
||||||
const parentIds = this.roomList.getAllParentSpaces(room.roomId);
|
const parentIds = this.roomList.getAllParentSpaces(room.roomId);
|
||||||
const parentRooms = [...parentIds].map((id) => this.matrixClient.getRoom(id));
|
const parentRooms = [...parentIds].map((id) => this.matrixClient.getRoom(id));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import { MatrixClient, Room } from 'matrix-js-sdk';
|
import { MatrixClient } from 'matrix-js-sdk';
|
||||||
import appDispatcher from '../dispatcher';
|
import appDispatcher from '../dispatcher';
|
||||||
import AccountData from './AccountData';
|
import AccountData from './AccountData';
|
||||||
import cons from './cons';
|
import cons from './cons';
|
||||||
|
@ -7,18 +7,27 @@ import RoomList from './RoomList';
|
||||||
|
|
||||||
class Navigation extends EventEmitter {
|
class Navigation extends EventEmitter {
|
||||||
initMatrix: { roomList: RoomList; accountData: AccountData; matrixClient: MatrixClient };
|
initMatrix: { roomList: RoomList; accountData: AccountData; matrixClient: MatrixClient };
|
||||||
|
|
||||||
selectedTab: string;
|
selectedTab: string;
|
||||||
|
|
||||||
selectedSpaceId: string;
|
selectedSpaceId: string;
|
||||||
|
|
||||||
selectedSpacePath: string[];
|
selectedSpacePath: string[];
|
||||||
|
|
||||||
selectedRoomId: string;
|
selectedRoomId: string;
|
||||||
|
|
||||||
isRoomSettings: boolean;
|
isRoomSettings: boolean;
|
||||||
|
|
||||||
recentRooms: string[];
|
recentRooms: string[];
|
||||||
|
|
||||||
spaceToRoom: Map<string, any>;
|
spaceToRoom: Map<string, any>;
|
||||||
|
|
||||||
rawModelStack: any[];
|
rawModelStack: any[];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
// this will attached by initMatrix
|
// this will attached by initMatrix
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
this.initMatrix = {};
|
this.initMatrix = {};
|
||||||
|
|
||||||
this.selectedTab = cons.tabs.HOME;
|
this.selectedTab = cons.tabs.HOME;
|
||||||
|
|
|
@ -16,7 +16,7 @@ export function getPrivateKey(keyId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deletePrivateKey(keyId) {
|
export function deletePrivateKey(keyId) {
|
||||||
//@ts-ignore
|
// @ts-ignore
|
||||||
delete secretStorageKeys.delete(keyId);
|
delete secretStorageKeys.delete(keyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import appDispatcher from '../dispatcher';
|
||||||
|
|
||||||
import cons from './cons';
|
import cons from './cons';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
function getSettings(): Settings {
|
function getSettings(): Settings {
|
||||||
const settings = localStorage.getItem('settings');
|
const settings = localStorage.getItem('settings');
|
||||||
if (settings === null) return null;
|
if (settings === null) return null;
|
||||||
|
@ -11,6 +12,7 @@ function getSettings(): Settings {
|
||||||
|
|
||||||
function setSettings(key: string, value) {
|
function setSettings(key: string, value) {
|
||||||
let settings = getSettings();
|
let settings = getSettings();
|
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
if (settings === null) settings = new Settings();
|
if (settings === null) settings = new Settings();
|
||||||
settings[key] = value;
|
settings[key] = value;
|
||||||
localStorage.setItem('settings', JSON.stringify(settings));
|
localStorage.setItem('settings', JSON.stringify(settings));
|
||||||
|
@ -18,15 +20,25 @@ function setSettings(key: string, value) {
|
||||||
|
|
||||||
class Settings extends EventEmitter {
|
class Settings extends EventEmitter {
|
||||||
themes: string[];
|
themes: string[];
|
||||||
|
|
||||||
themeIndex: number;
|
themeIndex: number;
|
||||||
|
|
||||||
useSystemTheme: boolean;
|
useSystemTheme: boolean;
|
||||||
|
|
||||||
isMarkdown: boolean;
|
isMarkdown: boolean;
|
||||||
|
|
||||||
isPeopleDrawer: boolean;
|
isPeopleDrawer: boolean;
|
||||||
|
|
||||||
hideMembershipEvents: boolean;
|
hideMembershipEvents: boolean;
|
||||||
|
|
||||||
hideNickAvatarEvents: boolean;
|
hideNickAvatarEvents: boolean;
|
||||||
|
|
||||||
_showNotifications: boolean;
|
_showNotifications: boolean;
|
||||||
|
|
||||||
isNotificationSounds: boolean;
|
isNotificationSounds: boolean;
|
||||||
|
|
||||||
isTouchScreenDevice: boolean;
|
isTouchScreenDevice: boolean;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,29 @@ import EventEmitter from 'events';
|
||||||
|
|
||||||
class AsyncSearch extends EventEmitter {
|
class AsyncSearch extends EventEmitter {
|
||||||
RESULT_SENT: string;
|
RESULT_SENT: string;
|
||||||
|
|
||||||
dataList: (string | object)[];
|
dataList: (string | object)[];
|
||||||
|
|
||||||
term: any;
|
term: any;
|
||||||
|
|
||||||
searchKeys: any;
|
searchKeys: any;
|
||||||
|
|
||||||
isContain: boolean;
|
isContain: boolean;
|
||||||
|
|
||||||
isCaseSensitive: boolean;
|
isCaseSensitive: boolean;
|
||||||
|
|
||||||
normalizeUnicode: boolean;
|
normalizeUnicode: boolean;
|
||||||
|
|
||||||
ignoreWhitespace: boolean;
|
ignoreWhitespace: boolean;
|
||||||
|
|
||||||
limit: number;
|
limit: number;
|
||||||
|
|
||||||
findingList: any[];
|
findingList: any[];
|
||||||
|
|
||||||
searchUptoIndex: number;
|
searchUptoIndex: number;
|
||||||
|
|
||||||
sessionStartTimestamp: number;
|
sessionStartTimestamp: number;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
class Postie {
|
class Postie {
|
||||||
_topics: Map<string, Map<string, Set<Function>>>;
|
_topics: Map<string, Map<string, Set<Function>>>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._topics = new Map();
|
this._topics = new Map();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +79,7 @@ class Postie {
|
||||||
* @param {*} data - Data to deliver to subscriber
|
* @param {*} data - Data to deliver to subscriber
|
||||||
*/
|
*/
|
||||||
post(topic: string, address: string | string[], data: any) {
|
post(topic: string, address: string | string[], data: any) {
|
||||||
const sendPost = (inboxes: Set<Function>, addr: string) => {
|
const sendPost = (inboxes: Set<Function>, addr: string) => {
|
||||||
if (inboxes === undefined) {
|
if (inboxes === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Unable to post on topic:"${topic}" at address:"${addr}". Subscriber doesn't exist.`
|
`Unable to post on topic:"${topic}" at address:"${addr}". Subscriber doesn't exist.`
|
||||||
|
|
|
@ -1,230 +0,0 @@
|
||||||
/* eslint-disable max-classes-per-file */
|
|
||||||
export function bytesToSize(bytes) {
|
|
||||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
||||||
if (bytes === 0) return 'n/a';
|
|
||||||
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);
|
|
||||||
if (i === 0) return `${bytes} ${sizes[i]}`;
|
|
||||||
return `${(bytes / (1024 ** i)).toFixed(1)} ${sizes[i]}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function diffMinutes(dt2, dt1) {
|
|
||||||
let diff = (dt2.getTime() - dt1.getTime()) / 1000;
|
|
||||||
diff /= 60;
|
|
||||||
return Math.abs(Math.round(diff));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isInSameDay(dt2, dt1) {
|
|
||||||
return (
|
|
||||||
dt2.getFullYear() === dt1.getFullYear()
|
|
||||||
&& dt2.getMonth() === dt1.getMonth()
|
|
||||||
&& dt2.getDate() === dt1.getDate()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} ev
|
|
||||||
* @param {string} [targetSelector] element selector for Element.matches([selector])
|
|
||||||
*/
|
|
||||||
export function getEventCords(ev, targetSelector) {
|
|
||||||
let boxInfo;
|
|
||||||
|
|
||||||
const path = ev.nativeEvent.composedPath();
|
|
||||||
const target = targetSelector
|
|
||||||
? path.find((element) => element.matches?.(targetSelector))
|
|
||||||
: null;
|
|
||||||
if (target) {
|
|
||||||
boxInfo = target.getBoundingClientRect();
|
|
||||||
} else {
|
|
||||||
boxInfo = ev.target.getBoundingClientRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: boxInfo.x,
|
|
||||||
y: boxInfo.y,
|
|
||||||
width: boxInfo.width,
|
|
||||||
height: boxInfo.height,
|
|
||||||
detail: ev.detail,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function abbreviateNumber(number) {
|
|
||||||
if (number > 99) return '99+';
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Debounce {
|
|
||||||
constructor() {
|
|
||||||
this.timeoutId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {function} func - callback function
|
|
||||||
* @param {number} wait - wait in milliseconds to call func
|
|
||||||
* @returns {func} debounceCallback - to pass arguments to func callback
|
|
||||||
*/
|
|
||||||
_(func, wait) {
|
|
||||||
const that = this;
|
|
||||||
return function debounceCallback(...args) {
|
|
||||||
clearTimeout(that.timeoutId);
|
|
||||||
that.timeoutId = setTimeout(() => {
|
|
||||||
func.apply(this, args);
|
|
||||||
that.timeoutId = null;
|
|
||||||
}, wait);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Throttle {
|
|
||||||
constructor() {
|
|
||||||
this.timeoutId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {function} func - callback function
|
|
||||||
* @param {number} wait - wait in milliseconds to call func
|
|
||||||
* @returns {function} throttleCallback - to pass arguments to func callback
|
|
||||||
*/
|
|
||||||
_(func, wait) {
|
|
||||||
const that = this;
|
|
||||||
return function throttleCallback(...args) {
|
|
||||||
if (that.timeoutId !== null) return;
|
|
||||||
that.timeoutId = setTimeout(() => {
|
|
||||||
func.apply(this, args);
|
|
||||||
that.timeoutId = null;
|
|
||||||
}, wait);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getUrlPrams(paramName) {
|
|
||||||
const queryString = window.location.search;
|
|
||||||
const urlParams = new URLSearchParams(queryString);
|
|
||||||
return urlParams.get(paramName);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getScrollInfo(target) {
|
|
||||||
const scroll = {};
|
|
||||||
scroll.top = Math.round(target.scrollTop);
|
|
||||||
scroll.height = Math.round(target.scrollHeight);
|
|
||||||
scroll.viewHeight = Math.round(target.offsetHeight);
|
|
||||||
scroll.isScrollable = scroll.height > scroll.viewHeight;
|
|
||||||
return scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function avatarInitials(text) {
|
|
||||||
return [...text][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function cssVar(name) {
|
|
||||||
return getComputedStyle(document.body).getPropertyValue(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setFavicon(url) {
|
|
||||||
const favicon = document.querySelector('#favicon');
|
|
||||||
if (!favicon) return;
|
|
||||||
favicon.setAttribute('href', url);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function copyToClipboard(text) {
|
|
||||||
if (navigator.clipboard) {
|
|
||||||
navigator.clipboard.writeText(text);
|
|
||||||
} else {
|
|
||||||
const host = document.body;
|
|
||||||
const copyInput = document.createElement('input');
|
|
||||||
copyInput.style.position = 'fixed';
|
|
||||||
copyInput.style.opacity = '0';
|
|
||||||
copyInput.value = text;
|
|
||||||
host.append(copyInput);
|
|
||||||
|
|
||||||
copyInput.select();
|
|
||||||
copyInput.setSelectionRange(0, 99999);
|
|
||||||
document.execCommand('Copy');
|
|
||||||
copyInput.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function suffixRename(name, validator) {
|
|
||||||
let suffix = 2;
|
|
||||||
let newName = name;
|
|
||||||
do {
|
|
||||||
newName = name + suffix;
|
|
||||||
suffix += 1;
|
|
||||||
} while (validator(newName));
|
|
||||||
|
|
||||||
return newName;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getImageDimension(file) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const img = new Image();
|
|
||||||
img.onload = async () => {
|
|
||||||
resolve({
|
|
||||||
w: img.width,
|
|
||||||
h: img.height,
|
|
||||||
});
|
|
||||||
URL.revokeObjectURL(img.src);
|
|
||||||
};
|
|
||||||
img.src = URL.createObjectURL(file);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function scaleDownImage(imageFile, width, height) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const imgURL = URL.createObjectURL(imageFile);
|
|
||||||
const img = new Image();
|
|
||||||
|
|
||||||
img.onload = () => {
|
|
||||||
let newWidth = img.width;
|
|
||||||
let newHeight = img.height;
|
|
||||||
if (newHeight <= height && newWidth <= width) {
|
|
||||||
resolve(imageFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newHeight > height) {
|
|
||||||
newWidth = Math.floor(newWidth * (height / newHeight));
|
|
||||||
newHeight = height;
|
|
||||||
}
|
|
||||||
if (newWidth > width) {
|
|
||||||
newHeight = Math.floor(newHeight * (width / newWidth));
|
|
||||||
newWidth = width;
|
|
||||||
}
|
|
||||||
|
|
||||||
const canvas = document.createElement('canvas');
|
|
||||||
canvas.width = newWidth;
|
|
||||||
canvas.height = newHeight;
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
ctx.drawImage(img, 0, 0, newWidth, newHeight);
|
|
||||||
|
|
||||||
canvas.toBlob((thumbnail) => {
|
|
||||||
URL.revokeObjectURL(imgURL);
|
|
||||||
resolve(thumbnail);
|
|
||||||
}, imageFile.type);
|
|
||||||
};
|
|
||||||
|
|
||||||
img.src = imgURL;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {sigil} string sigil to search for (for example '@', '#' or '$')
|
|
||||||
* @param {flags} string regex flags
|
|
||||||
* @param {prefix} string prefix appended at the beginning of the regex
|
|
||||||
* @returns {RegExp}
|
|
||||||
*/
|
|
||||||
export function idRegex(sigil, flags, prefix) {
|
|
||||||
const servername = '(?:[a-zA-Z0-9-.]*[a-zA-Z0-9]+|\\[\\S+?\\])(?::\\d+)?';
|
|
||||||
return new RegExp(`${prefix}(${sigil}\\S+:${servername})`, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
const matrixToRegex = /^https?:\/\/matrix.to\/#\/(\S+:\S+)/;
|
|
||||||
/**
|
|
||||||
* Parses a matrix.to URL into an matrix id.
|
|
||||||
* This function can later be extended to support matrix: URIs
|
|
||||||
* @param {string} uri The URI to parse
|
|
||||||
* @returns {string|null} The id or null if the URI does not match
|
|
||||||
*/
|
|
||||||
export function parseIdUri(uri) {
|
|
||||||
const res = decodeURIComponent(uri).match(matrixToRegex);
|
|
||||||
if (!res) return null;
|
|
||||||
return res[1];
|
|
||||||
}
|
|
|
@ -54,6 +54,7 @@ export function abbreviateNumber(number: number) {
|
||||||
|
|
||||||
export class Debounce {
|
export class Debounce {
|
||||||
timeoutId: any;
|
timeoutId: any;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.timeoutId = null;
|
this.timeoutId = null;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,7 @@ export class Debounce {
|
||||||
* @param {number} wait - wait in milliseconds to call func
|
* @param {number} wait - wait in milliseconds to call func
|
||||||
* @returns {func} debounceCallback - to pass arguments to func callback
|
* @returns {func} debounceCallback - to pass arguments to func callback
|
||||||
*/
|
*/
|
||||||
_(func: Function, wait: number) {
|
_(func: (...args) => void, wait: number) {
|
||||||
const debounceCallback = (...args) => {
|
const debounceCallback = (...args) => {
|
||||||
clearTimeout(this.timeoutId);
|
clearTimeout(this.timeoutId);
|
||||||
this.timeoutId = setTimeout(() => {
|
this.timeoutId = setTimeout(() => {
|
||||||
|
@ -77,6 +78,7 @@ export class Debounce {
|
||||||
|
|
||||||
export class Throttle {
|
export class Throttle {
|
||||||
timeoutId: any;
|
timeoutId: any;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.timeoutId = null;
|
this.timeoutId = null;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +88,7 @@ export class Throttle {
|
||||||
* @param {number} wait - wait in milliseconds to call func
|
* @param {number} wait - wait in milliseconds to call func
|
||||||
* @returns {function} throttleCallback - to pass arguments to func callback
|
* @returns {function} throttleCallback - to pass arguments to func callback
|
||||||
*/
|
*/
|
||||||
_(func: Function, wait: number) {
|
_(func: (...args) => void, wait: number) {
|
||||||
const throttleCallback = (...args) => {
|
const throttleCallback = (...args) => {
|
||||||
if (this.timeoutId !== null) return;
|
if (this.timeoutId !== null) return;
|
||||||
this.timeoutId = setTimeout(() => {
|
this.timeoutId = setTimeout(() => {
|
||||||
|
@ -146,7 +148,7 @@ export function copyToClipboard(text: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function suffixRename(name: string | number, validator: Function) {
|
export function suffixRename(name: string, validator: (newName: string) => boolean) {
|
||||||
let suffix = 2;
|
let suffix = 2;
|
||||||
let newName = name;
|
let newName = name;
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -5,45 +5,11 @@ const MAX_TAG_NESTING = 100;
|
||||||
let mx = null;
|
let mx = null;
|
||||||
|
|
||||||
const permittedHtmlTags = [
|
const permittedHtmlTags = [
|
||||||
'font',
|
'font', 'del', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
||||||
'del',
|
'blockquote', 'p', 'a', 'ul', 'ol', 'sup', 'sub',
|
||||||
'h1',
|
'li', 'b', 'i', 'u', 'strong', 'em', 'strike', 'code',
|
||||||
'h2',
|
'hr', 'br', 'div', 'table', 'thead', 'tbody', 'tr', 'th',
|
||||||
'h3',
|
'td', 'caption', 'pre', 'span', 'img', 'details', 'summary'];
|
||||||
'h4',
|
|
||||||
'h5',
|
|
||||||
'h6',
|
|
||||||
'blockquote',
|
|
||||||
'p',
|
|
||||||
'a',
|
|
||||||
'ul',
|
|
||||||
'ol',
|
|
||||||
'sup',
|
|
||||||
'sub',
|
|
||||||
'li',
|
|
||||||
'b',
|
|
||||||
'i',
|
|
||||||
'u',
|
|
||||||
'strong',
|
|
||||||
'em',
|
|
||||||
'strike',
|
|
||||||
'code',
|
|
||||||
'hr',
|
|
||||||
'br',
|
|
||||||
'div',
|
|
||||||
'table',
|
|
||||||
'thead',
|
|
||||||
'tbody',
|
|
||||||
'tr',
|
|
||||||
'th',
|
|
||||||
'td',
|
|
||||||
'caption',
|
|
||||||
'pre',
|
|
||||||
'span',
|
|
||||||
'img',
|
|
||||||
'details',
|
|
||||||
'summary',
|
|
||||||
];
|
|
||||||
|
|
||||||
const urlSchemes = ['https', 'http', 'ftp', 'mailto', 'magnet'];
|
const urlSchemes = ['https', 'http', 'ftp', 'mailto', 'magnet'];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue