Skip to content

Commit

Permalink
feat: fetch enterprise server platform version on load and use for fe…
Browse files Browse the repository at this point in the history
…ature availability
  • Loading branch information
setchy committed Jul 30, 2024
1 parent a3a3f92 commit 3bbf7e5
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 44 deletions.
27 changes: 16 additions & 11 deletions src/components/NotificationRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import { AppContext } from '../context/App';
import { Opacity, Size } from '../types';
import type { Notification } from '../typesGitHub';
import { cn } from '../utils/cn';
import { formatForDisplay } from '../utils/helpers';
import {
formatForDisplay,
isMarkAsDoneFeatureSupported,
} from '../utils/helpers';
import {
getNotificationTypeIcon,
getNotificationTypeIconColor,
Expand Down Expand Up @@ -125,16 +128,18 @@ export const NotificationRow: FC<INotificationRow> = ({
</div>

<HoverGroup>
<InteractionButton
title="Mark as Done"
icon={CheckIcon}
size={Size.MEDIUM}
onClick={() => {
setAnimateExit(!settings.delayNotificationState);
setShowAsRead(settings.delayNotificationState);
markNotificationDone(notification);
}}
/>
{isMarkAsDoneFeatureSupported(notification.account) && (
<InteractionButton
title="Mark as Done"
icon={CheckIcon}
size={Size.MEDIUM}
onClick={() => {
setAnimateExit(!settings.delayNotificationState);
setShowAsRead(settings.delayNotificationState);
markNotificationDone(notification);
}}
/>
)}
<InteractionButton
title="Mark as Read"
icon={ReadIcon}
Expand Down
27 changes: 15 additions & 12 deletions src/components/RepositoryNotifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AppContext } from '../context/App';
import { Opacity, Size } from '../types';
import type { Notification } from '../typesGitHub';
import { cn } from '../utils/cn';
import { isMarkAsDoneFeatureSupported } from '../utils/helpers';
import { openRepository } from '../utils/links';
import { HoverGroup } from './HoverGroup';
import { NotificationRow } from './NotificationRow';
Expand Down Expand Up @@ -79,18 +80,20 @@ export const RepositoryNotifications: FC<IRepositoryNotifications> = ({
</div>

<HoverGroup>
<InteractionButton
title="Mark Repository as Done"
icon={CheckIcon}
size={Size.MEDIUM}
onClick={(event: MouseEvent<HTMLElement>) => {
// Don't trigger onClick of parent element.
event.stopPropagation();
setAnimateExit(!settings.delayNotificationState);
setShowAsRead(settings.delayNotificationState);
markRepoNotificationsDone(repoNotifications[0]);
}}
/>
{isMarkAsDoneFeatureSupported(repoNotifications[0].account) && (
<InteractionButton
title="Mark Repository as Done"
icon={CheckIcon}
size={Size.MEDIUM}
onClick={(event: MouseEvent<HTMLElement>) => {
// Don't trigger onClick of parent element.
event.stopPropagation();
setAnimateExit(!settings.delayNotificationState);
setShowAsRead(settings.delayNotificationState);
markRepoNotificationsDone(repoNotifications[0]);
}}
/>
)}
<InteractionButton
title="Mark Repository as Read"
icon={ReadIcon}
Expand Down
7 changes: 7 additions & 0 deletions src/context/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,13 @@ export const AppProvider = ({ children }: { children: ReactNode }) => {
);
return existing.settings;
}

for (const account of auth.accounts.filter(
(a) => a.platform === 'GitHub Enterprise Server',
)) {
const res = await headNotifications(account.hostname, account.token);
account.version = res.headers['x-github-enterprise-version'];
}
}, []);

const fetchNotificationsWithAccounts = useCallback(
Expand Down
13 changes: 8 additions & 5 deletions src/hooks/useNotifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '../utils/api/client';
import { determineFailureType } from '../utils/api/errors';
import { getAccountUUID } from '../utils/auth/utils';
import { isMarkAsDoneFeatureSupported } from '../utils/helpers';
import {
getAllNotifications,
setTrayIconColor,
Expand Down Expand Up @@ -107,11 +108,13 @@ export const useNotifications = (): NotificationsState => {
setStatus('loading');

try {
await markNotificationThreadAsDone(
notification.id,
notification.account.hostname,
notification.account.token,
);
if (isMarkAsDoneFeatureSupported(notification.account)) {
await markNotificationThreadAsDone(
notification.id,
notification.account.hostname,
notification.account.token,
);
}

const updatedNotifications = removeNotification(
state.settings,
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export type Status = 'loading' | 'success' | 'error';
export interface Account {
method: AuthMethod;
platform: PlatformType;
version?: string;
hostname: Hostname;
token: Token;
user: GitifyUser | null;
Expand Down
14 changes: 0 additions & 14 deletions src/utils/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import type {
Release,
UserDetails,
} from '../../typesGitHub';
import { isEnterpriseServerHost } from '../helpers';
import { QUERY_SEARCH_DISCUSSIONS } from './graphql/discussions';
import { formatAsGitHubSearchSyntax } from './graphql/utils';
import { apiRequestAuth } from './request';
Expand Down Expand Up @@ -102,19 +101,6 @@ export function markNotificationThreadAsDone(
): AxiosPromise<void> {
const url = getGitHubAPIBaseUrl(hostname);
url.pathname += `notifications/threads/${threadId}`;

// GitHub Enterprise Server: This feature is only supported in v3.13 or later.
if (isEnterpriseServerHost(hostname)) {
try {
return apiRequestAuth(url.toString() as Link, 'DELETE', token, {});
} catch (err) {
log.warn(
'Failed to mark notification thread as done',
'Note: This feature requires GitHub Cloud or GitHub Enterprise Server 3.13 or later.',
);
}
}

return apiRequestAuth(url.toString() as Link, 'DELETE', token, {});
}

Expand Down
31 changes: 30 additions & 1 deletion src/utils/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { AxiosPromise, AxiosResponse } from 'axios';
import { mockPersonalAccessTokenAccount } from '../__mocks__/state-mocks';
import {
mockGitHubCloudAccount,
mockGitHubEnterpriseServerAccount,
mockPersonalAccessTokenAccount,
} from '../__mocks__/state-mocks';

import { defaultSettings } from '../context/App';
import type { Hostname, Link, SettingsState } from '../types';
Expand All @@ -17,6 +21,7 @@ import {
getFilterCount,
getPlatformFromHostname,
isEnterpriseServerHost,
isMarkAsDoneFeatureSupported,
} from './helpers';

describe('utils/helpers.ts', () => {
Expand Down Expand Up @@ -56,6 +61,30 @@ describe('utils/helpers.ts', () => {
});
});

describe('isMarkAsDoneFeatureSupported', () => {
it('should return true for GitHub Cloud', () => {
expect(isMarkAsDoneFeatureSupported(mockGitHubCloudAccount)).toBe(true);
});

it('should return false for GitHub Enterprise Server < v3.13', () => {
const account = {
...mockGitHubEnterpriseServerAccount,
version: '3.12.0',
};

expect(isMarkAsDoneFeatureSupported(account)).toBe(false);
});

it('should return true for GitHub Enterprise Server >= v3.13', () => {
const account = {
...mockGitHubEnterpriseServerAccount,
version: '3.13.3',
};

expect(isMarkAsDoneFeatureSupported(account)).toBe(true);
});
});

describe('generateNotificationReferrerId', () => {
it('should generate the notification_referrer_id', () => {
const referrerId = generateNotificationReferrerId(mockSingleNotification);
Expand Down
16 changes: 15 additions & 1 deletion src/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { formatDistanceToNowStrict, parseISO } from 'date-fns';
import { defaultSettings } from '../context/App';
import type { Hostname, Link, SettingsState } from '../types';
import type { Account, Hostname, Link, SettingsState } from '../types';
import type { Notification } from '../typesGitHub';
import { getHtmlUrl, getLatestDiscussion } from './api/client';
import type { PlatformType } from './auth/types';
Expand All @@ -21,6 +21,20 @@ export function isEnterpriseServerHost(hostname: Hostname): boolean {
return !hostname.endsWith(Constants.DEFAULT_AUTH_OPTIONS.hostname);
}

export function isMarkAsDoneFeatureSupported(account: Account): boolean {
if (isEnterpriseServerHost(account.hostname)) {
// Support for "Mark as Done" was added to GitHub Enterprise Server in v3.13 or newer
if (account.version) {
const version = account.version.split('.').map(Number);
return version[0] >= 3 && version[1] >= 13;
}

return false;
}

return true;
}

export function generateNotificationReferrerId(
notification: Notification,
): string {
Expand Down

0 comments on commit 3bbf7e5

Please sign in to comment.