From 80df59784df2aead7fcf83d65e26d5fa7dd3b5b5 Mon Sep 17 00:00:00 2001 From: Kiran Niranjan Date: Thu, 28 Sep 2023 12:38:15 +0530 Subject: [PATCH] SDA-4300 (Fix issues related to call toast notification) (#1961) * SDA-4300 - Fix issues related to call toast notification * SDA-4300 - Fix timer GitHub action issue --- src/app/activity-detection.ts | 6 +-- src/common/utils.ts | 9 ++-- src/renderer/components/call-notification.tsx | 25 +++++++---- src/renderer/notification.ts | 4 +- src/renderer/styles/call-notification.less | 44 +++++++++++++++++++ src/renderer/styles/theme.less | 2 + src/renderer/styles/tool-tip.less | 13 ++++++ 7 files changed, 86 insertions(+), 17 deletions(-) create mode 100644 src/renderer/styles/tool-tip.less diff --git a/src/app/activity-detection.ts b/src/app/activity-detection.ts index b7200d22..d0204d73 100644 --- a/src/app/activity-detection.ts +++ b/src/app/activity-detection.ts @@ -1,5 +1,5 @@ import { app, powerMonitor, WebContents } from 'electron'; -import Timer = NodeJS.Timer; +import Timeout = NodeJS.Timeout; import { logger } from '../common/logger'; import { windowHandler } from './window-handler'; @@ -7,8 +7,8 @@ import { windowHandler } from './window-handler'; class ActivityDetection { private idleThreshold: number; private window: WebContents | null; - private timer: Timer | undefined; - private queryInterval: NodeJS.Timer | undefined; + private timer: Timeout | undefined; + private queryInterval: Timeout | undefined; constructor() { this.idleThreshold = 60 * 60 * 1000; diff --git a/src/common/utils.ts b/src/common/utils.ts index 1f434157..4c13fd24 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -1,6 +1,7 @@ // regex match the semver (semantic version) this checks for the pattern X.Y.Z // ex-valid v1.2.0, 1.2.0, 2.3.4-r51 -const semver = /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(?:-[\da-z-]+(?:\.[\da-z-]+)*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?)?)?$/i; +const semver = + /^v?(?:\d+)(\.(?:[x*]|\d+)(\.(?:[x*]|\d+)(?:-[\da-z-]+(?:\.[\da-z-]+)*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?)?)?$/i; const patch = /-([0-9A-Za-z-.]+)/; /** @@ -205,7 +206,7 @@ export const throttle = ( ); } - let timer: NodeJS.Timer; + let timer: NodeJS.Timeout; let lastRan = 0; return (...args) => { @@ -213,7 +214,9 @@ export const throttle = ( func.apply(null, args); lastRan = Date.now(); } else { - clearTimeout(timer); + if (timer) { + clearTimeout(timer); + } timer = setTimeout(() => { if (Date.now() - lastRan >= wait) { func.apply(null, args); diff --git a/src/renderer/components/call-notification.tsx b/src/renderer/components/call-notification.tsx index a8797f5b..2c668d17 100644 --- a/src/renderer/components/call-notification.tsx +++ b/src/renderer/components/call-notification.tsx @@ -48,10 +48,11 @@ export default class CallNotification extends React.Component< onAccept: (data) => (event: mouseEventButton) => this.accept(event, data), onReject: (data) => (event: mouseEventButton) => this.reject(event, data), }; + private readonly defaultState: ICallNotificationState; constructor(props) { super(props); - this.state = { + this.defaultState = { title: 'Incoming call', primaryText: 'unknown', secondaryText: '', @@ -68,6 +69,7 @@ export default class CallNotification extends React.Component< isExternal: false, theme: '', }; + this.state = { ...this.defaultState }; this.updateState = this.updateState.bind(this); } @@ -134,11 +136,7 @@ export default class CallNotification extends React.Component< : callType === 'IM' || callType === 'ROOM' ? 'join' : 'answer'; - const rejectText = rejectButtonText - ? rejectButtonText - : callType === 'IM' || callType === 'ROOM' - ? 'ignore' - : 'decline'; + const rejectText = rejectButtonText ? rejectButtonText : 'decline'; return (
{primaryText}
+
+ {primaryText} +
{this.renderExtBadge(isExternal)}
{secondaryText ? (
-
+
+ {secondaryText} +
+
{secondaryText}
@@ -264,6 +270,7 @@ export default class CallNotification extends React.Component< * @param data {Object} */ private updateState(_event, data): void { + this.setState({ ...this.defaultState }); const { color } = data; // FYI: 1.5 sends hex color but without '#', reason why we check and add prefix if necessary. // Goal is to keep backward compatibility with 1.5 colors (SDA v. 9.2.0) @@ -305,7 +312,7 @@ export default class CallNotification extends React.Component< alt = 'Profile picture'; } - if (!imageUrl) { + if (!imageUrl || isDefaultUrl) { const profilePlaceHolderClassName = callType === 'IM' ? 'profilePlaceHolderContainer' diff --git a/src/renderer/notification.ts b/src/renderer/notification.ts index e322fa07..32e12360 100644 --- a/src/renderer/notification.ts +++ b/src/renderer/notification.ts @@ -31,7 +31,7 @@ const CONTAINER_WIDTH = 363; interface ICustomBrowserWindow extends Electron.BrowserWindow { winName: string; notificationData: INotificationData; - displayTimer: NodeJS.Timer; + displayTimer: NodeJS.Timeout; clientId: number; } @@ -75,7 +75,7 @@ class Notification extends NotificationHandler { }; private activeNotifications: ICustomBrowserWindow[] = []; private inactiveWindows: ICustomBrowserWindow[] = []; - private cleanUpTimer: NodeJS.Timer; + private cleanUpTimer: NodeJS.Timeout; private notificationQueue: INotificationData[] = []; private readonly notificationCallbacks: any[] = []; diff --git a/src/renderer/styles/call-notification.less b/src/renderer/styles/call-notification.less index 0bdd3da7..f565601d 100644 --- a/src/renderer/styles/call-notification.less +++ b/src/renderer/styles/call-notification.less @@ -140,6 +140,7 @@ body { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + position: relative; max-width: 200px; } @@ -266,6 +267,10 @@ text { .decline { background-color: @red-50; + + &:hover { + background-color: @red-40; + } } .action-icon { @@ -274,6 +279,45 @@ text { .accept { background-color: @green-50; + + &:hover { + background-color: @green-40; + } +} + +.tooltip-content { + visibility: hidden; + background-color: #333; + color: #fff; + border-radius: 4px; + padding: 5px 10px; + position: absolute; + z-index: 1; + left: 50%; + width: auto; + max-width: 200px; + white-space: pre-wrap; + word-wrap: break-word; + height: auto; + transform: translateX(-50%); + opacity: 0; + transition: opacity 0.3s, visibility 0.3s; +} + +.tooltip-primary { + bottom: 50%; +} +.tooltip-secondary { + bottom: 40%; +} + +.tooltip-trigger { + &:hover { + & + .tooltip-content { + visibility: visible; + opacity: 1; + } + } } .light-flashing { diff --git a/src/renderer/styles/theme.less b/src/renderer/styles/theme.less index 015bd64c..d7f6c04d 100644 --- a/src/renderer/styles/theme.less +++ b/src/renderer/styles/theme.less @@ -30,4 +30,6 @@ @red-05: #fbeeed; @red-50: #dd342e; +@red-40: #ff5d50; @green-50: #378535; +@green-40: #2eaa35; diff --git a/src/renderer/styles/tool-tip.less b/src/renderer/styles/tool-tip.less new file mode 100644 index 00000000..b6e13cdd --- /dev/null +++ b/src/renderer/styles/tool-tip.less @@ -0,0 +1,13 @@ +.tooltip { + position: absolute; + top: 0; + left: 0; + width: 100px; + height: 50px; + background-color: red; + border: 1px solid #ccc; + padding: 10px; + border-radius: 5px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + z-index: 999999; +}