diff --git a/web/.prettierignore b/web/.prettierignore index d50a46ce..14652726 100644 --- a/web/.prettierignore +++ b/web/.prettierignore @@ -1,2 +1,3 @@ build/ +dist/ public/static/langs/ diff --git a/web/package.json b/web/package.json index 10c198dc..727e790f 100644 --- a/web/package.json +++ b/web/package.json @@ -45,6 +45,6 @@ ] }, "prettier": { - "printWidth": 160 + "printWidth": 140 } } diff --git a/web/public/index.html b/web/public/index.html index e59a62e3..e8c7f8a6 100644 --- a/web/public/index.html +++ b/web/public/index.html @@ -39,7 +39,8 @@ <body> <noscript> ntfy web requires JavaScript, but you can also use the - <a href="https://ntfy.sh/docs/subscribe/cli/">CLI</a> or <a href="https://ntfy.sh/docs/subscribe/phone/">Android/iOS app</a> to subscribe. + <a href="https://ntfy.sh/docs/subscribe/cli/">CLI</a> or <a href="https://ntfy.sh/docs/subscribe/phone/">Android/iOS app</a> to + subscribe. </noscript> <div id="root"></div> <script src="%PUBLIC_URL%/config.js"></script> diff --git a/web/src/app/Api.js b/web/src/app/Api.js index 4d7ce822..b956e0bd 100644 --- a/web/src/app/Api.js +++ b/web/src/app/Api.js @@ -1,4 +1,12 @@ -import { fetchLinesIterator, maybeWithAuth, topicShortUrl, topicUrl, topicUrlAuth, topicUrlJsonPoll, topicUrlJsonPollWithSince } from "./utils"; +import { + fetchLinesIterator, + maybeWithAuth, + topicShortUrl, + topicUrl, + topicUrlAuth, + topicUrlJsonPoll, + topicUrlJsonPollWithSince, +} from "./utils"; import userManager from "./UserManager"; import { fetchOrThrow } from "./errors"; diff --git a/web/src/app/Connection.js b/web/src/app/Connection.js index 23416787..7b25467c 100644 --- a/web/src/app/Connection.js +++ b/web/src/app/Connection.js @@ -57,7 +57,9 @@ class Connection { }; this.ws.onclose = (event) => { if (event.wasClean) { - console.log(`[Connection, ${this.shortUrl}, ${this.connectionId}] Connection closed cleanly, code=${event.code} reason=${event.reason}`); + console.log( + `[Connection, ${this.shortUrl}, ${this.connectionId}] Connection closed cleanly, code=${event.code} reason=${event.reason}` + ); this.ws = null; } else { const retrySeconds = retryBackoffSeconds[Math.min(this.retryCount, retryBackoffSeconds.length - 1)]; diff --git a/web/src/app/ConnectionManager.js b/web/src/app/ConnectionManager.js index 15b94cd7..f50ed531 100644 --- a/web/src/app/ConnectionManager.js +++ b/web/src/app/ConnectionManager.js @@ -74,7 +74,9 @@ class ConnectionManager { ); this.connections.set(connectionId, connection); console.log( - `[ConnectionManager] Starting new connection ${connectionId} (subscription ${subscriptionId} with user ${user ? user.username : "anonymous"})` + `[ConnectionManager] Starting new connection ${connectionId} (subscription ${subscriptionId} with user ${ + user ? user.username : "anonymous" + })` ); connection.start(); } diff --git a/web/src/app/utils.js b/web/src/app/utils.js index d6bb02d8..88e3684b 100644 --- a/web/src/app/utils.js +++ b/web/src/app/utils.js @@ -10,7 +10,8 @@ import config from "./config"; import { Base64 } from "js-base64"; export const topicUrl = (baseUrl, topic) => `${baseUrl}/${topic}`; -export const topicUrlWs = (baseUrl, topic) => `${topicUrl(baseUrl, topic)}/ws`.replaceAll("https://", "wss://").replaceAll("http://", "ws://"); +export const topicUrlWs = (baseUrl, topic) => + `${topicUrl(baseUrl, topic)}/ws`.replaceAll("https://", "wss://").replaceAll("http://", "ws://"); export const topicUrlJson = (baseUrl, topic) => `${topicUrl(baseUrl, topic)}/json`; export const topicUrlJsonPoll = (baseUrl, topic) => `${topicUrlJson(baseUrl, topic)}?poll=1`; export const topicUrlJsonPollWithSince = (baseUrl, topic, since) => `${topicUrlJson(baseUrl, topic)}?poll=1&since=${since}`; diff --git a/web/src/components/Account.js b/web/src/components/Account.js index b6710c6c..5cb68c13 100644 --- a/web/src/components/Account.js +++ b/web/src/components/Account.js @@ -211,7 +211,10 @@ const ChangePasswordDialog = (props) => { </DialogContent> <DialogFooter status={error}> <Button onClick={props.onClose}>{t("common_cancel")}</Button> - <Button onClick={handleDialogSubmit} disabled={newPassword.length === 0 || currentPassword.length === 0 || newPassword !== confirmPassword}> + <Button + onClick={handleDialogSubmit} + disabled={newPassword.length === 0 || currentPassword.length === 0 || newPassword !== confirmPassword} + > {t("account_basics_password_dialog_button_submit")} </Button> </DialogFooter> @@ -288,7 +291,13 @@ const AccountType = () => { </Tooltip> )} {config.enable_payments && account.role === Role.USER && !account.billing?.subscription && ( - <Button variant="outlined" size="small" startIcon={<CelebrationIcon sx={{ color: "#55b86e" }} />} onClick={handleUpgradeClick} sx={{ ml: 1 }}> + <Button + variant="outlined" + size="small" + startIcon={<CelebrationIcon sx={{ color: "#55b86e" }} />} + onClick={handleUpgradeClick} + sx={{ ml: 1 }} + > {t("account_basics_tier_upgrade_button")} </Button> )} @@ -303,7 +312,11 @@ const AccountType = () => { </Button> )} {config.enable_payments && ( - <UpgradeDialog key={`upgradeDialogFromAccount${upgradeDialogKey}`} open={upgradeDialogOpen} onCancel={() => setUpgradeDialogOpen(false)} /> + <UpgradeDialog + key={`upgradeDialogFromAccount${upgradeDialogKey}`} + open={upgradeDialogOpen} + onCancel={() => setUpgradeDialogOpen(false)} + /> )} </div> {account.billing?.status === SubscriptionStatus.PAST_DUE && ( @@ -574,7 +587,11 @@ const Stats = () => { </div> <LinearProgress variant="determinate" - value={account.role === Role.USER && account.limits.reservations > 0 ? normalize(account.stats.reservations, account.limits.reservations) : 100} + value={ + account.role === Role.USER && account.limits.reservations > 0 + ? normalize(account.stats.reservations, account.limits.reservations) + : 100 + } /> </Pref> )} @@ -602,7 +619,10 @@ const Stats = () => { : t("account_usage_unlimited")} </Typography> </div> - <LinearProgress variant="determinate" value={account.role === Role.USER ? normalize(account.stats.messages, account.limits.messages) : 100} /> + <LinearProgress + variant="determinate" + value={account.role === Role.USER ? normalize(account.stats.messages, account.limits.messages) : 100} + /> </Pref> {config.enable_emails && ( <Pref @@ -629,7 +649,10 @@ const Stats = () => { : t("account_usage_unlimited")} </Typography> </div> - <LinearProgress variant="determinate" value={account.role === Role.USER ? normalize(account.stats.emails, account.limits.emails) : 100} /> + <LinearProgress + variant="determinate" + value={account.role === Role.USER ? normalize(account.stats.emails, account.limits.emails) : 100} + /> </Pref> )} {config.enable_calls && (account.role === Role.ADMIN || account.limits.calls > 0) && ( @@ -833,7 +856,12 @@ const TokensTable = (props) => { <TableBody> {tokens.map((token) => ( <TableRow key={token.token} sx={{ "&:last-child td, &:last-child th": { border: 0 } }}> - <TableCell component="th" scope="row" sx={{ paddingLeft: 0, whiteSpace: "nowrap" }} aria-label={t("account_tokens_table_token_header")}> + <TableCell + component="th" + scope="row" + sx={{ paddingLeft: 0, whiteSpace: "nowrap" }} + aria-label={t("account_tokens_table_token_header")} + > <span> <span style={{ fontFamily: "Monospace", fontSize: "0.9rem" }}>{token.token.slice(0, 12)}</span> ... @@ -893,7 +921,12 @@ const TokensTable = (props) => { ))} </TableBody> <Portal> - <Snackbar open={snackOpen} autoHideDuration={3000} onClose={() => setSnackOpen(false)} message={t("account_tokens_table_copied_to_clipboard")} /> + <Snackbar + open={snackOpen} + autoHideDuration={3000} + onClose={() => setSnackOpen(false)} + message={t("account_tokens_table_copied_to_clipboard")} + /> </Portal> <TokenDialog key={`tokenDialogEdit${upsertDialogKey}`} open={upsertDialogOpen} token={selectedToken} onClose={handleDialogClose} /> <TokenDeleteDialog open={deleteDialogOpen} token={selectedToken} onClose={handleDialogClose} /> @@ -958,7 +991,9 @@ const TokenDialog = (props) => { </DialogContent> <DialogFooter status={error}> <Button onClick={props.onClose}>{t("account_tokens_dialog_button_cancel")}</Button> - <Button onClick={handleSubmit}>{editMode ? t("account_tokens_dialog_button_update") : t("account_tokens_dialog_button_create")}</Button> + <Button onClick={handleSubmit}> + {editMode ? t("account_tokens_dialog_button_update") : t("account_tokens_dialog_button_create")} + </Button> </DialogFooter> </Dialog> ); diff --git a/web/src/components/ActionBar.js b/web/src/components/ActionBar.js index 2d440146..24aef720 100644 --- a/web/src/components/ActionBar.js +++ b/web/src/components/ActionBar.js @@ -98,7 +98,13 @@ const SettingsIcons = (props) => { <IconButton color="inherit" size="large" edge="end" onClick={handleToggleMute} aria-label={t("action_bar_toggle_mute")}> {subscription.mutedUntil ? <NotificationsOffIcon /> : <NotificationsIcon />} </IconButton> - <IconButton color="inherit" size="large" edge="end" onClick={(ev) => setAnchorEl(ev.currentTarget)} aria-label={t("action_bar_toggle_action_menu")}> + <IconButton + color="inherit" + size="large" + edge="end" + onClick={(ev) => setAnchorEl(ev.currentTarget)} + aria-label={t("action_bar_toggle_action_menu")} + > <MoreVertIcon /> </IconButton> <SubscriptionPopup subscription={subscription} anchor={anchorEl} placement="right" onClose={() => setAnchorEl(null)} /> diff --git a/web/src/components/EmojiPicker.js b/web/src/components/EmojiPicker.js index 3f9f4df7..04cc5c72 100644 --- a/web/src/components/EmojiPicker.js +++ b/web/src/components/EmojiPicker.js @@ -99,7 +99,13 @@ const EmojiPicker = (props) => { }} > {Object.keys(emojisByCategory).map((category) => ( - <Category key={category} title={category} emojis={emojisByCategory[category]} search={searchFields} onPick={props.onEmojiPick} /> + <Category + key={category} + title={category} + emojis={emojisByCategory[category]} + search={searchFields} + onPick={props.onEmojiPick} + /> ))} </Box> </Box> diff --git a/web/src/components/ErrorBoundary.js b/web/src/components/ErrorBoundary.js index 29282189..21ee6a92 100644 --- a/web/src/components/ErrorBoundary.js +++ b/web/src/components/ErrorBoundary.js @@ -46,7 +46,9 @@ class ErrorBoundaryImpl extends React.Component { // Fetch additional info and a better stack trace StackTrace.fromError(error).then((stack) => { console.error("[ErrorBoundary] Stacktrace fetched", stack); - const niceStack = `${error.toString()}\n` + stack.map((el) => ` at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})`).join("\n"); + const niceStack = + `${error.toString()}\n` + + stack.map((el) => ` at ${el.functionName} (${el.fileName}:${el.columnNumber}:${el.lineNumber})`).join("\n"); this.setState({ niceStack }); }); } diff --git a/web/src/components/Messaging.js b/web/src/components/Messaging.js index 2fa7ed57..b6ed952b 100644 --- a/web/src/components/Messaging.js +++ b/web/src/components/Messaging.js @@ -29,7 +29,9 @@ const Messaging = (props) => { return ( <> - {subscription && <MessageBar subscription={subscription} message={message} onMessageChange={setMessage} onOpenDialogClick={handleOpenDialogClick} />} + {subscription && ( + <MessageBar subscription={subscription} message={message} onMessageChange={setMessage} onOpenDialogClick={handleOpenDialogClick} /> + )} <PublishDialog key={`publishDialog${dialogKey}`} // Resets dialog when canceled/closed openMode={dialogOpenMode} @@ -95,7 +97,12 @@ const MessageBar = (props) => { <SendIcon /> </IconButton> <Portal> - <Snackbar open={snackOpen} autoHideDuration={3000} onClose={() => setSnackOpen(false)} message={t("message_bar_error_publishing")} /> + <Snackbar + open={snackOpen} + autoHideDuration={3000} + onClose={() => setSnackOpen(false)} + message={t("message_bar_error_publishing")} + /> </Portal> </Paper> ); diff --git a/web/src/components/Navigation.js b/web/src/components/Navigation.js index 922d6fed..1eeb3e83 100644 --- a/web/src/components/Navigation.js +++ b/web/src/components/Navigation.js @@ -108,7 +108,8 @@ const NavList = (props) => { const showNotificationBrowserNotSupportedBox = !notifier.browserSupported(); const showNotificationContextNotSupportedBox = notifier.browserSupported() && !notifier.contextSupported(); // Only show if notifications are generally supported in the browser const showNotificationGrantBox = notifier.supported() && props.subscriptions?.length > 0 && !props.notificationsGranted; - const navListPadding = showNotificationGrantBox || showNotificationBrowserNotSupportedBox || showNotificationContextNotSupportedBox ? "0" : ""; + const navListPadding = + showNotificationGrantBox || showNotificationBrowserNotSupportedBox || showNotificationContextNotSupportedBox ? "0" : ""; return ( <> diff --git a/web/src/components/Notifications.js b/web/src/components/Notifications.js index ad44873f..35fd080b 100644 --- a/web/src/components/Notifications.js +++ b/web/src/components/Notifications.js @@ -115,7 +115,12 @@ const NotificationList = (props) => { {notifications.slice(0, count).map((notification) => ( <NotificationItem key={notification.id} notification={notification} onShowSnack={() => setSnackOpen(true)} /> ))} - <Snackbar open={snackOpen} autoHideDuration={3000} onClose={() => setSnackOpen(false)} message={t("notifications_copied_to_clipboard")} /> + <Snackbar + open={snackOpen} + autoHideDuration={3000} + onClose={() => setSnackOpen(false)} + message={t("notifications_copied_to_clipboard")} + /> </Stack> </Container> </InfiniteScroll> @@ -156,7 +161,11 @@ const NotificationItem = (props) => { </Tooltip> {notification.new === 1 && ( <Tooltip title={t("notifications_mark_read")} enterDelay={500}> - <IconButton onClick={handleMarkRead} sx={{ float: "right", marginRight: -0.5, marginTop: -1 }} aria-label={t("notifications_mark_read")}> + <IconButton + onClick={handleMarkRead} + sx={{ float: "right", marginRight: -0.5, marginTop: -1 }} + aria-label={t("notifications_mark_read")} + > <CheckIcon /> </IconButton> </Tooltip> diff --git a/web/src/components/Preferences.js b/web/src/components/Preferences.js index 3a277013..22252d95 100644 --- a/web/src/components/Preferences.js +++ b/web/src/components/Preferences.js @@ -251,7 +251,14 @@ const Users = () => { </CardContent> <CardActions> <Button onClick={handleAddClick}>{t("prefs_users_add_button")}</Button> - <UserDialog key={`userAddDialog${dialogKey}`} open={dialogOpen} user={null} users={users} onCancel={handleDialogCancel} onSubmit={handleDialogSubmit} /> + <UserDialog + key={`userAddDialog${dialogKey}`} + open={dialogOpen} + user={null} + users={users} + onCancel={handleDialogCancel} + onSubmit={handleDialogSubmit} + /> </CardActions> </Card> ); @@ -449,7 +456,26 @@ const Language = () => { // Country flags are displayed using emoji. Emoji rendering is handled by platform fonts. // Windows in particular does not yet play nicely with flag emoji so for now, hide flags on Windows. - const randomFlags = shuffle(["🇬🇧", "🇺🇸", "🇪🇸", "🇫🇷", "🇧🇬", "🇨🇿", "🇩🇪", "🇵🇱", "🇺🇦", "🇨🇳", "🇮🇹", "ðŸ‡ðŸ‡º", "🇧🇷", "🇳🇱", "🇮🇩", "🇯🇵", "🇷🇺", "🇹🇷"]).slice(0, 3); + const randomFlags = shuffle([ + "🇬🇧", + "🇺🇸", + "🇪🇸", + "🇫🇷", + "🇧🇬", + "🇨🇿", + "🇩🇪", + "🇵🇱", + "🇺🇦", + "🇨🇳", + "🇮🇹", + "ðŸ‡ðŸ‡º", + "🇧🇷", + "🇳🇱", + "🇮🇩", + "🇯🇵", + "🇷🇺", + "🇹🇷", + ]).slice(0, 3); const showFlags = !navigator.userAgent.includes("Windows"); let title = t("prefs_appearance_language_title"); if (showFlags) { @@ -531,7 +557,12 @@ const Reservations = () => { <Button onClick={handleAddClick} disabled={limitReached}> {t("prefs_reservations_add_button")} </Button> - <ReserveAddDialog key={`reservationAddDialog${dialogKey}`} open={dialogOpen} reservations={reservations} onClose={() => setDialogOpen(false)} /> + <ReserveAddDialog + key={`reservationAddDialog${dialogKey}`} + open={dialogOpen} + reservations={reservations} + onClose={() => setDialogOpen(false)} + /> </CardActions> </Card> ); @@ -545,7 +576,9 @@ const ReservationsTable = (props) => { const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const { subscriptions } = useOutletContext(); const localSubscriptions = - subscriptions?.length > 0 ? Object.assign({}, ...subscriptions.filter((s) => s.baseUrl === config.base_url).map((s) => ({ [s.topic]: s }))) : {}; + subscriptions?.length > 0 + ? Object.assign({}, ...subscriptions.filter((s) => s.baseUrl === config.base_url).map((s) => ({ [s.topic]: s }))) + : {}; const handleEditClick = (reservation) => { setDialogKey((prev) => prev + 1); diff --git a/web/src/components/PublishDialog.js b/web/src/components/PublishDialog.js index 7d201034..240b0cc3 100644 --- a/web/src/components/PublishDialog.js +++ b/web/src/components/PublishDialog.js @@ -783,7 +783,12 @@ const AttachmentBox = (props) => { )} </Typography> </Box> - <DialogIconButton disabled={props.disabled} onClick={props.onClose} sx={{ marginLeft: "6px" }} aria-label={t("publish_dialog_attached_file_remove")}> + <DialogIconButton + disabled={props.disabled} + onClick={props.onClose} + sx={{ marginLeft: "6px" }} + aria-label={t("publish_dialog_attached_file_remove")} + > <Close /> </DialogIconButton> </Box> @@ -806,7 +811,13 @@ const ExpandingTextField = (props) => { }, [props.value]); return ( <> - <Typography ref={invisibleFieldRef} component="span" variant={props.variant} aria-hidden={true} sx={{ position: "absolute", left: "-200%" }}> + <Typography + ref={invisibleFieldRef} + component="span" + variant={props.variant} + aria-hidden={true} + sx={{ position: "absolute", left: "-200%" }} + > {props.value} </Typography> <TextField diff --git a/web/src/components/Signup.js b/web/src/components/Signup.js index 37a39287..2f660e3a 100644 --- a/web/src/components/Signup.js +++ b/web/src/components/Signup.js @@ -121,7 +121,13 @@ const Signup = () => { ), }} /> - <Button type="submit" fullWidth variant="contained" disabled={username === "" || password === "" || password !== confirm} sx={{ mt: 2, mb: 2 }}> + <Button + type="submit" + fullWidth + variant="contained" + disabled={username === "" || password === "" || password !== confirm} + sx={{ mt: 2, mb: 2 }} + > {t("signup_form_button_submit")} </Button> {error && ( diff --git a/web/src/components/SubscribeDialog.js b/web/src/components/SubscribeDialog.js index 7be69a6b..47a4ac78 100644 --- a/web/src/components/SubscribeDialog.js +++ b/web/src/components/SubscribeDialog.js @@ -68,7 +68,9 @@ const SubscribePage = (props) => { const baseUrl = anotherServerVisible ? props.baseUrl : config.base_url; const topic = props.topic; const existingTopicUrls = props.subscriptions.map((s) => topicUrl(s.baseUrl, s.topic)); - const existingBaseUrls = Array.from(new Set([publicBaseUrl, ...props.subscriptions.map((s) => s.baseUrl)])).filter((s) => s !== config.base_url); + const existingBaseUrls = Array.from(new Set([publicBaseUrl, ...props.subscriptions.map((s) => s.baseUrl)])).filter( + (s) => s !== config.base_url + ); const showReserveTopicCheckbox = config.enable_reservations && !anotherServerVisible && (config.enable_payments || account); const reserveTopicEnabled = session.exists() && (account?.role === Role.ADMIN || (account?.role === Role.USER && (account?.stats.reservations_remaining || 0) > 0)); @@ -212,7 +214,12 @@ const SubscribePage = (props) => { inputValue={props.baseUrl} onInputChange={updateBaseUrl} renderInput={(params) => ( - <TextField {...params} placeholder={config.base_url} variant="standard" aria-label={t("subscribe_dialog_subscribe_base_url_label")} /> + <TextField + {...params} + placeholder={config.base_url} + variant="standard" + aria-label={t("subscribe_dialog_subscribe_base_url_label")} + /> )} /> )} diff --git a/web/src/components/SubscriptionPopup.js b/web/src/components/SubscriptionPopup.js index 7452b8e7..2675db2f 100644 --- a/web/src/components/SubscriptionPopup.js +++ b/web/src/components/SubscriptionPopup.js @@ -40,7 +40,10 @@ export const SubscriptionPopup = (props) => { const showReservationAdd = config.enable_reservations && !subscription?.reservation && account?.stats.reservations_remaining > 0; const showReservationAddDisabled = - !showReservationAdd && config.enable_reservations && !subscription?.reservation && (config.enable_payments || account?.stats.reservations_remaining === 0); + !showReservationAdd && + config.enable_reservations && + !subscription?.reservation && + (config.enable_payments || account?.stats.reservations_remaining === 0); const showReservationEdit = config.enable_reservations && !!subscription?.reservation; const showReservationDelete = config.enable_reservations && !!subscription?.reservation; @@ -161,10 +164,20 @@ export const SubscriptionPopup = (props) => { <MenuItem onClick={handleUnsubscribe}>{t("action_bar_unsubscribe")}</MenuItem> </PopupMenu> <Portal> - <Snackbar open={showPublishError} autoHideDuration={3000} onClose={() => setShowPublishError(false)} message={t("message_bar_error_publishing")} /> + <Snackbar + open={showPublishError} + autoHideDuration={3000} + onClose={() => setShowPublishError(false)} + message={t("message_bar_error_publishing")} + /> <DisplayNameDialog open={displayNameDialogOpen} subscription={subscription} onClose={() => setDisplayNameDialogOpen(false)} /> {showReservationAdd && ( - <ReserveAddDialog open={reserveAddDialogOpen} topic={subscription.topic} reservations={reservations} onClose={() => setReserveAddDialogOpen(false)} /> + <ReserveAddDialog + open={reserveAddDialogOpen} + topic={subscription.topic} + reservations={reservations} + onClose={() => setReserveAddDialogOpen(false)} + /> )} {showReservationEdit && ( <ReserveEditDialog @@ -175,7 +188,11 @@ export const SubscriptionPopup = (props) => { /> )} {showReservationDelete && ( - <ReserveDeleteDialog open={reserveDeleteDialogOpen} topic={subscription.topic} onClose={() => setReserveDeleteDialogOpen(false)} /> + <ReserveDeleteDialog + open={reserveDeleteDialogOpen} + topic={subscription.topic} + onClose={() => setReserveDeleteDialogOpen(false)} + /> )} </Portal> </> diff --git a/web/src/components/UpgradeDialog.js b/web/src/components/UpgradeDialog.js index 5ebbd7b1..9ff991d4 100644 --- a/web/src/components/UpgradeDialog.js +++ b/web/src/components/UpgradeDialog.js @@ -363,7 +363,9 @@ const TierCard = (props) => { </Feature> )} <Feature> - {t("account_upgrade_dialog_tier_features_attachment_file_size", { filesize: formatBytes(tier.limits.attachment_file_size, 0) })} + {t("account_upgrade_dialog_tier_features_attachment_file_size", { + filesize: formatBytes(tier.limits.attachment_file_size, 0), + })} </Feature> {tier.limits.reservations === 0 && <NoFeature>{t("account_upgrade_dialog_tier_features_no_reservations")}</NoFeature>} {tier.limits.calls === 0 && <NoFeature>{t("account_upgrade_dialog_tier_features_no_calls")}</NoFeature>}