feat(ui): add GitLab connect settings
This commit is contained in:
@@ -20,6 +20,7 @@ import { useGitIdentitiesStore, type GitIdentityProfile, type DiscoveredGitCrede
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { GitSettings } from '@/components/sections/openchamber/GitSettings';
|
||||
import { GitHubSettings } from '@/components/sections/openchamber/GitHubSettings';
|
||||
import { GitLabSettings } from '@/components/sections/openchamber/GitLabSettings';
|
||||
import { GitIdentityEditorDialog } from './GitIdentityEditorDialog';
|
||||
import { Icon } from "@/components/icon/Icon";
|
||||
import type { IconName } from "@/components/icon/icons";
|
||||
@@ -122,6 +123,7 @@ export const GitPage: React.FC = () => {
|
||||
showSaveStatus
|
||||
>
|
||||
<GitHubSettings />
|
||||
<GitLabSettings />
|
||||
|
||||
<SettingsSection
|
||||
title={t('settings.gitIdentities.page.section.title')}
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { toast } from '@/components/ui';
|
||||
import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
|
||||
import { useGitLabAuthStore } from '@/stores/useGitLabAuthStore';
|
||||
import type { GitLabAuthStatus } from '@/lib/api/types';
|
||||
import { useDeviceInfo } from '@/lib/device';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { runtimeFetch } from '@/lib/runtime-fetch';
|
||||
import { Icon } from '@/components/icon/Icon';
|
||||
import { SettingsSection } from '@/components/sections/shared/SettingsSection';
|
||||
|
||||
const getBaseUrlHost = (baseUrl?: string | null): string => {
|
||||
if (!baseUrl) return '';
|
||||
try {
|
||||
return new URL(baseUrl).host;
|
||||
} catch {
|
||||
return baseUrl;
|
||||
}
|
||||
};
|
||||
|
||||
export const GitLabSettings: React.FC = () => {
|
||||
const { t } = useI18n();
|
||||
const { isMobile } = useDeviceInfo();
|
||||
const runtimeGitLab = getRegisteredRuntimeAPIs()?.gitlab;
|
||||
const status = useGitLabAuthStore((state) => state.status);
|
||||
const isLoading = useGitLabAuthStore((state) => state.isLoading);
|
||||
const hasChecked = useGitLabAuthStore((state) => state.hasChecked);
|
||||
const refreshStatus = useGitLabAuthStore((state) => state.refreshStatus);
|
||||
const setStatus = useGitLabAuthStore((state) => state.setStatus);
|
||||
|
||||
const [isBusy, setIsBusy] = React.useState(false);
|
||||
const [accessToken, setAccessToken] = React.useState('');
|
||||
const [baseUrl, setBaseUrl] = React.useState('');
|
||||
|
||||
React.useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
if (!hasChecked) {
|
||||
await refreshStatus(runtimeGitLab);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load GitLab auth status:', error);
|
||||
}
|
||||
})();
|
||||
}, [hasChecked, refreshStatus, runtimeGitLab]);
|
||||
|
||||
const connect = React.useCallback(async () => {
|
||||
const trimmedToken = accessToken.trim();
|
||||
if (!trimmedToken) {
|
||||
toast.error(t('settings.gitlab.page.errors.invalidToken'));
|
||||
return;
|
||||
}
|
||||
const trimmedBaseUrl = baseUrl.trim() || undefined;
|
||||
setIsBusy(true);
|
||||
try {
|
||||
const payload = runtimeGitLab
|
||||
? await runtimeGitLab.authConnect({ accessToken: trimmedToken, baseUrl: trimmedBaseUrl })
|
||||
: await (async () => {
|
||||
const response = await runtimeFetch('/api/gitlab/auth/connect', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
||||
body: JSON.stringify({ accessToken: trimmedToken, baseUrl: trimmedBaseUrl }),
|
||||
});
|
||||
const body = (await response.json().catch(() => null)) as GitLabAuthStatus | { error?: string } | null;
|
||||
if (!response.ok || !body) {
|
||||
throw new Error((body as { error?: string } | null)?.error || response.statusText);
|
||||
}
|
||||
return body as GitLabAuthStatus;
|
||||
})();
|
||||
|
||||
setStatus(payload);
|
||||
setAccessToken('');
|
||||
setBaseUrl('');
|
||||
toast.success(t('settings.gitlab.page.toast.connected'));
|
||||
} catch (error) {
|
||||
console.error('Failed to connect GitLab:', error);
|
||||
toast.error(t('settings.gitlab.page.errors.failed'));
|
||||
} finally {
|
||||
setIsBusy(false);
|
||||
}
|
||||
}, [accessToken, baseUrl, runtimeGitLab, setStatus, t]);
|
||||
|
||||
const disconnect = React.useCallback(async () => {
|
||||
setIsBusy(true);
|
||||
try {
|
||||
if (runtimeGitLab) {
|
||||
await runtimeGitLab.authDisconnect();
|
||||
} else {
|
||||
const response = await runtimeFetch('/api/gitlab/auth', {
|
||||
method: 'DELETE',
|
||||
headers: { Accept: 'application/json' },
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
}
|
||||
toast.success(t('settings.gitlab.page.toast.disconnected'));
|
||||
await refreshStatus(runtimeGitLab, { force: true });
|
||||
} catch (error) {
|
||||
console.error('Failed to disconnect GitLab:', error);
|
||||
toast.error(t('settings.gitlab.page.toast.disconnectFailed'));
|
||||
} finally {
|
||||
setIsBusy(false);
|
||||
}
|
||||
}, [refreshStatus, runtimeGitLab, t]);
|
||||
|
||||
const activateAccount = React.useCallback(async (accountId: string) => {
|
||||
if (!accountId) return;
|
||||
setIsBusy(true);
|
||||
try {
|
||||
const payload = runtimeGitLab
|
||||
? await runtimeGitLab.authActivate(accountId)
|
||||
: await (async () => {
|
||||
const response = await runtimeFetch('/api/gitlab/auth/activate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
||||
body: JSON.stringify({ accountId }),
|
||||
});
|
||||
const body = (await response.json().catch(() => null)) as GitLabAuthStatus | { error?: string } | null;
|
||||
if (!response.ok || !body) {
|
||||
throw new Error((body as { error?: string } | null)?.error || response.statusText);
|
||||
}
|
||||
return body as GitLabAuthStatus;
|
||||
})();
|
||||
|
||||
setStatus(payload);
|
||||
toast.success(t('settings.gitlab.page.toast.accountSwitched'));
|
||||
} catch (error) {
|
||||
console.error('Failed to switch GitLab account:', error);
|
||||
toast.error(t('settings.gitlab.page.toast.accountSwitchFailed'));
|
||||
} finally {
|
||||
setIsBusy(false);
|
||||
}
|
||||
}, [runtimeGitLab, setStatus, t]);
|
||||
|
||||
if (isLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const connected = Boolean(status?.connected);
|
||||
const user = status?.user;
|
||||
const accounts = status?.accounts ?? [];
|
||||
const otherAccounts = accounts.filter((account) => !account.current);
|
||||
const currentAccount = accounts.find((account) => account.current) ?? (accounts.length > 0 ? accounts[0] : null);
|
||||
const currentBaseUrlHost = getBaseUrlHost(currentAccount?.baseUrl ?? status?.defaultBaseUrl);
|
||||
|
||||
return (
|
||||
<SettingsSection
|
||||
title={t('settings.gitlab.page.title')}
|
||||
description={t('settings.gitlab.page.description')}
|
||||
info={t('settings.gitlab.page.tooltip.connectAccount')}
|
||||
settingsItem="git.gitlab-account"
|
||||
>
|
||||
<div className="rounded-lg bg-[var(--surface-elevated)]/70 overflow-hidden flex flex-col">
|
||||
{connected ? (
|
||||
<div className={cn('px-4 py-3', isMobile ? 'flex flex-col gap-3' : 'flex items-center justify-between gap-4')}>
|
||||
<div className={cn('flex min-w-0 items-center gap-4', isMobile ? 'w-full' : undefined)}>
|
||||
{user?.avatarUrl ? (
|
||||
<img
|
||||
src={user.avatarUrl}
|
||||
alt={user.username ? t('settings.gitlab.page.avatarAlt.withLogin', { login: user.username }) : t('settings.gitlab.page.avatarAlt.fallback')}
|
||||
className="h-10 w-10 shrink-0 rounded-full border border-[var(--interactive-border)] bg-[var(--surface-muted)] object-cover"
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer"
|
||||
/>
|
||||
) : (
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full border border-[var(--interactive-border)] bg-[var(--surface-muted)]">
|
||||
<Icon name="git-branch" className="h-4 w-4 text-muted-foreground" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="typography-ui-label text-foreground">
|
||||
{user?.name?.trim() || user?.username || 'GitLab'}
|
||||
</div>
|
||||
<div className={cn('flex items-center gap-2 typography-meta text-muted-foreground mt-0.5', isMobile ? 'flex-wrap' : 'truncate')}>
|
||||
<Icon name="git-branch" className="h-3.5 w-3.5 shrink-0" />
|
||||
<span>{t('settings.gitlab.page.connectedAs')}</span>
|
||||
<span className="font-mono">{user?.username || t('settings.gitlab.page.label.unknownUser')}</span>
|
||||
<span className="opacity-50">•</span>
|
||||
<span className="font-mono">{currentBaseUrlHost}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={disconnect}
|
||||
disabled={isBusy}
|
||||
className={cn('text-[var(--status-error)] hover:text-[var(--status-error)]', isMobile ? 'w-full' : undefined)}
|
||||
>
|
||||
{t('settings.gitlab.page.actions.disconnect')}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-4 px-4 py-4">
|
||||
<div className="flex min-w-0 flex-col gap-1">
|
||||
<label htmlFor="gitlab-access-token" className="typography-settings-field-label text-foreground">
|
||||
{t('settings.gitlab.page.accessToken.label')}
|
||||
</label>
|
||||
<Input
|
||||
id="gitlab-access-token"
|
||||
type="password"
|
||||
value={accessToken}
|
||||
onChange={(event) => setAccessToken(event.target.value)}
|
||||
placeholder={t('settings.gitlab.page.accessToken.placeholder')}
|
||||
className="h-9 max-w-[24rem]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex min-w-0 flex-col gap-1">
|
||||
<label htmlFor="gitlab-base-url" className="typography-settings-field-label text-foreground">
|
||||
{t('settings.gitlab.page.baseUrl.label')}
|
||||
</label>
|
||||
<Input
|
||||
id="gitlab-base-url"
|
||||
type="text"
|
||||
value={baseUrl}
|
||||
onChange={(event) => setBaseUrl(event.target.value)}
|
||||
placeholder={t('settings.gitlab.page.baseUrl.placeholder')}
|
||||
className="h-9 max-w-[24rem]"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="typography-ui-label text-foreground">{t('settings.gitlab.page.status.notConnected')}</span>
|
||||
<Button size="sm" variant="default" onClick={connect} disabled={isBusy || !accessToken.trim()}>
|
||||
{t('settings.gitlab.page.actions.connect')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{otherAccounts.length > 0 && (
|
||||
<div className="mt-2 border-t border-[var(--surface-subtle)] pt-2 px-2 pb-1">
|
||||
<div className="typography-micro text-muted-foreground mb-2 px-1">
|
||||
{t('settings.gitlab.page.label.otherAccounts')}
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
{otherAccounts.map((account) => {
|
||||
const accountUser = account.user;
|
||||
return (
|
||||
<div
|
||||
key={account.id}
|
||||
className="flex items-center justify-between gap-3 rounded-md border border-[var(--surface-subtle)] bg-[var(--surface-muted)] px-3 py-2"
|
||||
>
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
{accountUser?.avatarUrl ? (
|
||||
<img
|
||||
src={accountUser.avatarUrl}
|
||||
alt={accountUser.username ? t('settings.gitlab.page.avatarAlt.withLogin', { login: accountUser.username }) : t('settings.gitlab.page.avatarAlt.fallback')}
|
||||
className="h-6 w-6 shrink-0 rounded-full border border-[var(--interactive-border)] bg-[var(--surface-muted)] object-cover"
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer"
|
||||
/>
|
||||
) : (
|
||||
<div className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-[var(--interactive-border)] bg-[var(--surface-muted)]">
|
||||
<Icon name="git-branch" className="h-3 w-3 text-muted-foreground" />
|
||||
</div>
|
||||
)}
|
||||
<div className="min-w-0 flex flex-col">
|
||||
<span className="typography-ui-label text-foreground truncate">
|
||||
{accountUser?.name?.trim() || accountUser?.username || 'GitLab'}
|
||||
</span>
|
||||
{accountUser?.username && (
|
||||
<span className="typography-micro text-muted-foreground truncate">
|
||||
<span className="font-mono">{accountUser.username}</span>
|
||||
<span className="mx-1 opacity-50">·</span>
|
||||
<span className="font-mono">{getBaseUrlHost(account.baseUrl)}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
onClick={() => activateAccount(account.id)}
|
||||
disabled={isBusy}
|
||||
>
|
||||
{t('settings.gitlab.page.actions.switch')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</SettingsSection>
|
||||
);
|
||||
};
|
||||
@@ -1629,6 +1629,29 @@ export const settingsDict = {
|
||||
'settings.github.page.toast.ghCliEnabled': 'gh CLI Fallback aktiviert',
|
||||
'settings.github.page.toast.ghCliDisabled': 'gh CLI Fallback deaktiviert',
|
||||
'settings.github.page.toast.ghCliUpdateFailed': 'Fehler beim Aktualisieren der gh CLI Einstellung',
|
||||
'settings.gitlab.page.title': 'GitLab Personal Access Token',
|
||||
'settings.gitlab.page.description': 'Fügen Sie ein GitLab Personal Access Token ein, um eine Verbindung herzustellen. Legen Sie die Basis-URL fest, wenn Sie eine selbst gehostete GitLab-Instanz verwenden.',
|
||||
'settings.gitlab.page.tooltip.connectAccount': 'Verbinden Sie ein GitLab-Konto für Issue- und Merge-Request-Workflows in der App.',
|
||||
'settings.gitlab.page.accessToken.label': 'Personal Access Token',
|
||||
'settings.gitlab.page.accessToken.placeholder': 'Fügen Sie Ihr GitLab Personal Access Token ein',
|
||||
'settings.gitlab.page.baseUrl.label': 'Basis-URL (optional)',
|
||||
'settings.gitlab.page.baseUrl.placeholder': 'https://gitlab.com',
|
||||
'settings.gitlab.page.actions.connect': 'GitLab verbinden',
|
||||
'settings.gitlab.page.actions.disconnect': 'Trennen',
|
||||
'settings.gitlab.page.actions.switch': 'Wechseln zu',
|
||||
'settings.gitlab.page.status.notConnected': 'Nicht verbunden',
|
||||
'settings.gitlab.page.label.unknownUser': 'unbekannt',
|
||||
'settings.gitlab.page.label.otherAccounts': 'Andere Konten',
|
||||
'settings.gitlab.page.avatarAlt.withLogin': 'Avatar von {login}',
|
||||
'settings.gitlab.page.avatarAlt.fallback': 'GitLab-Avatar',
|
||||
'settings.gitlab.page.connectedAs': 'Verbunden als',
|
||||
'settings.gitlab.page.errors.invalidToken': 'Geben Sie ein gültiges GitLab Personal Access Token ein',
|
||||
'settings.gitlab.page.errors.failed': 'Verbindung zu GitLab fehlgeschlagen',
|
||||
'settings.gitlab.page.toast.connected': 'GitLab verbunden',
|
||||
'settings.gitlab.page.toast.disconnected': 'GitLab getrennt',
|
||||
'settings.gitlab.page.toast.disconnectFailed': 'Trennen von GitLab fehlgeschlagen',
|
||||
'settings.gitlab.page.toast.accountSwitched': 'GitLab-Konto gewechselt',
|
||||
'settings.gitlab.page.toast.accountSwitchFailed': 'Wechsel des GitLab-Kontos fehlgeschlagen',
|
||||
'settings.notifications.page.delivery.title': 'Benachrichtigungsübermittlung',
|
||||
'settings.notifications.page.delivery.enableAria': 'Benachrichtigungen aktivieren',
|
||||
'settings.notifications.page.delivery.enableLabel': 'Benachrichtigungen aktivieren',
|
||||
|
||||
@@ -1695,6 +1695,29 @@ export const settingsDict = {
|
||||
'settings.github.page.toast.ghCliEnabled': 'gh CLI fallback enabled',
|
||||
'settings.github.page.toast.ghCliDisabled': 'gh CLI fallback disabled',
|
||||
'settings.github.page.toast.ghCliUpdateFailed': 'Failed to update gh CLI setting',
|
||||
'settings.gitlab.page.title': 'GitLab Personal Access Token',
|
||||
'settings.gitlab.page.description': 'Paste a GitLab personal access token to connect. Set the base URL when using a self-hosted GitLab instance.',
|
||||
'settings.gitlab.page.tooltip.connectAccount': 'Connect a GitLab account for in-app issue and merge request workflows.',
|
||||
'settings.gitlab.page.accessToken.label': 'Personal Access Token',
|
||||
'settings.gitlab.page.accessToken.placeholder': 'Paste your GitLab personal access token',
|
||||
'settings.gitlab.page.baseUrl.label': 'Base URL (optional)',
|
||||
'settings.gitlab.page.baseUrl.placeholder': 'https://gitlab.com',
|
||||
'settings.gitlab.page.actions.connect': 'Connect GitLab',
|
||||
'settings.gitlab.page.actions.disconnect': 'Disconnect',
|
||||
'settings.gitlab.page.actions.switch': 'Switch to',
|
||||
'settings.gitlab.page.status.notConnected': 'Not Connected',
|
||||
'settings.gitlab.page.label.unknownUser': 'unknown',
|
||||
'settings.gitlab.page.label.otherAccounts': 'Other Accounts',
|
||||
'settings.gitlab.page.avatarAlt.withLogin': '{login} avatar',
|
||||
'settings.gitlab.page.avatarAlt.fallback': 'GitLab avatar',
|
||||
'settings.gitlab.page.connectedAs': 'Connected as',
|
||||
'settings.gitlab.page.errors.invalidToken': 'Enter a valid GitLab personal access token',
|
||||
'settings.gitlab.page.errors.failed': 'Failed to connect GitLab',
|
||||
'settings.gitlab.page.toast.connected': 'GitLab connected',
|
||||
'settings.gitlab.page.toast.disconnected': 'GitLab disconnected',
|
||||
'settings.gitlab.page.toast.disconnectFailed': 'Failed to disconnect GitLab',
|
||||
'settings.gitlab.page.toast.accountSwitched': 'GitLab account switched',
|
||||
'settings.gitlab.page.toast.accountSwitchFailed': 'Failed to switch GitLab account',
|
||||
'settings.notifications.page.delivery.title': 'Notification Delivery',
|
||||
'settings.notifications.page.delivery.enableAria': 'Enable notifications',
|
||||
'settings.notifications.page.delivery.enableLabel': 'Enable Notifications',
|
||||
|
||||
@@ -1672,6 +1672,29 @@ export const settingsDict = {
|
||||
"settings.github.page.toast.ghCliEnabled": "Respaldo de gh CLI activado",
|
||||
"settings.github.page.toast.ghCliDisabled": "Respaldo de gh CLI desactivado",
|
||||
"settings.github.page.toast.ghCliUpdateFailed": "No se pudo actualizar la configuración de gh CLI",
|
||||
"settings.gitlab.page.title": "Token de acceso personal de GitLab",
|
||||
"settings.gitlab.page.description": "Pega un token de acceso personal de GitLab para conectarte. Establece la URL base cuando uses una instancia de GitLab autoalojada.",
|
||||
"settings.gitlab.page.tooltip.connectAccount": "Conecta una cuenta de GitLab para los flujos de trabajo de issues y merge requests en la aplicación.",
|
||||
"settings.gitlab.page.accessToken.label": "Token de acceso personal",
|
||||
"settings.gitlab.page.accessToken.placeholder": "Pega tu token de acceso personal de GitLab",
|
||||
"settings.gitlab.page.baseUrl.label": "URL base (opcional)",
|
||||
"settings.gitlab.page.baseUrl.placeholder": "https://gitlab.com",
|
||||
"settings.gitlab.page.actions.connect": "Conectar GitLab",
|
||||
"settings.gitlab.page.actions.disconnect": "Desconectar",
|
||||
"settings.gitlab.page.actions.switch": "Cambiar a",
|
||||
"settings.gitlab.page.status.notConnected": "No conectado",
|
||||
"settings.gitlab.page.label.unknownUser": "desconocido",
|
||||
"settings.gitlab.page.label.otherAccounts": "Otras cuentas",
|
||||
"settings.gitlab.page.avatarAlt.withLogin": "Avatar de {login}",
|
||||
"settings.gitlab.page.avatarAlt.fallback": "Avatar de GitLab",
|
||||
"settings.gitlab.page.connectedAs": "Conectado como",
|
||||
"settings.gitlab.page.errors.invalidToken": "Introduce un token de acceso personal de GitLab válido",
|
||||
"settings.gitlab.page.errors.failed": "No se pudo conectar GitLab",
|
||||
"settings.gitlab.page.toast.connected": "GitLab conectado",
|
||||
"settings.gitlab.page.toast.disconnected": "GitLab desconectado",
|
||||
"settings.gitlab.page.toast.disconnectFailed": "No se pudo desconectar GitLab",
|
||||
"settings.gitlab.page.toast.accountSwitched": "Cuenta de GitLab cambiada",
|
||||
"settings.gitlab.page.toast.accountSwitchFailed": "No se pudo cambiar la cuenta de GitLab",
|
||||
"settings.notifications.page.delivery.title": "Entrega de notificaciones",
|
||||
"settings.notifications.page.delivery.enableAria": "Habilitar notificaciones",
|
||||
"settings.notifications.page.delivery.enableLabel": "Habilitar notificaciones",
|
||||
|
||||
@@ -1590,6 +1590,29 @@ export const settingsDict = {
|
||||
'settings.github.page.toast.ghCliEnabled': 'Solution de secours gh CLI activée',
|
||||
'settings.github.page.toast.ghCliDisabled': 'Solution de secours gh CLI désactivée',
|
||||
'settings.github.page.toast.ghCliUpdateFailed': 'Échec de la mise à jour du paramètre gh CLI',
|
||||
'settings.gitlab.page.title': 'Jeton d\'accès personnel GitLab',
|
||||
'settings.gitlab.page.description': 'Collez un jeton d\'accès personnel GitLab pour vous connecter. Définissez l\'URL de base si vous utilisez une instance GitLab auto-hébergée.',
|
||||
'settings.gitlab.page.tooltip.connectAccount': 'Connectez un compte GitLab pour les workflows d\'issues et de merge requests dans l\'application.',
|
||||
'settings.gitlab.page.accessToken.label': 'Jeton d\'accès personnel',
|
||||
'settings.gitlab.page.accessToken.placeholder': 'Collez votre jeton d\'accès personnel GitLab',
|
||||
'settings.gitlab.page.baseUrl.label': 'URL de base (facultatif)',
|
||||
'settings.gitlab.page.baseUrl.placeholder': 'https://gitlab.com',
|
||||
'settings.gitlab.page.actions.connect': 'Connecter GitLab',
|
||||
'settings.gitlab.page.actions.disconnect': 'Déconnecter',
|
||||
'settings.gitlab.page.actions.switch': 'Passer à',
|
||||
'settings.gitlab.page.status.notConnected': 'Non connecté',
|
||||
'settings.gitlab.page.label.unknownUser': 'inconnu',
|
||||
'settings.gitlab.page.label.otherAccounts': 'Autres comptes',
|
||||
'settings.gitlab.page.avatarAlt.withLogin': 'Avatar de {login}',
|
||||
'settings.gitlab.page.avatarAlt.fallback': 'Avatar GitLab',
|
||||
'settings.gitlab.page.connectedAs': 'Connecté en tant que',
|
||||
'settings.gitlab.page.errors.invalidToken': 'Saisissez un jeton d\'accès personnel GitLab valide',
|
||||
'settings.gitlab.page.errors.failed': 'Échec de la connexion à GitLab',
|
||||
'settings.gitlab.page.toast.connected': 'GitLab connecté',
|
||||
'settings.gitlab.page.toast.disconnected': 'GitLab déconnecté',
|
||||
'settings.gitlab.page.toast.disconnectFailed': 'Échec de la déconnexion du GitLab',
|
||||
'settings.gitlab.page.toast.accountSwitched': 'Le compte GitLab a changé',
|
||||
'settings.gitlab.page.toast.accountSwitchFailed': 'Échec du changement de compte GitLab',
|
||||
'settings.notifications.page.delivery.title': 'Envoi des notifications',
|
||||
'settings.notifications.page.delivery.enableAria': 'Activer les notifications',
|
||||
'settings.notifications.page.delivery.enableLabel': 'Activer les notifications',
|
||||
|
||||
@@ -1705,6 +1705,29 @@ export const settingsDict = {
|
||||
'settings.github.page.toast.ghCliEnabled': 'gh CLI フォールバックを有効化しました',
|
||||
'settings.github.page.toast.ghCliDisabled': 'gh CLI フォールバックを無効化しました',
|
||||
'settings.github.page.toast.ghCliUpdateFailed': 'gh CLI 設定の更新に失敗しました',
|
||||
'settings.gitlab.page.title': 'GitLab パーソナルアクセストークン',
|
||||
'settings.gitlab.page.description': 'GitLab パーソナルアクセストークンを貼り付けて接続します。セルフホストの GitLab インスタンスを使用する場合はベース URL を設定してください。',
|
||||
'settings.gitlab.page.tooltip.connectAccount': 'アプリ内の Issue とマージリクエストのワークフロー用に GitLab アカウントを接続します。',
|
||||
'settings.gitlab.page.accessToken.label': 'パーソナルアクセストークン',
|
||||
'settings.gitlab.page.accessToken.placeholder': 'GitLab パーソナルアクセストークンを貼り付け',
|
||||
'settings.gitlab.page.baseUrl.label': 'ベース URL(任意)',
|
||||
'settings.gitlab.page.baseUrl.placeholder': 'https://gitlab.com',
|
||||
'settings.gitlab.page.actions.connect': 'GitLab に接続',
|
||||
'settings.gitlab.page.actions.disconnect': '切断',
|
||||
'settings.gitlab.page.actions.switch': '切り替え',
|
||||
'settings.gitlab.page.status.notConnected': '未接続',
|
||||
'settings.gitlab.page.label.unknownUser': '不明',
|
||||
'settings.gitlab.page.label.otherAccounts': 'その他のアカウント',
|
||||
'settings.gitlab.page.avatarAlt.withLogin': '{login} のアバター',
|
||||
'settings.gitlab.page.avatarAlt.fallback': 'GitLab のアバター',
|
||||
'settings.gitlab.page.connectedAs': '接続アカウント:',
|
||||
'settings.gitlab.page.errors.invalidToken': '有効な GitLab パーソナルアクセストークンを入力してください',
|
||||
'settings.gitlab.page.errors.failed': 'GitLab に接続できませんでした',
|
||||
'settings.gitlab.page.toast.connected': 'GitLab に接続しました',
|
||||
'settings.gitlab.page.toast.disconnected': 'GitLab の接続を切断しました',
|
||||
'settings.gitlab.page.toast.disconnectFailed': 'GitLab の切断に失敗しました',
|
||||
'settings.gitlab.page.toast.accountSwitched': 'GitLab アカウントを切り替えました',
|
||||
'settings.gitlab.page.toast.accountSwitchFailed': 'GitLab アカウントの切り替えに失敗しました',
|
||||
'settings.notifications.page.delivery.title': '通知配信',
|
||||
'settings.notifications.page.delivery.enableAria': '通知を有効化',
|
||||
'settings.notifications.page.delivery.enableLabel': '通知を有効化',
|
||||
|
||||
@@ -1672,6 +1672,29 @@ export const settingsDict = {
|
||||
'settings.github.page.toast.ghCliEnabled': 'gh CLI 대체 활성화됨',
|
||||
'settings.github.page.toast.ghCliDisabled': 'gh CLI 대체 비활성화됨',
|
||||
'settings.github.page.toast.ghCliUpdateFailed': 'gh CLI 설정을 업데이트하지 못했습니다',
|
||||
'settings.gitlab.page.title': 'GitLab 개인 액세스 토큰',
|
||||
'settings.gitlab.page.description': '연결하려면 GitLab 개인 액세스 토큰을 붙여넣으세요. 자체 호스팅 GitLab 인스턴스를 사용하는 경우 기본 URL을 설정하세요.',
|
||||
'settings.gitlab.page.tooltip.connectAccount': '앱 내 이슈 및 병합 요청 워크플로에 GitLab 계정을 연결합니다.',
|
||||
'settings.gitlab.page.accessToken.label': '개인 액세스 토큰',
|
||||
'settings.gitlab.page.accessToken.placeholder': 'GitLab 개인 액세스 토큰을 붙여넣으세요',
|
||||
'settings.gitlab.page.baseUrl.label': '기본 URL(선택 사항)',
|
||||
'settings.gitlab.page.baseUrl.placeholder': 'https://gitlab.com',
|
||||
'settings.gitlab.page.actions.connect': 'GitLab 연결',
|
||||
'settings.gitlab.page.actions.disconnect': '연결 해제',
|
||||
'settings.gitlab.page.actions.switch': '전환',
|
||||
'settings.gitlab.page.status.notConnected': '연결되지 않음',
|
||||
'settings.gitlab.page.label.unknownUser': '알 수 없음',
|
||||
'settings.gitlab.page.label.otherAccounts': '기타 계정',
|
||||
'settings.gitlab.page.avatarAlt.withLogin': '{login} 아바타',
|
||||
'settings.gitlab.page.avatarAlt.fallback': 'GitLab 아바타',
|
||||
'settings.gitlab.page.connectedAs': '연결된 계정:',
|
||||
'settings.gitlab.page.errors.invalidToken': '유효한 GitLab 개인 액세스 토큰을 입력하세요',
|
||||
'settings.gitlab.page.errors.failed': 'GitLab에 연결하지 못했습니다',
|
||||
'settings.gitlab.page.toast.connected': 'GitLab에 연결되었습니다',
|
||||
'settings.gitlab.page.toast.disconnected': 'GitLab 연결이 해제되었습니다',
|
||||
'settings.gitlab.page.toast.disconnectFailed': 'GitLab 연결을 해제하지 못했습니다',
|
||||
'settings.gitlab.page.toast.accountSwitched': 'GitLab 계정이 전환되었습니다',
|
||||
'settings.gitlab.page.toast.accountSwitchFailed': 'GitLab 계정을 전환하지 못했습니다',
|
||||
'settings.notifications.page.delivery.title': '알림',
|
||||
'settings.notifications.page.delivery.enableAria': '알림 활성화',
|
||||
'settings.notifications.page.delivery.enableLabel': '알림 활성화',
|
||||
|
||||
@@ -326,6 +326,29 @@ export const settingsDict = {
|
||||
'settings.github.page.ghCli.actions.disable': 'Wyłącz',
|
||||
'settings.github.page.ghCli.actions.enable': 'Włącz',
|
||||
'settings.github.page.tooltip.connectAccount': 'Połącz konto GitHub, aby korzystać z przepływów pracy dla PR i Issue w aplikacji.',
|
||||
'settings.gitlab.page.title': 'Osobisty token dostępu GitLab',
|
||||
'settings.gitlab.page.description': 'Wklej osobisty token dostępu GitLab, aby się połączyć. Ustaw podstawowy adres URL, gdy używasz własnej instancji GitLab.',
|
||||
'settings.gitlab.page.tooltip.connectAccount': 'Połącz konto GitLab, aby korzystać z przepływów pracy dla Issues i Merge Requestów w aplikacji.',
|
||||
'settings.gitlab.page.accessToken.label': 'Osobisty token dostępu',
|
||||
'settings.gitlab.page.accessToken.placeholder': 'Wklej swój osobisty token dostępu GitLab',
|
||||
'settings.gitlab.page.baseUrl.label': 'Podstawowy URL (opcjonalnie)',
|
||||
'settings.gitlab.page.baseUrl.placeholder': 'https://gitlab.com',
|
||||
'settings.gitlab.page.actions.connect': 'Połącz GitLab',
|
||||
'settings.gitlab.page.actions.disconnect': 'Odłącz',
|
||||
'settings.gitlab.page.actions.switch': 'Przełącz na',
|
||||
'settings.gitlab.page.status.notConnected': 'Brak połączenia',
|
||||
'settings.gitlab.page.label.unknownUser': 'nieznany',
|
||||
'settings.gitlab.page.label.otherAccounts': 'Inne konta',
|
||||
'settings.gitlab.page.avatarAlt.withLogin': 'Awatar {login}',
|
||||
'settings.gitlab.page.avatarAlt.fallback': 'Awatar GitLab',
|
||||
'settings.gitlab.page.connectedAs': 'Połączono jako',
|
||||
'settings.gitlab.page.errors.invalidToken': 'Wprowadź prawidłowy osobisty token dostępu GitLab',
|
||||
'settings.gitlab.page.errors.failed': 'Nie udało się połączyć z GitLab',
|
||||
'settings.gitlab.page.toast.connected': 'Połączono z GitLab',
|
||||
'settings.gitlab.page.toast.disconnected': 'Odłączono od GitLab',
|
||||
'settings.gitlab.page.toast.disconnectFailed': 'Nie udało się odłączyć GitLab',
|
||||
'settings.gitlab.page.toast.accountSwitched': 'Konto GitLab zostało przełączone',
|
||||
'settings.gitlab.page.toast.accountSwitchFailed': 'Nie udało się przełączyć konta GitLab',
|
||||
'settings.magicPrompts.page.actions.resetAllOverrides': 'Zresetuj wszystkie nadpisania',
|
||||
'settings.magicPrompts.page.actions.resetToDefault': 'Zresetuj do domyślnych',
|
||||
'settings.magicPrompts.page.actions.resetting': 'Resetowanie...',
|
||||
|
||||
@@ -1672,6 +1672,29 @@ export const settingsDict = {
|
||||
"settings.github.page.toast.ghCliEnabled": "Alternativa gh CLI ativada",
|
||||
"settings.github.page.toast.ghCliDisabled": "Alternativa gh CLI desativada",
|
||||
"settings.github.page.toast.ghCliUpdateFailed": "Falha ao atualizar configuração do gh CLI",
|
||||
"settings.gitlab.page.title": "Token de acesso pessoal do GitLab",
|
||||
"settings.gitlab.page.description": "Cole um token de acesso pessoal do GitLab para conectar. Defina a URL base ao usar uma instância GitLab auto-hospedada.",
|
||||
"settings.gitlab.page.tooltip.connectAccount": "Conecte uma conta do GitLab para fluxos de trabalho de issues e merge requests no aplicativo.",
|
||||
"settings.gitlab.page.accessToken.label": "Token de acesso pessoal",
|
||||
"settings.gitlab.page.accessToken.placeholder": "Cole seu token de acesso pessoal do GitLab",
|
||||
"settings.gitlab.page.baseUrl.label": "URL base (opcional)",
|
||||
"settings.gitlab.page.baseUrl.placeholder": "https://gitlab.com",
|
||||
"settings.gitlab.page.actions.connect": "Conectar GitLab",
|
||||
"settings.gitlab.page.actions.disconnect": "Desconectar",
|
||||
"settings.gitlab.page.actions.switch": "Alternar para",
|
||||
"settings.gitlab.page.status.notConnected": "Não conectado",
|
||||
"settings.gitlab.page.label.unknownUser": "desconhecido",
|
||||
"settings.gitlab.page.label.otherAccounts": "Outras contas",
|
||||
"settings.gitlab.page.avatarAlt.withLogin": "Avatar de {login}",
|
||||
"settings.gitlab.page.avatarAlt.fallback": "Avatar do GitLab",
|
||||
"settings.gitlab.page.connectedAs": "Conectado como",
|
||||
"settings.gitlab.page.errors.invalidToken": "Insira um token de acesso pessoal do GitLab válido",
|
||||
"settings.gitlab.page.errors.failed": "Falha ao conectar o GitLab",
|
||||
"settings.gitlab.page.toast.connected": "GitLab conectado",
|
||||
"settings.gitlab.page.toast.disconnected": "GitLab desconectado",
|
||||
"settings.gitlab.page.toast.disconnectFailed": "Falha ao desconectar o GitLab",
|
||||
"settings.gitlab.page.toast.accountSwitched": "Conta do GitLab alterada",
|
||||
"settings.gitlab.page.toast.accountSwitchFailed": "Falha ao alternar a conta do GitLab",
|
||||
"settings.notifications.page.delivery.title": "Entrega de notificações",
|
||||
"settings.notifications.page.delivery.enableAria": "Ativar notificações",
|
||||
"settings.notifications.page.delivery.enableLabel": "Ativar notificações",
|
||||
|
||||
@@ -1672,6 +1672,29 @@ export const settingsDict = {
|
||||
"settings.github.page.toast.ghCliEnabled": "Резервний варіант gh CLI увімкнено",
|
||||
"settings.github.page.toast.ghCliDisabled": "Резервний варіант gh CLI вимкнено",
|
||||
"settings.github.page.toast.ghCliUpdateFailed": "Не вдалося оновити налаштування gh CLI",
|
||||
"settings.gitlab.page.title": "Персональний токен доступу GitLab",
|
||||
"settings.gitlab.page.description": "Вставте персональний токен доступу GitLab, щоб підключитися. Вкажіть базову URL-адресу, якщо використовуєте самостійно розміщену інстанцію GitLab.",
|
||||
"settings.gitlab.page.tooltip.connectAccount": "Підключіть обліковий запис GitLab для роботи з issues та merge requests в застосунку.",
|
||||
"settings.gitlab.page.accessToken.label": "Персональний токен доступу",
|
||||
"settings.gitlab.page.accessToken.placeholder": "Вставте ваш персональний токен доступу GitLab",
|
||||
"settings.gitlab.page.baseUrl.label": "Базова URL-адреса (необов'язково)",
|
||||
"settings.gitlab.page.baseUrl.placeholder": "https://gitlab.com",
|
||||
"settings.gitlab.page.actions.connect": "Підключити GitLab",
|
||||
"settings.gitlab.page.actions.disconnect": "Відключити",
|
||||
"settings.gitlab.page.actions.switch": "Перемкнути на",
|
||||
"settings.gitlab.page.status.notConnected": "Не підключено",
|
||||
"settings.gitlab.page.label.unknownUser": "невідомо",
|
||||
"settings.gitlab.page.label.otherAccounts": "Інші облікові записи",
|
||||
"settings.gitlab.page.avatarAlt.withLogin": "Аватар {login}",
|
||||
"settings.gitlab.page.avatarAlt.fallback": "Аватар GitLab",
|
||||
"settings.gitlab.page.connectedAs": "Підключено як",
|
||||
"settings.gitlab.page.errors.invalidToken": "Введіть дійсний персональний токен доступу GitLab",
|
||||
"settings.gitlab.page.errors.failed": "Не вдалося підключити GitLab",
|
||||
"settings.gitlab.page.toast.connected": "GitLab підключено",
|
||||
"settings.gitlab.page.toast.disconnected": "GitLab відключено",
|
||||
"settings.gitlab.page.toast.disconnectFailed": "Не вдалося відключити GitLab",
|
||||
"settings.gitlab.page.toast.accountSwitched": "Обліковий запис GitLab перемкнено",
|
||||
"settings.gitlab.page.toast.accountSwitchFailed": "Не вдалося перемкнути обліковий запис GitLab",
|
||||
"settings.notifications.page.delivery.title": "Доставка сповіщень",
|
||||
"settings.notifications.page.delivery.enableAria": "Увімкнути сповіщення",
|
||||
"settings.notifications.page.delivery.enableLabel": "Увімкнути сповіщення",
|
||||
|
||||
@@ -1672,6 +1672,29 @@ export const settingsDict = {
|
||||
'settings.github.page.toast.ghCliEnabled': 'gh CLI 备用已启用',
|
||||
'settings.github.page.toast.ghCliDisabled': 'gh CLI 备用已禁用',
|
||||
'settings.github.page.toast.ghCliUpdateFailed': '更新 gh CLI 设置失败',
|
||||
'settings.gitlab.page.title': 'GitLab 个人访问令牌',
|
||||
'settings.gitlab.page.description': '粘贴 GitLab 个人访问令牌以连接。使用自托管 GitLab 实例时,请设置基础 URL。',
|
||||
'settings.gitlab.page.tooltip.connectAccount': '连接 GitLab 账户,以便在应用内使用 Issue 和合并请求工作流。',
|
||||
'settings.gitlab.page.accessToken.label': '个人访问令牌',
|
||||
'settings.gitlab.page.accessToken.placeholder': '粘贴你的 GitLab 个人访问令牌',
|
||||
'settings.gitlab.page.baseUrl.label': '基础 URL(可选)',
|
||||
'settings.gitlab.page.baseUrl.placeholder': 'https://gitlab.com',
|
||||
'settings.gitlab.page.actions.connect': '连接 GitLab',
|
||||
'settings.gitlab.page.actions.disconnect': '断开连接',
|
||||
'settings.gitlab.page.actions.switch': '切换到',
|
||||
'settings.gitlab.page.status.notConnected': '未连接',
|
||||
'settings.gitlab.page.label.unknownUser': '未知',
|
||||
'settings.gitlab.page.label.otherAccounts': '其他账户',
|
||||
'settings.gitlab.page.avatarAlt.withLogin': '{login} 的头像',
|
||||
'settings.gitlab.page.avatarAlt.fallback': 'GitLab 头像',
|
||||
'settings.gitlab.page.connectedAs': '已连接为',
|
||||
'settings.gitlab.page.errors.invalidToken': '请输入有效的 GitLab 个人访问令牌',
|
||||
'settings.gitlab.page.errors.failed': '连接 GitLab 失败',
|
||||
'settings.gitlab.page.toast.connected': 'GitLab 已连接',
|
||||
'settings.gitlab.page.toast.disconnected': 'GitLab 已断开连接',
|
||||
'settings.gitlab.page.toast.disconnectFailed': '断开 GitLab 失败',
|
||||
'settings.gitlab.page.toast.accountSwitched': 'GitLab 账户已切换',
|
||||
'settings.gitlab.page.toast.accountSwitchFailed': '切换 GitLab 账户失败',
|
||||
'settings.notifications.page.delivery.title': '通知投递',
|
||||
'settings.notifications.page.delivery.enableAria': '启用通知',
|
||||
'settings.notifications.page.delivery.enableLabel': '启用通知',
|
||||
|
||||
@@ -1579,6 +1579,29 @@ export const settingsDict = {
|
||||
'settings.github.page.toast.ghCliEnabled': 'gh CLI 備用已啟用',
|
||||
'settings.github.page.toast.ghCliDisabled': 'gh CLI 備用已停用',
|
||||
'settings.github.page.toast.ghCliUpdateFailed': '更新 gh CLI 設定失敗',
|
||||
'settings.gitlab.page.title': 'GitLab 個人存取權杖',
|
||||
'settings.gitlab.page.description': '貼上 GitLab 個人存取權杖以連線。使用自架 GitLab 執行個體時,請設定基礎 URL。',
|
||||
'settings.gitlab.page.tooltip.connectAccount': '連線 GitLab 帳號,以在應用程式內使用 Issue 與合併請求工作流程。',
|
||||
'settings.gitlab.page.accessToken.label': '個人存取權杖',
|
||||
'settings.gitlab.page.accessToken.placeholder': '貼上你的 GitLab 個人存取權杖',
|
||||
'settings.gitlab.page.baseUrl.label': '基礎 URL(選用)',
|
||||
'settings.gitlab.page.baseUrl.placeholder': 'https://gitlab.com',
|
||||
'settings.gitlab.page.actions.connect': '連線 GitLab',
|
||||
'settings.gitlab.page.actions.disconnect': '中斷連線',
|
||||
'settings.gitlab.page.actions.switch': '切換到',
|
||||
'settings.gitlab.page.status.notConnected': '未連線',
|
||||
'settings.gitlab.page.label.unknownUser': '未知',
|
||||
'settings.gitlab.page.label.otherAccounts': '其他帳號',
|
||||
'settings.gitlab.page.avatarAlt.withLogin': '{login} 頭像',
|
||||
'settings.gitlab.page.avatarAlt.fallback': 'GitLab 頭像',
|
||||
'settings.gitlab.page.connectedAs': '已連線為',
|
||||
'settings.gitlab.page.errors.invalidToken': '請輸入有效的 GitLab 個人存取權杖',
|
||||
'settings.gitlab.page.errors.failed': '連線 GitLab 失敗',
|
||||
'settings.gitlab.page.toast.connected': 'GitLab 已連線',
|
||||
'settings.gitlab.page.toast.disconnected': 'GitLab 已中斷連線',
|
||||
'settings.gitlab.page.toast.disconnectFailed': '中斷 GitLab 失敗',
|
||||
'settings.gitlab.page.toast.accountSwitched': 'GitLab 帳號已切換',
|
||||
'settings.gitlab.page.toast.accountSwitchFailed': '切換 GitLab 帳號失敗',
|
||||
'settings.notifications.page.delivery.title': '通知傳遞',
|
||||
'settings.notifications.page.delivery.enableAria': '啟用通知',
|
||||
'settings.notifications.page.delivery.enableLabel': '啟用通知',
|
||||
|
||||
@@ -495,6 +495,12 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
|
||||
titleKey: 'settings.github.page.actions.connect',
|
||||
keywords: ['github', 'account', 'oauth', 'prs', 'issues'],
|
||||
},
|
||||
{
|
||||
id: 'git.gitlab-account',
|
||||
page: 'git',
|
||||
titleKey: 'settings.gitlab.page.actions.connect',
|
||||
keywords: ['gitlab', 'account', 'pat', 'personal access token', 'issues', 'merge requests'],
|
||||
},
|
||||
{
|
||||
id: 'git.identities',
|
||||
page: 'git',
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import { create } from 'zustand';
|
||||
import type { GitLabAuthStatus, RuntimeAPIs } from '@/lib/api/types';
|
||||
import { runtimeFetch } from '@/lib/runtime-fetch';
|
||||
|
||||
type GitLabAuthStatusWithError = GitLabAuthStatus & { error?: string };
|
||||
|
||||
type GitLabAuthStore = {
|
||||
status: GitLabAuthStatusWithError | null;
|
||||
isLoading: boolean;
|
||||
hasChecked: boolean;
|
||||
setStatus: (status: GitLabAuthStatusWithError | null) => void;
|
||||
refreshStatus: (
|
||||
runtimeGitLab?: RuntimeAPIs['gitlab'],
|
||||
options?: { force?: boolean }
|
||||
) => Promise<GitLabAuthStatusWithError | null>;
|
||||
};
|
||||
|
||||
const fetchStatus = async (
|
||||
runtimeGitLab?: RuntimeAPIs['gitlab']
|
||||
): Promise<GitLabAuthStatusWithError> => {
|
||||
if (runtimeGitLab) {
|
||||
const payload = await runtimeGitLab.authStatus();
|
||||
return payload as GitLabAuthStatus;
|
||||
}
|
||||
|
||||
const response = await runtimeFetch('/api/gitlab/auth/status', {
|
||||
method: 'GET',
|
||||
headers: { Accept: 'application/json' },
|
||||
});
|
||||
const payload = (await response.json().catch(() => null)) as GitLabAuthStatusWithError | null;
|
||||
if (!response.ok || !payload) {
|
||||
throw new Error(payload?.error || response.statusText || 'Failed to load GitLab status');
|
||||
}
|
||||
return payload;
|
||||
};
|
||||
|
||||
// In-flight dedup for refreshStatus
|
||||
let _inFlightAuthRefresh: Promise<GitLabAuthStatusWithError | null> | null = null;
|
||||
|
||||
export const useGitLabAuthStore = create<GitLabAuthStore>((set, get) => ({
|
||||
status: null,
|
||||
isLoading: false,
|
||||
hasChecked: false,
|
||||
setStatus: (status) => set({ status, hasChecked: true }),
|
||||
refreshStatus: async (runtimeGitLab, options) => {
|
||||
const { hasChecked, status } = get();
|
||||
if (hasChecked && !options?.force) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (_inFlightAuthRefresh) return _inFlightAuthRefresh;
|
||||
|
||||
set({ isLoading: true });
|
||||
_inFlightAuthRefresh = (async () => {
|
||||
try {
|
||||
const payload = await fetchStatus(runtimeGitLab);
|
||||
set({ status: payload, isLoading: false, hasChecked: true });
|
||||
return payload;
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
set({
|
||||
status: { connected: false, accounts: [], defaultBaseUrl: '', error: message },
|
||||
isLoading: false,
|
||||
hasChecked: true,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
})().finally(() => { _inFlightAuthRefresh = null; });
|
||||
|
||||
return _inFlightAuthRefresh;
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user