mirror of
https://github.com/tiennm99/ccs.git
synced 2026-09-02 14:19:56 +00:00
refactor(ui): address PR review feedback for device code auth
- Extract INITIAL_STATE constant to reduce code repetition (DRY) - Remove duplicate success toast for device code flow (useDeviceCode already shows toast via deviceCodeCompleted WebSocket event) - Replace 7 inline state reset objects with INITIAL_STATE reference
This commit is contained in:
@@ -32,16 +32,19 @@ const POLL_INTERVAL = 3000;
|
|||||||
/** Maximum polling duration (5 minutes) */
|
/** Maximum polling duration (5 minutes) */
|
||||||
const MAX_POLL_DURATION = 5 * 60 * 1000;
|
const MAX_POLL_DURATION = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
/** Initial state for auth flow - extracted for DRY */
|
||||||
|
const INITIAL_STATE: AuthFlowState = {
|
||||||
|
provider: null,
|
||||||
|
isAuthenticating: false,
|
||||||
|
error: null,
|
||||||
|
authUrl: null,
|
||||||
|
oauthState: null,
|
||||||
|
isSubmittingCallback: false,
|
||||||
|
isDeviceCodeFlow: false,
|
||||||
|
};
|
||||||
|
|
||||||
export function useCliproxyAuthFlow() {
|
export function useCliproxyAuthFlow() {
|
||||||
const [state, setState] = useState<AuthFlowState>({
|
const [state, setState] = useState<AuthFlowState>(INITIAL_STATE);
|
||||||
provider: null,
|
|
||||||
isAuthenticating: false,
|
|
||||||
error: null,
|
|
||||||
authUrl: null,
|
|
||||||
oauthState: null,
|
|
||||||
isSubmittingCallback: false,
|
|
||||||
isDeviceCodeFlow: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const abortControllerRef = useRef<AbortController | null>(null);
|
const abortControllerRef = useRef<AbortController | null>(null);
|
||||||
const pollIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
const pollIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||||
@@ -89,15 +92,7 @@ export function useCliproxyAuthFlow() {
|
|||||||
queryClient.invalidateQueries({ queryKey: ['cliproxy-auth'] });
|
queryClient.invalidateQueries({ queryKey: ['cliproxy-auth'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['account-quota'] });
|
queryClient.invalidateQueries({ queryKey: ['account-quota'] });
|
||||||
toast.success(`${provider} authentication successful`);
|
toast.success(`${provider} authentication successful`);
|
||||||
setState({
|
setState(INITIAL_STATE);
|
||||||
provider: null,
|
|
||||||
isAuthenticating: false,
|
|
||||||
error: null,
|
|
||||||
authUrl: null,
|
|
||||||
oauthState: null,
|
|
||||||
isSubmittingCallback: false,
|
|
||||||
isDeviceCodeFlow: false,
|
|
||||||
});
|
|
||||||
} else if (data.status === 'error') {
|
} else if (data.status === 'error') {
|
||||||
stopPolling();
|
stopPolling();
|
||||||
const errorMsg = data.error || 'Authentication failed';
|
const errorMsg = data.error || 'Authentication failed';
|
||||||
@@ -120,13 +115,8 @@ export function useCliproxyAuthFlow() {
|
|||||||
async (provider: string, options?: StartAuthOptions) => {
|
async (provider: string, options?: StartAuthOptions) => {
|
||||||
if (!isValidProvider(provider)) {
|
if (!isValidProvider(provider)) {
|
||||||
setState({
|
setState({
|
||||||
provider: null,
|
...INITIAL_STATE,
|
||||||
isAuthenticating: false,
|
|
||||||
error: `Unknown provider: ${provider}`,
|
error: `Unknown provider: ${provider}`,
|
||||||
authUrl: null,
|
|
||||||
oauthState: null,
|
|
||||||
isSubmittingCallback: false,
|
|
||||||
isDeviceCodeFlow: false,
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -167,16 +157,9 @@ export function useCliproxyAuthFlow() {
|
|||||||
if (response.ok && data.success) {
|
if (response.ok && data.success) {
|
||||||
queryClient.invalidateQueries({ queryKey: ['cliproxy-auth'] });
|
queryClient.invalidateQueries({ queryKey: ['cliproxy-auth'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['account-quota'] });
|
queryClient.invalidateQueries({ queryKey: ['account-quota'] });
|
||||||
toast.success(`${provider} authentication successful`);
|
// Note: No toast here - DeviceCodeDialog's useDeviceCode hook handles success toast
|
||||||
setState({
|
// via deviceCodeCompleted WebSocket event to avoid duplicate toasts
|
||||||
provider: null,
|
setState(INITIAL_STATE);
|
||||||
isAuthenticating: false,
|
|
||||||
error: null,
|
|
||||||
authUrl: null,
|
|
||||||
oauthState: null,
|
|
||||||
isSubmittingCallback: false,
|
|
||||||
isDeviceCodeFlow: false,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
const errorMsg = data.error || 'Authentication failed';
|
const errorMsg = data.error || 'Authentication failed';
|
||||||
toast.error(errorMsg);
|
toast.error(errorMsg);
|
||||||
@@ -238,15 +221,7 @@ export function useCliproxyAuthFlow() {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error && error.name === 'AbortError') {
|
if (error instanceof Error && error.name === 'AbortError') {
|
||||||
setState({
|
setState(INITIAL_STATE);
|
||||||
provider: null,
|
|
||||||
isAuthenticating: false,
|
|
||||||
error: null,
|
|
||||||
authUrl: null,
|
|
||||||
oauthState: null,
|
|
||||||
isSubmittingCallback: false,
|
|
||||||
isDeviceCodeFlow: false,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const message = error instanceof Error ? error.message : 'Authentication failed';
|
const message = error instanceof Error ? error.message : 'Authentication failed';
|
||||||
@@ -265,15 +240,7 @@ export function useCliproxyAuthFlow() {
|
|||||||
const currentProvider = state.provider;
|
const currentProvider = state.provider;
|
||||||
abortControllerRef.current?.abort();
|
abortControllerRef.current?.abort();
|
||||||
stopPolling();
|
stopPolling();
|
||||||
setState({
|
setState(INITIAL_STATE);
|
||||||
provider: null,
|
|
||||||
isAuthenticating: false,
|
|
||||||
error: null,
|
|
||||||
authUrl: null,
|
|
||||||
oauthState: null,
|
|
||||||
isSubmittingCallback: false,
|
|
||||||
isDeviceCodeFlow: false,
|
|
||||||
});
|
|
||||||
// Also cancel on backend
|
// Also cancel on backend
|
||||||
if (currentProvider) {
|
if (currentProvider) {
|
||||||
api.cliproxy.auth.cancel(currentProvider).catch(() => {
|
api.cliproxy.auth.cancel(currentProvider).catch(() => {
|
||||||
@@ -302,15 +269,7 @@ export function useCliproxyAuthFlow() {
|
|||||||
queryClient.invalidateQueries({ queryKey: ['cliproxy-auth'] });
|
queryClient.invalidateQueries({ queryKey: ['cliproxy-auth'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['account-quota'] });
|
queryClient.invalidateQueries({ queryKey: ['account-quota'] });
|
||||||
toast.success(`${state.provider} authentication successful`);
|
toast.success(`${state.provider} authentication successful`);
|
||||||
setState({
|
setState(INITIAL_STATE);
|
||||||
provider: null,
|
|
||||||
isAuthenticating: false,
|
|
||||||
error: null,
|
|
||||||
authUrl: null,
|
|
||||||
oauthState: null,
|
|
||||||
isSubmittingCallback: false,
|
|
||||||
isDeviceCodeFlow: false,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error(data.error || 'Callback submission failed');
|
throw new Error(data.error || 'Callback submission failed');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user