Merge pull request #13756 from vector-im/t3chguy/toasts2

Convert platforms to Typescript
This commit is contained in:
Michael Telatynski 2020-05-22 16:35:57 +01:00 committed by GitHub
commit b4284b4c68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 118 deletions

View file

@ -32,3 +32,10 @@ declare global {
InstallTrigger: any; InstallTrigger: any;
} }
} }
// add method which is missing from the node typing
declare module "url" {
interface Url {
format(): string;
}
}

View file

@ -1,5 +1,3 @@
// @flow
/* /*
Copyright 2016 Aviral Dasgupta Copyright 2016 Aviral Dasgupta
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
@ -21,11 +19,20 @@ limitations under the License.
*/ */
import VectorBasePlatform, {updateCheckStatusEnum} from './VectorBasePlatform'; import VectorBasePlatform, {updateCheckStatusEnum} from './VectorBasePlatform';
import BaseEventIndexManager from 'matrix-react-sdk/src/indexing/BaseEventIndexManager'; import BaseEventIndexManager, {
MatrixEvent,
MatrixProfile,
SearchResult,
CrawlerCheckpoint,
EventAndProfile,
SearchArgs,
IndexStats
} from 'matrix-react-sdk/src/indexing/BaseEventIndexManager';
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher'; import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
import { _t, _td } from 'matrix-react-sdk/src/languageHandler'; import { _t, _td } from 'matrix-react-sdk/src/languageHandler';
import * as rageshake from 'matrix-react-sdk/src/rageshake/rageshake'; import * as rageshake from 'matrix-react-sdk/src/rageshake/rageshake';
import {MatrixClient} from "matrix-js-sdk"; import {MatrixClient} from "matrix-js-sdk/src/client";
import {Room} from "matrix-js-sdk/src/models/room";
import Modal from "matrix-react-sdk/src/Modal"; import Modal from "matrix-react-sdk/src/Modal";
import InfoDialog from "matrix-react-sdk/src/components/views/dialogs/InfoDialog"; import InfoDialog from "matrix-react-sdk/src/components/views/dialogs/InfoDialog";
import Spinner from "matrix-react-sdk/src/components/views/elements/Spinner"; import Spinner from "matrix-react-sdk/src/components/views/elements/Spinner";
@ -34,6 +41,7 @@ import {Key} from "matrix-react-sdk/src/Keyboard";
import React from "react"; import React from "react";
import {randomString} from "matrix-js-sdk/src/randomstring"; import {randomString} from "matrix-js-sdk/src/randomstring";
import {Action} from "matrix-react-sdk/src/dispatcher/actions"; import {Action} from "matrix-react-sdk/src/dispatcher/actions";
import { ActionPayload } from "matrix-react-sdk/src/dispatcher/payloads";
const ipcRenderer = window.ipcRenderer; const ipcRenderer = window.ipcRenderer;
const isMac = navigator.platform.toUpperCase().includes('MAC'); const isMac = navigator.platform.toUpperCase().includes('MAC');
@ -57,7 +65,7 @@ function platformFriendlyName(): string {
} }
} }
function _onAction(payload: Object) { function _onAction(payload: ActionPayload) {
// Whitelist payload actions, no point sending most across // Whitelist payload actions, no point sending most across
if (['call_state'].includes(payload.action)) { if (['call_state'].includes(payload.action)) {
ipcRenderer.send('app_onAction', payload); ipcRenderer.send('app_onAction', payload);
@ -77,53 +85,60 @@ function getUpdateCheckStatus(status) {
} }
} }
interface IPCPayload {
id?: number;
error?: string;
reply?: any;
}
class SeshatIndexManager extends BaseEventIndexManager { class SeshatIndexManager extends BaseEventIndexManager {
private pendingIpcCalls: Record<number, { resolve, reject }> = {};
private nextIpcCallId: number = 0;
constructor() { constructor() {
super(); super();
this._pendingIpcCalls = {}; ipcRenderer.on('seshatReply', this._onIpcReply);
this._nextIpcCallId = 0;
ipcRenderer.on('seshatReply', this._onIpcReply.bind(this));
} }
async _ipcCall(name: string, ...args: []): Promise<{}> { async _ipcCall(name: string, ...args: any[]): Promise<any> {
// TODO this should be moved into the preload.js file. // TODO this should be moved into the preload.js file.
const ipcCallId = ++this._nextIpcCallId; const ipcCallId = ++this.nextIpcCallId;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._pendingIpcCalls[ipcCallId] = {resolve, reject}; this.pendingIpcCalls[ipcCallId] = {resolve, reject};
window.ipcRenderer.send('seshat', {id: ipcCallId, name, args}); window.ipcRenderer.send('seshat', {id: ipcCallId, name, args});
}); });
} }
_onIpcReply(ev: {}, payload: {}) { _onIpcReply = (ev: {}, payload: IPCPayload) => {
if (payload.id === undefined) { if (payload.id === undefined) {
console.warn("Ignoring IPC reply with no ID"); console.warn("Ignoring IPC reply with no ID");
return; return;
} }
if (this._pendingIpcCalls[payload.id] === undefined) { if (this.pendingIpcCalls[payload.id] === undefined) {
console.warn("Unknown IPC payload ID: " + payload.id); console.warn("Unknown IPC payload ID: " + payload.id);
return; return;
} }
const callbacks = this._pendingIpcCalls[payload.id]; const callbacks = this.pendingIpcCalls[payload.id];
delete this._pendingIpcCalls[payload.id]; delete this.pendingIpcCalls[payload.id];
if (payload.error) { if (payload.error) {
callbacks.reject(payload.error); callbacks.reject(payload.error);
} else { } else {
callbacks.resolve(payload.reply); callbacks.resolve(payload.reply);
} }
} };
async supportsEventIndexing(): Promise<boolean> { async supportsEventIndexing(): Promise<boolean> {
return this._ipcCall('supportsEventIndexing'); return this._ipcCall('supportsEventIndexing');
} }
async initEventIndex(): Promise<> { async initEventIndex(): Promise<void> {
return this._ipcCall('initEventIndex'); return this._ipcCall('initEventIndex');
} }
async addEventToIndex(ev: MatrixEvent, profile: MatrixProfile): Promise<> { async addEventToIndex(ev: MatrixEvent, profile: MatrixProfile): Promise<void> {
return this._ipcCall('addEventToIndex', ev, profile); return this._ipcCall('addEventToIndex', ev, profile);
} }
@ -135,27 +150,27 @@ class SeshatIndexManager extends BaseEventIndexManager {
return this._ipcCall('isEventIndexEmpty'); return this._ipcCall('isEventIndexEmpty');
} }
async commitLiveEvents(): Promise<> { async commitLiveEvents(): Promise<void> {
return this._ipcCall('commitLiveEvents'); return this._ipcCall('commitLiveEvents');
} }
async searchEventIndex(searchConfig: SearchConfig): Promise<SearchResult> { async searchEventIndex(searchConfig: SearchArgs): Promise<SearchResult> {
return this._ipcCall('searchEventIndex', searchConfig); return this._ipcCall('searchEventIndex', searchConfig);
} }
async addHistoricEvents( async addHistoricEvents(
events: [HistoricEvent], events: [EventAndProfile],
checkpoint: CrawlerCheckpoint | null, checkpoint: CrawlerCheckpoint | null,
oldCheckpoint: CrawlerCheckpoint | null, oldCheckpoint: CrawlerCheckpoint | null,
): Promise<> { ): Promise<boolean> {
return this._ipcCall('addHistoricEvents', events, checkpoint, oldCheckpoint); return this._ipcCall('addHistoricEvents', events, checkpoint, oldCheckpoint);
} }
async addCrawlerCheckpoint(checkpoint: CrawlerCheckpoint): Promise<> { async addCrawlerCheckpoint(checkpoint: CrawlerCheckpoint): Promise<void> {
return this._ipcCall('addCrawlerCheckpoint', checkpoint); return this._ipcCall('addCrawlerCheckpoint', checkpoint);
} }
async removeCrawlerCheckpoint(checkpoint: CrawlerCheckpoint): Promise<> { async removeCrawlerCheckpoint(checkpoint: CrawlerCheckpoint): Promise<void> {
return this._ipcCall('removeCrawlerCheckpoint', checkpoint); return this._ipcCall('removeCrawlerCheckpoint', checkpoint);
} }
@ -167,27 +182,29 @@ class SeshatIndexManager extends BaseEventIndexManager {
return this._ipcCall('loadCheckpoints'); return this._ipcCall('loadCheckpoints');
} }
async closeEventIndex(): Promise<> { async closeEventIndex(): Promise<void> {
return this._ipcCall('closeEventIndex'); return this._ipcCall('closeEventIndex');
} }
async getStats(): Promise<> { async getStats(): Promise<IndexStats> {
return this._ipcCall('getStats'); return this._ipcCall('getStats');
} }
async deleteEventIndex(): Promise<> { async deleteEventIndex(): Promise<void> {
return this._ipcCall('deleteEventIndex'); return this._ipcCall('deleteEventIndex');
} }
} }
export default class ElectronPlatform extends VectorBasePlatform { export default class ElectronPlatform extends VectorBasePlatform {
private eventIndexManager: BaseEventIndexManager = new SeshatIndexManager();
private pendingIpcCalls: Record<number, { resolve, reject }> = {};
private nextIpcCallId: number = 0;
// this is the opaque token we pass to the HS which when we get it in our callback we can resolve to a profile
private ssoID: string = randomString(32);
constructor() { constructor() {
super(); super();
this._pendingIpcCalls = {};
this._nextIpcCallId = 0;
this.eventIndexManager = new SeshatIndexManager();
dis.register(_onAction); dis.register(_onAction);
/* /*
IPC Call `check_updates` returns: IPC Call `check_updates` returns:
@ -217,9 +234,6 @@ export default class ElectronPlatform extends VectorBasePlatform {
dis.fire(Action.ViewUserSettings); dis.fire(Action.ViewUserSettings);
}); });
this.startUpdateCheck = this.startUpdateCheck.bind(this);
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
// register OS-specific shortcuts // register OS-specific shortcuts
if (isMac) { if (isMac) {
registerShortcut(Categories.NAVIGATION, { registerShortcut(Categories.NAVIGATION, {
@ -253,8 +267,6 @@ export default class ElectronPlatform extends VectorBasePlatform {
}); });
} }
// this is the opaque token we pass to the HS which when we get it in our callback we can resolve to a profile
this.ssoID = randomString(32);
this._ipcCall("startSSOFlow", this.ssoID); this._ipcCall("startSSOFlow", this.ssoID);
} }
@ -290,7 +302,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
return true; return true;
} }
displayNotification(title: string, msg: string, avatarUrl: string, room: Object): Notification { displayNotification(title: string, msg: string, avatarUrl: string, room: Room): Notification {
// GNOME notification spec parses HTML tags for styling... // GNOME notification spec parses HTML tags for styling...
// Electron Docs state all supported linux notification systems follow this markup spec // Electron Docs state all supported linux notification systems follow this markup spec
// https://github.com/electron/electron/blob/master/docs/tutorial/desktop-environment-integration.md#linux // https://github.com/electron/electron/blob/master/docs/tutorial/desktop-environment-integration.md#linux
@ -307,14 +319,14 @@ export default class ElectronPlatform extends VectorBasePlatform {
silent: true, // we play our own sounds silent: true, // we play our own sounds
}; };
if (avatarUrl) notifBody['icon'] = avatarUrl; if (avatarUrl) notifBody['icon'] = avatarUrl;
const notification = new global.Notification(title, notifBody); const notification = new window.Notification(title, notifBody);
notification.onclick = () => { notification.onclick = () => {
dis.dispatch({ dis.dispatch({
action: 'view_room', action: 'view_room',
room_id: room.roomId, room_id: room.roomId,
}); });
global.focus(); window.focus();
this._ipcCall('focusWindow'); this._ipcCall('focusWindow');
}; };
@ -337,11 +349,11 @@ export default class ElectronPlatform extends VectorBasePlatform {
return true; return true;
} }
async getAutoLaunchEnabled(): boolean { async getAutoLaunchEnabled(): Promise<boolean> {
return this._ipcCall('getAutoLaunchEnabled'); return this._ipcCall('getAutoLaunchEnabled');
} }
async setAutoLaunchEnabled(enabled: boolean): void { async setAutoLaunchEnabled(enabled: boolean): Promise<void> {
return this._ipcCall('setAutoLaunchEnabled', enabled); return this._ipcCall('setAutoLaunchEnabled', enabled);
} }
@ -350,11 +362,11 @@ export default class ElectronPlatform extends VectorBasePlatform {
return !isMac; return !isMac;
} }
async getAutoHideMenuBarEnabled(): boolean { async getAutoHideMenuBarEnabled(): Promise<boolean> {
return this._ipcCall('getAutoHideMenuBarEnabled'); return this._ipcCall('getAutoHideMenuBarEnabled');
} }
async setAutoHideMenuBarEnabled(enabled: boolean): void { async setAutoHideMenuBarEnabled(enabled: boolean): Promise<void> {
return this._ipcCall('setAutoHideMenuBarEnabled', enabled); return this._ipcCall('setAutoHideMenuBarEnabled', enabled);
} }
@ -363,25 +375,25 @@ export default class ElectronPlatform extends VectorBasePlatform {
return !isMac; return !isMac;
} }
async getMinimizeToTrayEnabled(): boolean { async getMinimizeToTrayEnabled(): Promise<boolean> {
return this._ipcCall('getMinimizeToTrayEnabled'); return this._ipcCall('getMinimizeToTrayEnabled');
} }
async setMinimizeToTrayEnabled(enabled: boolean): void { async setMinimizeToTrayEnabled(enabled: boolean): Promise<void> {
return this._ipcCall('setMinimizeToTrayEnabled', enabled); return this._ipcCall('setMinimizeToTrayEnabled', enabled);
} }
async canSelfUpdate(): boolean { async canSelfUpdate(): Promise<boolean> {
const feedUrl = await this._ipcCall('getUpdateFeedUrl'); const feedUrl = await this._ipcCall('getUpdateFeedUrl');
return Boolean(feedUrl); return Boolean(feedUrl);
} }
startUpdateCheck() { startUpdateCheck = () => {
if (this.showUpdateCheck) return; if (this.showUpdateCheck) return;
super.startUpdateCheck(); super.startUpdateCheck();
ipcRenderer.send('check_updates'); ipcRenderer.send('check_updates');
} };
installUpdate() { installUpdate() {
// IPC to the main process to install the update, since quitAndInstall // IPC to the main process to install the update, since quitAndInstall
@ -394,7 +406,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
return _t('Riot Desktop (%(platformName)s)', { platformName: platformFriendlyName() }); return _t('Riot Desktop (%(platformName)s)', { platformName: platformFriendlyName() });
} }
screenCaptureErrorString(): ?string { screenCaptureErrorString(): string | null {
return null; return null;
} }
@ -409,10 +421,10 @@ export default class ElectronPlatform extends VectorBasePlatform {
window.location.reload(false); window.location.reload(false);
} }
async _ipcCall(name, ...args) { async _ipcCall(name: string, ...args: any[]): Promise<any> {
const ipcCallId = ++this._nextIpcCallId; const ipcCallId = ++this.nextIpcCallId;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this._pendingIpcCalls[ipcCallId] = {resolve, reject}; this.pendingIpcCalls[ipcCallId] = {resolve, reject};
window.ipcRenderer.send('ipcCall', {id: ipcCallId, name, args}); window.ipcRenderer.send('ipcCall', {id: ipcCallId, name, args});
// Maybe add a timeout to these? Probably not necessary. // Maybe add a timeout to these? Probably not necessary.
}); });
@ -424,13 +436,13 @@ export default class ElectronPlatform extends VectorBasePlatform {
return; return;
} }
if (this._pendingIpcCalls[payload.id] === undefined) { if (this.pendingIpcCalls[payload.id] === undefined) {
console.warn("Unknown IPC payload ID: " + payload.id); console.warn("Unknown IPC payload ID: " + payload.id);
return; return;
} }
const callbacks = this._pendingIpcCalls[payload.id]; const callbacks = this.pendingIpcCalls[payload.id];
delete this._pendingIpcCalls[payload.id]; delete this.pendingIpcCalls[payload.id];
if (payload.error) { if (payload.error) {
callbacks.reject(payload.error); callbacks.reject(payload.error);
} else { } else {

View file

@ -1,9 +1,7 @@
// @flow
/* /*
Copyright 2016 Aviral Dasgupta Copyright 2016 Aviral Dasgupta
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd Copyright 2018, 2020 New Vector Ltd
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
@ -24,7 +22,7 @@ import { _t } from 'matrix-react-sdk/src/languageHandler';
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher'; import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
import {getVectorConfig} from "../getconfig"; import {getVectorConfig} from "../getconfig";
import Favico from '../../favicon'; import Favicon from "../../favicon";
export const updateCheckStatusEnum = { export const updateCheckStatusEnum = {
CHECKING: 'CHECKING', CHECKING: 'CHECKING',
@ -37,14 +35,9 @@ export const updateCheckStatusEnum = {
/** /**
* Vector-specific extensions to the BasePlatform template * Vector-specific extensions to the BasePlatform template
*/ */
export default class VectorBasePlatform extends BasePlatform { export default abstract class VectorBasePlatform extends BasePlatform {
constructor() { protected showUpdateCheck: boolean = false;
super(); protected _favicon: Favicon;
this.showUpdateCheck = false;
this.startUpdateCheck = this.startUpdateCheck.bind(this);
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
}
async getConfig(): Promise<{}> { async getConfig(): Promise<{}> {
return getVectorConfig(); return getVectorConfig();
@ -55,40 +48,27 @@ export default class VectorBasePlatform extends BasePlatform {
} }
/** /**
* Delay creating the `Favico` instance until first use (on the first notification) as * Delay creating the `Favicon` instance until first use (on the first notification) as
* it uses canvas, which can trigger a permission prompt in Firefox's resist * it uses canvas, which can trigger a permission prompt in Firefox's resist fingerprinting mode.
* fingerprinting mode.
* See https://github.com/vector-im/riot-web/issues/9605. * See https://github.com/vector-im/riot-web/issues/9605.
*/ */
get favicon() { get favicon() {
if (this._favicon) { if (this._favicon) {
return this._favicon; return this._favicon;
} }
// The 'animations' are really low framerate and look terrible. return this._favicon = new Favicon();
// Also it re-starts the animation every time you set the badge,
// and we set the state each time, even if the value hasn't changed,
// so we'd need to fix that if enabling the animation.
this._favicon = new Favico({ animation: 'none' });
return this._favicon;
} }
_updateFavicon() { _updateFavicon() {
try { let bgColor = "#d00";
// This needs to be in in a try block as it will throw let notif: string | number = this.notificationCount;
// if there are more than 100 badge count changes in
// its internal queue
let bgColor = "#d00";
let notif = this.notificationCount;
if (this.errorDidOccur) { if (this.errorDidOccur) {
notif = notif || "×"; notif = notif || "×";
bgColor = "#f00"; bgColor = "#f00";
}
this.favicon.badge(notif, { bgColor });
} catch (e) {
console.warn(`Failed to set badge count: ${e.message}`);
} }
this.favicon.badge(notif, { bgColor });
} }
setNotificationCount(count: number) { setNotificationCount(count: number) {
@ -112,25 +92,25 @@ export default class VectorBasePlatform extends BasePlatform {
/** /**
* Whether we can call checkForUpdate on this platform build * Whether we can call checkForUpdate on this platform build
*/ */
async canSelfUpdate(): boolean { async canSelfUpdate(): Promise<boolean> {
return false; return false;
} }
startUpdateCheck() { startUpdateCheck = () => {
this.showUpdateCheck = true; this.showUpdateCheck = true;
dis.dispatch({ dis.dispatch({
action: 'check_updates', action: 'check_updates',
value: { status: updateCheckStatusEnum.CHECKING }, value: { status: updateCheckStatusEnum.CHECKING },
}); });
} };
stopUpdateCheck() { stopUpdateCheck = () => {
this.showUpdateCheck = false; this.showUpdateCheck = false;
dis.dispatch({ dis.dispatch({
action: 'check_updates', action: 'check_updates',
value: false, value: false,
}); });
} };
getUpdateCheckStatusEnum() { getUpdateCheckStatusEnum() {
return updateCheckStatusEnum; return updateCheckStatusEnum;

View file

@ -1,5 +1,3 @@
// @flow
/* /*
Copyright 2016 Aviral Dasgupta Copyright 2016 Aviral Dasgupta
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
@ -22,6 +20,7 @@ import VectorBasePlatform, {updateCheckStatusEnum} from './VectorBasePlatform';
import request from 'browser-request'; import request from 'browser-request';
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher'; import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
import { _t } from 'matrix-react-sdk/src/languageHandler'; import { _t } from 'matrix-react-sdk/src/languageHandler';
import {Room} from "matrix-js-sdk/src/models/room";
import url from 'url'; import url from 'url';
import UAParser from 'ua-parser-js'; import UAParser from 'ua-parser-js';
@ -29,13 +28,7 @@ import UAParser from 'ua-parser-js';
const POKE_RATE_MS = 10 * 60 * 1000; // 10 min const POKE_RATE_MS = 10 * 60 * 1000; // 10 min
export default class WebPlatform extends VectorBasePlatform { export default class WebPlatform extends VectorBasePlatform {
constructor() { private runningVersion: string = null;
super();
this.runningVersion = null;
this.startUpdateCheck = this.startUpdateCheck.bind(this);
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
}
getHumanReadableName(): string { getHumanReadableName(): string {
return 'Web Platform'; // no translation required: only used for analytics return 'Web Platform'; // no translation required: only used for analytics
@ -46,7 +39,7 @@ export default class WebPlatform extends VectorBasePlatform {
* notifications, otherwise false. * notifications, otherwise false.
*/ */
supportsNotifications(): boolean { supportsNotifications(): boolean {
return Boolean(global.Notification); return Boolean(window.Notification);
} }
/** /**
@ -54,7 +47,7 @@ export default class WebPlatform extends VectorBasePlatform {
* to display notifications. Otherwise false. * to display notifications. Otherwise false.
*/ */
maySendNotifications(): boolean { maySendNotifications(): boolean {
return global.Notification.permission === 'granted'; return window.Notification.permission === 'granted';
} }
/** /**
@ -69,27 +62,27 @@ export default class WebPlatform extends VectorBasePlatform {
// promise, but this is only supported in Chrome 46 // promise, but this is only supported in Chrome 46
// and Firefox 47, so adapt the callback API. // and Firefox 47, so adapt the callback API.
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
global.Notification.requestPermission((result) => { window.Notification.requestPermission((result) => {
resolve(result); resolve(result);
}); });
}); });
} }
displayNotification(title: string, msg: string, avatarUrl: string, room: Object) { displayNotification(title: string, msg: string, avatarUrl: string, room: Room) {
const notifBody = { const notifBody = {
body: msg, body: msg,
tag: "vector", tag: "vector",
silent: true, // we play our own sounds silent: true, // we play our own sounds
}; };
if (avatarUrl) notifBody['icon'] = avatarUrl; if (avatarUrl) notifBody['icon'] = avatarUrl;
const notification = new global.Notification(title, notifBody); const notification = new window.Notification(title, notifBody);
notification.onclick = function() { notification.onclick = function() {
dis.dispatch({ dis.dispatch({
action: 'view_room', action: 'view_room',
room_id: room.roomId, room_id: room.roomId,
}); });
global.focus(); window.focus();
notification.close(); notification.close();
}; };
} }
@ -131,14 +124,14 @@ export default class WebPlatform extends VectorBasePlatform {
startUpdater() { startUpdater() {
this.pollForUpdate(); this.pollForUpdate();
setInterval(this.pollForUpdate.bind(this), POKE_RATE_MS); setInterval(this.pollForUpdate, POKE_RATE_MS);
} }
async canSelfUpdate(): boolean { async canSelfUpdate(): Promise<boolean> {
return true; return true;
} }
pollForUpdate() { pollForUpdate = () => {
return this._getVersion().then((ver) => { return this._getVersion().then((ver) => {
if (this.runningVersion === null) { if (this.runningVersion === null) {
this.runningVersion = ver; this.runningVersion = ver;
@ -159,9 +152,9 @@ export default class WebPlatform extends VectorBasePlatform {
detail: err.message || err.status ? err.status.toString() : 'Unknown Error', detail: err.message || err.status ? err.status.toString() : 'Unknown Error',
}; };
}); });
} };
startUpdateCheck() { startUpdateCheck = () => {
if (this.showUpdateCheck) return; if (this.showUpdateCheck) return;
super.startUpdateCheck(); super.startUpdateCheck();
this.pollForUpdate().then((updateState) => { this.pollForUpdate().then((updateState) => {
@ -172,7 +165,7 @@ export default class WebPlatform extends VectorBasePlatform {
value: updateState, value: updateState,
}); });
}); });
} };
installUpdate() { installUpdate() {
window.location.reload(true); window.location.reload(true);
@ -204,9 +197,9 @@ export default class WebPlatform extends VectorBasePlatform {
}); });
} }
screenCaptureErrorString(): ?string { screenCaptureErrorString(): string | null {
// it won't work at all if you're not on HTTPS so whine whine whine // it won't work at all if you're not on HTTPS so whine whine whine
if (!global.window || global.window.location.protocol !== "https:") { if (window.location.protocol !== "https:") {
return _t("You need to be using HTTPS to place a screen-sharing call."); return _t("You need to be using HTTPS to place a screen-sharing call.");
} }
return null; return null;