From 980881f28af12ebc4e7f26f4020d16a0d12e4df9 Mon Sep 17 00:00:00 2001 From: netcon Date: Fri, 18 Sep 2026 18:31:13 +0800 Subject: [PATCH 1/4] chore: update docs --- README.md | 4 ++-- docs/usage.md | 5 ++-- extensions/github1s/src/statusbar/index.ts | 4 ++-- .../src/statusbar/{sponsors.ts => thanks.ts} | 24 +++++++++---------- 4 files changed, 19 insertions(+), 18 deletions(-) rename extensions/github1s/src/statusbar/{sponsors.ts => thanks.ts} (66%) diff --git a/README.md b/README.md index 3c941c8ab..d81ce7fe3 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,9 @@ See the [development guide](docs/development.md) to run GitHub1s locally. Report [conwnet](https://github.com/conwnet) ยท [xcv58](https://github.com/xcv58) ยท [Siddhant Khare](https://github.com/Siddhant-K-code) -## ๐Ÿ’– Acknowledgments +## ๐Ÿ’– Thanks -Thanks to everyone who has contributed to GitHub1s, and to [Sourcegraph](https://sourcegraph.com/), [searchcode](https://searchcode.com/), and [OSS Insight](https://ossinsight.io/) for their support of the project. +Thanks to everyone who has contributed to GitHub1s, and to [Sourcegraph](https://sourcegraph.com/), [searchcode](https://searchcode.com/), and [OSS Insight](https://ossinsight.io/) for the tools and services used by GitHub1s. ## ๐Ÿ“„ License diff --git a/docs/usage.md b/docs/usage.md index b487229c6..e87a68466 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -35,8 +35,9 @@ For branches or tags, you can also run **GitHub1s: Checkout to...**. Its **Check - Use **Explorer** to browse files and directories, or **Go to File** to find a file by name. - Use **Search** for text across the repository and the editor's **Find** action for the open file. -- Open **Source Control** to inspect **Commits**, **File History**, and **Code Reviews** where the platform supports them. -- Select a commit or pull/merge request to inspect its changed files and diffs. +- Open a file and expand **Timeline** in **Explorer** to inspect its history. Select a commit entry to open that file's diff. +- In **Source Control**, use the built-in **Graph** view to browse commits for the current ref and inspect their changed files and diffs. +- In **Source Control**, select a pull/merge request from **Pull Requests** (GitHub) or **Merge Requests** (GitLab) to inspect its changed files and diffs. - Run **GitHub1s: Toggle File Blame** to display revision information beside file lines where available. Open the Command Palette with `F1`, `Ctrl+Shift+P`, or `Cmd+Shift+P` on macOS. Browser and operating-system shortcuts can take precedence. diff --git a/extensions/github1s/src/statusbar/index.ts b/extensions/github1s/src/statusbar/index.ts index 594391d6d..43ff49c89 100644 --- a/extensions/github1s/src/statusbar/index.ts +++ b/extensions/github1s/src/statusbar/index.ts @@ -4,9 +4,9 @@ */ import { updateCheckoutTo } from './checkout'; -import { showSponsors } from './sponsors'; +import { showThanks } from './thanks'; export const decorateStatusBar = () => { updateCheckoutTo(); - showSponsors(); + showThanks(); }; diff --git a/extensions/github1s/src/statusbar/sponsors.ts b/extensions/github1s/src/statusbar/thanks.ts similarity index 66% rename from extensions/github1s/src/statusbar/sponsors.ts rename to extensions/github1s/src/statusbar/thanks.ts index 60e78e32b..0da8d2832 100644 --- a/extensions/github1s/src/statusbar/sponsors.ts +++ b/extensions/github1s/src/statusbar/thanks.ts @@ -1,5 +1,5 @@ /** - * @file Show Sponsors In Status Bar + * @file Show Thanks In Status Bar * @author netcon */ @@ -22,7 +22,7 @@ const resolveSourcegraphLink = async () => { } }; -const resolveSponsors = async () => { +const resolveThanks = async () => { return [ { name: 'Sourcegraph', @@ -32,20 +32,20 @@ const resolveSponsors = async () => { ]; }; -export const showSponsors = async () => { +export const showThanks = async () => { const titleItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0); - titleItem.text = ' $(heart) Sponsors:'; + titleItem.text = ' $(heart) Thanks:'; titleItem.show(); - (await resolveSponsors()).forEach((sponsor) => { - const sponsorItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0); - sponsorItem.text = sponsor.name; - sponsorItem.tooltip = sponsor.description; - sponsorItem.command = { - title: `Visit ${sponsor.name}`, + (await resolveThanks()).forEach((service) => { + const serviceItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0); + serviceItem.text = service.name; + serviceItem.tooltip = service.description; + serviceItem.command = { + title: `Visit ${service.name}`, command: 'vscode.open', - arguments: [vscode.Uri.parse(sponsor.link)], + arguments: [vscode.Uri.parse(service.link)], }; - sponsorItem.show(); + serviceItem.show(); }); }; From 75229e3e8a7205e2b918dda81c2cd5ae87365907 Mon Sep 17 00:00:00 2001 From: netcon Date: Fri, 18 Sep 2026 19:27:30 +0800 Subject: [PATCH 2/4] chore: remove unused codes --- extensions/github1s/src/adapters/bitbucket1s/index.ts | 2 -- extensions/github1s/src/adapters/github1s/index.ts | 2 -- extensions/github1s/src/adapters/gitlab1s/index.ts | 2 -- .../github1s/src/providers/decorations/source-control.ts | 7 ------- 4 files changed, 13 deletions(-) diff --git a/extensions/github1s/src/adapters/bitbucket1s/index.ts b/extensions/github1s/src/adapters/bitbucket1s/index.ts index 11a4bded2..e2c9d7ebc 100644 --- a/extensions/github1s/src/adapters/bitbucket1s/index.ts +++ b/extensions/github1s/src/adapters/bitbucket1s/index.ts @@ -22,12 +22,10 @@ export class BitbucketAdapter implements Adapter { } activateAsDefault() { - setVSCodeContext('github1s:views:commitList:visible', true); setVSCodeContext('github1s:features:gutterBlame:enabled', true); } deactivateAsDefault() { - setVSCodeContext('github1s:views:commitList:visible', false); setVSCodeContext('github1s:features:gutterBlame:enabled', false); } } diff --git a/extensions/github1s/src/adapters/github1s/index.ts b/extensions/github1s/src/adapters/github1s/index.ts index cb42e44af..207240a25 100644 --- a/extensions/github1s/src/adapters/github1s/index.ts +++ b/extensions/github1s/src/adapters/github1s/index.ts @@ -30,7 +30,6 @@ export class GitHub1sAdapter implements Adapter { // register settings view and show it in activity bar setVSCodeContext('github1s:views:settings:visible', true); setVSCodeContext('github1s:views:codeReviewList:visible', true); - setVSCodeContext('github1s:views:commitList:visible', true); setVSCodeContext('github1s:features:gutterBlame:enabled', true); vscode.window.registerWebviewViewProvider( @@ -52,7 +51,6 @@ export class GitHub1sAdapter implements Adapter { deactivateAsDefault() { setVSCodeContext('github1s:views:settings:visible', false); setVSCodeContext('github1s:views:codeReviewList:visible', false); - setVSCodeContext('github1s:views:commitList:visible', false); setVSCodeContext('github1s:features:gutterBlame:enabled', false); } } diff --git a/extensions/github1s/src/adapters/gitlab1s/index.ts b/extensions/github1s/src/adapters/gitlab1s/index.ts index 34091859e..72f988f4c 100644 --- a/extensions/github1s/src/adapters/gitlab1s/index.ts +++ b/extensions/github1s/src/adapters/gitlab1s/index.ts @@ -30,7 +30,6 @@ export class GitLab1sAdapter implements Adapter { // register settings view and show it in activity bar setVSCodeContext('github1s:views:settings:visible', true); setVSCodeContext('github1s:views:codeReviewList:visible', true); - setVSCodeContext('github1s:views:commitList:visible', true); setVSCodeContext('github1s:features:gutterBlame:enabled', true); vscode.window.registerWebviewViewProvider( @@ -50,7 +49,6 @@ export class GitLab1sAdapter implements Adapter { deactivateAsDefault() { setVSCodeContext('github1s:views:settings:visible', false); setVSCodeContext('github1s:views:codeReviewList:visible', false); - setVSCodeContext('github1s:views:commitList:visible', false); setVSCodeContext('github1s:features:gutterBlame:enabled', false); } } diff --git a/extensions/github1s/src/providers/decorations/source-control.ts b/extensions/github1s/src/providers/decorations/source-control.ts index 3f24f7623..9b52e1b43 100644 --- a/extensions/github1s/src/providers/decorations/source-control.ts +++ b/extensions/github1s/src/providers/decorations/source-control.ts @@ -25,7 +25,6 @@ const selectedViewItemDecoration: FileDecoration = { export class GitHub1sSourceControlDecorationProvider implements FileDecorationProvider, Disposable { public static codeReviewSchema: string = 'github1s-source-control-code-review'; - public static commitSchema: string = 'github1s-source-control-commit'; private static instance: GitHub1sSourceControlDecorationProvider | null = null; private readonly disposable: Disposable; @@ -60,11 +59,5 @@ export class GitHub1sSourceControlDecorationProvider implements FileDecorationPr const query = queryString.parse(uri.query); return +(routerState as any).codeReviewId === +query.id! ? selectedViewItemDecoration : null; } - - if (uri.scheme === GitHub1sSourceControlDecorationProvider.commitSchema) { - const routerState = router.getState(); - const query = queryString.parse(uri.query); - return (routerState as any).commitSha === query.sha ? selectedViewItemDecoration : null; - } } } From dc0f9d01690cf8cfd32b3d04379a34bf76681f95 Mon Sep 17 00:00:00 2001 From: netcon Date: Sun, 20 Sep 2026 17:51:01 +0800 Subject: [PATCH 3/4] feat: add feature enablement control --- .../src/adapters/bitbucket1s/index.ts | 9 ------ .../github1s/src/adapters/github1s/index.ts | 4 --- .../github1s/src/adapters/gitlab1s/index.ts | 4 --- extensions/github1s/src/adapters/index.ts | 31 +++++++++++++++++++ extensions/github1s/src/changes/index.ts | 9 ++++-- extensions/github1s/src/commands/editor.ts | 13 +++++--- extensions/github1s/src/providers/index.ts | 9 ++++-- extensions/github1s/src/providers/timeline.ts | 8 ++--- 8 files changed, 54 insertions(+), 33 deletions(-) diff --git a/extensions/github1s/src/adapters/bitbucket1s/index.ts b/extensions/github1s/src/adapters/bitbucket1s/index.ts index e2c9d7ebc..5b1b845fe 100644 --- a/extensions/github1s/src/adapters/bitbucket1s/index.ts +++ b/extensions/github1s/src/adapters/bitbucket1s/index.ts @@ -6,7 +6,6 @@ import { BitbucketRouterParser } from './router-parser'; import { SourcegraphDataSource } from '../sourcegraph/data-source'; import { Adapter, CodeReviewType, PlatformName } from '../types'; -import { setVSCodeContext } from '@/helpers/vscode'; export class BitbucketAdapter implements Adapter { public scheme: string = 'bitbucket1s'; @@ -20,12 +19,4 @@ export class BitbucketAdapter implements Adapter { resolveRouterParser() { return Promise.resolve(BitbucketRouterParser.getInstance()); } - - activateAsDefault() { - setVSCodeContext('github1s:features:gutterBlame:enabled', true); - } - - deactivateAsDefault() { - setVSCodeContext('github1s:features:gutterBlame:enabled', false); - } } diff --git a/extensions/github1s/src/adapters/github1s/index.ts b/extensions/github1s/src/adapters/github1s/index.ts index 207240a25..d0bb93ed0 100644 --- a/extensions/github1s/src/adapters/github1s/index.ts +++ b/extensions/github1s/src/adapters/github1s/index.ts @@ -29,8 +29,6 @@ export class GitHub1sAdapter implements Adapter { activateAsDefault() { // register settings view and show it in activity bar setVSCodeContext('github1s:views:settings:visible', true); - setVSCodeContext('github1s:views:codeReviewList:visible', true); - setVSCodeContext('github1s:features:gutterBlame:enabled', true); vscode.window.registerWebviewViewProvider( GitHub1sSettingsViewProvider.viewType, @@ -50,7 +48,5 @@ export class GitHub1sAdapter implements Adapter { deactivateAsDefault() { setVSCodeContext('github1s:views:settings:visible', false); - setVSCodeContext('github1s:views:codeReviewList:visible', false); - setVSCodeContext('github1s:features:gutterBlame:enabled', false); } } diff --git a/extensions/github1s/src/adapters/gitlab1s/index.ts b/extensions/github1s/src/adapters/gitlab1s/index.ts index 72f988f4c..bd80c1e02 100644 --- a/extensions/github1s/src/adapters/gitlab1s/index.ts +++ b/extensions/github1s/src/adapters/gitlab1s/index.ts @@ -29,8 +29,6 @@ export class GitLab1sAdapter implements Adapter { activateAsDefault() { // register settings view and show it in activity bar setVSCodeContext('github1s:views:settings:visible', true); - setVSCodeContext('github1s:views:codeReviewList:visible', true); - setVSCodeContext('github1s:features:gutterBlame:enabled', true); vscode.window.registerWebviewViewProvider( GitLab1sSettingsViewProvider.viewType, @@ -48,7 +46,5 @@ export class GitLab1sAdapter implements Adapter { deactivateAsDefault() { setVSCodeContext('github1s:views:settings:visible', false); - setVSCodeContext('github1s:views:codeReviewList:visible', false); - setVSCodeContext('github1s:features:gutterBlame:enabled', false); } } diff --git a/extensions/github1s/src/adapters/index.ts b/extensions/github1s/src/adapters/index.ts index db0ec4901..76abdf0ac 100644 --- a/extensions/github1s/src/adapters/index.ts +++ b/extensions/github1s/src/adapters/index.ts @@ -10,6 +10,7 @@ import { BitbucketAdapter } from './bitbucket1s'; import { Npmjs1sAdapter } from './npmjs1s'; import { DiscoveryAdapter } from './discovery'; import { Adapter, DataSource, PlatformName, RouterParser } from './types'; +import { setVSCodeContext } from '@/helpers/vscode'; const emptyAdapter = { scheme: 'empty', @@ -27,6 +28,8 @@ export const registerAdapters = async (): Promise => { adapterManager.registerAdapter(new Npmjs1sAdapter()), adapterManager.registerAdapter(new DiscoveryAdapter()), ]); + await setVSCodeContext('github1s:views:codeReviewList:visible', await supportsCodeReviewFeatures()); + await setVSCodeContext('github1s:features:gutterBlame:enabled', await supportsGutterBlameFeatures()); }; export const getAdapter = (scheme?: string): Adapter => { @@ -36,3 +39,31 @@ export const getAdapter = (scheme?: string): Adapter => { export const getAllAdapters = (): Adapter[] => { return adapterManager.getAllAdapters(); }; + +export const supportsDataSourceMethods = async ( + methods: (keyof DataSource)[], + scheme: string = getAdapter().scheme, +): Promise => { + const adapter = getAllAdapters().find((adapter) => adapter.scheme === scheme); + if (!adapter) { + return false; + } + const dataSource = await adapter.resolveDataSource(); + // Inherited default methods return empty results and do not indicate support. + return methods.every((method) => dataSource[method] !== DataSource.prototype[method]); +}; + +export const supportsCommitFeatures = (scheme?: string): Promise => { + return supportsDataSourceMethods(['provideCommits', 'provideCommit', 'provideCommitChangedFiles'], scheme); +}; + +export const supportsCodeReviewFeatures = (scheme?: string): Promise => { + return supportsDataSourceMethods( + ['provideCodeReviews', 'provideCodeReview', 'provideCodeReviewChangedFiles'], + scheme, + ); +}; + +export const supportsGutterBlameFeatures = (scheme?: string): Promise => { + return supportsDataSourceMethods(['provideFileBlameRanges'], scheme); +}; diff --git a/extensions/github1s/src/changes/index.ts b/extensions/github1s/src/changes/index.ts index 89a734990..aa0a27dad 100644 --- a/extensions/github1s/src/changes/index.ts +++ b/extensions/github1s/src/changes/index.ts @@ -5,6 +5,7 @@ import * as vscode from 'vscode'; import * as adapterTypes from '@/adapters/types'; +import { supportsCommitFeatures } from '@/adapters'; import { getExtensionContext } from '@/helpers/context'; import { GitHub1sQuickDiffProvider } from './quick-diff'; import { getChangedFileDiffCommand, getChangedFiles } from './files'; @@ -14,11 +15,15 @@ const sourceControl = vscode.scm.createSourceControl('github1s', 'GitHub1s'); const changesGroup = sourceControl.createResourceGroup('changes', 'Changes'); sourceControl.quickDiffProvider = new GitHub1sQuickDiffProvider(); -export const registerSourceControlHistory = () => { +export const registerSourceControlHistory = async () => { const context = getExtensionContext(); + context.subscriptions.push(sourceControl); + if (!(await supportsCommitFeatures())) { + return; + } const historyProvider = GitHub1sHistoryProvider.getInstance(); sourceControl.historyProvider = historyProvider; - context.subscriptions.push(sourceControl, historyProvider); + context.subscriptions.push(historyProvider); historyProvider.refresh(); }; diff --git a/extensions/github1s/src/commands/editor.ts b/extensions/github1s/src/commands/editor.ts index 193a41761..b7af15895 100644 --- a/extensions/github1s/src/commands/editor.ts +++ b/extensions/github1s/src/commands/editor.ts @@ -7,6 +7,7 @@ import * as vscode from 'vscode'; import queryString from 'query-string'; import router from '@/router'; import { emptyFileUri } from '@/providers'; +import { supportsCommitFeatures } from '@/adapters'; import { FileChangeStatus } from '@/adapters/types'; import { Repository } from '@/repository'; import { getChangedFiles, getChangedFileDiffCommand, getChangedFileDiffTitle } from '@/changes/files'; @@ -36,8 +37,8 @@ const commandDiffChangedFile = async (fileUri: vscode.Uri) => { vscode.commands.executeCommand(command.command, ...(command.arguments || [])); }; -const isRepositoryFileUri = (uri: vscode.Uri | undefined): uri is vscode.Uri => { - return !!uri && /^(github1s|gitlab1s|bitbucket1s)$/.test(uri.scheme); +const isRepositoryFileUri = async (uri: vscode.Uri | undefined): Promise => { + return !!uri && supportsCommitFeatures(uri.scheme); }; const getActiveDiffInput = (resource?: vscode.Uri): vscode.TabInputTextDiff | undefined => { @@ -74,8 +75,10 @@ const resolveOpenFileRevisionArgs = async ( if (textDiffInput) { // this is a diff editor const { original, modified } = textDiffInput; - const hasLeftFile = isRepositoryFileUri(original); - const hasRightFile = isRepositoryFileUri(modified); + const [hasLeftFile, hasRightFile] = await Promise.all([ + isRepositoryFileUri(original), + isRepositoryFileUri(modified), + ]); if (direction === 'previous' && hasLeftFile) { baseUri = original; @@ -86,7 +89,7 @@ const resolveOpenFileRevisionArgs = async ( if (hasRightFile) { from = getQueryFrom(modified); } - } else if (isRepositoryFileUri(fileUri)) { + } else if (fileUri && (await isRepositoryFileUri(fileUri))) { // this is a single file editor from = getQueryFrom(fileUri); baseUri = fileUri; diff --git a/extensions/github1s/src/providers/index.ts b/extensions/github1s/src/providers/index.ts index df8ad4e9f..a77755984 100644 --- a/extensions/github1s/src/providers/index.ts +++ b/extensions/github1s/src/providers/index.ts @@ -4,7 +4,7 @@ */ import * as vscode from 'vscode'; -import { getAllAdapters } from '@/adapters'; +import { getAllAdapters, supportsCommitFeatures } from '@/adapters'; import { getExtensionContext } from '@/helpers/context'; import { GitHub1sFileSystemProvider } from './file-system'; import { GitHub1sFileSearchProvider } from './file-search'; @@ -20,7 +20,7 @@ import { FileHistoryTimelineProvider } from './timeline'; export const EMPTY_FILE_SCHEME = 'github1s-empty-file'; export const emptyFileUri = vscode.Uri.from({ scheme: EMPTY_FILE_SCHEME }); -export const registerVSCodeProviders = () => { +export const registerVSCodeProviders = async () => { const context = getExtensionContext(); const fileHistoryProvider = FileHistoryTimelineProvider.getInstance(); const allSchemes = getAllAdapters().map((item) => item.scheme); @@ -39,9 +39,12 @@ export const registerVSCodeProviders = () => { ); }); + const timelineSupport = await Promise.all(allSchemes.map(supportsCommitFeatures)); + const timelineSchemes = allSchemes.filter((_, index) => timelineSupport[index]); + context.subscriptions.push( fileHistoryProvider, - vscode.workspace.registerTimelineProvider(FileHistoryTimelineProvider.schemes, fileHistoryProvider), + vscode.workspace.registerTimelineProvider(timelineSchemes, fileHistoryProvider), vscode.window.registerFileDecorationProvider(GitHub1sSubmoduleDecorationProvider.getInstance()), vscode.window.registerFileDecorationProvider(GitHub1sChangedFileDecorationProvider.getInstance()), vscode.window.registerFileDecorationProvider(GitHub1sSourceControlDecorationProvider.getInstance()), diff --git a/extensions/github1s/src/providers/timeline.ts b/extensions/github1s/src/providers/timeline.ts index 6fdac4501..260278af2 100644 --- a/extensions/github1s/src/providers/timeline.ts +++ b/extensions/github1s/src/providers/timeline.ts @@ -7,10 +7,10 @@ import router, { UriState } from '@/router'; import { Repository } from '@/repository'; import { getCommitTooltip } from '@/helpers/commit'; import { Commit } from '@/adapters/types'; +import { supportsCommitFeatures } from '@/adapters'; export class FileHistoryTimelineProvider implements vscode.TimelineProvider, vscode.Disposable { private static instance: FileHistoryTimelineProvider | null = null; - public static readonly schemes = ['github1s', 'gitlab1s', 'bitbucket1s']; readonly id = 'github1s.fileHistory'; readonly label = 'Git History'; @@ -43,11 +43,7 @@ export class FileHistoryTimelineProvider implements vscode.TimelineProvider, vsc options: vscode.TimelineOptions, token: vscode.CancellationToken, ): Promise { - if ( - !FileHistoryTimelineProvider.schemes.includes(uri.scheme) || - uri.path === '/' || - token.isCancellationRequested - ) { + if (uri.path === '/' || token.isCancellationRequested || !(await supportsCommitFeatures(uri.scheme))) { return undefined; } From dbc579bb1aefae25d7d2fa39dc643a81fad14d27 Mon Sep 17 00:00:00 2001 From: netcon Date: Sun, 20 Sep 2026 17:55:23 +0800 Subject: [PATCH 4/4] feat: update discovery key --- workers/discovery/src/snapshots.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workers/discovery/src/snapshots.ts b/workers/discovery/src/snapshots.ts index 8e57aacbc..8162eb5f0 100644 --- a/workers/discovery/src/snapshots.ts +++ b/workers/discovery/src/snapshots.ts @@ -1,6 +1,6 @@ import type { DiscoverySnapshot } from './types.ts'; -export const LATEST_KEY = 'latest'; +export const LATEST_KEY = 'github:latest'; export const SNAPSHOT_RETENTION_SECONDS = 90 * 24 * 60 * 60; // Use the scheduled UTC date so execution delays cannot change the archive day.