mirror of
				https://github.com/zulip/zulip-desktop.git
				synced 2025-10-31 20:13:43 +00:00 
			
		
		
		
	typescript: Enable strictNullChecks.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
		| @@ -292,7 +292,7 @@ function getHelpSubmenu(): Electron.MenuItemConstructorOptions[] { | ||||
|  | ||||
| function getWindowSubmenu( | ||||
|   tabs: TabData[], | ||||
|   activeTabIndex: number, | ||||
|   activeTabIndex?: number, | ||||
| ): Electron.MenuItemConstructorOptions[] { | ||||
|   const initialSubmenu: Electron.MenuItemConstructorOptions[] = [ | ||||
|     { | ||||
| @@ -342,7 +342,7 @@ function getWindowSubmenu( | ||||
|           if (focusedWindow) { | ||||
|             sendAction( | ||||
|               "switch-server-tab", | ||||
|               getNextServer(tabs, activeTabIndex), | ||||
|               getNextServer(tabs, activeTabIndex!), | ||||
|             ); | ||||
|           } | ||||
|         }, | ||||
| @@ -355,7 +355,7 @@ function getWindowSubmenu( | ||||
|           if (focusedWindow) { | ||||
|             sendAction( | ||||
|               "switch-server-tab", | ||||
|               getPreviousServer(tabs, activeTabIndex), | ||||
|               getPreviousServer(tabs, activeTabIndex!), | ||||
|             ); | ||||
|           } | ||||
|         }, | ||||
| @@ -367,7 +367,7 @@ function getWindowSubmenu( | ||||
| } | ||||
|  | ||||
| function getDarwinTpl(props: MenuProps): Electron.MenuItemConstructorOptions[] { | ||||
|   const {tabs, activeTabIndex, enableMenu} = props; | ||||
|   const {tabs, activeTabIndex, enableMenu = false} = props; | ||||
|  | ||||
|   return [ | ||||
|     { | ||||
| @@ -533,7 +533,7 @@ function getDarwinTpl(props: MenuProps): Electron.MenuItemConstructorOptions[] { | ||||
| } | ||||
|  | ||||
| function getOtherTpl(props: MenuProps): Electron.MenuItemConstructorOptions[] { | ||||
|   const {tabs, activeTabIndex, enableMenu} = props; | ||||
|   const {tabs, activeTabIndex, enableMenu = false} = props; | ||||
|   return [ | ||||
|     { | ||||
|       label: t.__("File"), | ||||
|   | ||||
| @@ -6,7 +6,8 @@ import type {TabProps} from "./tab"; | ||||
| import Tab from "./tab"; | ||||
|  | ||||
| export default class FunctionalTab extends Tab { | ||||
|   $closeButton: Element; | ||||
|   $el: Element; | ||||
|   $closeButton?: Element; | ||||
|  | ||||
|   constructor(props: TabProps) { | ||||
|     super(props); | ||||
| @@ -14,7 +15,7 @@ export default class FunctionalTab extends Tab { | ||||
|     this.$el = generateNodeFromHTML(this.templateHTML()); | ||||
|     if (this.props.name !== "Settings") { | ||||
|       this.props.$root.append(this.$el); | ||||
|       this.$closeButton = this.$el.querySelector(".server-tab-badge"); | ||||
|       this.$closeButton = this.$el.querySelector(".server-tab-badge")!; | ||||
|       this.registerListeners(); | ||||
|     } | ||||
|   } | ||||
| @@ -36,15 +37,15 @@ export default class FunctionalTab extends Tab { | ||||
|     super.registerListeners(); | ||||
|  | ||||
|     this.$el.addEventListener("mouseover", () => { | ||||
|       this.$closeButton.classList.add("active"); | ||||
|       this.$closeButton?.classList.add("active"); | ||||
|     }); | ||||
|  | ||||
|     this.$el.addEventListener("mouseout", () => { | ||||
|       this.$closeButton.classList.remove("active"); | ||||
|       this.$closeButton?.classList.remove("active"); | ||||
|     }); | ||||
|  | ||||
|     this.$closeButton.addEventListener("click", (event: Event) => { | ||||
|       this.props.onDestroy(); | ||||
|     this.$closeButton?.addEventListener("click", (event: Event) => { | ||||
|       this.props.onDestroy?.(); | ||||
|       event.stopPropagation(); | ||||
|     }); | ||||
|   } | ||||
|   | ||||
| @@ -59,7 +59,7 @@ export default function handleExternalLink( | ||||
|             body: "Download failed", | ||||
|           }); | ||||
|         } else { | ||||
|           this.$el.downloadURL(url.href); | ||||
|           this.$el!.downloadURL(url.href); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import type {TabProps} from "./tab"; | ||||
| import Tab from "./tab"; | ||||
|  | ||||
| export default class ServerTab extends Tab { | ||||
|   $el: Element; | ||||
|   $badge: Element; | ||||
|  | ||||
|   constructor(props: TabProps) { | ||||
| @@ -17,7 +18,7 @@ export default class ServerTab extends Tab { | ||||
|     this.$el = generateNodeFromHTML(this.templateHTML()); | ||||
|     this.props.$root.append(this.$el); | ||||
|     this.registerListeners(); | ||||
|     this.$badge = this.$el.querySelector(".server-tab-badge"); | ||||
|     this.$badge = this.$el.querySelector(".server-tab-badge")!; | ||||
|   } | ||||
|  | ||||
|   templateHTML(): HTML { | ||||
|   | ||||
| @@ -15,10 +15,11 @@ export interface TabProps { | ||||
|   onDestroy?: () => void; | ||||
| } | ||||
|  | ||||
| export default class Tab { | ||||
| export default abstract class Tab { | ||||
|   props: TabProps; | ||||
|   webview: WebView; | ||||
|   $el: Element; | ||||
|   abstract $el: Element; | ||||
|  | ||||
|   constructor(props: TabProps) { | ||||
|     this.props = props; | ||||
|     this.webview = this.props.webview; | ||||
| @@ -26,9 +27,15 @@ export default class Tab { | ||||
|  | ||||
|   registerListeners(): void { | ||||
|     this.$el.addEventListener("click", this.props.onClick); | ||||
|  | ||||
|     if (this.props.onHover !== undefined) { | ||||
|       this.$el.addEventListener("mouseover", this.props.onHover); | ||||
|     } | ||||
|  | ||||
|     if (this.props.onHoverOut !== undefined) { | ||||
|       this.$el.addEventListener("mouseout", this.props.onHoverOut); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   showNetworkError(): void { | ||||
|     this.webview.forceLoad(); | ||||
| @@ -46,6 +53,6 @@ export default class Tab { | ||||
|  | ||||
|   destroy(): void { | ||||
|     this.$el.remove(); | ||||
|     this.webview.$el.remove(); | ||||
|     this.webview.$el!.remove(); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -35,9 +35,9 @@ export default class WebView { | ||||
|   zoomFactor: number; | ||||
|   badgeCount: number; | ||||
|   loading: boolean; | ||||
|   customCSS: string; | ||||
|   customCSS: string | null; | ||||
|   $webviewsContainer: DOMTokenList; | ||||
|   $el: Electron.WebviewTag; | ||||
|   $el?: Electron.WebviewTag; | ||||
|   domReady?: Promise<void>; | ||||
|  | ||||
|   constructor(props: WebViewProps) { | ||||
| @@ -48,7 +48,7 @@ export default class WebView { | ||||
|     this.customCSS = ConfigUtil.getConfigItem("customCSS"); | ||||
|     this.$webviewsContainer = document.querySelector( | ||||
|       "#webviews-container", | ||||
|     ).classList; | ||||
|     )!.classList; | ||||
|   } | ||||
|  | ||||
|   templateHTML(): HTML { | ||||
| @@ -74,7 +74,7 @@ export default class WebView { | ||||
|   init(): void { | ||||
|     this.$el = generateNodeFromHTML(this.templateHTML()) as Electron.WebviewTag; | ||||
|     this.domReady = new Promise((resolve) => { | ||||
|       this.$el.addEventListener( | ||||
|       this.$el!.addEventListener( | ||||
|         "dom-ready", | ||||
|         () => { | ||||
|           resolve(); | ||||
| @@ -88,23 +88,23 @@ export default class WebView { | ||||
|   } | ||||
|  | ||||
|   registerListeners(): void { | ||||
|     this.$el.addEventListener("new-window", (event) => { | ||||
|     this.$el!.addEventListener("new-window", (event) => { | ||||
|       handleExternalLink.call(this, event); | ||||
|     }); | ||||
|  | ||||
|     if (shouldSilentWebview) { | ||||
|       this.$el.addEventListener("dom-ready", () => { | ||||
|         this.$el.setAudioMuted(true); | ||||
|       this.$el!.addEventListener("dom-ready", () => { | ||||
|         this.$el!.setAudioMuted(true); | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     this.$el.addEventListener("page-title-updated", (event) => { | ||||
|     this.$el!.addEventListener("page-title-updated", (event) => { | ||||
|       const {title} = event; | ||||
|       this.badgeCount = this.getBadgeCount(title); | ||||
|       this.props.onTitleChange(); | ||||
|     }); | ||||
|  | ||||
|     this.$el.addEventListener("did-navigate-in-page", (event) => { | ||||
|     this.$el!.addEventListener("did-navigate-in-page", (event) => { | ||||
|       const isSettingPage = event.url.includes("renderer/preference.html"); | ||||
|       if (isSettingPage) { | ||||
|         return; | ||||
| @@ -113,11 +113,11 @@ export default class WebView { | ||||
|       this.canGoBackButton(); | ||||
|     }); | ||||
|  | ||||
|     this.$el.addEventListener("did-navigate", () => { | ||||
|     this.$el!.addEventListener("did-navigate", () => { | ||||
|       this.canGoBackButton(); | ||||
|     }); | ||||
|  | ||||
|     this.$el.addEventListener("page-favicon-updated", (event) => { | ||||
|     this.$el!.addEventListener("page-favicon-updated", (event) => { | ||||
|       const {favicons} = event; | ||||
|  | ||||
|       // This returns a string of favicons URL. If there is a PM counts in unread messages then the URL would be like | ||||
| @@ -135,16 +135,16 @@ export default class WebView { | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     this.$el.addEventListener("dom-ready", () => { | ||||
|     this.$el!.addEventListener("dom-ready", () => { | ||||
|       const webContents = remote.webContents.fromId( | ||||
|         this.$el.getWebContentsId(), | ||||
|         this.$el!.getWebContentsId(), | ||||
|       ); | ||||
|       webContents.addListener("context-menu", (event, menuParameters) => { | ||||
|         contextMenu(webContents, event, menuParameters); | ||||
|       }); | ||||
|  | ||||
|       if (this.props.role === "server") { | ||||
|         this.$el.classList.add("onload"); | ||||
|         this.$el!.classList.add("onload"); | ||||
|       } | ||||
|  | ||||
|       this.loading = false; | ||||
| @@ -153,11 +153,11 @@ export default class WebView { | ||||
|  | ||||
|       // Refocus text boxes after reload | ||||
|       // Remove when upstream issue https://github.com/electron/electron/issues/14474 is fixed | ||||
|       this.$el.blur(); | ||||
|       this.$el.focus(); | ||||
|       this.$el!.blur(); | ||||
|       this.$el!.focus(); | ||||
|     }); | ||||
|  | ||||
|     this.$el.addEventListener("did-fail-load", (event) => { | ||||
|     this.$el!.addEventListener("did-fail-load", (event) => { | ||||
|       const {errorDescription} = event; | ||||
|       const hasConnectivityError = SystemUtil.connectivityERR.includes( | ||||
|         errorDescription, | ||||
| @@ -170,14 +170,14 @@ export default class WebView { | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     this.$el.addEventListener("did-start-loading", () => { | ||||
|     this.$el!.addEventListener("did-start-loading", () => { | ||||
|       const isSettingPage = this.props.url.includes("renderer/preference.html"); | ||||
|       if (!isSettingPage) { | ||||
|         this.props.switchLoading(true, this.props.url); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     this.$el.addEventListener("did-stop-loading", () => { | ||||
|     this.$el!.addEventListener("did-stop-loading", () => { | ||||
|       this.props.switchLoading(false, this.props.url); | ||||
|     }); | ||||
|   } | ||||
| @@ -189,7 +189,7 @@ export default class WebView { | ||||
|  | ||||
|   showNotificationSettings(): void { | ||||
|     ipcRenderer.sendTo( | ||||
|       this.$el.getWebContentsId(), | ||||
|       this.$el!.getWebContentsId(), | ||||
|       "show-notification-settings", | ||||
|     ); | ||||
|   } | ||||
| @@ -207,18 +207,18 @@ export default class WebView { | ||||
|       this.$webviewsContainer.add("loaded"); | ||||
|     } | ||||
|  | ||||
|     this.$el.classList.remove("disabled"); | ||||
|     this.$el.classList.add("active"); | ||||
|     this.$el!.classList.remove("disabled"); | ||||
|     this.$el!.classList.add("active"); | ||||
|     setTimeout(() => { | ||||
|       if (this.props.role === "server") { | ||||
|         this.$el.classList.remove("onload"); | ||||
|         this.$el!.classList.remove("onload"); | ||||
|       } | ||||
|     }, 1000); | ||||
|     this.focus(); | ||||
|     this.props.onTitleChange(); | ||||
|     // Injecting preload css in webview to override some css rules | ||||
|     (async () => | ||||
|       this.$el.insertCSS( | ||||
|       this.$el!.insertCSS( | ||||
|         fs.readFileSync(path.join(__dirname, "/../../css/preload.css"), "utf8"), | ||||
|       ))(); | ||||
|  | ||||
| @@ -235,15 +235,15 @@ export default class WebView { | ||||
|       } | ||||
|  | ||||
|       (async () => | ||||
|         this.$el.insertCSS( | ||||
|           fs.readFileSync(path.resolve(__dirname, this.customCSS), "utf8"), | ||||
|         this.$el!.insertCSS( | ||||
|           fs.readFileSync(path.resolve(__dirname, this.customCSS!), "utf8"), | ||||
|         ))(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   focus(): void { | ||||
|     // Focus Webview and it's contents when Window regain focus. | ||||
|     const webContents = remote.webContents.fromId(this.$el.getWebContentsId()); | ||||
|     const webContents = remote.webContents.fromId(this.$el!.getWebContentsId()); | ||||
|     // HACK: webContents.isFocused() seems to be true even without the element | ||||
|     // being in focus. So, we check against `document.activeElement`. | ||||
|     if (webContents && this.$el !== document.activeElement) { | ||||
| @@ -251,14 +251,14 @@ export default class WebView { | ||||
|       // element to transfer focus correctly, in Electron v3.0.10 | ||||
|       // See https://github.com/electron/electron/issues/15718 | ||||
|       (document.activeElement as HTMLElement).blur(); | ||||
|       this.$el.focus(); | ||||
|       this.$el!.focus(); | ||||
|       webContents.focus(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   hide(): void { | ||||
|     this.$el.classList.add("disabled"); | ||||
|     this.$el.classList.remove("active"); | ||||
|     this.$el!.classList.add("disabled"); | ||||
|     this.$el!.classList.remove("active"); | ||||
|   } | ||||
|  | ||||
|   load(): void { | ||||
| @@ -271,34 +271,34 @@ export default class WebView { | ||||
|  | ||||
|   zoomIn(): void { | ||||
|     this.zoomFactor += 0.1; | ||||
|     this.$el.setZoomFactor(this.zoomFactor); | ||||
|     this.$el!.setZoomFactor(this.zoomFactor); | ||||
|   } | ||||
|  | ||||
|   zoomOut(): void { | ||||
|     this.zoomFactor -= 0.1; | ||||
|     this.$el.setZoomFactor(this.zoomFactor); | ||||
|     this.$el!.setZoomFactor(this.zoomFactor); | ||||
|   } | ||||
|  | ||||
|   zoomActualSize(): void { | ||||
|     this.zoomFactor = 1; | ||||
|     this.$el.setZoomFactor(this.zoomFactor); | ||||
|     this.$el!.setZoomFactor(this.zoomFactor); | ||||
|   } | ||||
|  | ||||
|   logOut(): void { | ||||
|     ipcRenderer.sendTo(this.$el.getWebContentsId(), "logout"); | ||||
|     ipcRenderer.sendTo(this.$el!.getWebContentsId(), "logout"); | ||||
|   } | ||||
|  | ||||
|   showKeyboardShortcuts(): void { | ||||
|     ipcRenderer.sendTo(this.$el.getWebContentsId(), "show-keyboard-shortcuts"); | ||||
|     ipcRenderer.sendTo(this.$el!.getWebContentsId(), "show-keyboard-shortcuts"); | ||||
|   } | ||||
|  | ||||
|   openDevTools(): void { | ||||
|     this.$el.openDevTools(); | ||||
|     this.$el!.openDevTools(); | ||||
|   } | ||||
|  | ||||
|   back(): void { | ||||
|     if (this.$el.canGoBack()) { | ||||
|       this.$el.goBack(); | ||||
|     if (this.$el!.canGoBack()) { | ||||
|       this.$el!.goBack(); | ||||
|       this.focus(); | ||||
|     } | ||||
|   } | ||||
| @@ -306,8 +306,8 @@ export default class WebView { | ||||
|   canGoBackButton(): void { | ||||
|     const $backButton = document.querySelector( | ||||
|       "#actions-container #back-action", | ||||
|     ); | ||||
|     if (this.$el.canGoBack()) { | ||||
|     )!; | ||||
|     if (this.$el!.canGoBack()) { | ||||
|       $backButton.classList.remove("disable"); | ||||
|     } else { | ||||
|       $backButton.classList.add("disable"); | ||||
| @@ -315,8 +315,8 @@ export default class WebView { | ||||
|   } | ||||
|  | ||||
|   forward(): void { | ||||
|     if (this.$el.canGoForward()) { | ||||
|       this.$el.goForward(); | ||||
|     if (this.$el!.canGoForward()) { | ||||
|       this.$el!.goForward(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -326,7 +326,7 @@ export default class WebView { | ||||
|     this.$webviewsContainer.remove("loaded"); | ||||
|     this.loading = true; | ||||
|     this.props.switchLoading(true, this.props.url); | ||||
|     this.$el.reload(); | ||||
|     this.$el!.reload(); | ||||
|   } | ||||
|  | ||||
|   forceLoad(): void { | ||||
| @@ -335,6 +335,6 @@ export default class WebView { | ||||
|  | ||||
|   async send(channel: string, ...parameters: unknown[]): Promise<void> { | ||||
|     await this.domReady; | ||||
|     await this.$el.send(channel, ...parameters); | ||||
|     await this.$el!.send(channel, ...parameters); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -9,8 +9,8 @@ const {app} = remote; | ||||
| customElements.define("send-feedback", SendFeedback); | ||||
| export const sendFeedback: SendFeedback = document.querySelector( | ||||
|   "send-feedback", | ||||
| ); | ||||
| export const feedbackHolder = sendFeedback.parentElement; | ||||
| )!; | ||||
| export const feedbackHolder = sendFeedback.parentElement!; | ||||
|  | ||||
| // Make the button color match zulip app's theme | ||||
| sendFeedback.customStylesheet = "css/feedback.css"; | ||||
|   | ||||
| @@ -86,21 +86,25 @@ class ServerManagerView { | ||||
|   tabIndex: number; | ||||
|   presetOrgs: string[]; | ||||
|   constructor() { | ||||
|     this.$addServerButton = document.querySelector("#add-tab"); | ||||
|     this.$tabsContainer = document.querySelector("#tabs-container"); | ||||
|     this.$addServerButton = document.querySelector("#add-tab")!; | ||||
|     this.$tabsContainer = document.querySelector("#tabs-container")!; | ||||
|  | ||||
|     const $actionsContainer = document.querySelector("#actions-container"); | ||||
|     this.$reloadButton = $actionsContainer.querySelector("#reload-action"); | ||||
|     this.$loadingIndicator = $actionsContainer.querySelector("#loading-action"); | ||||
|     this.$settingsButton = $actionsContainer.querySelector("#settings-action"); | ||||
|     this.$webviewsContainer = document.querySelector("#webviews-container"); | ||||
|     this.$backButton = $actionsContainer.querySelector("#back-action"); | ||||
|     this.$dndButton = $actionsContainer.querySelector("#dnd-action"); | ||||
|     const $actionsContainer = document.querySelector("#actions-container")!; | ||||
|     this.$reloadButton = $actionsContainer.querySelector("#reload-action")!; | ||||
|     this.$loadingIndicator = $actionsContainer.querySelector( | ||||
|       "#loading-action", | ||||
|     )!; | ||||
|     this.$settingsButton = $actionsContainer.querySelector("#settings-action")!; | ||||
|     this.$webviewsContainer = document.querySelector("#webviews-container")!; | ||||
|     this.$backButton = $actionsContainer.querySelector("#back-action")!; | ||||
|     this.$dndButton = $actionsContainer.querySelector("#dnd-action")!; | ||||
|  | ||||
|     this.$addServerTooltip = document.querySelector("#add-server-tooltip"); | ||||
|     this.$reloadTooltip = $actionsContainer.querySelector("#reload-tooltip"); | ||||
|     this.$loadingTooltip = $actionsContainer.querySelector("#loading-tooltip"); | ||||
|     this.$settingsTooltip = $actionsContainer.querySelector("#setting-tooltip"); | ||||
|     this.$addServerTooltip = document.querySelector("#add-server-tooltip")!; | ||||
|     this.$reloadTooltip = $actionsContainer.querySelector("#reload-tooltip")!; | ||||
|     this.$loadingTooltip = $actionsContainer.querySelector("#loading-tooltip")!; | ||||
|     this.$settingsTooltip = $actionsContainer.querySelector( | ||||
|       "#setting-tooltip", | ||||
|     )!; | ||||
|  | ||||
|     // TODO: This should have been querySelector but the problem is that | ||||
|     // querySelector doesn't return elements not present in dom whereas somehow | ||||
| @@ -110,12 +114,12 @@ class ServerManagerView { | ||||
|     this.$serverIconTooltip = document.getElementsByClassName( | ||||
|       "server-tooltip", | ||||
|     ) as HTMLCollectionOf<HTMLElement>; | ||||
|     this.$backTooltip = $actionsContainer.querySelector("#back-tooltip"); | ||||
|     this.$dndTooltip = $actionsContainer.querySelector("#dnd-tooltip"); | ||||
|     this.$backTooltip = $actionsContainer.querySelector("#back-tooltip")!; | ||||
|     this.$dndTooltip = $actionsContainer.querySelector("#dnd-tooltip")!; | ||||
|  | ||||
|     this.$sidebar = document.querySelector("#sidebar"); | ||||
|     this.$sidebar = document.querySelector("#sidebar")!; | ||||
|  | ||||
|     this.$fullscreenPopup = document.querySelector("#fullscreen-popup"); | ||||
|     this.$fullscreenPopup = document.querySelector("#fullscreen-popup")!; | ||||
|     this.$fullscreenEscapeKey = process.platform === "darwin" ? "^⌘F" : "F11"; | ||||
|     this.$fullscreenPopup.textContent = `Press ${this.$fullscreenEscapeKey} to exit full screen`; | ||||
|  | ||||
| @@ -486,12 +490,12 @@ class ServerManagerView { | ||||
|     // error | ||||
|  | ||||
|     const $altIcon = document.createElement("div"); | ||||
|     const $parent = $img.parentElement; | ||||
|     const $container = $parent.parentElement; | ||||
|     const webviewId = $container.dataset.tabId; | ||||
|     const $parent = $img.parentElement!; | ||||
|     const $container = $parent.parentElement!; | ||||
|     const webviewId = $container.dataset.tabId!; | ||||
|     const $webview = document.querySelector( | ||||
|       `webview[data-tab-id="${CSS.escape(webviewId)}"]`, | ||||
|     ); | ||||
|     )!; | ||||
|     const realmName = $webview.getAttribute("name"); | ||||
|  | ||||
|     if (realmName === null) { | ||||
| @@ -539,7 +543,7 @@ class ServerManagerView { | ||||
|     // as that of its parent element. | ||||
|     const {top} = this.$serverIconTooltip[ | ||||
|       index | ||||
|     ].parentElement.getBoundingClientRect(); | ||||
|     ].parentElement!.getBoundingClientRect(); | ||||
|     this.$serverIconTooltip[index].style.top = `${top}px`; | ||||
|   } | ||||
|  | ||||
| @@ -549,7 +553,7 @@ class ServerManagerView { | ||||
|  | ||||
|   openFunctionalTab(tabProps: FunctionalTabProps): void { | ||||
|     if (this.functionalTabs.has(tabProps.name)) { | ||||
|       this.activateTab(this.functionalTabs.get(tabProps.name)); | ||||
|       this.activateTab(this.functionalTabs.get(tabProps.name)!); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
| @@ -563,20 +567,20 @@ class ServerManagerView { | ||||
|         materialIcon: tabProps.materialIcon, | ||||
|         name: tabProps.name, | ||||
|         $root: this.$tabsContainer, | ||||
|         index: this.functionalTabs.get(tabProps.name), | ||||
|         index: this.functionalTabs.get(tabProps.name)!, | ||||
|         tabIndex, | ||||
|         onClick: this.activateTab.bind( | ||||
|           this, | ||||
|           this.functionalTabs.get(tabProps.name), | ||||
|           this.functionalTabs.get(tabProps.name)!, | ||||
|         ), | ||||
|         onDestroy: this.destroyTab.bind( | ||||
|           this, | ||||
|           tabProps.name, | ||||
|           this.functionalTabs.get(tabProps.name), | ||||
|           this.functionalTabs.get(tabProps.name)!, | ||||
|         ), | ||||
|         webview: new WebView({ | ||||
|           $root: this.$webviewsContainer, | ||||
|           index: this.functionalTabs.get(tabProps.name), | ||||
|           index: this.functionalTabs.get(tabProps.name)!, | ||||
|           tabIndex, | ||||
|           url: tabProps.url, | ||||
|           role: "function", | ||||
| @@ -610,7 +614,7 @@ class ServerManagerView { | ||||
|     // closed when the functional tab DOM is ready, handled in webview.js | ||||
|     this.$webviewsContainer.classList.remove("loaded"); | ||||
|  | ||||
|     this.activateTab(this.functionalTabs.get(tabProps.name)); | ||||
|     this.activateTab(this.functionalTabs.get(tabProps.name)!); | ||||
|   } | ||||
|  | ||||
|   async openSettings(nav: NavItem = "General"): Promise<void> { | ||||
| @@ -620,7 +624,7 @@ class ServerManagerView { | ||||
|       url: `file://${rendererDirectory}/preference.html#${nav}`, | ||||
|     }); | ||||
|     this.$settingsButton.classList.add("active"); | ||||
|     await this.tabs[this.functionalTabs.get("Settings")].webview.send( | ||||
|     await this.tabs[this.functionalTabs.get("Settings")!].webview.send( | ||||
|       "switch-settings-nav", | ||||
|       nav, | ||||
|     ); | ||||
| @@ -798,19 +802,19 @@ class ServerManagerView { | ||||
|   toggleDNDButton(alert: boolean): void { | ||||
|     this.$dndTooltip.textContent = | ||||
|       (alert ? "Disable" : "Enable") + " Do Not Disturb"; | ||||
|     this.$dndButton.querySelector("i").textContent = alert | ||||
|     this.$dndButton.querySelector("i")!.textContent = alert | ||||
|       ? "notifications_off" | ||||
|       : "notifications"; | ||||
|   } | ||||
|  | ||||
|   isLoggedIn(tabIndex: number): boolean { | ||||
|     const url = this.tabs[tabIndex].webview.$el.src; | ||||
|     const url = this.tabs[tabIndex].webview.$el!.src; | ||||
|     return !(url.endsWith("/login/") || this.tabs[tabIndex].webview.loading); | ||||
|   } | ||||
|  | ||||
|   getActiveWebview(): Electron.WebviewTag { | ||||
|     const selector = "webview:not(.disabled)"; | ||||
|     const webview: Electron.WebviewTag = document.querySelector(selector); | ||||
|     const webview: Electron.WebviewTag = document.querySelector(selector)!; | ||||
|     return webview; | ||||
|   } | ||||
|  | ||||
| @@ -954,7 +958,7 @@ class ServerManagerView { | ||||
|             : this.tabs.some( | ||||
|                 ({webview}) => | ||||
|                   !webview.loading && | ||||
|                   webview.$el.getWebContentsId() === webContentsId && | ||||
|                   webview.$el!.getWebContentsId() === webContentsId && | ||||
|                   webview.props.hasPermission?.(origin, permission), | ||||
|               ); | ||||
|         console.log( | ||||
| @@ -1132,10 +1136,10 @@ class ServerManagerView { | ||||
|         ); | ||||
|         for (const webview of webviews) { | ||||
|           const currentId = webview.getWebContentsId(); | ||||
|           const tabId = webview.getAttribute("data-tab-id"); | ||||
|           const tabId = webview.getAttribute("data-tab-id")!; | ||||
|           const concurrentTab: HTMLButtonElement = document.querySelector( | ||||
|             `div[data-tab-id="${CSS.escape(tabId)}"]`, | ||||
|           ); | ||||
|           )!; | ||||
|           if (currentId === webviewId) { | ||||
|             concurrentTab.click(); | ||||
|           } | ||||
| @@ -1152,7 +1156,7 @@ class ServerManagerView { | ||||
|           canvas.height = 128; | ||||
|           canvas.width = 128; | ||||
|           canvas.style.letterSpacing = "-5px"; | ||||
|           const ctx = canvas.getContext("2d"); | ||||
|           const ctx = canvas.getContext("2d")!; | ||||
|           ctx.fillStyle = "#f42020"; | ||||
|           ctx.beginPath(); | ||||
|           ctx.ellipse(64, 64, 64, 64, 0, 0, 2 * Math.PI); | ||||
|   | ||||
| @@ -53,7 +53,7 @@ export default class PreferenceNav { | ||||
|  | ||||
|   registerListeners(): void { | ||||
|     for (const navItem of this.navItems) { | ||||
|       const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`); | ||||
|       const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`)!; | ||||
|       $item.addEventListener("click", () => { | ||||
|         this.props.onItemSelected(navItem); | ||||
|       }); | ||||
| @@ -71,12 +71,12 @@ export default class PreferenceNav { | ||||
|   } | ||||
|  | ||||
|   activate(navItem: NavItem): void { | ||||
|     const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`); | ||||
|     const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`)!; | ||||
|     $item.classList.add("active"); | ||||
|   } | ||||
|  | ||||
|   deactivate(navItem: NavItem): void { | ||||
|     const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`); | ||||
|     const $item = document.querySelector(`#nav-${CSS.escape(navItem)}`)!; | ||||
|     $item.classList.remove("active"); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -12,7 +12,7 @@ ipcRenderer.on("logout", () => { | ||||
|   } | ||||
|  | ||||
|   // Create the menu for the below | ||||
|   const dropdown: HTMLElement = document.querySelector(".dropdown-toggle"); | ||||
|   const dropdown: HTMLElement = document.querySelector(".dropdown-toggle")!; | ||||
|   dropdown.click(); | ||||
|  | ||||
|   const nodes: NodeListOf<HTMLElement> = document.querySelectorAll( | ||||
| @@ -29,13 +29,13 @@ ipcRenderer.on("show-keyboard-shortcuts", () => { | ||||
|   // Create the menu for the below | ||||
|   const node: HTMLElement = document.querySelector( | ||||
|     "a[data-overlay-trigger=keyboard-shortcuts]", | ||||
|   ); | ||||
|   )!; | ||||
|   // Additional check | ||||
|   if (node.textContent.trim().toLowerCase() === "keyboard shortcuts (?)") { | ||||
|   if (node.textContent!.trim().toLowerCase() === "keyboard shortcuts (?)") { | ||||
|     node.click(); | ||||
|   } else { | ||||
|     // Atleast click the dropdown | ||||
|     const dropdown: HTMLElement = document.querySelector(".dropdown-toggle"); | ||||
|     const dropdown: HTMLElement = document.querySelector(".dropdown-toggle")!; | ||||
|     dropdown.click(); | ||||
|   } | ||||
| }); | ||||
| @@ -46,7 +46,7 @@ ipcRenderer.on("show-notification-settings", () => { | ||||
|   } | ||||
|  | ||||
|   // Create the menu for the below | ||||
|   const dropdown: HTMLElement = document.querySelector(".dropdown-toggle"); | ||||
|   const dropdown: HTMLElement = document.querySelector(".dropdown-toggle")!; | ||||
|   dropdown.click(); | ||||
|  | ||||
|   const nodes: NodeListOf<HTMLElement> = document.querySelectorAll( | ||||
| @@ -69,8 +69,8 @@ window.addEventListener("load", (event: any): void => { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   const $reconnectButton = document.querySelector("#reconnect"); | ||||
|   const $settingsButton = document.querySelector("#settings"); | ||||
|   const $reconnectButton = document.querySelector("#reconnect")!; | ||||
|   const $settingsButton = document.querySelector("#settings")!; | ||||
|   NetworkError.init($reconnectButton, $settingsButton); | ||||
| }); | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import * as ConfigUtil from "../../common/config-util"; | ||||
|  | ||||
| const {Tray, Menu, nativeImage, BrowserWindow} = remote; | ||||
|  | ||||
| let tray: Electron.Tray; | ||||
| let tray: Electron.Tray | null = null; | ||||
|  | ||||
| const ICON_DIR = "../../resources/tray"; | ||||
|  | ||||
| @@ -69,7 +69,7 @@ const renderCanvas = function (arg: number): HTMLCanvasElement { | ||||
|   const canvas = document.createElement("canvas"); | ||||
|   canvas.width = SIZE; | ||||
|   canvas.height = SIZE; | ||||
|   const ctx = canvas.getContext("2d"); | ||||
|   const ctx = canvas.getContext("2d")!; | ||||
|  | ||||
|   // Circle | ||||
|   // If (!config.thick || config.thick && HAS_COUNT) { | ||||
| @@ -210,15 +210,15 @@ function toggleTray(): void { | ||||
|     createTray(); | ||||
|     if (process.platform === "linux" || process.platform === "win32") { | ||||
|       const image = renderNativeImage(unread); | ||||
|       tray.setImage(image); | ||||
|       tray.setToolTip(`${unread} unread messages`); | ||||
|       tray!.setImage(image); | ||||
|       tray!.setToolTip(`${unread} unread messages`); | ||||
|     } | ||||
|  | ||||
|     ConfigUtil.setConfigItem("trayIcon", true); | ||||
|   } | ||||
|  | ||||
|   const selector = "webview:not([class*=disabled])"; | ||||
|   const webview: WebviewTag = document.querySelector(selector); | ||||
|   const webview: WebviewTag = document.querySelector(selector)!; | ||||
|   const webContents = remote.webContents.fromId(webview.getWebContentsId()); | ||||
|   webContents.send("toggletray", state); | ||||
| } | ||||
|   | ||||
| @@ -17,7 +17,7 @@ const logger = new Logger({ | ||||
|  | ||||
| const defaultIconUrl = "../renderer/img/icon.png"; | ||||
|  | ||||
| let db: JsonDB; | ||||
| let db!: JsonDB; | ||||
|  | ||||
| reloadDB(); | ||||
| // Migrate from old schema | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
|     /* Strict type-checking */ | ||||
|     "strict": true, | ||||
|     "noImplicitAny": true, | ||||
|     "strictNullChecks": false, | ||||
|     "noImplicitThis": true, | ||||
|     "alwaysStrict": true, | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user