From 80b499fb36b69e8ded67c21634a587bddf5f0038 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Wed, 9 Jul 2025 21:51:17 +0100 Subject: [PATCH 1/9] Support custom settings (#229) * Support custom settings * Build plugin --- .../electron-plugin/dist/server/api/system.js | 16 +++++++------- .../electron-plugin/src/server/api/system.ts | 21 ++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/resources/js/electron-plugin/dist/server/api/system.js b/resources/js/electron-plugin/dist/server/api/system.js index 6cb9594a..73042e27 100644 --- a/resources/js/electron-plugin/dist/server/api/system.js +++ b/resources/js/electron-plugin/dist/server/api/system.js @@ -62,15 +62,17 @@ router.get('/printers', (req, res) => __awaiter(void 0, void 0, void 0, function }); })); router.post('/print', (req, res) => __awaiter(void 0, void 0, void 0, function* () { - const { printer, html } = req.body; + const { printer, html, settings } = req.body; let printWindow = new BrowserWindow({ show: false, }); + const defaultSettings = { + silent: true, + deviceName: printer, + }; + const mergedSettings = Object.assign(Object.assign({}, defaultSettings), (settings && typeof settings === 'object' ? settings : {})); printWindow.webContents.on('did-finish-load', () => { - printWindow.webContents.print({ - silent: true, - deviceName: printer, - }, (success, errorType) => { + printWindow.webContents.print(mergedSettings, (success, errorType) => { if (success) { console.log('Print job completed successfully.'); res.sendStatus(200); @@ -88,12 +90,12 @@ router.post('/print', (req, res) => __awaiter(void 0, void 0, void 0, function* yield printWindow.loadURL(`data:text/html;charset=UTF-8,${html}`); })); router.post('/print-to-pdf', (req, res) => __awaiter(void 0, void 0, void 0, function* () { - const { html } = req.body; + const { html, settings } = req.body; let printWindow = new BrowserWindow({ show: false, }); printWindow.webContents.on('did-finish-load', () => { - printWindow.webContents.printToPDF({}).then(data => { + printWindow.webContents.printToPDF(settings !== null && settings !== void 0 ? settings : {}).then(data => { printWindow.close(); res.json({ result: data.toString('base64'), diff --git a/resources/js/electron-plugin/src/server/api/system.ts b/resources/js/electron-plugin/src/server/api/system.ts index 8c6fa213..4c74e0a0 100644 --- a/resources/js/electron-plugin/src/server/api/system.ts +++ b/resources/js/electron-plugin/src/server/api/system.ts @@ -60,17 +60,24 @@ router.get('/printers', async (req, res) => { }); router.post('/print', async (req, res) => { - const {printer, html} = req.body; + const {printer, html, settings} = req.body; let printWindow = new BrowserWindow({ show: false, }); + const defaultSettings = { + silent: true, + deviceName: printer, + }; + + const mergedSettings = { + ...defaultSettings, + ...(settings && typeof settings === 'object' ? settings : {}), + }; + printWindow.webContents.on('did-finish-load', () => { - printWindow.webContents.print({ - silent: true, - deviceName: printer, - }, (success, errorType) => { + printWindow.webContents.print(mergedSettings, (success, errorType) => { if (success) { console.log('Print job completed successfully.'); res.sendStatus(200); @@ -89,14 +96,14 @@ router.post('/print', async (req, res) => { }); router.post('/print-to-pdf', async (req, res) => { - const {html} = req.body; + const {html, settings} = req.body; let printWindow = new BrowserWindow({ show: false, }); printWindow.webContents.on('did-finish-load', () => { - printWindow.webContents.printToPDF({}).then(data => { + printWindow.webContents.printToPDF(settings ?? {}).then(data => { printWindow.close(); res.json({ result: data.toString('base64'), From ef114f3ec138fa82525e3f2c78d6f18dcdb788a0 Mon Sep 17 00:00:00 2001 From: Willem Leuverink Date: Wed, 16 Jul 2025 09:50:34 +0200 Subject: [PATCH 2/9] remove storage:link (#232) --- .github/workflows/build-plugin.yml | 2 +- resources/js/electron-plugin/dist/server/php.js | 4 ---- resources/js/electron-plugin/src/server/php.ts | 12 ------------ 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/.github/workflows/build-plugin.yml b/.github/workflows/build-plugin.yml index 7d00c675..c811ab37 100644 --- a/.github/workflows/build-plugin.yml +++ b/.github/workflows/build-plugin.yml @@ -36,7 +36,7 @@ jobs: - name: Commit changes if: github.event_name == 'pull_request' - uses: stefanzweifel/git-auto-commit-action@v6 + uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: Build plugin diff --git a/resources/js/electron-plugin/dist/server/php.js b/resources/js/electron-plugin/dist/server/php.js index 0d65dc55..aa6420f5 100644 --- a/resources/js/electron-plugin/dist/server/php.js +++ b/resources/js/electron-plugin/dist/server/php.js @@ -208,10 +208,6 @@ function serveApp(secret, apiPort, phpIniSettings) { const store = new Store({ name: 'nativephp', }); - if (!runningSecureBuild()) { - console.log('Linking storage path...'); - callPhp(['artisan', 'storage:link', '--force'], phpOptions, phpIniSettings); - } if (shouldOptimize(store)) { console.log('Caching view and routes...'); let result = callPhpSync(['artisan', 'optimize'], phpOptions, phpIniSettings); diff --git a/resources/js/electron-plugin/src/server/php.ts b/resources/js/electron-plugin/src/server/php.ts index e6301ad9..2d0f5ebe 100644 --- a/resources/js/electron-plugin/src/server/php.ts +++ b/resources/js/electron-plugin/src/server/php.ts @@ -311,18 +311,6 @@ function serveApp(secret, apiPort, phpIniSettings): Promise { name: 'nativephp', // So it doesn't conflict with settings of the app }); - // Make sure the storage path is linked - as people can move the app around, we - // need to run this every time the app starts - if (!runningSecureBuild()) { - /* - * Simon: Note for later that we should strip out using storage:link - * all of the necessary files for the app to function should be a part of the bundle - * (whether it's a secured bundle or not), so symlinking feels redundant - */ - console.log('Linking storage path...'); - callPhp(['artisan', 'storage:link', '--force'], phpOptions, phpIniSettings) - } - // Cache the project if (shouldOptimize(store)) { console.log('Caching view and routes...'); From 5a850c0e366cce918305ea39c35e6bee05e94d25 Mon Sep 17 00:00:00 2001 From: Brian Faust Date: Sat, 26 Jul 2025 14:20:37 +0300 Subject: [PATCH 3/9] feat: add Azure code signing configuration (#235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add Azure code signing configuration Add support for Azure code signing in Electron builder configuration. Includes environment variables for publisher name, endpoint, certificate profile name, and code signing account name. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * feat: add Azure Trusted Signing environment variables Add support for Azure Trusted Signing by including necessary environment variables in the build process. This enables code signing for Windows applications using Azure's Trusted Signing service. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- resources/js/electron-builder.js | 16 +++++++++++++++- src/Commands/BuildCommand.php | 8 ++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/resources/js/electron-builder.js b/resources/js/electron-builder.js index 8a8a9a2f..71390562 100644 --- a/resources/js/electron-builder.js +++ b/resources/js/electron-builder.js @@ -1,5 +1,5 @@ -import { join } from 'path'; import { exec } from 'child_process'; +import { join } from 'path'; const appUrl = process.env.APP_URL; const appId = process.env.NATIVEPHP_APP_ID; @@ -11,6 +11,12 @@ const appVersion = process.env.NATIVEPHP_APP_VERSION; const appCopyright = process.env.NATIVEPHP_APP_COPYRIGHT; const deepLinkProtocol = process.env.NATIVEPHP_DEEPLINK_SCHEME; +// Azure signing configuration +const azurePublisherName = process.env.NATIVEPHP_AZURE_PUBLISHER_NAME; +const azureEndpoint = process.env.NATIVEPHP_AZURE_ENDPOINT; +const azureCertificateProfileName = process.env.NATIVEPHP_AZURE_CERTIFICATE_PROFILE_NAME; +const azureCodeSigningAccountName = process.env.NATIVEPHP_AZURE_CODE_SIGNING_ACCOUNT_NAME; + // Since we do not copy the php executable here, we only need these for building const isWindows = process.argv.includes('--win'); const isLinux = process.argv.includes('--linux'); @@ -78,6 +84,14 @@ export default { afterSign: 'build/notarize.js', win: { executableName: fileName, + ...(azurePublisherName && azureEndpoint && azureCertificateProfileName && azureCodeSigningAccountName ? { + azureSignOptions: { + publisherName: azurePublisherName, + endpoint: azureEndpoint, + certificateProfileName: azureCertificateProfileName, + codeSigningAccountName: azureCodeSigningAccountName + } + } : {}), }, nsis: { artifactName: appName + '-${version}-setup.${ext}', diff --git a/src/Commands/BuildCommand.php b/src/Commands/BuildCommand.php index 50649647..e5db8d23 100644 --- a/src/Commands/BuildCommand.php +++ b/src/Commands/BuildCommand.php @@ -154,6 +154,14 @@ protected function getEnvironmentVariables(): array 'NATIVEPHP_APPLE_ID' => config('nativephp-internal.notarization.apple_id'), 'NATIVEPHP_APPLE_ID_PASS' => config('nativephp-internal.notarization.apple_id_pass'), 'NATIVEPHP_APPLE_TEAM_ID' => config('nativephp-internal.notarization.apple_team_id'), + // Azure Trusted Signing + 'AZURE_TENANT_ID' => config('nativephp-internal.azure_trusted_signing.tenant_id'), + 'AZURE_CLIENT_ID' => config('nativephp-internal.azure_trusted_signing.client_id'), + 'AZURE_CLIENT_SECRET' => config('nativephp-internal.azure_trusted_signing.client_secret'), + 'NATIVEPHP_AZURE_PUBLISHER_NAME' => config('nativephp-internal.azure_trusted_signing.publisher_name'), + 'NATIVEPHP_AZURE_ENDPOINT' => config('nativephp-internal.azure_trusted_signing.endpoint'), + 'NATIVEPHP_AZURE_CERTIFICATE_PROFILE_NAME' => config('nativephp-internal.azure_trusted_signing.certificate_profile_name'), + 'NATIVEPHP_AZURE_CODE_SIGNING_ACCOUNT_NAME' => config('nativephp-internal.azure_trusted_signing.code_signing_account_name'), ], Updater::environmentVariables(), ); From effb9a5763fe4944b5107f7bb4708e5f7cb7d321 Mon Sep 17 00:00:00 2001 From: Simon Hamp Date: Sat, 26 Jul 2025 10:18:22 -0400 Subject: [PATCH 4/9] Update funding.yml --- .github/funding.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/funding.yml b/.github/funding.yml index 23b9601c..f91f9af1 100644 --- a/.github/funding.yml +++ b/.github/funding.yml @@ -1,2 +1 @@ -github: simonhamp open_collective: nativephp From e07e23b9e6e429e9a2383568831a816290708392 Mon Sep 17 00:00:00 2001 From: Willem Leuverink Date: Wed, 30 Jul 2025 22:18:57 +0200 Subject: [PATCH 5/9] only notarize mac builds (#239) --- resources/js/build/notarize.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/js/build/notarize.js b/resources/js/build/notarize.js index 4ac77f9e..8f2b6ccd 100644 --- a/resources/js/build/notarize.js +++ b/resources/js/build/notarize.js @@ -1,7 +1,11 @@ import { notarize } from '@electron/notarize'; export default async (context) => { - if (process.platform !== 'darwin') return + // Only notarize when process is running on a Mac + if (process.platform !== 'darwin') return; + + // And the current build target is macOS + if (context.packager.platform.name !== 'mac') return; console.log('aftersign hook triggered, start to notarize app.') From f924edc7249ee99e4543c7818713419e727f69ca Mon Sep 17 00:00:00 2001 From: Willem Leuverink Date: Mon, 4 Aug 2025 17:40:13 +0200 Subject: [PATCH 6/9] always use php-bin cacert.pem - even for custom binaries (#238) --- src/Traits/CopiesCertificateAuthority.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Traits/CopiesCertificateAuthority.php b/src/Traits/CopiesCertificateAuthority.php index ce627cce..83ba132e 100644 --- a/src/Traits/CopiesCertificateAuthority.php +++ b/src/Traits/CopiesCertificateAuthority.php @@ -17,13 +17,6 @@ protected function copyCertificateAuthorityCertificate(): void $phpBinaryDirectory = base_path('vendor/nativephp/php-bin/'); - // Check if the class this trait is used in also uses LocatesPhpBinary - /* @phpstan-ignore-next-line */ - if (method_exists($this, 'phpBinaryPath')) { - // Get binary directory but up one level - $phpBinaryDirectory = dirname(base_path($this->phpBinaryPath())); - } - $certificateFileName = 'cacert.pem'; $certFilePath = Path::join($phpBinaryDirectory, $certificateFileName); From 0375d392c97ba976b509571748c5cc415568574d Mon Sep 17 00:00:00 2001 From: Willem Leuverink Date: Mon, 4 Aug 2025 19:22:46 +0200 Subject: [PATCH 7/9] add `storage/hot` to exclude files (#242) --- src/Traits/CopiesToBuildDirectory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Traits/CopiesToBuildDirectory.php b/src/Traits/CopiesToBuildDirectory.php index f3e2f066..d6a36881 100644 --- a/src/Traits/CopiesToBuildDirectory.php +++ b/src/Traits/CopiesToBuildDirectory.php @@ -44,6 +44,7 @@ abstract protected function sourcePath(string $path = ''): string; 'storage/framework/cache/*', 'storage/framework/views/*', 'storage/logs/*', + 'storage/hot', // Only needed for local testing 'vendor/nativephp/electron/resources', From 8f1686243a06e86f930de0b34b8c1de99af5783e Mon Sep 17 00:00:00 2001 From: Willem Leuverink Date: Mon, 4 Aug 2025 19:23:44 +0200 Subject: [PATCH 8/9] remove workingDirectory from Windows deep-link handler (#241) * remove workingDirectory * Build plugin --------- Co-authored-by: gwleuverink <17123491+gwleuverink@users.noreply.github.com> --- resources/js/electron-plugin/dist/index.js | 1 - resources/js/electron-plugin/src/index.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/resources/js/electron-plugin/dist/index.js b/resources/js/electron-plugin/dist/index.js index 830fddd1..c8540284 100644 --- a/resources/js/electron-plugin/dist/index.js +++ b/resources/js/electron-plugin/dist/index.js @@ -149,7 +149,6 @@ class NativePHP { event: "\\Native\\Laravel\\Events\\App\\OpenedFromURL", payload: { url: commandLine[commandLine.length - 1], - workingDirectory: workingDirectory, }, }); }); diff --git a/resources/js/electron-plugin/src/index.ts b/resources/js/electron-plugin/src/index.ts index 52532359..65757030 100644 --- a/resources/js/electron-plugin/src/index.ts +++ b/resources/js/electron-plugin/src/index.ts @@ -201,7 +201,6 @@ class NativePHP { event: "\\Native\\Laravel\\Events\\App\\OpenedFromURL", payload: { url: commandLine[commandLine.length - 1], - workingDirectory: workingDirectory, }, }); }, From c093f8aade01ed92cc27aca363e39a7647d147bc Mon Sep 17 00:00:00 2001 From: WINBIGFOX Date: Mon, 4 Aug 2025 19:24:32 +0200 Subject: [PATCH 9/9] Add `skipTaskbar` and `hiddenInMissionControl` properties to window API (#240) Enhanced the window API by including support for the `skipTaskbar` and `hiddenInMissionControl` properties, enabling more control over window visibility and behavior. --- resources/js/electron-plugin/dist/server/api/window.js | 4 +++- resources/js/electron-plugin/src/server/api/window.ts | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/resources/js/electron-plugin/dist/server/api/window.js b/resources/js/electron-plugin/dist/server/api/window.js index b94d3770..9e1e0a2e 100644 --- a/resources/js/electron-plugin/dist/server/api/window.js +++ b/resources/js/electron-plugin/dist/server/api/window.js @@ -139,7 +139,7 @@ function getWindowData(id) { }; } router.post('/open', (req, res) => { - let { id, x, y, frame, width, height, minWidth, minHeight, maxWidth, maxHeight, focusable, hasShadow, url, resizable, movable, minimizable, maximizable, closable, title, alwaysOnTop, titleBarStyle, trafficLightPosition, vibrancy, backgroundColor, transparency, showDevTools, fullscreen, fullscreenable, kiosk, autoHideMenuBar, webPreferences, } = req.body; + let { id, x, y, frame, width, height, minWidth, minHeight, maxWidth, maxHeight, focusable, skipTaskbar, hiddenInMissionControl, hasShadow, url, resizable, movable, minimizable, maximizable, closable, title, alwaysOnTop, titleBarStyle, trafficLightPosition, vibrancy, backgroundColor, transparency, showDevTools, fullscreen, fullscreenable, kiosk, autoHideMenuBar, webPreferences, } = req.body; if (state.windows[id]) { state.windows[id].show(); state.windows[id].focus(); @@ -179,6 +179,8 @@ router.post('/open', (req, res) => { trafficLightPosition, vibrancy, focusable, + skipTaskbar, + hiddenInMissionControl, autoHideMenuBar }, (process.platform === 'linux' ? { icon: state.icon } : {})), { webPreferences: Object.assign(Object.assign({}, webPreferences), defaultWebPreferences), fullscreen, fullscreenable, kiosk })); diff --git a/resources/js/electron-plugin/src/server/api/window.ts b/resources/js/electron-plugin/src/server/api/window.ts index 3ee8083e..640e0be1 100644 --- a/resources/js/electron-plugin/src/server/api/window.ts +++ b/resources/js/electron-plugin/src/server/api/window.ts @@ -203,6 +203,8 @@ router.post('/open', (req, res) => { maxWidth, maxHeight, focusable, + skipTaskbar, + hiddenInMissionControl, hasShadow, url, resizable, @@ -283,6 +285,8 @@ router.post('/open', (req, res) => { trafficLightPosition, vibrancy, focusable, + skipTaskbar, + hiddenInMissionControl, autoHideMenuBar, ...(process.platform === 'linux' ? {icon: state.icon} : {}), webPreferences: {