From 28004bbac22e06cb9b7b76f9a95082560e691954 Mon Sep 17 00:00:00 2001
From: vhashimotoo
Date: Thu, 24 Jul 2025 09:40:17 +0300
Subject: [PATCH] feat: add support to update gist token without sign out
---
src/renderer/components/dialog-token.tsx | 11 +++++++++--
.../components/settings-general-github.tsx | 14 ++++++++++++--
.../settings-general-github-spec.tsx.snap | 17 ++++++++++++-----
.../renderer/components/dialog-token-spec.tsx | 18 ++++++++++++++++++
4 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/src/renderer/components/dialog-token.tsx b/src/renderer/components/dialog-token.tsx
index dddcf72d5b..29cf9c8445 100644
--- a/src/renderer/components/dialog-token.tsx
+++ b/src/renderer/components/dialog-token.tsx
@@ -15,6 +15,7 @@ interface TokenDialogState {
verifying: boolean;
error: boolean;
errorMessage?: string;
+ isTokenUpdateAction?: boolean;
}
const TOKEN_SCOPES = ['gist'].join();
@@ -40,6 +41,7 @@ export const TokenDialog = observer(
error: false,
errorMessage: undefined,
tokenInput: '',
+ isTokenUpdateAction: props.appState.gitHubToken !== '',
};
this.onSubmitToken = this.onSubmitToken.bind(this);
@@ -101,7 +103,9 @@ export const TokenDialog = observer(
errorMessage:
'Invalid GitHub token. Please check your token and try again.',
});
- this.props.appState.gitHubToken = null;
+ if (!this.state.isTokenUpdateAction) {
+ this.props.appState.gitHubToken = null;
+ }
return;
}
@@ -113,7 +117,9 @@ export const TokenDialog = observer(
errorMessage:
'Token is missing the "gist" scope. Please generate a new token with gist permissions.',
});
- this.props.appState.gitHubToken = null;
+ if (!this.state.isTokenUpdateAction) {
+ this.props.appState.gitHubToken = null;
+ }
return;
}
@@ -144,6 +150,7 @@ export const TokenDialog = observer(
error: false,
errorMessage: undefined,
tokenInput: '',
+ isTokenUpdateAction: false,
});
}
diff --git a/src/renderer/components/settings-general-github.tsx b/src/renderer/components/settings-general-github.tsx
index ddd6949fb6..40ccfbe030 100644
--- a/src/renderer/components/settings-general-github.tsx
+++ b/src/renderer/components/settings-general-github.tsx
@@ -1,6 +1,12 @@
import * as React from 'react';
-import { Button, Callout, Checkbox, FormGroup } from '@blueprintjs/core';
+import {
+ Button,
+ ButtonGroup,
+ Callout,
+ Checkbox,
+ FormGroup,
+} from '@blueprintjs/core';
import { observer } from 'mobx-react';
import { AppState } from '../state';
@@ -55,7 +61,11 @@ export const GitHubSettings = observer(
personal access token you gave us, we logged you into GitHub as{' '}
{gitHubLogin}
.
-
+
+
+
+
+
);
}
diff --git a/tests/renderer/components/__snapshots__/settings-general-github-spec.tsx.snap b/tests/renderer/components/__snapshots__/settings-general-github-spec.tsx.snap
index 1e08b14670..88815d28c5 100644
--- a/tests/renderer/components/__snapshots__/settings-general-github-spec.tsx.snap
+++ b/tests/renderer/components/__snapshots__/settings-general-github-spec.tsx.snap
@@ -45,11 +45,18 @@ exports[`GitHubSettings component > renders when signed in 1`] = `
.
-
+
+
+
+
diff --git a/tests/renderer/components/dialog-token-spec.tsx b/tests/renderer/components/dialog-token-spec.tsx
index a9835563c5..98efe029c0 100644
--- a/tests/renderer/components/dialog-token-spec.tsx
+++ b/tests/renderer/components/dialog-token-spec.tsx
@@ -75,6 +75,7 @@ describe('TokenDialog component', () => {
expect(wrapper.state()).toEqual({
verifying: false,
error: false,
+ isTokenUpdateAction: false,
errorMessage: undefined,
tokenInput: '',
});
@@ -94,6 +95,7 @@ describe('TokenDialog component', () => {
expect(wrapper.state()).toEqual({
verifying: false,
error: false,
+ isTokenUpdateAction: false,
errorMessage: undefined,
tokenInput: '',
});
@@ -186,6 +188,22 @@ describe('TokenDialog component', () => {
expect(store.gitHubToken).toEqual(null);
});
+ it('handles the invalid token update', async () => {
+ vi.mocked(mockOctokit.users.getAuthenticated).mockRejectedValue(
+ new Error('Bad credentials'),
+ );
+
+ store.gitHubToken = mockValidToken;
+ const wrapper = shallow();
+ wrapper.setState({ tokenInput: mockInvalidToken });
+ const instance: any = wrapper.instance();
+
+ expect(store.gitHubToken).toEqual(mockValidToken);
+ expect(wrapper.state('isTokenUpdateAction')).toBe(true);
+ await instance.onSubmitToken();
+ expect(store.gitHubToken).toEqual(mockValidToken);
+ });
+
it('handles missing gist scope', async () => {
vi.mocked(mockOctokit.users.getAuthenticated).mockResolvedValue({
data: mockUser,