From bb6fc4aa9deca20014c9d75ecf34a116ae60d05b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Tue, 1 Jul 2025 14:27:13 +0200 Subject: [PATCH 1/2] add test qr gen for mobile client --- .../AddDeviceTokenStep/AddDeviceTokenStep.tsx | 34 +++++++++++++++++++ .../steps/AddDeviceTokenStep/style.scss | 20 ++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/web/src/pages/addDevice/steps/AddDeviceTokenStep/AddDeviceTokenStep.tsx b/web/src/pages/addDevice/steps/AddDeviceTokenStep/AddDeviceTokenStep.tsx index 61a6f48b74..a332d9e095 100644 --- a/web/src/pages/addDevice/steps/AddDeviceTokenStep/AddDeviceTokenStep.tsx +++ b/web/src/pages/addDevice/steps/AddDeviceTokenStep/AddDeviceTokenStep.tsx @@ -3,6 +3,7 @@ import './style.scss'; import parse from 'html-react-parser'; import { isUndefined } from 'lodash-es'; import { ReactNode, useEffect, useMemo } from 'react'; +import QRCode from 'react-qr-code'; import { useNavigate } from 'react-router'; import { shallow } from 'zustand/shallow'; @@ -13,12 +14,15 @@ import { Card } from '../../../../shared/defguard-ui/components/Layout/Card/Card import { ExpandableCard } from '../../../../shared/defguard-ui/components/Layout/ExpandableCard/ExpandableCard'; import { MessageBox } from '../../../../shared/defguard-ui/components/Layout/MessageBox/MessageBox'; import { MessageBoxType } from '../../../../shared/defguard-ui/components/Layout/MessageBox/types'; +import { isPresent } from '../../../../shared/defguard-ui/utils/isPresent'; import { useAppStore } from '../../../../shared/hooks/store/useAppStore'; import { useAuthStore } from '../../../../shared/hooks/store/useAuthStore'; import useApi from '../../../../shared/hooks/useApi'; import { useClipboard } from '../../../../shared/hooks/useClipboard'; import { useAddDevicePageStore } from '../../hooks/useAddDevicePageStore'; +const useLocalProxy = true; + export const AddDeviceTokenStep = () => { const { writeToClipboard } = useClipboard(); const { LL } = useI18nContext(); @@ -40,6 +44,25 @@ export const AddDeviceTokenStep = () => { shallow, ); + const mobileQrData = useMemo(() => { + if (isPresent(url) && isPresent(token)) { + let targetUrl: string; + if (useLocalProxy) { + targetUrl = 'http://10.0.2.2:8080'; + } else { + targetUrl = url; + } + const registration = { + token, + url: targetUrl, + }; + const registrationJson = JSON.stringify(registration); + const encoded = btoa(registrationJson); + return encoded; + } + return undefined; + }, [token, url]); + const tokenActions = useMemo( (): ReactNode[] => [ {

{token}

+ + {isPresent(mobileQrData) && ( + + + + )} ); diff --git a/web/src/pages/addDevice/steps/AddDeviceTokenStep/style.scss b/web/src/pages/addDevice/steps/AddDeviceTokenStep/style.scss index 72f1b14387..a178a3efc1 100644 --- a/web/src/pages/addDevice/steps/AddDeviceTokenStep/style.scss +++ b/web/src/pages/addDevice/steps/AddDeviceTokenStep/style.scss @@ -3,5 +3,23 @@ .expandable-card { margin-bottom: 25px; } + + #mobile-qr-code { + .expanded-content { + display: flex; + flex-flow: column; + align-items: center; + justify-content: center; + overflow: hidden; + box-sizing: border-box; + row-gap: 20px; + + p { + max-width: 80%; + margin: 0; + padding: 0; + } + } + } } -} +} \ No newline at end of file From fd69b003a7926076d58a114cc4589868a4393378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Thu, 3 Jul 2025 15:11:30 +0200 Subject: [PATCH 2/2] mobile client qr for dev --- .../AddDeviceTokenStep/AddDeviceTokenStep.tsx | 21 ++++++++++++++++--- .../steps/AddDeviceTokenStep/style.scss | 2 +- .../overview-index/OverviewIndexPage.tsx | 4 +++- .../OverviewNetworkSelection.tsx | 3 +++ web/src/pages/overview/OverviewPage.tsx | 2 ++ 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/web/src/pages/addDevice/steps/AddDeviceTokenStep/AddDeviceTokenStep.tsx b/web/src/pages/addDevice/steps/AddDeviceTokenStep/AddDeviceTokenStep.tsx index a332d9e095..8ab83f0294 100644 --- a/web/src/pages/addDevice/steps/AddDeviceTokenStep/AddDeviceTokenStep.tsx +++ b/web/src/pages/addDevice/steps/AddDeviceTokenStep/AddDeviceTokenStep.tsx @@ -21,7 +21,21 @@ import useApi from '../../../../shared/hooks/useApi'; import { useClipboard } from '../../../../shared/hooks/useClipboard'; import { useAddDevicePageStore } from '../../hooks/useAddDevicePageStore'; -const useLocalProxy = true; +const useLocalProxy = import.meta.env.DEV; + +const extractProxyPort = (input: string): string | undefined => { + try { + const url = new URL(input); + const port = url.port; + const parsed = port ? parseInt(port, 10) : undefined; + if (parsed && !isNaN(parsed)) { + return `:${parsed}`; + } + return undefined; + } catch { + return undefined; + } +}; export const AddDeviceTokenStep = () => { const { writeToClipboard } = useClipboard(); @@ -48,7 +62,8 @@ export const AddDeviceTokenStep = () => { if (isPresent(url) && isPresent(token)) { let targetUrl: string; if (useLocalProxy) { - targetUrl = 'http://10.0.2.2:8080'; + const proxyPort = extractProxyPort(url) ?? ''; + targetUrl = `http://10.0.2.2${proxyPort}`; } else { targetUrl = url; } @@ -131,7 +146,7 @@ export const AddDeviceTokenStep = () => {

{token}

- + {isPresent(mobileQrData) && ( { queryKey: ['network'], queryFn: getNetworks, placeholderData: (perv) => perv, + select: (networks) => + orderBy(networks, (network) => network.name.toLowerCase(), ['asc']), }); const resetWizard = useWizardStore((state) => state.resetState); diff --git a/web/src/pages/overview-index/components/OverviewNetworkSelection/OverviewNetworkSelection.tsx b/web/src/pages/overview-index/components/OverviewNetworkSelection/OverviewNetworkSelection.tsx index 5f8f544159..117ced75c9 100644 --- a/web/src/pages/overview-index/components/OverviewNetworkSelection/OverviewNetworkSelection.tsx +++ b/web/src/pages/overview-index/components/OverviewNetworkSelection/OverviewNetworkSelection.tsx @@ -1,4 +1,5 @@ import { useQuery } from '@tanstack/react-query'; +import { orderBy } from 'lodash-es'; import { useMemo } from 'react'; import { useLocation, useNavigate, useParams } from 'react-router-dom'; @@ -26,6 +27,8 @@ export const OverviewNetworkSelection = () => { queryKey: ['network'], queryFn: getNetworks, placeholderData: (perv) => perv, + select: (networks) => + orderBy(networks, (network) => network.name.toLowerCase(), ['asc']), }); const selectionValue = useMemo(() => { diff --git a/web/src/pages/overview/OverviewPage.tsx b/web/src/pages/overview/OverviewPage.tsx index 616a34f5ae..09bce1726d 100644 --- a/web/src/pages/overview/OverviewPage.tsx +++ b/web/src/pages/overview/OverviewPage.tsx @@ -47,6 +47,8 @@ export const OverviewPage = () => { queryKey: ['network'], queryFn: getNetworks, placeholderData: (perv) => perv, + select: (networks) => + orderBy(networks, (network) => network.name.toLowerCase(), ['asc']), }); const { data: networkStats } = useQuery({