From daeccdab323fff38ac09395c486db3e695dfa05e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 7 May 2024 10:00:52 +0530 Subject: [PATCH 1/6] Move --- .../PhotoViewer/FileInfo/RenderFileName.tsx | 2 +- .../individual/usageSection.tsx | 2 +- .../contentOverlay/storageSection.tsx | 2 +- .../gallery/PlanSelector/plans/BfAddOnRow.tsx | 2 +- .../gallery/PlanSelector/plans/planRow.tsx | 7 +-- web/apps/photos/src/utils/billing/index.ts | 43 +------------------ web/apps/photos/src/utils/units.ts | 39 +++++++++++++++++ 7 files changed, 47 insertions(+), 50 deletions(-) create mode 100644 web/apps/photos/src/utils/units.ts diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx index 3990511855..7e2786c422 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx @@ -7,7 +7,7 @@ import VideocamOutlined from "@mui/icons-material/VideocamOutlined"; import Box from "@mui/material/Box"; import { useEffect, useState } from "react"; import { EnteFile } from "types/file"; -import { makeHumanReadableStorage } from "utils/billing"; +import { makeHumanReadableStorage } from "utils/units"; import { changeFileName, updateExistingFilePubMetadata } from "utils/file"; import { FileNameEditDialog } from "./FileNameEditDialog"; import InfoItem from "./InfoItem"; diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx index 4b0ce31b04..2acfc2e766 100644 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx +++ b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx @@ -1,7 +1,7 @@ import { SpaceBetweenFlex } from "@ente/shared/components/Container"; import { Box, Typography } from "@mui/material"; import { t } from "i18next"; -import { makeHumanReadableStorage } from "utils/billing"; +import { makeHumanReadableStorage } from "utils/units"; import { Progressbar } from "../../styledComponents"; diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx index 6143044f0d..8ef5bea5ec 100644 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx +++ b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx @@ -1,6 +1,6 @@ import { Box, styled, Typography } from "@mui/material"; import { t } from "i18next"; -import { convertBytesToGBs, makeHumanReadableStorage } from "utils/billing"; +import { convertBytesToGBs, makeHumanReadableStorage } from "utils/units"; const MobileSmallBox = styled(Box)` display: none; diff --git a/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx b/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx index 8b0ce7bd5f..aed1fba47e 100644 --- a/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx +++ b/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx @@ -2,7 +2,7 @@ import { SpaceBetweenFlex } from "@ente/shared/components/Container"; import { Box, styled, Typography } from "@mui/material"; import { Trans } from "react-i18next"; -import { makeHumanReadableStorage } from "utils/billing"; +import { makeHumanReadableStorage } from "utils/units"; const RowContainer = styled(SpaceBetweenFlex)(({ theme }) => ({ // gap: theme.spacing(1.5), diff --git a/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/planRow.tsx b/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/planRow.tsx index 6363caee4d..ca01b40b39 100644 --- a/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/planRow.tsx +++ b/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/planRow.tsx @@ -6,11 +6,8 @@ import { Badge } from "components/Badge"; import { PLAN_PERIOD } from "constants/gallery"; import { t } from "i18next"; import { Plan, Subscription } from "types/billing"; -import { - convertBytesToGBs, - hasPaidSubscription, - isUserSubscribedPlan, -} from "utils/billing"; +import { hasPaidSubscription, isUserSubscribedPlan } from "utils/billing"; +import { convertBytesToGBs } from "utils/units"; interface Iprops { plan: Plan; diff --git a/web/apps/photos/src/utils/billing/index.ts b/web/apps/photos/src/utils/billing/index.ts index 3dfde5384b..d2e593e9e1 100644 --- a/web/apps/photos/src/utils/billing/index.ts +++ b/web/apps/photos/src/utils/billing/index.ts @@ -31,44 +31,6 @@ enum RESPONSE_STATUS { fail = "fail", } -const StorageUnits = ["B", "KB", "MB", "GB", "TB"]; - -const ONE_GB = 1024 * 1024 * 1024; - -export function convertBytesToGBs(bytes: number, precision = 0): string { - return (bytes / (1024 * 1024 * 1024)).toFixed(precision); -} - -export function makeHumanReadableStorage( - bytes: number, - { roundUp } = { roundUp: false }, -): string { - if (bytes <= 0) { - return `0 ${t("STORAGE_UNITS.MB")}`; - } - const i = Math.floor(Math.log(bytes) / Math.log(1024)); - - let quantity = bytes / Math.pow(1024, i); - let unit = StorageUnits[i]; - - if (quantity > 100 && unit !== "GB") { - quantity /= 1024; - unit = StorageUnits[i + 1]; - } - - quantity = Number(quantity.toFixed(1)); - - if (bytes >= 10 * ONE_GB) { - if (roundUp) { - quantity = Math.ceil(quantity); - } else { - quantity = Math.round(quantity); - } - } - - return `${quantity} ${t(`STORAGE_UNITS.${unit}`)}`; -} - export function hasPaidSubscription(subscription: Subscription) { return ( subscription && @@ -160,9 +122,8 @@ export function isSubscriptionPastDue(subscription: Subscription) { ); } -export function isPopularPlan(plan: Plan) { - return plan.storage === 100 * ONE_GB; -} +export const isPopularPlan = (plan: Plan) => + plan.storage === 100 * 1024 * 1024 * 1024; /* 100 GB */ export async function updateSubscription( plan: Plan, diff --git a/web/apps/photos/src/utils/units.ts b/web/apps/photos/src/utils/units.ts new file mode 100644 index 0000000000..44ef4e023e --- /dev/null +++ b/web/apps/photos/src/utils/units.ts @@ -0,0 +1,39 @@ +import { t } from "i18next"; + +const StorageUnits = ["B", "KB", "MB", "GB", "TB"]; + +const ONE_GB = 1024 * 1024 * 1024; + +export function convertBytesToGBs(bytes: number, precision = 0): string { + return (bytes / (1024 * 1024 * 1024)).toFixed(precision); +} + +export function makeHumanReadableStorage( + bytes: number, + { roundUp } = { roundUp: false }, +): string { + if (bytes <= 0) { + return `0 ${t("STORAGE_UNITS.MB")}`; + } + const i = Math.floor(Math.log(bytes) / Math.log(1024)); + + let quantity = bytes / Math.pow(1024, i); + let unit = StorageUnits[i]; + + if (quantity > 100 && unit !== "GB") { + quantity /= 1024; + unit = StorageUnits[i + 1]; + } + + quantity = Number(quantity.toFixed(1)); + + if (bytes >= 10 * ONE_GB) { + if (roundUp) { + quantity = Math.ceil(quantity); + } else { + quantity = Math.round(quantity); + } + } + + return `${quantity} ${t(`STORAGE_UNITS.${unit}`)}`; +} From 7993a076077e6ebb07f135ca9e2064115a9b836e Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 7 May 2024 10:28:05 +0530 Subject: [PATCH 2/6] 1 --- .../src/components/PhotoList/dedupe.tsx | 2 +- .../photos/src/components/PhotoList/index.tsx | 2 +- .../contentOverlay/storageSection.tsx | 6 ++--- .../pages/gallery/PlanSelector/card/paid.tsx | 12 ++++------ .../gallery/PlanSelector/plans/planRow.tsx | 4 ++-- web/apps/photos/src/utils/file/index.ts | 13 ----------- web/apps/photos/src/utils/units.ts | 22 +++++++++++++++++-- 7 files changed, 30 insertions(+), 31 deletions(-) diff --git a/web/apps/photos/src/components/PhotoList/dedupe.tsx b/web/apps/photos/src/components/PhotoList/dedupe.tsx index ab7badf1f6..be412ad782 100644 --- a/web/apps/photos/src/components/PhotoList/dedupe.tsx +++ b/web/apps/photos/src/components/PhotoList/dedupe.tsx @@ -19,7 +19,7 @@ import { } from "react-window"; import { Duplicate } from "services/deduplicationService"; import { EnteFile } from "types/file"; -import { convertBytesToHumanReadable } from "utils/file"; +import { convertBytesToHumanReadable } from "utils/units"; export enum ITEM_TYPE { TIME = "TIME", diff --git a/web/apps/photos/src/components/PhotoList/index.tsx b/web/apps/photos/src/components/PhotoList/index.tsx index 4803995d4f..508e9eab5a 100644 --- a/web/apps/photos/src/components/PhotoList/index.tsx +++ b/web/apps/photos/src/components/PhotoList/index.tsx @@ -22,9 +22,9 @@ import { areEqual, } from "react-window"; import { EnteFile } from "types/file"; -import { convertBytesToHumanReadable } from "utils/file"; import { handleSelectCreator } from "utils/photoFrame"; import { PublicCollectionGalleryContext } from "utils/publicCollectionGallery"; +import { convertBytesToHumanReadable } from "utils/units"; const A_DAY = 24 * 60 * 60 * 1000; const FOOTER_HEIGHT = 90; diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx index 8ef5bea5ec..90705753b9 100644 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx +++ b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx @@ -1,6 +1,6 @@ import { Box, styled, Typography } from "@mui/material"; import { t } from "i18next"; -import { convertBytesToGBs, makeHumanReadableStorage } from "utils/units"; +import { bytesInGB, makeHumanReadableStorage } from "utils/units"; const MobileSmallBox = styled(Box)` display: none; @@ -40,9 +40,7 @@ export default function StorageSection({ usage, storage }: Iprops) { fontWeight={"bold"} sx={{ fontSize: "24px", lineHeight: "30px" }} > - {`${convertBytesToGBs(usage)} / ${convertBytesToGBs( - storage, - )} ${t("GB")} ${t("USED")}`} + {`${bytesInGB(usage)} / ${bytesInGB(storage)} ${t("GB")} ${t("USED")}`} diff --git a/web/apps/photos/src/components/pages/gallery/PlanSelector/card/paid.tsx b/web/apps/photos/src/components/pages/gallery/PlanSelector/card/paid.tsx index 4ef76a491f..0ef4b15947 100644 --- a/web/apps/photos/src/components/pages/gallery/PlanSelector/card/paid.tsx +++ b/web/apps/photos/src/components/pages/gallery/PlanSelector/card/paid.tsx @@ -5,11 +5,8 @@ import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import { t } from "i18next"; import { Trans } from "react-i18next"; -import { - convertBytesToGBs, - hasAddOnBonus, - isSubscriptionCancelled, -} from "utils/billing"; +import { hasAddOnBonus, isSubscriptionCancelled } from "utils/billing"; +import { bytesInGB } from "utils/units"; import { ManageSubscription } from "../manageSubscription"; import { PeriodToggler } from "../periodToggler"; import Plans from "../plans"; @@ -35,8 +32,7 @@ export default function PaidSubscriptionPlanSelectorCard({ {t("SUBSCRIPTION")} - {convertBytesToGBs(subscription.storage, 2)}{" "} - {t("GB")} + {bytesInGB(subscription.storage, 2)} {t("GB")} @@ -50,7 +46,7 @@ export default function PaidSubscriptionPlanSelectorCard({ diff --git a/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/planRow.tsx b/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/planRow.tsx index ca01b40b39..bb2347ddcc 100644 --- a/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/planRow.tsx +++ b/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/planRow.tsx @@ -7,7 +7,7 @@ import { PLAN_PERIOD } from "constants/gallery"; import { t } from "i18next"; import { Plan, Subscription } from "types/billing"; import { hasPaidSubscription, isUserSubscribedPlan } from "utils/billing"; -import { convertBytesToGBs } from "utils/units"; +import { bytesInGB } from "utils/units"; interface Iprops { plan: Plan; @@ -63,7 +63,7 @@ export function PlanRow({ - {convertBytesToGBs(plan.storage)} + {bytesInGB(plan.storage)} diff --git a/web/apps/photos/src/utils/file/index.ts b/web/apps/photos/src/utils/file/index.ts index bb212ff21e..98a8dd9481 100644 --- a/web/apps/photos/src/utils/file/index.ts +++ b/web/apps/photos/src/utils/file/index.ts @@ -103,19 +103,6 @@ export async function getUpdatedEXIFFileForDownload( } } -export function convertBytesToHumanReadable( - bytes: number, - precision = 2, -): string { - if (bytes === 0 || isNaN(bytes)) { - return "0 MB"; - } - - const i = Math.floor(Math.log(bytes) / Math.log(1024)); - const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; - return (bytes / Math.pow(1024, i)).toFixed(precision) + " " + sizes[i]; -} - export async function downloadFile(file: EnteFile) { try { const fileReader = new FileReader(); diff --git a/web/apps/photos/src/utils/units.ts b/web/apps/photos/src/utils/units.ts index 44ef4e023e..20a90e4c29 100644 --- a/web/apps/photos/src/utils/units.ts +++ b/web/apps/photos/src/utils/units.ts @@ -4,8 +4,26 @@ const StorageUnits = ["B", "KB", "MB", "GB", "TB"]; const ONE_GB = 1024 * 1024 * 1024; -export function convertBytesToGBs(bytes: number, precision = 0): string { - return (bytes / (1024 * 1024 * 1024)).toFixed(precision); +/** + * Convert the given number of {@link bytes} to their equivalent GB string with + * {@link precision}. + * + * The returned string does not have the GB prefix. + */ +export const bytesInGB = (bytes: number, precision = 0): string => + (bytes / (1024 * 1024 * 1024)).toFixed(precision); + +export function convertBytesToHumanReadable( + bytes: number, + precision = 2, +): string { + if (bytes === 0 || isNaN(bytes)) { + return "0 MB"; + } + + const i = Math.floor(Math.log(bytes) / Math.log(1024)); + const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + return (bytes / Math.pow(1024, i)).toFixed(precision) + " " + sizes[i]; } export function makeHumanReadableStorage( From ccf336e00f70d6f74de4f30c47e150e3f57a5a31 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 7 May 2024 10:35:22 +0530 Subject: [PATCH 3/6] 2 --- .../photos/src/components/PhotoList/dedupe.tsx | 5 ++--- web/apps/photos/src/components/PhotoList/index.tsx | 5 ++--- .../PhotoViewer/FileInfo/RenderFileName.tsx | 4 ++-- web/apps/photos/src/utils/units.ts | 14 ++++++++++---- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/web/apps/photos/src/components/PhotoList/dedupe.tsx b/web/apps/photos/src/components/PhotoList/dedupe.tsx index be412ad782..b911fad372 100644 --- a/web/apps/photos/src/components/PhotoList/dedupe.tsx +++ b/web/apps/photos/src/components/PhotoList/dedupe.tsx @@ -19,7 +19,7 @@ import { } from "react-window"; import { Duplicate } from "services/deduplicationService"; import { EnteFile } from "types/file"; -import { convertBytesToHumanReadable } from "utils/units"; +import { formattedBytes } from "utils/units"; export enum ITEM_TYPE { TIME = "TIME", @@ -310,8 +310,7 @@ export function DedupePhotoList({ */ {listItem.fileCount} {t("FILES")},{" "} - {convertBytesToHumanReadable(listItem.fileSize || 0)}{" "} - {t("EACH")} + {formattedBytes(listItem.fileSize || 0)} {t("EACH")} ); case ITEM_TYPE.FILE: { diff --git a/web/apps/photos/src/components/PhotoList/index.tsx b/web/apps/photos/src/components/PhotoList/index.tsx index 508e9eab5a..f052e4b358 100644 --- a/web/apps/photos/src/components/PhotoList/index.tsx +++ b/web/apps/photos/src/components/PhotoList/index.tsx @@ -24,7 +24,7 @@ import { import { EnteFile } from "types/file"; import { handleSelectCreator } from "utils/photoFrame"; import { PublicCollectionGalleryContext } from "utils/publicCollectionGallery"; -import { convertBytesToHumanReadable } from "utils/units"; +import { formattedBytes } from "utils/units"; const A_DAY = 24 * 60 * 60 * 1000; const FOOTER_HEIGHT = 90; @@ -829,8 +829,7 @@ export function PhotoList({ return ( {listItem.fileCount} {t("FILES")},{" "} - {convertBytesToHumanReadable(listItem.fileSize || 0)}{" "} - {t("EACH")} + {formattedBytes(listItem.fileSize || 0)} {t("EACH")} ); case ITEM_TYPE.FILE: { diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx index 7e2786c422..e05eacc071 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx @@ -7,8 +7,8 @@ import VideocamOutlined from "@mui/icons-material/VideocamOutlined"; import Box from "@mui/material/Box"; import { useEffect, useState } from "react"; import { EnteFile } from "types/file"; -import { makeHumanReadableStorage } from "utils/units"; import { changeFileName, updateExistingFilePubMetadata } from "utils/file"; +import { formattedBytes } from "utils/units"; import { FileNameEditDialog } from "./FileNameEditDialog"; import InfoItem from "./InfoItem"; @@ -33,7 +33,7 @@ const getCaption = (file: EnteFile, parsedExifData) => { captionParts.push(resolution); } if (fileSize) { - captionParts.push(makeHumanReadableStorage(fileSize)); + captionParts.push(formattedBytes(fileSize)); } return ( diff --git a/web/apps/photos/src/utils/units.ts b/web/apps/photos/src/utils/units.ts index 20a90e4c29..79add3b827 100644 --- a/web/apps/photos/src/utils/units.ts +++ b/web/apps/photos/src/utils/units.ts @@ -13,10 +13,16 @@ const ONE_GB = 1024 * 1024 * 1024; export const bytesInGB = (bytes: number, precision = 0): string => (bytes / (1024 * 1024 * 1024)).toFixed(precision); -export function convertBytesToHumanReadable( - bytes: number, - precision = 2, -): string { +/** + * Convert the given number of {@link bytes} to a user visible string in an + * appropriately sized unit. + * + * The returned string includes the (localized) unit suffix, e.g. "TB". + * + * @param precision Modify the number of digits after the decimal point. + * Defaults to 2. + */ +export function formattedBytes(bytes: number, precision = 2): string { if (bytes === 0 || isNaN(bytes)) { return "0 MB"; } From 491b814a2e2c9019087a5f4138565636e33b7757 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 7 May 2024 10:45:06 +0530 Subject: [PATCH 4/6] Convert the third one too --- .../src/components/PhotoList/dedupe.tsx | 4 +- .../photos/src/components/PhotoList/index.tsx | 4 +- .../PhotoViewer/FileInfo/RenderFileName.tsx | 4 +- .../individual/usageSection.tsx | 4 +- .../contentOverlay/storageSection.tsx | 6 +-- .../gallery/PlanSelector/plans/BfAddOnRow.tsx | 4 +- web/apps/photos/src/utils/units.ts | 42 ++++++++++++++----- 7 files changed, 45 insertions(+), 23 deletions(-) diff --git a/web/apps/photos/src/components/PhotoList/dedupe.tsx b/web/apps/photos/src/components/PhotoList/dedupe.tsx index b911fad372..61b9958ef0 100644 --- a/web/apps/photos/src/components/PhotoList/dedupe.tsx +++ b/web/apps/photos/src/components/PhotoList/dedupe.tsx @@ -19,7 +19,7 @@ import { } from "react-window"; import { Duplicate } from "services/deduplicationService"; import { EnteFile } from "types/file"; -import { formattedBytes } from "utils/units"; +import { formattedByteSize } from "utils/units"; export enum ITEM_TYPE { TIME = "TIME", @@ -310,7 +310,7 @@ export function DedupePhotoList({ */ {listItem.fileCount} {t("FILES")},{" "} - {formattedBytes(listItem.fileSize || 0)} {t("EACH")} + {formattedByteSize(listItem.fileSize || 0)} {t("EACH")} ); case ITEM_TYPE.FILE: { diff --git a/web/apps/photos/src/components/PhotoList/index.tsx b/web/apps/photos/src/components/PhotoList/index.tsx index f052e4b358..5ac6b263ed 100644 --- a/web/apps/photos/src/components/PhotoList/index.tsx +++ b/web/apps/photos/src/components/PhotoList/index.tsx @@ -24,7 +24,7 @@ import { import { EnteFile } from "types/file"; import { handleSelectCreator } from "utils/photoFrame"; import { PublicCollectionGalleryContext } from "utils/publicCollectionGallery"; -import { formattedBytes } from "utils/units"; +import { formattedByteSize } from "utils/units"; const A_DAY = 24 * 60 * 60 * 1000; const FOOTER_HEIGHT = 90; @@ -829,7 +829,7 @@ export function PhotoList({ return ( {listItem.fileCount} {t("FILES")},{" "} - {formattedBytes(listItem.fileSize || 0)} {t("EACH")} + {formattedByteSize(listItem.fileSize || 0)} {t("EACH")} ); case ITEM_TYPE.FILE: { diff --git a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx index e05eacc071..e9e27d55e8 100644 --- a/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx +++ b/web/apps/photos/src/components/PhotoViewer/FileInfo/RenderFileName.tsx @@ -8,7 +8,7 @@ import Box from "@mui/material/Box"; import { useEffect, useState } from "react"; import { EnteFile } from "types/file"; import { changeFileName, updateExistingFilePubMetadata } from "utils/file"; -import { formattedBytes } from "utils/units"; +import { formattedByteSize } from "utils/units"; import { FileNameEditDialog } from "./FileNameEditDialog"; import InfoItem from "./InfoItem"; @@ -33,7 +33,7 @@ const getCaption = (file: EnteFile, parsedExifData) => { captionParts.push(resolution); } if (fileSize) { - captionParts.push(formattedBytes(fileSize)); + captionParts.push(formattedByteSize(fileSize)); } return ( diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx index 2acfc2e766..8975941ad5 100644 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx +++ b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/individual/usageSection.tsx @@ -1,7 +1,7 @@ import { SpaceBetweenFlex } from "@ente/shared/components/Container"; import { Box, Typography } from "@mui/material"; import { t } from "i18next"; -import { makeHumanReadableStorage } from "utils/units"; +import { formattedStorageByteSize } from "utils/units"; import { Progressbar } from "../../styledComponents"; @@ -19,7 +19,7 @@ export function IndividualUsageSection({ usage, storage, fileCount }: Iprops) { marginTop: 1.5, }} > - {`${makeHumanReadableStorage( + {`${formattedStorageByteSize( storage - usage, )} ${t("FREE")}`} diff --git a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx index 90705753b9..78a3677972 100644 --- a/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx +++ b/web/apps/photos/src/components/Sidebar/SubscriptionCard/contentOverlay/storageSection.tsx @@ -1,6 +1,6 @@ import { Box, styled, Typography } from "@mui/material"; import { t } from "i18next"; -import { bytesInGB, makeHumanReadableStorage } from "utils/units"; +import { bytesInGB, formattedStorageByteSize } from "utils/units"; const MobileSmallBox = styled(Box)` display: none; @@ -30,9 +30,9 @@ export default function StorageSection({ usage, storage }: Iprops) { fontWeight={"bold"} sx={{ fontSize: "24px", lineHeight: "30px" }} > - {`${makeHumanReadableStorage(usage, { roundUp: true })} ${t( + {`${formattedStorageByteSize(usage, { round: true })} ${t( "OF", - )} ${makeHumanReadableStorage(storage)} ${t("USED")}`} + )} ${formattedStorageByteSize(storage)} ${t("USED")}`} diff --git a/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx b/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx index aed1fba47e..5f7e13deb8 100644 --- a/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx +++ b/web/apps/photos/src/components/pages/gallery/PlanSelector/plans/BfAddOnRow.tsx @@ -2,7 +2,7 @@ import { SpaceBetweenFlex } from "@ente/shared/components/Container"; import { Box, styled, Typography } from "@mui/material"; import { Trans } from "react-i18next"; -import { makeHumanReadableStorage } from "utils/units"; +import { formattedStorageByteSize } from "utils/units"; const RowContainer = styled(SpaceBetweenFlex)(({ theme }) => ({ // gap: theme.spacing(1.5), @@ -24,7 +24,7 @@ export function BFAddOnRow({ bonusData, closeModal }) { (bytes / (1024 * 1024 * 1024)).toFixed(precision); @@ -22,7 +20,7 @@ export const bytesInGB = (bytes: number, precision = 0): string => * @param precision Modify the number of digits after the decimal point. * Defaults to 2. */ -export function formattedBytes(bytes: number, precision = 2): string { +export function formattedByteSize(bytes: number, precision = 2): string { if (bytes === 0 || isNaN(bytes)) { return "0 MB"; } @@ -32,10 +30,34 @@ export function formattedBytes(bytes: number, precision = 2): string { return (bytes / Math.pow(1024, i)).toFixed(precision) + " " + sizes[i]; } -export function makeHumanReadableStorage( +interface FormattedStorageByteSizeOptions { + /** + * If `true` then round up the fractional quantity we obtain when dividing + * the number of bytes by the number of bytes in the unit that got chosen. + * + * The default behaviour is to take the ceiling. + */ + round?: boolean; +} + +/** + * Convert the given number of storage {@link bytes} to a user visible string in + * an appropriately sized unit. + * + * This differs from {@link formattedByteSize} in that while + * {@link formattedByteSize} is meant for arbitrary byte sizes, this function + * has a few additional beautification heuristics that we want to apply when + * displaying the "storage size" (in different contexts) as opposed to, say, a + * generic "file size". + * + * @param options + * + * @return A user visible string, including the localized unit suffix. + */ +export const formattedStorageByteSize = ( bytes: number, - { roundUp } = { roundUp: false }, -): string { + options?: FormattedStorageByteSizeOptions, +): string => { if (bytes <= 0) { return `0 ${t("STORAGE_UNITS.MB")}`; } @@ -51,8 +73,8 @@ export function makeHumanReadableStorage( quantity = Number(quantity.toFixed(1)); - if (bytes >= 10 * ONE_GB) { - if (roundUp) { + if (bytes >= 10 * 1024 * 1024 * 1024 /* 10 GB */) { + if (options?.round) { quantity = Math.ceil(quantity); } else { quantity = Math.round(quantity); @@ -60,4 +82,4 @@ export function makeHumanReadableStorage( } return `${quantity} ${t(`STORAGE_UNITS.${unit}`)}`; -} +}; From e9bf6d7171de84ec92b8fa5c97c1586cecd5d58a Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 7 May 2024 11:10:09 +0530 Subject: [PATCH 5/6] Add a new action --- .github/workflows/web-crowdin-update.yml | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/web-crowdin-update.yml diff --git a/.github/workflows/web-crowdin-update.yml b/.github/workflows/web-crowdin-update.yml new file mode 100644 index 0000000000..63a643cfcf --- /dev/null +++ b/.github/workflows/web-crowdin-update.yml @@ -0,0 +1,39 @@ +name: "Update Crowdin translations (web)" + +# This is a variant of web-crowdin.yml that also uploads the translated strings +# (in addition to the source strings). This allows us to change the strings in +# our source code for an automated refactoring (e.g. renaming a key), and then +# run this workflow to update the data in Crowdin taking our source code as the +# source of truth. + +on: + # Only allow running manually. + workflow_dispatch: + +jobs: + synchronize-with-crowdin: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Crowdin's action + uses: crowdin/github-action@v1 + with: + base_path: "web/" + config: "web/crowdin.yml" + upload_sources: true + # This is what differs from web-crowdin.yml + upload_translations: true + download_translations: true + localization_branch_name: translations/web + create_pull_request: true + skip_untranslated_strings: true + pull_request_title: "[web] Updated translations" + pull_request_body: "Updated translations from [Crowdin](https://crowdin.com/project/ente-photos-web)" + pull_request_base_branch_name: "main" + project_id: 569613 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} From 521950075f7dc89983d9ccbafd050f8d10b997bb Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 7 May 2024 11:12:23 +0530 Subject: [PATCH 6/6] yarn lint-fix --- web/apps/cast/src/pages/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/apps/cast/src/pages/index.tsx b/web/apps/cast/src/pages/index.tsx index 00a9fdc72d..bc0f6253db 100644 --- a/web/apps/cast/src/pages/index.tsx +++ b/web/apps/cast/src/pages/index.tsx @@ -83,7 +83,8 @@ export default function Index() { fontWeight: "normal", }} > - Enter this code on Ente Photos to pair this screen + Enter this code on Ente Photos to pair this + screen