Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
90 changes: 88 additions & 2 deletions .github/workflows/desktop-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ jobs:
source_path: linux
build_cmd: "--linux AppImage"
artifact_glob: "packages/desktop/dist/*.AppImage"
- os: macos-15-intel
- os: macos-26-intel
target: macos
source_path: darwin
build_cmd: "--mac"
artifact_glob: "packages/desktop/dist/*.dmg"
- os: macos-latest
target: macos-arm
source_path: darwin
build_cmd: "--mac --arm64"
artifact_glob: "packages/desktop/dist/*.dmg"
- os: windows-latest
target: win
source_path: win32
Expand Down Expand Up @@ -218,7 +223,7 @@ jobs:

build-macos-prod:
# needs: run-e2e-tests-mac
runs-on: macos-15-intel
runs-on: macos-26-intel
if: |
startsWith(github.ref, 'refs/tags/@quiet/desktop')

Expand Down Expand Up @@ -296,6 +301,87 @@ jobs:
version: ${{ steps.extract_version.outputs.version }}
status: ${{ job.status }}
slack_oauth_token: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }}

build-macos-arm64-prod:
# needs: run-e2e-tests-mac
Comment thread
islathehut marked this conversation as resolved.
Outdated
runs-on: macos-26
if: |
startsWith(github.ref, 'refs/tags/@quiet/desktop')

env:
TEST_MODE: ${{ github.event.action == 'prereleased' }}
S3_BUCKET: ${{ github.event.action == 'released' && 'quiet.7.x' || 'test.quiet' }}

steps:
- uses: actions/checkout@v5
with:
submodules: 'recursive'

- name: Extract version
id: extract_version
uses: Saionaro/extract-package-version@fdb5b74adc1278ddb777dfed4c988b9d098bb48d # v1.2.1
with:
path: packages/desktop

- uses: actions-rs/toolchain@16499b5e05bf2e26879000db0c1d13f7e13fa3af # v1.0.7
with:
toolchain: stable
components: clippy
override: true

- name: Setup environment
uses: ./.github/actions/setup-env
with:
bootstrap-packages: "@quiet/eslint-config,@quiet/logger,@quiet/common,@quiet/types,@quiet/state-manager,@quiet/backend,@quiet/identity,@quiet/desktop,backend-bundle,helia,@quiet/node-common"

- name: Before build
uses: ./.github/actions/before-build
with:
source-path: darwin

- name: "Remove crud files"
run: xattr -crs .

- name: "Set electron-builder props"
run: echo "ELECTRON_BUILDER_PROPS=-c.publish.bucket=$S3_BUCKET" >> $GITHUB_ENV

- name: "Release"
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.MAC_CSC_LINK }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASS: ${{ secrets.APPLE_ID_PASS }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
USE_HARD_LINKS: false
run: cd packages/desktop && node_modules/.bin/electron-builder -p always --mac --arm64 ${{ env.ELECTRON_BUILDER_PROPS }}

- name: Get release
id: get_release
uses: bruceadams/get-release@74c3d60f5a28f358ccf241a00c9021ea16f0569f # v1.3.2
env:
GITHUB_TOKEN: ${{ github.token }}

- name: Upload Release Assets
uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5 # v1.0.2
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./packages/desktop/dist/Quiet-${{ steps.extract_version.outputs.version}}-arm64.dmg
asset_name: Quiet-${{ steps.extract_version.outputs.version}}-arm64.dmg
asset_content_type: application/.dmg

- name: Send Release Notificaton
uses: ./.github/actions/release-notifier
if: always()
with:
os-name: MacOS
version: ${{ steps.extract_version.outputs.version }}
status: ${{ job.status }}
slack_oauth_token: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }}

build-windows-prod:
# needs: run-e2e-tests-win
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2e-mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: E2E Mac
on: [workflow_call]
jobs:
mac:
runs-on: macos-15
runs-on: macos-latest
timeout-minutes: 180
env:
TEST_MODE: true
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
### Chores

* Change autoupdater text [#2971](https://github.com/TryQuiet/quiet/issues/2971)
* Fixed issues with testing workflows [#3030] (https://github.com/TryQuiet/quiet/issues/3030)
* Fixed issues with testing workflows [#3030](https://github.com/TryQuiet/quiet/issues/3030)
* Add MacOS arm64-specific build jobs to resolve slow UI startup on Apple Silicon [#3146](https://github.com/TryQuiet/quiet/issues/3146)

### Fixes

Expand Down
41 changes: 32 additions & 9 deletions packages/desktop/src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ let browserHeight: number
// Default title bar must be hidden for macos because we have custom styles for it
const titleBarStyle = process.platform === 'darwin' ? 'hidden' : 'default'
export const createWindow = async () => {
logger.trace('Creating splash and main windows')
logger.trace('Creating main window')
logger.time('Created mainWindow')
mainWindow = new BrowserWindow({
width: windowSize.width,
height: windowSize.height,
Expand All @@ -193,6 +196,8 @@ export const createWindow = async () => {

remote.enable(mainWindow.webContents)

logger.trace('Creating splash window')
logger.time('Created splash')
splash = new BrowserWindow({
width: windowSize.width,
height: windowSize.height,
Expand All @@ -208,8 +213,11 @@ export const createWindow = async () => {

remote.enable(splash.webContents)

logger.trace('Loading splash HTML', splash.id)
// eslint-disable-next-line
splash.loadURL(`file://${__dirname}/splash.html`)
splash.loadURL(`file://${__dirname}/splash.html`)?.then(() => {
logger.timeEnd('Created splash')
})
splash.setAlwaysOnTop(false)
splash.setMovable(true)
splash.show()
Expand All @@ -226,6 +234,7 @@ export const createWindow = async () => {
})

mainWindow.setMinimumSize(600, 400)
logger.trace('Loading main HTML', mainWindow.id)
/* eslint-disable */
mainWindow.loadURL(
url.format({
Expand All @@ -235,7 +244,9 @@ export const createWindow = async () => {
slashes: true,
hash: '/',
})
)
)?.then(() => {
logger.timeEnd('Created mainWindow')
})
/* eslint-enable */
// Emitted when the window is closed.
mainWindow.on('closed', () => {
Expand Down Expand Up @@ -272,7 +283,7 @@ export const createWindow = async () => {
if (!mainWindow || currentFactor <= 0.25) return
mainWindow.webContents.zoomFactor = currentFactor - 0.2
})
logger.info('Created mainWindow')
logger.debug('App windows created')
}

export async function openHCaptcha(siteKey: string): Promise<string> {
Expand Down Expand Up @@ -508,10 +519,13 @@ app.on('ready', async () => {
await sodium.ready
SOCKET_IO_SECRET = sodium.to_hex(sodium.randombytes_buf(32))

logger.trace('Setting application menu')
Menu.setApplicationMenu(null)

logger.trace('Applying dev tools')
await applyDevTools()

logger.trace('Creating context menu')
contextMenu({
showInspectElement: false,
showSaveLinkAs: true,
Expand All @@ -522,17 +536,21 @@ app.on('ready', async () => {
})

if (quitting) {
logger.info('Quit requested before backend setup, skipping startup')
logger.warn('Quit requested before backend setup, skipping startup')
return
}

logger.trace('Getting ports')
ports = await getPorts()

await createWindow()

mainWindow?.webContents.on('did-finish-load', () => {
logger.info('Main window finished loading')
rendererReady = true
// Only send the secret to the renderer via IPC, not via URL
if (splash && !splash.isDestroyed()) {
logger.trace('Destroying splash window and showing main window')
const [width, height] = splash.getSize()
mainWindow?.setSize(width, height)

Expand All @@ -543,6 +561,7 @@ app.on('ready', async () => {
mainWindow?.show()
}

logger.trace('Creating temp files directory')
const temporaryFilesDirectory = path.join(appDataPath, 'temporaryFiles')
fs.mkdirSync(temporaryFilesDirectory, { recursive: true })
fs.readdir(temporaryFilesDirectory, (err, files) => {
Expand All @@ -555,6 +574,7 @@ app.on('ready', async () => {
})
})

logger.info('Forking backend process')
const forkArgvs = [
'-d',
`${ports.dataServer}`,
Expand Down Expand Up @@ -682,11 +702,12 @@ app.on('ready', async () => {
})

mainWindow.on('close', e => {
logger.info('Main window close event received')
if (resetting) return

// --- macOS: hide instead of destroying the renderer ---
if (process.platform === 'darwin' && !updating && backendProcess !== null) {
logger.info('Main window close (macOS) will hide after saving state')
logger.trace('Main window close (macOS) will hide after saving state')
e.preventDefault()
mainWindow?.webContents.send('force-save-state') // state‑saved → hide
return
Expand All @@ -707,6 +728,7 @@ app.on('ready', async () => {

// splash window is destroyed when mainWindow is ready and close should not fire in regular case
splash?.once('close', e => {
logger.trace('Splash window close event received')
if (resetting) return

// in the case where the user closes the splash window before the main window is ready
Expand All @@ -715,15 +737,16 @@ app.on('ready', async () => {
if (!updating) {
e.preventDefault()
}
logger.info('Closing splash window')
logger.trace('Closing splash window')
backendProcess?.send('close')
return
}
logger.info('Splash window close event, saving state')
logger.trace('Splash window close event, saving state')
mainWindow?.webContents.send('force-save-state')
})

ipcMain.on('state-saved', () => {
logger.info('ipcMain: state-saved')
if (updating) return

if (backendProcess === null) {
Expand All @@ -732,7 +755,7 @@ app.on('ready', async () => {
return
}
if (process.platform === 'darwin' && !updating) {
logger.info('Saved state hiding window (macOS)')
logger.trace('Saved state hiding window (macOS)')
mainWindow?.hide()
} else {
logger.info('Saved state closing window')
Expand Down Expand Up @@ -841,7 +864,7 @@ app.on('ready', async () => {
})

app.on('browser-window-created', (_, window) => {
logger.info('Event: app.browser-window-created', window.getTitle())
logger.info('Event: app.browser-window-created', window.id)
remote.enable(window.webContents)
})

Expand Down
Loading