Skip to content

Commit c4f9e71

Browse files
authored
build: copy static resources for dev mode (#2725)
* build: copy static assets in dev Signed-off-by: Adam Setch <adam.setch@outlook.com> * build: copy static assets in dev Signed-off-by: Adam Setch <adam.setch@outlook.com> --------- Signed-off-by: Adam Setch <adam.setch@outlook.com>
1 parent e4f3e33 commit c4f9e71

File tree

9 files changed

+81
-108
lines changed

9 files changed

+81
-108
lines changed

.env.template

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
# GitHub Personal Access Token for GraphQL Codegen
2-
GITHUB_TOKEN=some-pat
2+
GITHUB_TOKEN=some-pat
3+
4+
# Custom OAuth Client ID for GitHub Device Flow
5+
#OAUTH_CLIENT_ID=some-client-id

.github/actions/setup-node/action.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,28 @@
44
name: Setup Node, pnpm and install dependencies
55
description: Setup pnpm and Node.js with caching
66

7+
inputs:
8+
run-install:
9+
description: 'Whether to run `pnpm install`'
10+
required: false
11+
default: 'true'
12+
713
runs:
814
using: composite
915
steps:
1016
- name: Setup pnpm
1117
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
18+
with:
19+
run_install: false
1220

1321
- name: Setup Node
1422
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
1523
with:
1624
node-version-file: .nvmrc
1725
cache: pnpm
26+
cache-dependency-path: pnpm-lock.yaml
1827

1928
- name: Install dependencies
29+
if: ${{ inputs.run-install == 'true' }}
2030
run: pnpm install --frozen-lockfile
2131
shell: bash

.github/workflows/publish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ jobs:
3737

3838
release:
3939
name: Publish ${{ matrix.platform }} (electron-builder)
40+
needs: prepare
4041
strategy:
4142
matrix:
4243
include:

.github/workflows/renovate.yml

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,9 @@ jobs:
2121
- name: Checkout
2222
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2323

24-
- name: Setup pnpm
25-
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
24+
- uses: ./.github/actions/setup-node
2625
with:
27-
run_install: false
28-
29-
- name: Setup Node
30-
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
31-
with:
32-
node-version-file: .nvmrc
33-
cache: pnpm
26+
run-install: "false"
3427

3528
- name: Install Renovate
3629
run: pnpm install --global renovate

.github/workflows/test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ jobs:
1515
- name: Checkout
1616
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1717

18-
- uses: ./.github/actions/setup-node
18+
- name: Setup Node.js
19+
uses: ./.github/actions/setup-node
1920

2021
- name: Check TypeScript
2122
run: pnpm tsc --noEmit

CONTRIBUTING.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,6 @@ Copy the `.env.template` to `.env` and add update `GITHUB_TOKEN` with a GitHub P
2525
GITHUB_TOKEN=<some personal access token>
2626
```
2727

28-
Build static resources (tray icons, twemojis, etc). You only need to rebuild if you change static assets:
29-
```shell
30-
pnpm build
31-
```
32-
3328
Start development mode (includes GraphQL codegen and hot module reload):
3429
```shell
3530
pnpm dev

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@
125125
"vite-plugin-checker": "0.12.0",
126126
"vite-plugin-electron": "0.29.1",
127127
"vite-plugin-electron-renderer": "0.14.6",
128-
"vite-plugin-static-copy": "3.3.0",
129128
"vitest": "4.1.0",
130129
"zustand": "5.0.12"
131130
},

pnpm-lock.yaml

Lines changed: 0 additions & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vite.config.ts

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
13
import { fileURLToPath } from 'node:url';
24

35
import twemoji from '@discordapp/twemoji';
@@ -7,15 +9,15 @@ import type { Plugin } from 'vite';
79
import { defineConfig } from 'vite';
810
import checker from 'vite-plugin-checker';
911
import electron from 'vite-plugin-electron/simple';
10-
import { viteStaticCopy } from 'vite-plugin-static-copy';
1112

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

1415
/**
15-
* Helper to generate Twemoji static copy targets.
16-
* Extracts all emojis from Constants.EMOJIS and maps them to their SVG filenames.
16+
* Vite plugin that copies static assets to disk on startup.
17+
* Runs in both dev and build modes so the Electron main process can resolve
18+
* asset file URLs without requiring a prior `pnpm build`.
1719
*/
18-
const getTwemojiCopyTargets = () => {
20+
const copyStaticAssetsPlugin = (): Plugin => {
1921
const flatten = (obj: object): string[] =>
2022
Object.values(obj).flatMap((v) =>
2123
Array.isArray(v) ? v : flatten(v as object),
@@ -27,15 +29,59 @@ const getTwemojiCopyTargets = () => {
2729
.split('/')
2830
.pop();
2931

30-
const allEmojis = flatten(Constants.EMOJIS);
31-
const emojiFilenames = allEmojis.map((emoji) =>
32-
extractSvgFilename(twemoji.parse(emoji, { folder: 'svg', ext: '.svg' })),
33-
);
32+
let isBuild = false;
3433

35-
return emojiFilenames.map((filename) => ({
36-
src: `../../node_modules/@discordapp/twemoji/dist/svg/${filename}`,
37-
dest: 'assets/images/twemoji',
38-
}));
34+
const copyAssets = () => {
35+
// Copy the root assets/ directory (images, sounds, etc.) into build/
36+
fs.cpSync(
37+
fileURLToPath(new URL('assets', import.meta.url)),
38+
fileURLToPath(new URL('build/assets', import.meta.url)),
39+
{ recursive: true },
40+
);
41+
42+
// Copy individual Twemoji SVGs needed by the app into build/assets/images/twemoji/
43+
const twemojiSrcDir = fileURLToPath(
44+
new URL('node_modules/@discordapp/twemoji/dist/svg', import.meta.url),
45+
);
46+
const twemojiDestDir = fileURLToPath(
47+
new URL('build/assets/images/twemoji', import.meta.url),
48+
);
49+
50+
fs.mkdirSync(twemojiDestDir, { recursive: true });
51+
52+
const allEmojis = flatten(Constants.EMOJIS);
53+
for (const emoji of allEmojis) {
54+
const filename = extractSvgFilename(
55+
twemoji.parse(emoji, { folder: 'svg', ext: '.svg' }),
56+
);
57+
if (filename) {
58+
fs.copyFileSync(
59+
path.join(twemojiSrcDir, filename),
60+
path.join(twemojiDestDir, filename),
61+
);
62+
}
63+
}
64+
};
65+
66+
return {
67+
name: 'copy-static-assets',
68+
configResolved(config) {
69+
isBuild = config.command === 'build';
70+
},
71+
// In serve/dev mode, copy before the build starts (emptyOutDir doesn't run).
72+
// In build mode, copy after all output is written — buildStart runs before
73+
// Vite's emptyOutDir wipe, so assets copied there would be deleted.
74+
buildStart() {
75+
if (!isBuild) {
76+
copyAssets();
77+
}
78+
},
79+
closeBundle() {
80+
if (isBuild) {
81+
copyAssets();
82+
}
83+
},
84+
};
3985
};
4086

4187
/**
@@ -90,6 +136,9 @@ export default defineConfig(({ command }) => {
90136
main: {
91137
entry: fileURLToPath(new URL('src/main/index.ts', import.meta.url)),
92138
vite: {
139+
// The outer Vite config sets root:'src/renderer', so we must
140+
// explicitly tell the main-process sub-build where to find .env files.
141+
envDir: fileURLToPath(new URL('.', import.meta.url)),
93142
build: {
94143
outDir: fileURLToPath(new URL('build', import.meta.url)),
95144
rollupOptions: {
@@ -118,15 +167,7 @@ export default defineConfig(({ command }) => {
118167
},
119168
},
120169
}),
121-
viteStaticCopy({
122-
targets: [
123-
...getTwemojiCopyTargets(),
124-
{
125-
src: '../../assets',
126-
dest: '.',
127-
},
128-
],
129-
}),
170+
copyStaticAssetsPlugin(),
130171
],
131172
root: 'src/renderer',
132173
publicDir: false as const,

0 commit comments

Comments
 (0)