mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-10-15 19:45:42 -04:00
refactor(i18n): share integration status text between web and native
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4 files changed
+30
-46
No files matched your search
@@ -10,7 +10,7 @@ import {
|
||||
SonarrIcon,
|
||||
} from "@/components/settings/icons";
|
||||
import { getServerUrl } from "@/lib/server";
|
||||
import { formatRelativeTime } from "@sofa/i18n/format";
|
||||
import { listStatus, webhookStatus } from "@sofa/i18n/integration-status";
|
||||
|
||||
export interface IntegrationConfig {
|
||||
provider: "plex" | "jellyfin" | "emby" | "sonarr" | "radarr";
|
||||
@@ -24,22 +24,6 @@ export interface IntegrationConfig {
|
||||
setupSteps: string[];
|
||||
}
|
||||
|
||||
function webhookStatus(i18n: I18n, lastEventAt: string | null): string {
|
||||
if (lastEventAt) {
|
||||
const timeAgo = formatRelativeTime(new Date(lastEventAt));
|
||||
return i18n._(msg`Last event ${timeAgo}`);
|
||||
}
|
||||
return i18n._(msg`Ready — nothing received yet`);
|
||||
}
|
||||
|
||||
function listStatus(i18n: I18n, lastEventAt: string | null): string {
|
||||
if (lastEventAt) {
|
||||
const timeAgo = formatRelativeTime(new Date(lastEventAt));
|
||||
return i18n._(msg`Last polled ${timeAgo}`);
|
||||
}
|
||||
return i18n._(msg`Ready — not polled yet`);
|
||||
}
|
||||
|
||||
export function getIntegrationConfigs(i18n: I18n): IntegrationConfig[] {
|
||||
return [
|
||||
{
|
||||
@@ -49,7 +33,7 @@ export function getIntegrationConfigs(i18n: I18n): IntegrationConfig[] {
|
||||
type: "webhook",
|
||||
buildUrl: (token) => `${getServerUrl()}/api/webhooks/${token}`,
|
||||
urlLabel: i18n._(msg`Webhook URL`),
|
||||
connectedStatus: (lastEventAt) => webhookStatus(i18n, lastEventAt),
|
||||
connectedStatus: (lastEventAt) => webhookStatus(lastEventAt, i18n),
|
||||
requirementNote: i18n._(msg`Requires an active Plex Pass subscription.`),
|
||||
setupSteps: [
|
||||
i18n._(msg`Open Plex, go to Settings > Webhooks`),
|
||||
@@ -64,7 +48,7 @@ export function getIntegrationConfigs(i18n: I18n): IntegrationConfig[] {
|
||||
type: "webhook",
|
||||
buildUrl: (token) => `${getServerUrl()}/api/webhooks/${token}`,
|
||||
urlLabel: i18n._(msg`Webhook URL`),
|
||||
connectedStatus: (lastEventAt) => webhookStatus(i18n, lastEventAt),
|
||||
connectedStatus: (lastEventAt) => webhookStatus(lastEventAt, i18n),
|
||||
setupSteps: [
|
||||
i18n._(msg`Install the Webhook plugin from Jellyfin's plugin catalog`),
|
||||
i18n._(msg`Go to Dashboard > Plugins > Webhook`),
|
||||
@@ -80,7 +64,7 @@ export function getIntegrationConfigs(i18n: I18n): IntegrationConfig[] {
|
||||
type: "webhook",
|
||||
buildUrl: (token) => `${getServerUrl()}/api/webhooks/${token}`,
|
||||
urlLabel: i18n._(msg`Webhook URL`),
|
||||
connectedStatus: (lastEventAt) => webhookStatus(i18n, lastEventAt),
|
||||
connectedStatus: (lastEventAt) => webhookStatus(lastEventAt, i18n),
|
||||
requirementNote: i18n._(
|
||||
msg`Requires Emby Server 4.7.9+ and an active Emby Premiere license.`,
|
||||
),
|
||||
@@ -98,7 +82,7 @@ export function getIntegrationConfigs(i18n: I18n): IntegrationConfig[] {
|
||||
type: "list",
|
||||
buildUrl: (token) => `${getServerUrl()}/api/lists/${token}`,
|
||||
urlLabel: i18n._(msg`Sonarr List URL`),
|
||||
connectedStatus: (lastEventAt) => listStatus(i18n, lastEventAt),
|
||||
connectedStatus: (lastEventAt) => listStatus(lastEventAt, i18n),
|
||||
setupSteps: [
|
||||
i18n._(msg`Open Sonarr, go to Settings > Import Lists`),
|
||||
i18n._(msg`Click "+" and select "Custom Lists"`),
|
||||
@@ -116,7 +100,7 @@ export function getIntegrationConfigs(i18n: I18n): IntegrationConfig[] {
|
||||
type: "list",
|
||||
buildUrl: (token) => `${getServerUrl()}/api/lists/${token}`,
|
||||
urlLabel: i18n._(msg`Radarr List URL`),
|
||||
connectedStatus: (lastEventAt) => listStatus(i18n, lastEventAt),
|
||||
connectedStatus: (lastEventAt) => listStatus(lastEventAt, i18n),
|
||||
setupSteps: [
|
||||
i18n._(msg`Open Radarr, go to Settings > Import Lists`),
|
||||
i18n._(msg`Click "+" and select "Custom Lists"`),
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { msg } from "@lingui/core/macro";
|
||||
import { Trans, useLingui } from "@lingui/react/macro";
|
||||
import {
|
||||
IconBook2,
|
||||
@@ -27,8 +26,6 @@ import {
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { orpc } from "@/lib/orpc/client";
|
||||
import { i18n } from "@sofa/i18n";
|
||||
import { formatRelativeTime } from "@sofa/i18n/format";
|
||||
|
||||
// ─── Types ──────────────────────────────────────────────────────────
|
||||
|
||||
@@ -280,23 +277,3 @@ export function IntegrationCard({
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
// ─── Helpers for config authoring ───────────────────────────────────
|
||||
|
||||
/** Status line for webhook integrations (shows last event time). */
|
||||
export function webhookStatus(lastEventAt: string | null): string {
|
||||
if (lastEventAt) {
|
||||
const relativeTime = formatRelativeTime(lastEventAt);
|
||||
return i18n._(msg`Last event ${relativeTime}`);
|
||||
}
|
||||
return i18n._(msg`Ready — nothing received yet`);
|
||||
}
|
||||
|
||||
/** Status line for list integrations (shows last event time). */
|
||||
export function listStatus(lastEventAt: string | null): string {
|
||||
if (lastEventAt) {
|
||||
const relativeTime = formatRelativeTime(lastEventAt);
|
||||
return i18n._(msg`Last polled ${relativeTime}`);
|
||||
}
|
||||
return i18n._(msg`Ready — not polled yet`);
|
||||
}
|
||||
@@ -2,10 +2,10 @@ import { Trans } from "@lingui/react/macro";
|
||||
import { IconExternalLink, IconInfoCircle } from "@tabler/icons-react";
|
||||
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
import { listStatus, webhookStatus } from "@sofa/i18n/integration-status";
|
||||
|
||||
import { EmbyIcon, JellyfinIcon, PlexIcon, RadarrIcon, SonarrIcon } from "./icons";
|
||||
import type { IntegrationConfig } from "./integration-card";
|
||||
import { listStatus, webhookStatus } from "./integration-card";
|
||||
|
||||
function origin() {
|
||||
return typeof window !== "undefined" ? window.location.origin : "";
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { I18n } from "@lingui/core";
|
||||
import { msg } from "@lingui/core/macro";
|
||||
|
||||
import { formatRelativeTime } from "./format";
|
||||
import { i18n as defaultI18n } from "./index";
|
||||
|
||||
/** Status line for webhook integrations (last event time). */
|
||||
export function webhookStatus(lastEventAt: string | null, i18n: I18n = defaultI18n): string {
|
||||
if (lastEventAt) {
|
||||
const relativeTime = formatRelativeTime(lastEventAt);
|
||||
return i18n._(msg`Last event ${relativeTime}`);
|
||||
}
|
||||
return i18n._(msg`Ready — nothing received yet`);
|
||||
}
|
||||
|
||||
/** Status line for list integrations (last poll time). */
|
||||
export function listStatus(lastEventAt: string | null, i18n: I18n = defaultI18n): string {
|
||||
if (lastEventAt) {
|
||||
const relativeTime = formatRelativeTime(lastEventAt);
|
||||
return i18n._(msg`Last polled ${relativeTime}`);
|
||||
}
|
||||
return i18n._(msg`Ready — not polled yet`);
|
||||
}
|
||||
Reference in new issue
Block a user