Merge pull request #4669 from matrix-org/t3chguy/toasts6_1

Allow deferring of Update Toast until the next morning
pull/21833/head
Michael Telatynski 2020-05-30 12:54:42 +01:00 committed by GitHub
commit 6472ca451e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 5 deletions

19
src/@types/common.ts Normal file
View File

@ -0,0 +1,19 @@
/*
Copyright 2020 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Based on https://stackoverflow.com/a/53229857/3532235
export type Without<T, U> = {[P in Exclude<keyof T, keyof U>] ? : never}
export type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;

View File

@ -23,6 +23,7 @@ import BaseEventIndexManager from './indexing/BaseEventIndexManager';
import {ActionPayload} from "./dispatcher/payloads"; import {ActionPayload} from "./dispatcher/payloads";
import {CheckUpdatesPayload} from "./dispatcher/payloads/CheckUpdatesPayload"; import {CheckUpdatesPayload} from "./dispatcher/payloads/CheckUpdatesPayload";
import {Action} from "./dispatcher/actions"; import {Action} from "./dispatcher/actions";
import {hideToast as hideUpdateToast} from "./toasts/UpdateToast";
export enum UpdateCheckStatus { export enum UpdateCheckStatus {
Checking = "CHECKING", Checking = "CHECKING",
@ -32,6 +33,8 @@ export enum UpdateCheckStatus {
Ready = "READY", Ready = "READY",
} }
const UPDATE_DEFER_KEY = "mx_defer_update";
/** /**
* Base class for classes that provide platform-specific functionality * Base class for classes that provide platform-specific functionality
* eg. Setting an application badge or displaying notifications * eg. Setting an application badge or displaying notifications
@ -74,12 +77,45 @@ export default abstract class BasePlatform {
} }
startUpdateCheck() { startUpdateCheck() {
hideUpdateToast();
localStorage.removeItem(UPDATE_DEFER_KEY);
dis.dispatch<CheckUpdatesPayload>({ dis.dispatch<CheckUpdatesPayload>({
action: Action.CheckUpdates, action: Action.CheckUpdates,
status: UpdateCheckStatus.Checking, status: UpdateCheckStatus.Checking,
}); });
} }
/**
* Update the currently running app to the latest available version
* and replace this instance of the app with the new version.
*/
installUpdate() {
}
/**
* Check if the version update has been deferred and that deferment is still in effect
* @param newVersion the version string to check
*/
protected shouldShowUpdate(newVersion: string): boolean {
try {
const [version, deferUntil] = JSON.parse(localStorage.getItem(UPDATE_DEFER_KEY));
return newVersion !== version || Date.now() > deferUntil;
} catch (e) {
return true;
}
}
/**
* Ignore the pending update and don't prompt about this version
* until the next morning (8am).
*/
deferUpdate(newVersion: string) {
const date = new Date(Date.now() + 24 * 60 * 60 * 1000);
date.setHours(8, 0, 0, 0); // set to next 8am
localStorage.setItem(UPDATE_DEFER_KEY, JSON.stringify([newVersion, date.getTime()]));
hideUpdateToast();
}
/** /**
* Returns true if the platform supports displaying * Returns true if the platform supports displaying
* notifications, otherwise false. * notifications, otherwise false.

View File

@ -18,7 +18,6 @@ import React, {useState} from "react";
import {UpdateCheckStatus} from "../../../BasePlatform"; import {UpdateCheckStatus} from "../../../BasePlatform";
import PlatformPeg from "../../../PlatformPeg"; import PlatformPeg from "../../../PlatformPeg";
import {hideToast as hideUpdateToast} from "../../../toasts/UpdateToast";
import {useDispatcher} from "../../../hooks/useDispatcher"; import {useDispatcher} from "../../../hooks/useDispatcher";
import dis from "../../../dispatcher/dispatcher"; import dis from "../../../dispatcher/dispatcher";
import {Action} from "../../../dispatcher/actions"; import {Action} from "../../../dispatcher/actions";
@ -60,7 +59,6 @@ const UpdateCheckButton = () => {
const onCheckForUpdateClick = () => { const onCheckForUpdateClick = () => {
setState(null); setState(null);
PlatformPeg.get().startUpdateCheck(); PlatformPeg.get().startUpdateCheck();
hideUpdateToast();
}; };
useDispatcher(dis, ({action, ...params}) => { useDispatcher(dis, ({action, ...params}) => {

View File

@ -17,17 +17,21 @@ limitations under the License.
import React, {ReactChild} from "react"; import React, {ReactChild} from "react";
import FormButton from "../elements/FormButton"; import FormButton from "../elements/FormButton";
import {XOR} from "../../../@types/common";
interface IProps { interface IProps {
description: ReactChild; description: ReactChild;
acceptLabel: string; acceptLabel: string;
rejectLabel?: string;
onAccept(); onAccept();
onReject?();
} }
const GenericToast: React.FC<IProps> = ({description, acceptLabel, rejectLabel, onAccept, onReject}) => { interface IPropsExtended extends IProps {
rejectLabel: string;
onReject();
}
const GenericToast: React.FC<XOR<IPropsExtended, IProps>> = ({description, acceptLabel, rejectLabel, onAccept, onReject}) => {
return <div> return <div>
<div className="mx_Toast_description"> <div className="mx_Toast_description">
{ description } { description }

View File

@ -40,6 +40,10 @@ function installUpdate() {
} }
export const showToast = (version: string, newVersion: string, releaseNotes?: string) => { export const showToast = (version: string, newVersion: string, releaseNotes?: string) => {
function onReject() {
PlatformPeg.get().deferUpdate(newVersion);
}
let onAccept; let onAccept;
let acceptLabel = _t("What's new?"); let acceptLabel = _t("What's new?");
if (releaseNotes) { if (releaseNotes) {
@ -79,6 +83,8 @@ export const showToast = (version: string, newVersion: string, releaseNotes?: st
description: _t("A new version of Riot is available!"), description: _t("A new version of Riot is available!"),
acceptLabel, acceptLabel,
onAccept, onAccept,
rejectLabel: _t("Later"),
onReject,
}, },
component: GenericToast, component: GenericToast,
priority: 20, priority: 20,