diff --git a/src/__mocks__/state-mocks.ts b/src/__mocks__/state-mocks.ts
index 68278bc84..5226657c3 100644
--- a/src/__mocks__/state-mocks.ts
+++ b/src/__mocks__/state-mocks.ts
@@ -84,6 +84,7 @@ export const mockSettings: SettingsState = {
showAccountHostname: false,
delayNotificationState: false,
showPills: true,
+ showNumber: true,
keyboardShortcut: true,
groupBy: GroupBy.REPOSITORY,
filterReasons: [],
diff --git a/src/components/NotificationRow.test.tsx b/src/components/NotificationRow.test.tsx
index bb781f14a..15a6abb5b 100644
--- a/src/components/NotificationRow.test.tsx
+++ b/src/components/NotificationRow.test.tsx
@@ -61,6 +61,26 @@ describe('components/NotificationRow.tsx', () => {
expect(tree).toMatchSnapshot();
});
+ it('should render itself & its children - hide numbers', async () => {
+ jest
+ .spyOn(global.Date, 'now')
+ .mockImplementation(() => new Date('2024').valueOf());
+
+ const props = {
+ notification: mockSingleNotification,
+ account: mockGitHubCloudAccount,
+ };
+
+ const tree = render(
+
+
+ ,
+ );
+ expect(tree).toMatchSnapshot();
+ });
+
describe('notification interactions', () => {
it('should open a notification in the browser - click', () => {
const removeNotificationFromState = jest.fn();
diff --git a/src/components/NotificationRow.tsx b/src/components/NotificationRow.tsx
index bfcead590..5f635e214 100644
--- a/src/components/NotificationRow.tsx
+++ b/src/components/NotificationRow.tsx
@@ -71,6 +71,13 @@ export const NotificationRow: FC = ({
notification.subject.type,
]);
+ const notificationNumber = notification.subject?.number
+ ? `#${notification.subject.number}`
+ : '';
+
+ const notificationTitle =
+ `${notification.subject.title} ${notificationNumber}`.trim();
+
const groupByDate = settings.groupBy === 'DATE';
return (
@@ -102,9 +109,18 @@ export const NotificationRow: FC = ({
{notification.subject.title}
+
+ {notificationNumber}
+
diff --git a/src/components/__snapshots__/AccountNotifications.test.tsx.snap b/src/components/__snapshots__/AccountNotifications.test.tsx.snap
index 9250db70f..cec4888c3 100644
--- a/src/components/__snapshots__/AccountNotifications.test.tsx.snap
+++ b/src/components/__snapshots__/AccountNotifications.test.tsx.snap
@@ -121,6 +121,9 @@ exports[`components/AccountNotifications.tsx should render itself (github.com wi
title="I am a robot and this is a test!"
>
I am a robot and this is a test!
+
Improve the UI
+
I am a robot and this is a test!
+
Improve the UI
+
I am a robot and this is a test!
+
I am a robot and this is a test!
+
I am a robot and this is a test!
+
+
+
+
+
+
+
+ Updated
+
+
+ 7 years ago
+
+
+
+
+
+
+ 1
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ I am a robot and this is a test!
+
I am a robot and this is a test!
+
{
expect(updateSetting).toHaveBeenCalledWith('showPills', false);
});
+ it('should toggle show number checkbox', async () => {
+ await act(async () => {
+ render(
+
+
+
+
+ ,
+ );
+ });
+
+ await screen.findByLabelText('Show number');
+
+ fireEvent.click(screen.getByLabelText('Show number'));
+
+ expect(updateSetting).toHaveBeenCalledTimes(1);
+ expect(updateSetting).toHaveBeenCalledWith('showNumber', false);
+ });
+
it('should toggle account hostname checkbox', async () => {
await act(async () => {
render(
diff --git a/src/components/settings/AppearanceSettings.tsx b/src/components/settings/AppearanceSettings.tsx
index 1d0da8e5a..ae0b959b7 100644
--- a/src/components/settings/AppearanceSettings.tsx
+++ b/src/components/settings/AppearanceSettings.tsx
@@ -1,6 +1,7 @@
import {
CheckIcon,
CommentIcon,
+ GitPullRequestIcon,
IssueClosedIcon,
MilestoneIcon,
PaintbrushIcon,
@@ -99,6 +100,41 @@ export const AppearanceSettings: FC = () => {
}
/>
+
+ settings.detailedNotifications &&
+ updateSetting('showNumber', evt.target.checked)
+ }
+ disabled={!settings.detailedNotifications}
+ tooltip={
+
+
Show GitHub number for:
+
+
+
+
+ Discussion
+
+
+
+ Issue
+
+
+
+ Pull Request
+
+
+
+
+ ⚠️ This setting requires Detailed Notifications to
+ be enabled.
+
+
+ }
+ />
{
showAccountHostname: false,
delayNotificationState: false,
showPills: true,
+ showNumber: true,
keyboardShortcut: true,
groupBy: 'REPOSITORY',
filterReasons: [],
@@ -433,6 +434,7 @@ describe('context/App.tsx', () => {
showAccountHostname: false,
delayNotificationState: false,
showPills: true,
+ showNumber: true,
keyboardShortcut: true,
groupBy: 'REPOSITORY',
filterReasons: [],
diff --git a/src/context/App.tsx b/src/context/App.tsx
index 05ac5594a..36ea47424 100644
--- a/src/context/App.tsx
+++ b/src/context/App.tsx
@@ -67,6 +67,7 @@ export const defaultSettings: SettingsState = {
showAccountHostname: false,
delayNotificationState: false,
showPills: true,
+ showNumber: true,
keyboardShortcut: true,
groupBy: GroupBy.REPOSITORY,
...defaultFilters,
diff --git a/src/routes/__snapshots__/Settings.test.tsx.snap b/src/routes/__snapshots__/Settings.test.tsx.snap
index 0e2fa07a7..2241044b9 100644
--- a/src/routes/__snapshots__/Settings.test.tsx.snap
+++ b/src/routes/__snapshots__/Settings.test.tsx.snap
@@ -231,6 +231,54 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = `
+
+
+
+
+
+
+
+ Show number
+
+
+
+
+
+
+
+
+
diff --git a/src/types.ts b/src/types.ts
index 6fe2d25c3..f60c03f7d 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -63,6 +63,7 @@ interface AppearanceSettingsState {
detailedNotifications: boolean;
showAccountHostname: boolean;
showPills: boolean;
+ showNumber: boolean;
}
interface NotificationSettingsState {
diff --git a/src/typesGitHub.ts b/src/typesGitHub.ts
index 2fed9d328..39e567236 100644
--- a/src/typesGitHub.ts
+++ b/src/typesGitHub.ts
@@ -261,6 +261,7 @@ interface GitHubSubject {
// This is not in the GitHub API, but we add it to the type to make it easier to work with
export interface GitifySubject {
+ number?: number;
state?: StateType;
user?: SubjectUser;
reviews?: GitifyPullRequestReview[];
@@ -494,6 +495,7 @@ export interface GraphQLSearch {
}
export interface Discussion {
+ number: number;
title: string;
stateReason: DiscussionStateType;
isAnswered: boolean;
diff --git a/src/utils/api/__mocks__/response-mocks.ts b/src/utils/api/__mocks__/response-mocks.ts
index 74097fb37..714635ab5 100644
--- a/src/utils/api/__mocks__/response-mocks.ts
+++ b/src/utils/api/__mocks__/response-mocks.ts
@@ -419,6 +419,7 @@ export const mockGraphQLResponse: GraphQLSearch = {
search: {
nodes: [
{
+ number: 123,
title: '1.16.0',
isAnswered: false,
stateReason: 'OPEN',
diff --git a/src/utils/api/graphql/discussions.ts b/src/utils/api/graphql/discussions.ts
index b5ce239af..93ec4c91a 100644
--- a/src/utils/api/graphql/discussions.ts
+++ b/src/utils/api/graphql/discussions.ts
@@ -31,6 +31,7 @@ export const QUERY_SEARCH_DISCUSSIONS = gql`
search(query: $queryStatement, type: DISCUSSION, first: $firstDiscussions) {
nodes {
... on Discussion {
+ number
title
stateReason
isAnswered
diff --git a/src/utils/subject.test.ts b/src/utils/subject.test.ts
index 5b030539f..bb53ac8c9 100644
--- a/src/utils/subject.test.ts
+++ b/src/utils/subject.test.ts
@@ -221,6 +221,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'ANSWERED',
user: {
login: mockDiscussionAuthor.login,
@@ -247,6 +248,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'DUPLICATE',
user: {
login: mockDiscussionAuthor.login,
@@ -273,6 +275,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'OPEN',
user: {
login: mockDiscussionAuthor.login,
@@ -299,6 +302,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'OUTDATED',
user: {
login: mockDiscussionAuthor.login,
@@ -325,6 +329,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'REOPENED',
user: {
login: mockDiscussionAuthor.login,
@@ -351,6 +356,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'RESOLVED',
user: {
login: mockDiscussionAuthor.login,
@@ -385,6 +391,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'ANSWERED',
user: {
login: mockDiscussionAuthor.login,
@@ -414,7 +421,12 @@ describe('utils/subject.ts', () => {
it('open issue state', async () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/1')
- .reply(200, { state: 'open', user: mockAuthor, labels: [] });
+ .reply(200, {
+ number: 123,
+ state: 'open',
+ user: mockAuthor,
+ labels: [],
+ });
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/comments/302888448')
@@ -423,6 +435,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockCommenter.login,
@@ -437,7 +450,12 @@ describe('utils/subject.ts', () => {
it('closed issue state', async () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/1')
- .reply(200, { state: 'closed', user: mockAuthor, labels: [] });
+ .reply(200, {
+ number: 123,
+ state: 'closed',
+ user: mockAuthor,
+ labels: [],
+ });
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/comments/302888448')
@@ -446,6 +464,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'closed',
user: {
login: mockCommenter.login,
@@ -461,6 +480,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/1')
.reply(200, {
+ number: 123,
state: 'closed',
state_reason: 'completed',
user: mockAuthor,
@@ -474,6 +494,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'completed',
user: {
login: mockCommenter.login,
@@ -489,6 +510,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/1')
.reply(200, {
+ number: 123,
state: 'open',
state_reason: 'not_planned',
user: mockAuthor,
@@ -502,6 +524,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'not_planned',
user: {
login: mockCommenter.login,
@@ -517,6 +540,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/1')
.reply(200, {
+ number: 123,
state: 'open',
state_reason: 'reopened',
user: mockAuthor,
@@ -530,6 +554,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'reopened',
user: {
login: mockCommenter.login,
@@ -547,6 +572,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/1')
.reply(200, {
+ number: 123,
state: 'open',
draft: false,
merged: false,
@@ -557,6 +583,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockAuthor.login,
@@ -573,6 +600,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/1')
.reply(200, {
+ number: 123,
state: 'open',
user: mockAuthor,
labels: [{ name: 'enhancement' }],
@@ -587,6 +615,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockCommenter.login,
@@ -602,6 +631,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/issues/1')
.reply(200, {
+ number: 123,
state: 'open',
user: mockAuthor,
labels: null,
@@ -616,6 +646,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockCommenter.login,
@@ -646,6 +677,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/pulls/1')
.reply(200, {
+ number: 123,
state: 'closed',
draft: false,
merged: false,
@@ -664,6 +696,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'closed',
user: {
login: mockCommenter.login,
@@ -681,6 +714,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/pulls/1')
.reply(200, {
+ number: 123,
state: 'open',
draft: true,
merged: false,
@@ -699,6 +733,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'draft',
user: {
login: mockCommenter.login,
@@ -716,6 +751,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/pulls/1')
.reply(200, {
+ number: 123,
state: 'open',
draft: false,
merged: true,
@@ -734,6 +770,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'merged',
user: {
login: mockCommenter.login,
@@ -751,6 +788,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/pulls/1')
.reply(200, {
+ number: 123,
state: 'open',
draft: false,
merged: false,
@@ -769,6 +807,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockCommenter.login,
@@ -789,6 +828,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/pulls/1')
.reply(200, {
+ number: 123,
state: 'open',
draft: false,
merged: false,
@@ -803,6 +843,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockAuthor.login,
@@ -822,6 +863,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/pulls/1')
.reply(200, {
+ number: 123,
state: 'open',
draft: false,
merged: false,
@@ -836,6 +878,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockAuthor.login,
@@ -912,6 +955,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/pulls/1')
.reply(200, {
+ number: 123,
state: 'open',
draft: false,
merged: false,
@@ -932,6 +976,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockCommenter.login,
@@ -949,6 +994,7 @@ describe('utils/subject.ts', () => {
nock('https://api.github.com')
.get('/repos/gitify-app/notifications-test/pulls/1')
.reply(200, {
+ number: 123,
state: 'open',
draft: false,
merged: false,
@@ -969,6 +1015,7 @@ describe('utils/subject.ts', () => {
const result = await getGitifySubjectDetails(mockNotification);
expect(result).toEqual({
+ number: 123,
state: 'open',
user: {
login: mockCommenter.login,
@@ -1293,6 +1340,7 @@ function mockDiscussionNode(
isAnswered: boolean,
): Discussion {
return {
+ number: 123,
title: 'This is a mock discussion',
url: 'https://github.com/gitify-app/notifications-test/discussions/1' as Link,
stateReason: state,
diff --git a/src/utils/subject.ts b/src/utils/subject.ts
index ba0c7853b..a4063c0a3 100644
--- a/src/utils/subject.ts
+++ b/src/utils/subject.ts
@@ -183,6 +183,7 @@ async function getGitifySubjectForDiscussion(
}
return {
+ number: discussion.number,
state: discussionState,
user: discussionUser,
comments: discussion.comments.totalCount,
@@ -226,6 +227,7 @@ async function getGitifySubjectForIssue(
}
return {
+ number: issue.number,
state: issue.state_reason ?? issue.state,
user: {
login: issueCommentUser?.login ?? issue.user.login,
@@ -272,6 +274,7 @@ async function getGitifySubjectForPullRequest(
const linkedIssues = parseLinkedIssuesFromPr(pr);
return {
+ number: pr.number,
state: prState,
user: {
login: prCommentUser?.login ?? pr.user.login,