From 59324322f676c229f0da4ba95570abdfb060c989 Mon Sep 17 00:00:00 2001 From: Tom Richards Date: Thu, 8 Dec 2022 12:36:25 +0000 Subject: [PATCH 1/4] attempt to focus relevant browser tab when clicking a desktop/push notification --- client/src/push-notifications/serviceWorker.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/client/src/push-notifications/serviceWorker.ts b/client/src/push-notifications/serviceWorker.ts index cb56f725..56b4aafb 100644 --- a/client/src/push-notifications/serviceWorker.ts +++ b/client/src/push-notifications/serviceWorker.ts @@ -94,13 +94,14 @@ self.addEventListener("notificationclick", (event: any) => { const client = // eslint-disable-next-line @typescript-eslint/no-explicit-any clients.find((_: any) => _.id === item.clientId) || clients[0]; - client.postMessage({ - item, - }); + console.log( + "Pinboard push notification click, attempting to focus client" + ); + return client.focus(); } else if (event.action === "grid") { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - self.clients.openWindow( + return self.clients.openWindow( `https://media.${toolsDomain}/search?${openToPinboardQueryParam}&${openToPinboardItemIdQueryParam}`.replace( ".code.", ".test." @@ -113,10 +114,11 @@ self.addEventListener("notificationclick", (event: any) => { ) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - self.clients.openWindow( + return self.clients.openWindow( `https://workflow.${toolsDomain}/redirect/${item.pinboardId}?${EXPAND_PINBOARD_QUERY_PARAM}=true&${openToPinboardItemIdQueryParam}` ); } + return Promise.resolve(); }) ); }); From 4ea9556546140828744aeb2a939676cb265e121e Mon Sep 17 00:00:00 2001 From: Tom Richards Date: Tue, 13 Dec 2022 20:34:22 +0000 Subject: [PATCH 2/4] pass the selected pinboard id to the hidden iframe, so the service worker can better select the tab to focus when there a multiple tabs open running pinboard, and scroll to and highlight the item in question --- client/src/app.tsx | 108 +++++++++--------- client/src/globalState.tsx | 16 +-- .../src/push-notifications/serviceWorker.ts | 13 ++- client/src/pushNotificationPreferences.tsx | 27 +++-- client/src/scrollableItems.tsx | 16 ++- client/tsconfig.json | 6 +- 6 files changed, 112 insertions(+), 74 deletions(-) diff --git a/client/src/app.tsx b/client/src/app.tsx index 67adbf41..3b7f3d1d 100644 --- a/client/src/app.tsx +++ b/client/src/app.tsx @@ -336,53 +336,53 @@ export const PinBoardApp = ({ apolloClient, userEmail }: PinBoardAppProps) => { return ( - - - - isGridDragEvent(event) && event.preventDefault() + { - if (isGridDragEvent(event)) { - event.preventDefault(); - setIsDropTarget(true); - } - }} - onDragLeave={() => setIsDropTarget(false)} - onDragEnd={() => setIsDropTarget(false)} - onDragExit={() => setIsDropTarget(false)} - onDrop={(event) => { - if (isGridDragEvent(event)) { - event.preventDefault(); - const payload = convertGridDragEventToPayload(event); - setPayloadToBeSent(payload); - setIsExpanded(true); - payload && - sendTelemetryEvent?.(PINBOARD_TELEMETRY_TYPE.DRAG_AND_DROP, { - assetType: payload.type, - }); - } - setIsDropTarget(false); - }} > - + + + isGridDragEvent(event) && event.preventDefault() } + onDragEnter={(event) => { + if (isGridDragEvent(event)) { + event.preventDefault(); + setIsDropTarget(true); + } + }} + onDragLeave={() => setIsDropTarget(false)} + onDragEnd={() => setIsDropTarget(false)} + onDragExit={() => setIsDropTarget(false)} + onDrop={(event) => { + if (isGridDragEvent(event)) { + event.preventDefault(); + const payload = convertGridDragEventToPayload(event); + setPayloadToBeSent(payload); + setIsExpanded(true); + payload && + sendTelemetryEvent?.(PINBOARD_TELEMETRY_TYPE.DRAG_AND_DROP, { + assetType: payload.type, + }); + } + setIsDropTarget(false); + }} > {isInlineMode ? ( @@ -396,16 +396,16 @@ export const PinBoardApp = ({ apolloClient, userEmail }: PinBoardAppProps) => { )} - - - {assetHandles.map((node, index) => ( - - ))} + + {assetHandles.map((node, index) => ( + + ))} + ); diff --git a/client/src/globalState.tsx b/client/src/globalState.tsx index ae3ef7be..91a15bef 100644 --- a/client/src/globalState.tsx +++ b/client/src/globalState.tsx @@ -384,15 +384,17 @@ export const GlobalStateProvider: React.FC = ({ useEffect(() => { window.addEventListener("message", (event) => { - if ( - event.source !== window && - Object.prototype.hasOwnProperty.call(event.data, "item") - ) { - const item = event.data.item; + if (Object.prototype.hasOwnProperty.call(event.data, "item")) { + const item: Item = event.data.item; window.focus(); setIsExpanded(true); - setSelectedPinboardId(item.pinboardId); // FIXME handle if said pinboard is not active (i.e. load data) - // TODO ideally highlight the item + if ( + !preselectedPinboardId || + preselectedPinboardId === item.pinboardId + ) { + setSelectedPinboardId(item.pinboardId); // FIXME handle if said pinboard is not active (i.e. load data) + // highlighting the item is handled in ScrollableItems component + } } }); }, []); diff --git a/client/src/push-notifications/serviceWorker.ts b/client/src/push-notifications/serviceWorker.ts index 56b4aafb..883cea4c 100644 --- a/client/src/push-notifications/serviceWorker.ts +++ b/client/src/push-notifications/serviceWorker.ts @@ -88,12 +88,17 @@ self.addEventListener("notificationclick", (event: any) => { .matchAll({ includeUncontrolled: true, }) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .then((clients: any[]) => { + .then((clients: WindowClient[]) => { if (!event.action && clients.length > 0) { const client = - // eslint-disable-next-line @typescript-eslint/no-explicit-any - clients.find((_: any) => _.id === item.clientId) || clients[0]; + clients.find( + (client: WindowClient) => + client.id === item.clientId || + client.url?.includes( + `?${OPEN_PINBOARD_QUERY_PARAM}=${item.pinboardId}` + ) + ) || clients[0]; + client.postMessage({ item }); // send this item to the client, so ideally it can highlight the message from the notification console.log( "Pinboard push notification click, attempting to focus client" ); diff --git a/client/src/pushNotificationPreferences.tsx b/client/src/pushNotificationPreferences.tsx index e5830bd6..c48a5f11 100644 --- a/client/src/pushNotificationPreferences.tsx +++ b/client/src/pushNotificationPreferences.tsx @@ -1,6 +1,9 @@ import React, { useContext } from "react"; import { agateSans } from "../fontNormaliser"; import { TelemetryContext, PINBOARD_TELEMETRY_TYPE } from "./types/Telemetry"; +import { useGlobalStateContext } from "./globalState"; +import { OPEN_PINBOARD_QUERY_PARAM } from "../../shared/constants"; +import { isPinboardData } from "../../shared/graphql/extraTypes"; interface PushNotificationPreferencesOpenerProps { hasWebPushSubscription: boolean | null | undefined; } @@ -50,10 +53,20 @@ interface HiddenIFrameForServiceWorkerProps { export const HiddenIFrameForServiceWorker = ({ iFrameRef, -}: HiddenIFrameForServiceWorkerProps) => ( -