mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
fix(self-hosting): use instance contacts and live product name (#3333)
This commit is contained in:
1 parent
454fefdb92
commit
a5c1362f4a
308 files changed
+16533
-13512
No files matched your search
@@ -33,7 +33,7 @@ function snapshot(branding: Partial<Branding>, origin = 'https://chat.example.or
|
||||
...branding,
|
||||
},
|
||||
setup: {configured: true, admin_url: null},
|
||||
legal: {terms_url: null, privacy_url: null},
|
||||
legal: {terms_url: null, privacy_url: null, guidelines_url: null},
|
||||
registration: {collect_date_of_birth: false},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {GenericErrorModal} from '@app/features/app/components/alerts/GenericErrorModal';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
@@ -17,12 +18,22 @@ const YOUR_ACTION_COULD_NOT_BE_COMPLETED_BECAUSE_IT_DESCRIPTOR = msg({
|
||||
comment:
|
||||
'Modal body shown when the safety system blocks the requested action. Keep plain and calm; offer support path.',
|
||||
});
|
||||
const YOUR_ACTION_COULD_NOT_BE_COMPLETED_SELF_HOSTED_DESCRIPTOR = msg({
|
||||
message:
|
||||
'Your action could not be completed because it was flagged by our safety systems. If you believe this is a mistake, please contact the administrators of this instance.',
|
||||
comment:
|
||||
'Modal body shown on a self-hosted instance when the safety system blocks the requested action. Keep plain and calm.',
|
||||
});
|
||||
const ContentBlockedModal = observer(() => {
|
||||
const {i18n} = useLingui();
|
||||
return (
|
||||
<GenericErrorModal
|
||||
title={i18n._(CONTENT_BLOCKED_DESCRIPTOR)}
|
||||
message={i18n._(YOUR_ACTION_COULD_NOT_BE_COMPLETED_BECAUSE_IT_DESCRIPTOR)}
|
||||
message={i18n._(
|
||||
RuntimeConfig.isSelfHosted()
|
||||
? YOUR_ACTION_COULD_NOT_BE_COMPLETED_SELF_HOSTED_DESCRIPTOR
|
||||
: YOUR_ACTION_COULD_NOT_BE_COMPLETED_BECAUSE_IT_DESCRIPTOR,
|
||||
)}
|
||||
data-flx="auth.content-blocked-handler.content-blocked-modal.confirm-modal"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -294,10 +294,18 @@ const SudoVerificationModal: React.FC = observer(() => {
|
||||
className={styles.unavailableBody}
|
||||
data-flx="auth.sudo-verification-modal.unavailable-body"
|
||||
>
|
||||
<Trans>
|
||||
Your account requires multi-factor authentication, but no supported methods are set up on this
|
||||
device. Sign in on a device with your authenticator app or security key, or contact support.
|
||||
</Trans>
|
||||
{RuntimeConfig.isSelfHosted() ? (
|
||||
<Trans>
|
||||
Your account requires multi-factor authentication, but no supported methods are set up on this
|
||||
device. Sign in on a device with your authenticator app or security key, or contact the
|
||||
administrators of this instance.
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
Your account requires multi-factor authentication, but no supported methods are set up on this
|
||||
device. Sign in on a device with your authenticator app or security key, or contact support.
|
||||
</Trans>
|
||||
)}
|
||||
</Modal.Description>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {Routes} from '@app/app/Routes';
|
||||
import * as Modal from '@app/features/app/components/dialogs/Modal';
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
import {CLOSE_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
||||
import {acceptTerms} from '@app/features/terms/commands/TermsAcceptanceCommands';
|
||||
import {remFromPx} from '@app/features/theme/layout/RemFromPx';
|
||||
@@ -72,7 +72,7 @@ export const TermsAcceptanceModal = observer(() => {
|
||||
const kind = getUpdateKind(user.termsAgreedAt, user.privacyAgreedAt);
|
||||
const termsUrl = Routes.terms();
|
||||
const privacyUrl = Routes.privacy();
|
||||
const productName = PRODUCT_NAME;
|
||||
const productName = RuntimeConfig.productName;
|
||||
return (
|
||||
<Modal.Root
|
||||
size="small"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
import * as AuthenticationCommands from '@app/features/auth/commands/AuthenticationCommands';
|
||||
import styles from '@app/features/auth/components/pages/LoginPage.module.css';
|
||||
import {useAuthSingleUseRequest} from '@app/features/auth/flow/AuthSingleUseRequest';
|
||||
@@ -267,7 +267,7 @@ const SsoCallbackPage = observer(function SsoCallbackPage() {
|
||||
className={styles.ssoRetryButton}
|
||||
data-flx="auth.sso-callback-page.sso-open-app-button"
|
||||
>
|
||||
{i18n._(OPEN_PRODUCT_DESCRIPTOR, {productName: PRODUCT_NAME})}
|
||||
{i18n._(OPEN_PRODUCT_DESCRIPTOR, {productName: RuntimeConfig.productName})}
|
||||
</a>
|
||||
</flx-auth-sso-callback-page-actions>
|
||||
</flx-auth-sso-callback-page>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {Routes} from '@app/app/Routes';
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import {detectDomainMigrationInstallKind} from '@app/features/app/domain_migration/DomainMigrationBrowser';
|
||||
import type {RuntimeConfigSnapshot} from '@app/features/app/state/InstanceSnapshotStore';
|
||||
import {describeAPIEndpoint, type InstanceSsoConfig} from '@app/features/app/state/RuntimeConfig';
|
||||
import RuntimeConfig, {describeAPIEndpoint, type InstanceSsoConfig} from '@app/features/app/state/RuntimeConfig';
|
||||
import {
|
||||
FORGOT_YOUR_PASSWORD_DESCRIPTOR,
|
||||
SIGN_IN_WITH_BROWSER_DESCRIPTOR,
|
||||
@@ -860,10 +859,10 @@ export const AuthLoginLayout = observer(function AuthLoginLayout({
|
||||
type="button"
|
||||
data-flx="auth.flow.auth-login-layout.button.old-app-sign-in"
|
||||
>
|
||||
{i18n._(SIGN_IN_WITH_OLD_APP_DESCRIPTOR, {productName: PRODUCT_NAME})}
|
||||
{i18n._(SIGN_IN_WITH_OLD_APP_DESCRIPTOR, {productName: RuntimeConfig.productName})}
|
||||
</Button>
|
||||
<div className={styles.ssoSubtitle} data-flx="auth.flow.auth-login-layout.old-app-subtitle">
|
||||
{i18n._(OLD_APP_SIGN_IN_HINT_DESCRIPTOR, {productName: PRODUCT_NAME})}
|
||||
{i18n._(OLD_APP_SIGN_IN_HINT_DESCRIPTOR, {productName: RuntimeConfig.productName})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
import styles from '@app/features/auth/flow/AuthPageStyles.module.css';
|
||||
import type {LoadableErrorProps} from '@app/features/platform/components/loadable/LoadableComponent';
|
||||
import {Button} from '@app/features/ui/button/Button';
|
||||
@@ -15,7 +15,7 @@ export function AuthRouteLoadError({retry}: LoadableErrorProps): React.JSX.Eleme
|
||||
<Trans>Could not load this page</Trans>
|
||||
</div>
|
||||
<div className={styles.errorText} data-flx="auth.flow.auth-route-load-error.text">
|
||||
<Trans>Try again, or refresh {ph({productName: PRODUCT_NAME})} if the problem continues.</Trans>
|
||||
<Trans>Try again, or refresh {ph({productName: RuntimeConfig.productName})} if the problem continues.</Trans>
|
||||
</div>
|
||||
<div className={styles.disabledActions} data-flx="auth.flow.auth-route-load-error.actions">
|
||||
<Button onClick={retry} fitContainer data-flx="auth.flow.auth-route-load-error.retry">
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import * as Modal from '@app/features/app/components/dialogs/Modal';
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
import * as AuthenticationCommands from '@app/features/auth/commands/AuthenticationCommands';
|
||||
import styles from '@app/features/auth/flow/BrowserLoginHandoffModal.module.css';
|
||||
@@ -14,7 +13,7 @@ import * as ModalCommands from '@app/features/ui/commands/ModalCommands';
|
||||
import {modal} from '@app/features/ui/commands/ModalCommands';
|
||||
import {openExternalUrl} from '@app/features/ui/utils/NativeUtils';
|
||||
import * as FormUtils from '@app/lib/forms';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
import {msg, ph} from '@lingui/core/macro';
|
||||
import {Trans, useLingui} from '@lingui/react/macro';
|
||||
import {ArrowSquareOutIcon} from '@phosphor-icons/react';
|
||||
import {observer} from 'mobx-react-lite';
|
||||
@@ -123,7 +122,7 @@ const BrowserLoginHandoffModal = observer(({onSuccess, prefillLogin, variant}: B
|
||||
<Modal.Header
|
||||
title={
|
||||
isOldAppVariant
|
||||
? i18n._(SIGN_IN_WITH_OLD_APP_DESCRIPTOR, {productName: PRODUCT_NAME})
|
||||
? i18n._(SIGN_IN_WITH_OLD_APP_DESCRIPTOR, {productName: RuntimeConfig.productName})
|
||||
: i18n._(ADD_ACCOUNT_DESCRIPTOR)
|
||||
}
|
||||
data-flx="auth.flow.browser-login-handoff-modal.modal-header"
|
||||
@@ -132,7 +131,10 @@ const BrowserLoginHandoffModal = observer(({onSuccess, prefillLogin, variant}: B
|
||||
<Modal.ContentLayout className={styles.content} data-flx="auth.flow.browser-login-handoff-modal.content">
|
||||
<Modal.Description data-flx="auth.flow.browser-login-handoff-modal.description">
|
||||
{isOldAppVariant ? (
|
||||
<Trans>Open your old {PRODUCT_NAME} app and choose Link a new device, then enter the code below.</Trans>
|
||||
<Trans>
|
||||
Open your old {ph({PRODUCT_NAME: RuntimeConfig.productName})} app and choose Link a new device, then
|
||||
enter the code below.
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>Open your browser, sign in, then enter the code below to link your account.</Trans>
|
||||
)}
|
||||
@@ -145,7 +147,9 @@ const BrowserLoginHandoffModal = observer(({onSuccess, prefillLogin, variant}: B
|
||||
onRetry={generateCode}
|
||||
description={
|
||||
isOldAppVariant ? (
|
||||
<Trans>Enter this code in your old {PRODUCT_NAME} app to complete sign-in.</Trans>
|
||||
<Trans>
|
||||
Enter this code in your old {ph({PRODUCT_NAME: RuntimeConfig.productName})} app to complete sign-in.
|
||||
</Trans>
|
||||
) : undefined
|
||||
}
|
||||
data-flx="auth.flow.browser-login-handoff-modal.handoff-code-display"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {Routes} from '@app/app/Routes';
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
import styles from '@app/features/auth/flow/DesktopDeepLinkPrompt.module.css';
|
||||
import {Platform} from '@app/features/platform/types/Platform';
|
||||
import {remFromPx} from '@app/features/theme/layout/RemFromPx';
|
||||
@@ -64,7 +64,7 @@ export const DesktopDeepLinkPrompt: React.FC<DesktopDeepLinkPromptProps> = ({cod
|
||||
<div className={styles.banner} data-flx="auth.flow.desktop-deep-link-prompt.banner">
|
||||
<div className={styles.copy} data-flx="auth.flow.desktop-deep-link-prompt.copy">
|
||||
<p className={styles.title} data-flx="auth.flow.desktop-deep-link-prompt.title">
|
||||
{i18n._(OPEN_IN_DESKTOP_PRODUCT_DESCRIPTOR, {productName: PRODUCT_NAME})}
|
||||
{i18n._(OPEN_IN_DESKTOP_PRODUCT_DESCRIPTOR, {productName: RuntimeConfig.productName})}
|
||||
</p>
|
||||
{error ? (
|
||||
<p className={styles.notInstalled} data-flx="auth.flow.desktop-deep-link-prompt.not-installed">
|
||||
@@ -89,7 +89,7 @@ export const DesktopDeepLinkPrompt: React.FC<DesktopDeepLinkPromptProps> = ({cod
|
||||
data-flx="auth.flow.desktop-deep-link-prompt.arrow-square-out-icon"
|
||||
/>
|
||||
<span data-flx="auth.flow.desktop-deep-link-prompt.span">
|
||||
{i18n._(OPEN_PRODUCT_DESCRIPTOR, {productName: PRODUCT_NAME})}
|
||||
{i18n._(OPEN_PRODUCT_DESCRIPTOR, {productName: RuntimeConfig.productName})}
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import styles from '@app/features/app/components/ErrorFallback.module.css';
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import {Endpoints} from '@app/features/app/constants/Endpoints';
|
||||
import type {DomainMigrationSide} from '@app/features/app/domain_migration/DomainMigrationCore';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
import {
|
||||
readPasskeyBridgePageLoginReturnPath,
|
||||
readPasskeyBridgeReturn,
|
||||
@@ -183,7 +183,7 @@ const LegacyPasskeyBridgePage: React.FC<PasskeyBridgePageProps> = ({side, hash,
|
||||
<div className={styles.errorFallbackActions} data-flx="auth.passkey-bridge-page.actions">
|
||||
{expired ? (
|
||||
<Button onClick={handleBack} autoFocus data-flx="auth.passkey-bridge-page.button.back">
|
||||
{i18n._(BACK_TO_PRODUCT_DESCRIPTOR, {productName: PRODUCT_NAME})}
|
||||
{i18n._(BACK_TO_PRODUCT_DESCRIPTOR, {productName: RuntimeConfig.productName})}
|
||||
</Button>
|
||||
) : failed ? (
|
||||
<>
|
||||
@@ -258,7 +258,7 @@ const TargetPasskeyBridgePage: React.FC<{hash: string}> = ({hash}) => {
|
||||
{i18n._(YOU_CAN_CLOSE_THIS_TAB_DESCRIPTOR)}
|
||||
</h1>
|
||||
<p className={styles.errorFallbackDescription} data-flx="auth.passkey-bridge-page.description">
|
||||
{i18n._(GO_BACK_TO_CONTINUE_DESCRIPTOR, {productName: PRODUCT_NAME})}
|
||||
{i18n._(GO_BACK_TO_CONTINUE_DESCRIPTOR, {productName: RuntimeConfig.productName})}
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {ConfirmModal} from '@app/features/app/components/dialogs/ConfirmModal';
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import type {DomainMigrationMediaDeviceKind} from '@app/features/app/domain_migration/DomainMigrationCore';
|
||||
import {remapMigratedDeviceIds} from '@app/features/app/domain_migration/DomainMigrationDeviceRemap';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
import styles from '@app/features/auth/state/NewDeviceMonitoring.module.css';
|
||||
import {
|
||||
getNewDevicePromptCandidates,
|
||||
@@ -18,7 +18,7 @@ import VoiceDevicePermissionState from '@app/features/voice/engine/VoiceDevicePe
|
||||
import VoiceSettings from '@app/features/voice/state/VoiceSettings';
|
||||
import type {VoiceDeviceState} from '@app/features/voice/utils/VoiceDeviceManager';
|
||||
import type {I18n} from '@lingui/core';
|
||||
import {msg} from '@lingui/core/macro';
|
||||
import {msg, ph} from '@lingui/core/macro';
|
||||
import {Trans} from '@lingui/react/macro';
|
||||
import {makeAutoObservable, runInAction} from 'mobx';
|
||||
import type React from 'react';
|
||||
@@ -195,18 +195,18 @@ class NewDeviceMonitoring {
|
||||
description={
|
||||
deviceType === 'input' ? (
|
||||
<Trans>
|
||||
{PRODUCT_NAME} has found a new audio input device named{' '}
|
||||
{ph({PRODUCT_NAME: RuntimeConfig.productName})} has found a new audio input device named{' '}
|
||||
<strong data-flx="auth.new-device-monitoring.strong">{deviceName}</strong>. Do you want to switch to it?
|
||||
</Trans>
|
||||
) : deviceType === 'output' ? (
|
||||
<Trans>
|
||||
{PRODUCT_NAME} has found a new audio output device named{' '}
|
||||
{ph({PRODUCT_NAME: RuntimeConfig.productName})} has found a new audio output device named{' '}
|
||||
<strong data-flx="auth.new-device-monitoring.strong--2">{deviceName}</strong>. Do you want to switch to
|
||||
it?
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
{PRODUCT_NAME} has found a new audio device named{' '}
|
||||
{ph({PRODUCT_NAME: RuntimeConfig.productName})} has found a new audio device named{' '}
|
||||
<strong data-flx="auth.new-device-monitoring.strong--3">{deviceName}</strong>. Do you want to switch to
|
||||
it?
|
||||
</Trans>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {PRODUCT_NAME} from '@app/features/app/config/I18nDisplayConstants';
|
||||
import RuntimeConfig from '@app/features/app/state/RuntimeConfig';
|
||||
|
||||
const TOTP_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
|
||||
const getRandomBytes = (length = 20): Uint8Array => {
|
||||
@@ -34,7 +34,7 @@ export function encodeTotpSecret(secret: string) {
|
||||
return secret.replace(/[\s._-]+/g, '').toUpperCase();
|
||||
}
|
||||
|
||||
export function encodeTotpSecretAsURL(accountName: string, secret: string, issuer = PRODUCT_NAME) {
|
||||
export function encodeTotpSecretAsURL(accountName: string, secret: string, issuer = RuntimeConfig.productName) {
|
||||
const url = new URL('otpauth://totp');
|
||||
url.pathname = `/${encodeURIComponent(issuer)}:${encodeURIComponent(accountName)}`;
|
||||
url.searchParams.set('secret', encodeTotpSecret(secret));
|
||||
|
||||
Reference in new issue
Block a user