Skip to content

Commit f9841d9

Browse files
committed
Add popup opener
1 parent c68af21 commit f9841d9

File tree

3 files changed

+53
-12
lines changed

3 files changed

+53
-12
lines changed

src/CryptoSetup/EncryptionFlowViewModel.ts

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ export type EncryptionFlowResult =
2929
| { type: "success" }
3030
| { type: "cancelled" };
3131

32+
/**
33+
* Handle to an opened popup window.
34+
* Abstraction to keep UI code out of the ViewModel.
35+
*/
36+
export interface PopupHandle {
37+
/** Check if the popup is closed */
38+
readonly closed: boolean;
39+
/** Close the popup */
40+
close(): void;
41+
}
42+
43+
/**
44+
* Props for EncryptionFlowViewModel
45+
*/
46+
/**
47+
* Type for the popup opener callback
48+
*/
49+
export type PopupOpener = (url: string, name: string) => PopupHandle | null;
50+
3251
/**
3352
* Props for EncryptionFlowViewModel
3453
*/
@@ -77,6 +96,14 @@ export class EncryptionFlowViewModel
7796
{
7897
private encryption: EncryptionInterface;
7998
private cancelled = false;
99+
private popupOpener: PopupOpener | null = null;
100+
101+
/**
102+
* Set the popup opener callback. Should be called by the View.
103+
*/
104+
public setPopupOpener(opener: PopupOpener): void {
105+
this.popupOpener = opener;
106+
}
80107

81108
public constructor(props: EncryptionFlowViewModelProps) {
82109
super(props, {
@@ -351,17 +378,8 @@ export class EncryptionFlowViewModel
351378
screenType: oidcWarningVm.screenType,
352379
});
353380

354-
// Open OIDC popup
355-
const width = 600;
356-
const height = 900;
357-
const left = window.screenX + (window.outerWidth - width) / 2;
358-
const top = window.screenY + (window.outerHeight - height) / 2;
359-
360-
const popup = window.open(
361-
approvalUrl,
362-
"oidc-reset-approval",
363-
`width=${width},height=${height},left=${left},top=${top},scrollbars=yes`,
364-
);
381+
// Open OIDC popup via callback from View
382+
const popup = this.popupOpener?.(approvalUrl, "oidc-reset-approval") ?? null;
365383

366384
if (!popup) {
367385
console.error("Failed to open OIDC popup");

src/CryptoSetup/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ export type {
9595
EncryptionFlowViewActions,
9696
EncryptionFlowResult,
9797
EncryptionFlowViewModelProps,
98+
PopupHandle,
99+
PopupOpener,
98100
} from "./EncryptionFlowViewModel";
99101

100102
export { FlowStepViewModel } from "./FlowStepViewModel";

src/Encryption.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Please see LICENSE files in the repository root for full details.
66
*/
77

8-
import { useEffect, useRef } from "react";
8+
import { useCallback, useEffect, useRef } from "react";
99
import { createPortal } from "react-dom";
1010
import { useViewModel } from "@element-hq/web-shared-components";
1111
import { InlineSpinner, Glass, TooltipProvider } from "@vector-im/compound-web";
@@ -20,6 +20,21 @@ export interface EncryptionProps {
2020
encryptionFlowViewModel: EncryptionFlowViewModel;
2121
}
2222

23+
/**
24+
* Opens a centered popup window.
25+
*/
26+
function openPopup(url: string, name: string): Window | null {
27+
const width = 600;
28+
const height = 900;
29+
const left = window.screenX + (window.outerWidth - width) / 2;
30+
const top = window.screenY + (window.outerHeight - height) / 2;
31+
return window.open(
32+
url,
33+
name,
34+
`width=${width},height=${height},left=${left},top=${top},scrollbars=yes`,
35+
);
36+
}
37+
2338
/**
2439
* Encryption page component.
2540
*
@@ -33,6 +48,12 @@ export const Encryption: React.FC<EncryptionProps> = ({
3348
const flowStartedRef = useRef(false);
3449
const { isLoading, isActive, currentScreen, screenType } = useViewModel(encryptionFlowViewModel);
3550

51+
// Provide the popup opener to the ViewModel (View -> ViewModel callback)
52+
const popupOpener = useCallback(openPopup, []);
53+
useEffect(() => {
54+
encryptionFlowViewModel.setPopupOpener(popupOpener);
55+
}, [encryptionFlowViewModel, popupOpener]);
56+
3657
console.log("[Encryption] Render:", { isLoading, isActive, hasCurrentScreen: !!currentScreen, screenType });
3758

3859
useEffect(() => {

0 commit comments

Comments
 (0)