From 5cb878b9ae63267a52d3b4422500fa80bf8ff7d0 Mon Sep 17 00:00:00 2001 From: Montassar Ghanmy Date: Wed, 27 Nov 2024 12:50:42 +0100 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=90=9B=20Fix=20anonymous=20features?= =?UTF-8?q?=20hook=20(#750)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature-toggles-hooks.tsx | 37 +++++++++++++++++-- .../app/views/client/body/drive/shared.tsx | 2 +- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/tdrive/frontend/src/app/components/locked-features-components/feature-toggles-hooks.tsx b/tdrive/frontend/src/app/components/locked-features-components/feature-toggles-hooks.tsx index d14827fd..d1a32bc1 100644 --- a/tdrive/frontend/src/app/components/locked-features-components/feature-toggles-hooks.tsx +++ b/tdrive/frontend/src/app/components/locked-features-components/feature-toggles-hooks.tsx @@ -1,18 +1,47 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; +import Api from '@features/global/framework/api-service'; import FeatureTogglesService, { FeatureNames, } from '@features/global/services/feature-toggles-service'; import { FeatureToggles, Feature, withFeatures } from '@paralleldrive/react-feature-toggles'; +import RouterService from '@features/router/services/router-service'; import { useCurrentCompany } from '@features/companies/hooks/use-companies'; +import { CompanyType } from 'app/features/companies/types/company'; +import Logger from '@features/global/framework/logger-service'; -export const useFeatureToggles = () => { +export const useFeatureToggles = (anonymous = false) => { + const routeState = RouterService.getStateFromRoute(); const { activeFeatureNames } = FeatureTogglesService; - const { company } = useCurrentCompany(); + const [fetchedCompany, setFetchedCompany] = useState(); + const company = anonymous ? fetchedCompany : useCurrentCompany()?.company; + + useEffect(() => { + if (anonymous) { + const fetchCompany = async () => { + try { + if (!routeState?.companyId) return; + + const res = (await Api.get( + `/internal/services/users/v1/companies/${routeState.companyId}`, + )) as any; + if (res?.resource) { + setFetchedCompany(res.resource); // Assuming `res.resource` is structured correctly. + } + } catch (error) { + Logger.error('Error fetching company', error); + } + }; + + fetchCompany(); + } + }, [anonymous, routeState?.companyId]); useEffect(() => { const companyPlan = company?.plan; - companyPlan && FeatureTogglesService.setFeaturesFromCompanyPlan(companyPlan as any); + if (companyPlan) { + FeatureTogglesService.setFeaturesFromCompanyPlan(companyPlan as any); + } }, [JSON.stringify(company)]); return { diff --git a/tdrive/frontend/src/app/views/client/body/drive/shared.tsx b/tdrive/frontend/src/app/views/client/body/drive/shared.tsx index 77b75c62..f8ee4fa2 100755 --- a/tdrive/frontend/src/app/views/client/body/drive/shared.tsx +++ b/tdrive/frontend/src/app/views/client/body/drive/shared.tsx @@ -29,7 +29,7 @@ import LocalStorage from 'app/features/global/framework/local-storage-service'; export default () => { const companyId = useRouterCompany(); - const { FeatureToggles, activeFeatureNames } = useFeatureToggles(); + const { FeatureToggles, activeFeatureNames } = useFeatureToggles(true); // use toggle for anonymous user on public view //Create a different local storage for shared view useEffect(() => { From f51592a4503206a0f9d5294e806ac212f3772977 Mon Sep 17 00:00:00 2001 From: Montassar Ghanmy Date: Wed, 27 Nov 2024 12:51:06 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9B=20Fix=20custom=20download=20fi?= =?UTF-8?q?le=20helper=20with=20safari=20fallback=20(#751)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../drive/hooks/use-drive-actions.tsx | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/tdrive/frontend/src/app/features/drive/hooks/use-drive-actions.tsx b/tdrive/frontend/src/app/features/drive/hooks/use-drive-actions.tsx index 8a035c5f..5ad7e05b 100644 --- a/tdrive/frontend/src/app/features/drive/hooks/use-drive-actions.tsx +++ b/tdrive/frontend/src/app/features/drive/hooks/use-drive-actions.tsx @@ -17,6 +17,8 @@ import AlertManager from 'app/features/global/services/alert-manager-service'; import FeatureTogglesService, { FeatureNames, } from '@features/global/services/feature-toggles-service'; +import Logger from '@features/global/framework/logger-service'; + /** * Returns the children of a drive item * @returns @@ -25,10 +27,38 @@ export const useDriveActions = (inPublicSharing?: boolean) => { const companyId = useRouterCompany(); const sharedFilter = useRecoilValue(SharedWithMeFilterState); const sortItem = useRecoilValue(DriveItemSort); - const [ paginateItem ] = useRecoilState(DriveItemPagination); + const [paginateItem] = useRecoilState(DriveItemPagination); const { getQuota } = useUserQuota(); const AVEnabled = FeatureTogglesService.isActiveFeatureName(FeatureNames.COMPANY_AV_ENABLED); + /** + * Downloads a file from the given URL, ensuring compatibility across all browsers, including Safari. + * + * @param fileUrl - The URL of the file to download. + */ + const downloadFile = (fileUrl: string) => { + try { + // Attempt to open the URL in a new tab + const popupWindow = window.open(fileUrl, '_blank'); + + if (popupWindow) { + popupWindow.focus(); + } else { + // Fallback for Safari or blocked pop-ups + const downloadLink = document.createElement('a'); + downloadLink.href = fileUrl; + downloadLink.download = ''; // Suggests a download instead of navigation + downloadLink.target = '_self'; // Ensures it opens in the same tab + + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + } + } catch (error) { + Logger.error('Error during file download:', error); + } + }; + const refresh = useRecoilCallback( ({ set, snapshot }) => async (parentId: string, resetPagination?: boolean) => { @@ -112,7 +142,7 @@ export const useDriveActions = (inPublicSharing?: boolean) => { // toggle confirm for user AlertManager.confirm( () => { - (window as any).open(url, '_blank').focus(); + downloadFile(url); }, () => { return; @@ -122,10 +152,10 @@ export const useDriveActions = (inPublicSharing?: boolean) => { }, ); } else { - (window as any).open(url, '_blank').focus(); + downloadFile(url); } } else { - (window as any).open(url, '_blank').focus(); + downloadFile(url); } } catch (e) { ToasterService.error(Languages.t('hooks.use-drive-actions.unable_download_file')); @@ -139,7 +169,7 @@ export const useDriveActions = (inPublicSharing?: boolean) => { try { const triggerDownload = async () => { const url = await DriveApiClient.getDownloadZipUrl(companyId, ids, isDirectory); - (window as any).open(url, '_blank').focus(); + downloadFile(url); }; if (AVEnabled) { const containsMaliciousFiles = @@ -254,7 +284,7 @@ export const useDriveActions = (inPublicSharing?: boolean) => { }, [paginateItem, refresh], ); - + const checkMalware = useCallback( async (item: Partial) => { try {