Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"codegen": "graphql-codegen --config codegen.ts",
"codegen:watch": "pnpm codegen --watch",
"dev": "concurrently --names \"vite,codegen\" --prefix-colors \"blue,magenta\" \"vite dev\" \"pnpm codegen:watch\"",
"devtools": "concurrently --names \"dev,devtools\" --prefix-colors \"cyan,green\" \"pnpm dev\" \"react-devtools\"",
"start": "pnpm build && pnpm dev",
"package:linux": "electron-builder --linux",
"package:macos": "electron-builder --mac",
Expand Down Expand Up @@ -114,6 +115,7 @@
"graphql": "16.13.0",
"happy-dom": "20.7.0",
"husky": "9.1.7",
"react-devtools": "7.0.1",
"rimraf": "6.1.3",
"semver": "7.7.4",
"tailwind-merge": "3.5.0",
Expand Down
696 changes: 696 additions & 0 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/renderer/components/AllRead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export const AllRead: FC<AllReadProps> = ({

const emoji = useMemo(
() =>
Constants.ALL_READ_EMOJIS[
Math.floor(Math.random() * Constants.ALL_READ_EMOJIS.length)
Constants.EMOJIS.ALL_READ[
Math.floor(Math.random() * Constants.EMOJIS.ALL_READ.length)
],
[],
);
Expand Down
12 changes: 11 additions & 1 deletion src/renderer/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,17 @@ export const Constants = {
GITHUB_API_GRAPHQL_URL: 'https://api.github.com/graphql',
GITHUB_API_MERGE_BATCH_SIZE: 100,

ALL_READ_EMOJIS: ['🎉', '🎊', '🥳', '👏', '🙌', '😎', '🏖️', '🚀', '✨', '🏆'],
// Emojis for different states and events
EMOJIS: {
ALL_READ: ['🎉', '🎊', '🥳', '👏', '🙌', '😎', '🏖️', '🚀', '✨', '🏆'],
ERRORS: {
BAD_CREDENTIALS: ['🔓'],
MISSING_SCOPES: ['🔭'],
NETWORK: ['🛜'],
RATE_LIMITED: ['😮‍💨'],
UNKNOWN: ['🤔', '🥲', '😳', '🫠', '🙃', '🙈'],
},
},

DEFAULT_FETCH_NOTIFICATIONS_INTERVAL_MS: 60 * 1000, // 1 minute
MIN_FETCH_NOTIFICATIONS_INTERVAL_MS: 60 * 1000, // 1 minute
Expand Down
12 changes: 12 additions & 0 deletions src/renderer/utils/api/graphql/generated/graphql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions src/renderer/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { Constants } from '../constants';

import type { AccountNotifications, ErrorType, GitifyError } from '../types';

export const Errors: Record<ErrorType, GitifyError> = {
BAD_CREDENTIALS: {
title: 'Bad Credentials',
descriptions: ['Your credentials are either invalid or expired.'],
emojis: ['🔓'],
emojis: Constants.EMOJIS.ERRORS.BAD_CREDENTIALS,
},
MISSING_SCOPES: {
title: 'Missing Scopes',
descriptions: ['Your credentials are missing a required API scope.'],
emojis: ['🔭'],
emojis: Constants.EMOJIS.ERRORS.MISSING_SCOPES,
},
NETWORK: {
title: 'Network Error',
descriptions: [
'Unable to connect to one or more of your GitHub environments.',
'Please check your network connection, including whether you require a VPN, and try again.',
],
emojis: ['🛜'],
emojis: Constants.EMOJIS.ERRORS.NETWORK,
},
RATE_LIMITED: {
title: 'Rate Limited',
descriptions: ['Please wait a while before trying again.'],
emojis: ['😮‍💨'],
emojis: Constants.EMOJIS.ERRORS.RATE_LIMITED,
},
UNKNOWN: {
title: 'Oops! Something went wrong',
descriptions: ['Please try again later.'],
emojis: ['🤔', '🥲', '😳', '🫠', '🙃', '🙈'],
emojis: Constants.EMOJIS.ERRORS.UNKNOWN,
},
};

Expand Down
68 changes: 47 additions & 21 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,61 @@ import { fileURLToPath } from 'node:url';
import twemoji from '@discordapp/twemoji';
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react-swc';
import type { Plugin } from 'vite';
import { defineConfig } from 'vite';
import checker from 'vite-plugin-checker';
import electron from 'vite-plugin-electron/simple';
import { viteStaticCopy } from 'vite-plugin-static-copy';

import { Constants } from './src/renderer/constants';

import { Errors } from './src/renderer/utils/errors';
/**
* Helper to generate Twemoji static copy targets.
* Extracts all emojis from Constants.EMOJIS and maps them to their SVG filenames.
*/
const getTwemojiCopyTargets = () => {
const flatten = (obj: object): string[] =>
Object.values(obj).flatMap((v) =>
Array.isArray(v) ? v : flatten(v as object),
);

const ALL_EMOJIS = [
...Constants.ALL_READ_EMOJIS,
...Errors.BAD_CREDENTIALS.emojis,
...Errors.MISSING_SCOPES.emojis,
...Errors.NETWORK.emojis,
...Errors.RATE_LIMITED.emojis,
...Errors.UNKNOWN.emojis,
];
const extractSvgFilename = (imgHtml: string) =>
imgHtml
.match(/src="(.*)"/)?.[1]
.split('/')
.pop();

const extractSvgFilename = (imgHtml: string) =>
imgHtml
.match(/src="(.*)"/)?.[1]
.split('/')
.pop();
const allEmojis = flatten(Constants.EMOJIS);
const emojiFilenames = allEmojis.map((emoji) =>
extractSvgFilename(twemoji.parse(emoji, { folder: 'svg', ext: '.svg' })),
);

const ALL_EMOJI_SVG_FILENAMES = ALL_EMOJIS.map((emoji) =>
extractSvgFilename(twemoji.parse(emoji, { folder: 'svg', ext: '.svg' })),
);
return emojiFilenames.map((filename) => ({
src: `../../node_modules/@discordapp/twemoji/dist/svg/${filename}`,
dest: 'assets/images/twemoji',
}));
};

/**
* Vite plugin that injects React DevTools connection script in dev mode only.
* This script connects the renderer process to the standalone react-devtools instance.
*/
const reactDevToolsPlugin = (): Plugin => ({
name: 'react-devtools',
apply: 'serve', // Only apply in dev mode (vite dev)
transformIndexHtml(html) {
// Inject devtools connection script and update CSP to allow localhost:8097
return html
.replace(
'<meta http-equiv="Content-Security-Policy" content="script-src \'self\';',
'<meta http-equiv="Content-Security-Policy" content="script-src \'self\' http://localhost:8097;',
)
.replace(
'</head>',
' <script src="http://localhost:8097"></script>\n </head>',
);
},
});

export default defineConfig(({ command }) => {
const isBuild = command === 'build';
Expand All @@ -45,6 +73,7 @@ export default defineConfig(({ command }) => {
biome: { dev: { logLevel: ['error'] } },
}),
]),
reactDevToolsPlugin(),
react({
plugins: [
[
Expand Down Expand Up @@ -91,10 +120,7 @@ export default defineConfig(({ command }) => {
}),
viteStaticCopy({
targets: [
...ALL_EMOJI_SVG_FILENAMES.map((filename) => ({
src: `../../node_modules/@discordapp/twemoji/dist/svg/${filename}`,
dest: 'assets/images/twemoji',
})),
...getTwemojiCopyTargets(),
{
src: '../../assets',
dest: '.',
Expand Down