mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-17 18:05:42 +02:00
EQMS-1548: TraceX desktop app (#9666)
Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
This commit is contained in:
@@ -26,6 +26,7 @@ env:
|
||||
common
|
||||
desktop
|
||||
desktop-package
|
||||
qms-desktop-package
|
||||
dev
|
||||
models
|
||||
packages
|
||||
@@ -807,3 +808,108 @@ jobs:
|
||||
with:
|
||||
name: Huly-Linux
|
||||
path: ./desktop-package/deploy/Huly-linux-*.zip
|
||||
|
||||
qms-dist-build:
|
||||
# if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/s') }}
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/s') }}
|
||||
needs: build
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
filter: tree:0
|
||||
submodules: recursive
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
cache-name: node
|
||||
with:
|
||||
path: |
|
||||
common/temp
|
||||
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
|
||||
- name: Prepare .npmrc for GitHub Packages
|
||||
run: |
|
||||
echo "//npm.pkg.github.com/:_authToken=${{secrets.GITHUB_TOKEN}}" > ~/.npmrc
|
||||
|
||||
- name: Installing...
|
||||
run: node common/scripts/install-run-rush.js install --purge
|
||||
- name: Model version from git tags
|
||||
run: node common/scripts/install-run-rush.js model-version
|
||||
- name: Package
|
||||
run: node common/scripts/install-run-rush.js package --to qms-desktop -v
|
||||
- name: Package JSON
|
||||
run: |
|
||||
cd qms-desktop-package
|
||||
cat ./package.json
|
||||
- name: Install the Apple certificate and provisioning profile
|
||||
env:
|
||||
DEV_ID_P12_BASE64: ${{ secrets.DEV_ID_P12_BASE64 }}
|
||||
DEV_ID_P12_PASSWORD: ${{ secrets.DEV_ID_P12_PASSWORD }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
# create variables
|
||||
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
|
||||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||||
|
||||
# import certificate from secret
|
||||
echo -n "$DEV_ID_P12_BASE64" | base64 --decode -o $CERTIFICATE_PATH
|
||||
|
||||
# create temporary keychain
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
|
||||
# import certificate to keychain
|
||||
security import $CERTIFICATE_PATH -P "$DEV_ID_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||||
- name: Build distribution's
|
||||
env:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_ID_APP_PASS: ${{ secrets.APPLE_ID_APP_PASS }}
|
||||
TEAM_ID: ${{ secrets.TEAM_ID }}
|
||||
run: |
|
||||
cd qms-desktop-package
|
||||
node ../common/scripts/install-run-rushx.js dist --linux --x64
|
||||
node ../common/scripts/install-run-rushx.js dist --windows --x64 --arm64
|
||||
node ../common/scripts/install-run-rushx.js dist-signed --macos --x64 --arm64
|
||||
./scripts/copy-publish-artifacts.sh ${{ env.PublishTempFolder}}
|
||||
- name: Publish distribution assets and version
|
||||
uses: ryand56/r2-upload-action@latest
|
||||
with:
|
||||
r2-account-id: ${{ secrets.R2_ACCOUNT_ID }}
|
||||
r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||
r2-bucket: desktop-distro
|
||||
source-dir: qms-desktop-package/${{ env.PublishTempFolder}}
|
||||
destination-dir: ./
|
||||
- name: Upload MacOS
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: TraceX-MacOS-x64
|
||||
path: ./qms-desktop-package/deploy/TraceX-macos-*-x64.dmg
|
||||
- name: Upload MacOS arm64
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: TraceX-MacOS-arm64
|
||||
path: ./qms-desktop-package/deploy/TraceX-macos-*-arm64.dmg
|
||||
- name: Upload Windows
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: TraceX-Windows
|
||||
path: ./qms-desktop-package/deploy/TraceX-windows-*.zip
|
||||
- name: Upload Linux
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: TraceX-Linux
|
||||
path: ./qms-desktop-package/deploy/TraceX-linux-*.zip
|
||||
Generated
+25
-1
@@ -991,6 +991,9 @@ importers:
|
||||
'@rush-temp/products-resources':
|
||||
specifier: file:./projects/products-resources.tgz
|
||||
version: file:projects/products-resources.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(@types/node@22.15.29)(babel-jest@29.7.0(@babel/core@7.23.9))(esbuild@0.24.2)(postcss-load-config@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3)))(postcss@8.5.3)(ts-node@10.9.2(@types/node@22.15.29)(typescript@5.8.3))
|
||||
'@rush-temp/qms-desktop':
|
||||
specifier: file:./projects/qms-desktop.tgz
|
||||
version: file:projects/qms-desktop.tgz(webpack@5.97.1)
|
||||
'@rush-temp/qms-doc-import-tool':
|
||||
specifier: file:./projects/qms-doc-import-tool.tgz
|
||||
version: file:projects/qms-doc-import-tool.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))
|
||||
@@ -5458,6 +5461,10 @@ packages:
|
||||
resolution: {integrity: sha512-B+3fRdypqBSE3ui4MgFE10DBtbZVLW8Lr+cQQDF7ti1GWp04Vbr0njLPtVvySOAab8pHun4xb2yVz8B31Hr5Nw==, tarball: file:projects/products.tgz}
|
||||
version: 0.0.0
|
||||
|
||||
'@rush-temp/qms-desktop@file:projects/qms-desktop.tgz':
|
||||
resolution: {integrity: sha512-euhJQtYB9bi4EajhGq+TYdDJkmGP5CyFcaAVBLPkmhhKENYJFcLd+E/QbDkWPAZZu7lP9EQ88yFHL5oRBOzyrw==, tarball: file:projects/qms-desktop.tgz}
|
||||
version: 0.0.0
|
||||
|
||||
'@rush-temp/qms-doc-import-tool@file:projects/qms-doc-import-tool.tgz':
|
||||
resolution: {integrity: sha512-sP2ZgSJ1hu7G2DG9l+/D/ZV2T/5TO3Mc5sEfb8zmoAnAqaZM11uPbsfhoJPalgC/gOQGEL7ZYdKhA5EJXU/v4g==, tarball: file:projects/qms-doc-import-tool.tgz}
|
||||
version: 0.0.0
|
||||
@@ -15174,7 +15181,7 @@ snapshots:
|
||||
|
||||
'@electron/notarize@2.5.0':
|
||||
dependencies:
|
||||
debug: 4.3.5
|
||||
debug: 4.4.0
|
||||
fs-extra: 9.1.0
|
||||
promise-retry: 2.0.1
|
||||
transitivePeerDependencies:
|
||||
@@ -25048,6 +25055,23 @@ snapshots:
|
||||
- supports-color
|
||||
- ts-node
|
||||
|
||||
'@rush-temp/qms-desktop@file:projects/qms-desktop.tgz(webpack@5.97.1)':
|
||||
dependencies:
|
||||
'@electron/notarize': 2.5.0
|
||||
'@types/node': 22.15.29
|
||||
'@vercel/webpack-asset-relocator-loader': 1.7.4
|
||||
cross-env: 7.0.3
|
||||
dotenv: 16.0.3
|
||||
electron: 36.3.1
|
||||
electron-builder: 25.1.8
|
||||
electron-squirrel-startup: 1.0.1
|
||||
node-loader: 2.0.0(webpack@5.97.1)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- electron-builder-squirrel-windows
|
||||
- supports-color
|
||||
- webpack
|
||||
|
||||
'@rush-temp/qms-doc-import-tool@file:projects/qms-doc-import-tool.tgz(@babel/core@7.23.9)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))':
|
||||
dependencies:
|
||||
'@types/domhandler': 2.4.5
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Automatomatic updates
|
||||
## Automatic updates
|
||||
|
||||
All builds are published to R2 storage bucket avaialble at https://dist.huly.io
|
||||
All builds are published to R2 storage bucket available at https://dist.huly.io
|
||||
|
||||
To check the latest auto-updatable distributions see
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright © 2025 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
|
||||
interface PackedConfig {
|
||||
server?: string
|
||||
updatesChannelKey?: string
|
||||
}
|
||||
|
||||
const configPath = path.join(process.resourcesPath, 'config/config.json')
|
||||
|
||||
export function readPackedConfig (): PackedConfig | undefined {
|
||||
if (fs.existsSync(configPath)) {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(configPath, 'utf8')) as PackedConfig
|
||||
} catch (err) {
|
||||
console.log('Failed to read packed config', err)
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
-25
@@ -31,7 +31,7 @@ import autoUpdater from './updater'
|
||||
import { generateId } from '@hcengineering/core'
|
||||
import { DownloadItem } from '@hcengineering/desktop-downloads'
|
||||
import { rebuildJumpList, setupWindowsSpecific } from './windowsSpecificSetup'
|
||||
|
||||
import { readPackedConfig } from './config'
|
||||
|
||||
let mainWindow: BrowserWindow | undefined
|
||||
let winBadge: any
|
||||
@@ -47,6 +47,9 @@ const preloadScriptPath = path.join(app.getAppPath(), 'dist', 'main', 'preload.j
|
||||
const defaultWidth = 1440
|
||||
const defaultHeight = 960
|
||||
|
||||
const packedConfig = readPackedConfig()
|
||||
log.info('packed config', packedConfig)
|
||||
|
||||
const envPath = path.join(app.getAppPath(), isDev ? '.env-dev' : '.env')
|
||||
console.log('do loading env from', envPath)
|
||||
dotenvConfig({
|
||||
@@ -74,7 +77,7 @@ function readServerUrl (): string {
|
||||
return process.env.FRONT_URL ?? 'http://huly.local:8087'
|
||||
}
|
||||
|
||||
return ((settings as any).get('server', process.env.FRONT_URL) as string) ?? 'https://huly.app'
|
||||
return ((settings as any).get('server') as string) ?? packedConfig?.server ?? process.env.FRONT_URL ?? 'https://huly.app'
|
||||
}
|
||||
|
||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
||||
@@ -94,7 +97,7 @@ const disabledFeatures = [
|
||||
|
||||
app.commandLine.appendSwitch('disable-features', disabledFeatures.join(','))
|
||||
|
||||
function setupWindowTitleBar(windowOptions: Electron.BrowserWindowConstructorOptions): void {
|
||||
function setupWindowTitleBar (windowOptions: Electron.BrowserWindowConstructorOptions): void {
|
||||
if (isWindows) {
|
||||
// on Windows we use frameless window with custom hand-made title bar
|
||||
windowOptions.frame = false
|
||||
@@ -269,31 +272,31 @@ const createWindow = async (): Promise<void> => {
|
||||
}
|
||||
})
|
||||
|
||||
function sendWindowMaximizedMessage(maximized: boolean): void {
|
||||
function sendWindowMaximizedMessage (maximized: boolean): void {
|
||||
mainWindow?.webContents.send('window-state-changed', maximized ? 'maximized' : 'unmaximized')
|
||||
}
|
||||
|
||||
mainWindow.on('blur', () => {
|
||||
mainWindow?.webContents.send('window-focus-loss')
|
||||
});
|
||||
})
|
||||
|
||||
mainWindow.on('maximize', () => {
|
||||
sendWindowMaximizedMessage(true)
|
||||
});
|
||||
})
|
||||
|
||||
mainWindow.on('unmaximize', () => {
|
||||
sendWindowMaximizedMessage(false)
|
||||
});
|
||||
})
|
||||
|
||||
mainWindow.on('enter-full-screen', () => {
|
||||
sendWindowMaximizedMessage(true)
|
||||
});
|
||||
})
|
||||
|
||||
mainWindow.on('leave-full-screen', () => {
|
||||
if (mainWindow) {
|
||||
if (mainWindow != null) {
|
||||
sendWindowMaximizedMessage(mainWindow.isMaximized())
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (isMac) {
|
||||
mainWindow.on('close', (event) => {
|
||||
@@ -309,12 +312,12 @@ const createWindow = async (): Promise<void> => {
|
||||
}
|
||||
}
|
||||
|
||||
function sendCommand(cmd: string, ...args: any[]): void {
|
||||
function sendCommand (cmd: string, ...args: any[]): void {
|
||||
mainWindow?.webContents.send(cmd, ...args)
|
||||
}
|
||||
|
||||
function activateWindow (): void {
|
||||
if (mainWindow) {
|
||||
if (mainWindow != null) {
|
||||
if (mainWindow.isMinimized()) {
|
||||
mainWindow.restore()
|
||||
}
|
||||
@@ -373,7 +376,23 @@ ipcMain.on('set-combined-config', (_event: any, config: Config) => {
|
||||
setupCookieHandler(config)
|
||||
|
||||
const updatesUrl = process.env.DESKTOP_UPDATES_URL ?? config.DESKTOP_UPDATES_URL ?? 'https://dist.huly.io'
|
||||
const updatesChannel = process.env.DESKTOP_UPDATES_CHANNEL ?? config.DESKTOP_UPDATES_CHANNEL ?? 'huly'
|
||||
// NOTE: env format is: default_value;key1:value1;key2:value2...
|
||||
const updatesChannels = (process.env.DESKTOP_UPDATES_CHANNEL ?? config.DESKTOP_UPDATES_CHANNEL ?? 'huly').split(';').map(c => c.trim().split(':'))
|
||||
const updateChannelsMap: Record<string, string> = {}
|
||||
for (const channelInfo of updatesChannels) {
|
||||
if (channelInfo.length === 1) {
|
||||
updateChannelsMap.default = channelInfo[0]
|
||||
} else if (channelInfo.length === 2) {
|
||||
const [key, value] = channelInfo
|
||||
updateChannelsMap[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
const updatesChannelKey = packedConfig?.updatesChannelKey ?? 'default'
|
||||
const updatesChannel = updateChannelsMap[updatesChannelKey] ?? updateChannelsMap.default ?? 'huly'
|
||||
|
||||
log.info('updates channels', updatesChannels)
|
||||
log.info('updates channel', updatesChannelKey, updatesChannel)
|
||||
|
||||
autoUpdater.setFeedURL({
|
||||
provider: 'generic',
|
||||
@@ -414,35 +433,35 @@ ipcMain.on('set-front-cookie', function (event: any, host: string, name: string,
|
||||
})
|
||||
|
||||
ipcMain.handle('window-minimize', () => {
|
||||
mainWindow?.minimize();
|
||||
});
|
||||
mainWindow?.minimize()
|
||||
})
|
||||
|
||||
ipcMain.handle('window-maximize', () => {
|
||||
if (mainWindow) {
|
||||
if (mainWindow != null) {
|
||||
if (mainWindow.isMaximized()) {
|
||||
mainWindow.unmaximize();
|
||||
mainWindow.unmaximize()
|
||||
} else {
|
||||
mainWindow.maximize();
|
||||
mainWindow.maximize()
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
ipcMain.handle('window-close', () => {
|
||||
mainWindow?.close();
|
||||
});
|
||||
mainWindow?.close()
|
||||
})
|
||||
|
||||
ipcMain.handle('get-is-os-using-dark-theme', () => {
|
||||
return nativeTheme.shouldUseDarkColors;
|
||||
});
|
||||
return nativeTheme.shouldUseDarkColors
|
||||
})
|
||||
|
||||
ipcMain.handle('menu-action', async (_event: any, action: MenuBarAction) => {
|
||||
dipatchMenuBarAction(mainWindow, action)
|
||||
});
|
||||
})
|
||||
|
||||
if (isWindows) {
|
||||
ipcMain.on('rebuild-user-jump-list', (_event: any, spares: JumpListSpares) => {
|
||||
rebuildJumpList(spares)
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
+17
-20
@@ -3,7 +3,7 @@ import { loveId } from '@hcengineering/love'
|
||||
import { timeId } from '@hcengineering/time'
|
||||
|
||||
import { getEmbeddedLabel, getMetadata, translate } from '@hcengineering/platform'
|
||||
import presentation, { MessageBox, setDownloadProgress } from '@hcengineering/presentation'
|
||||
import presentation, { MessageBox, setDownloadProgress, getClient } from '@hcengineering/presentation'
|
||||
import setting, { settingId } from '@hcengineering/setting'
|
||||
import {
|
||||
closePanel,
|
||||
@@ -19,25 +19,21 @@ import {
|
||||
import { handleDownloadItem } from '@hcengineering/desktop-downloads'
|
||||
import notification, { notificationId } from '@hcengineering/notification'
|
||||
import { inboxId } from '@hcengineering/inbox'
|
||||
import { workbenchId, logOut } from '@hcengineering/workbench'
|
||||
import workbench, { workbenchId, logOut } from '@hcengineering/workbench'
|
||||
import { encodeObjectURI } from '@hcengineering/view'
|
||||
import { resolveLocation } from '@hcengineering/notification-resources'
|
||||
|
||||
import { isOwnerOrMaintainer } from '@hcengineering/core'
|
||||
import { isOwnerOrMaintainer, getCurrentAccount } from '@hcengineering/core'
|
||||
import { configurePlatform } from './platform'
|
||||
import { setupTitleBarMenu } from './titleBarMenu'
|
||||
import { defineScreenShare, defineGetDisplayMedia } from './screenShare'
|
||||
import { CommandLogout, CommandSelectWorkspace, CommandOpenSettings, CommandOpenInbox, CommandOpenPlanner, CommandOpenOffice, CommandOpenApplication, LaunchApplication, NotificationParams } from './types'
|
||||
import { ipcMainExposed } from './typesUtils'
|
||||
import { themeStore } from '@hcengineering/theme'
|
||||
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import type { Application } from '@hcengineering/workbench'
|
||||
import { isAllowedToRole } from '@hcengineering/workbench-resources'
|
||||
import workbench from '@hcengineering/workbench'
|
||||
import { getCurrentAccount } from '@hcengineering/core'
|
||||
|
||||
function currentOsIsWindows(): boolean {
|
||||
function currentOsIsWindows (): boolean {
|
||||
return (window as any).windowsPlatform === true
|
||||
}
|
||||
|
||||
@@ -45,12 +41,11 @@ defineScreenShare()
|
||||
defineGetDisplayMedia()
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
const ipcMain = ipcMainExposed()
|
||||
|
||||
if (currentOsIsWindows()) {
|
||||
const titleBarRoot = document.getElementById('desktop-app-titlebar-root')
|
||||
if (titleBarRoot) {
|
||||
if (titleBarRoot != null) {
|
||||
const menuBar = setupTitleBarMenu(ipcMain, titleBarRoot)
|
||||
|
||||
themeStore.subscribe((themeOptions) => {
|
||||
@@ -63,12 +58,13 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
void ipcMain.isOsUsingDarkTheme().then((isDarkTheme) => {
|
||||
menuBar.setTheme(isDarkTheme ? 'dark' : 'light')
|
||||
}).catch(() => {
|
||||
menuBar.setTheme('light'); // fallback
|
||||
menuBar.setTheme('light') // fallback
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const onWorkbenchConnect = currentOsIsWindows() ? async () => {
|
||||
const onWorkbenchConnect = currentOsIsWindows()
|
||||
? async () => {
|
||||
const client = getClient()
|
||||
const account = getCurrentAccount()
|
||||
const excludedApps = getMetadata(workbench.metadata.ExcludedApplications) ?? []
|
||||
@@ -79,33 +75,34 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
.filter((it: Application) => !excludedApps.includes(it._id))
|
||||
.filter((it: Application) => isAllowedToRole(it.accessLevel, account))
|
||||
|
||||
const tasks: LaunchApplication[] = [];
|
||||
const tasks: LaunchApplication[] = []
|
||||
|
||||
for (const application of applications) {
|
||||
const title = await translate(application.label, {})
|
||||
tasks.push({
|
||||
title: title,
|
||||
title,
|
||||
id: application._id,
|
||||
alias: application.alias,
|
||||
});
|
||||
alias: application.alias
|
||||
})
|
||||
}
|
||||
ipcMain.rebuildJumpList({
|
||||
applications: tasks,
|
||||
settingsLabel: await translate(setting.string.Settings, {}),
|
||||
inboxLabel: await translate(notification.string.Inbox, {}),
|
||||
inboxLabel: await translate(notification.string.Inbox, {})
|
||||
})
|
||||
} : undefined
|
||||
}
|
||||
: undefined
|
||||
|
||||
void configurePlatform(onWorkbenchConnect).then((parameters) => {
|
||||
const windowTitle = document.getElementById('application-title-bar-caption')
|
||||
if (windowTitle) {
|
||||
if (windowTitle != null) {
|
||||
windowTitle.textContent = parameters.getBranding().getTitle()
|
||||
}
|
||||
|
||||
createApp(document.body)
|
||||
})
|
||||
|
||||
function openScreen(screenId: any): void {
|
||||
function openScreen (screenId: any): void {
|
||||
closePopup()
|
||||
closePanel()
|
||||
const loc = getCurrentResolvedLocation()
|
||||
|
||||
@@ -198,7 +198,7 @@ services:
|
||||
- SIGN_URL=http://huly.local:4006
|
||||
# - ANALYTICS_COLLECTOR_URL=http://huly.local:4017
|
||||
- DESKTOP_UPDATES_URL=https://dist.huly.io
|
||||
- DESKTOP_UPDATES_CHANNEL=dev
|
||||
- DESKTOP_UPDATES_CHANNEL=dev;tracex:dev-tracex
|
||||
- BRANDING_URL=http://huly.local:8087/branding.json
|
||||
- STREAM_URL=http://huly.local:1080/recording
|
||||
# - DISABLE_SIGNUP=true
|
||||
|
||||
@@ -252,7 +252,7 @@ services:
|
||||
- SIGN_URL=http://huly.local:4006
|
||||
# - ANALYTICS_COLLECTOR_URL=http://huly.local:4017
|
||||
- DESKTOP_UPDATES_URL=https://dist.huly.io
|
||||
- DESKTOP_UPDATES_CHANNEL=dev
|
||||
- DESKTOP_UPDATES_CHANNEL=dev;tracex:dev-tracex
|
||||
- BRANDING_URL=http://huly.local:8087/branding.json
|
||||
- STREAM_URL=http://huly.local:1080/recording
|
||||
- COMMUNICATION_API_ENABLED=true
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# APPLE_ID=team-member-apple-id
|
||||
# APPLE_ID_APP_PASS=team-members-app-pass
|
||||
# TEAM_ID=apple-dev-team-id
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig",
|
||||
"rigProfile": "package"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,3 @@
|
||||
!macro customInit
|
||||
StrCpy $INSTDIR "$LOCALAPPDATA\Programs\TraceXDesktop"
|
||||
!macroend
|
||||
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"name": "qms-desktop",
|
||||
"version": "0.7.158",
|
||||
"main": "dist/main/electron.js",
|
||||
"author": "Hardcore Engineering <hey@huly.io>",
|
||||
"template": "@hcengineering/default-package",
|
||||
"scripts": {
|
||||
"_phase:package": "rushx package",
|
||||
"package": "rushx bump && rm -rf ./dist && cp -r ../desktop/dist . && cp ../desktop/.env ./dist && cp src/AppIcon.png ./dist/ui/public && cp src/AppIcon.ico ./dist/ui/public && echo 'done'",
|
||||
"dist": "cross-env CSC_IDENTITY_AUTO_DISCOVERY=false NODE_ENV=production VERSION=$(node ../common/scripts/show_tag.js) MODEL_VERSION=$(node ../common/scripts/show_version.js) electron-builder build -p onTag",
|
||||
"dist-local": "cross-env CSC_IDENTITY_AUTO_DISCOVERY=false NODE_ENV=production VERSION=$(node ../common/scripts/show_tag.js) MODEL_VERSION=$(node ../common/scripts/show_version.js) electron-builder build",
|
||||
"dist-signed": "cross-env CSC_IDENTITY_AUTO_DISCOVERY=true NODE_ENV=production VERSION=$(node ../common/scripts/show_tag.js) MODEL_VERSION=$(node ../common/scripts/show_version.js) electron-builder build -c.afterSign=scripts/notarize.js -p onTag",
|
||||
"dist-mac-win": "cross-env CSC_IDENTITY_AUTO_DISCOVERY=false NODE_ENV=production VERSION=$(node ../common/scripts/show_tag.js) MODEL_VERSION=$(node ../common/scripts/show_version.js) electron-builder build --windows --x64",
|
||||
"format": "echo done",
|
||||
"bump": "bump-package-version"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@hcengineering/desktop": "^0.6.0",
|
||||
"@vercel/webpack-asset-relocator-loader": "^1.7.3",
|
||||
"node-loader": "~2.0.0",
|
||||
"cross-env": "~7.0.3",
|
||||
"typescript": "^5.8.3",
|
||||
"electron": "^36.3.1",
|
||||
"@types/node": "^22.15.29",
|
||||
"electron-builder": "^25.1.8",
|
||||
"@electron/notarize": "^2.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-squirrel-startup": "~1.0.0",
|
||||
"dotenv": "~16.0.0"
|
||||
},
|
||||
"homepage": "https://tracex.co/",
|
||||
"productName": "TraceX Desktop",
|
||||
"description": "TraceX Desktop experience",
|
||||
"build": {
|
||||
"productName": "TraceX",
|
||||
"appId": "app.huly.TraceX",
|
||||
"directories": {
|
||||
"output": "deploy"
|
||||
},
|
||||
"files": [
|
||||
"./dist/**"
|
||||
],
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "./src/config/",
|
||||
"to": "./config/",
|
||||
"filter": [
|
||||
"**/*.json"
|
||||
]
|
||||
}
|
||||
],
|
||||
"mac": {
|
||||
"category": "public.app-category.utilities",
|
||||
"artifactName": "TraceX-macos-${version}-${arch}.${ext}",
|
||||
"target": "default",
|
||||
"icon": "./src/AppIcon.icns",
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "./entitlements.mac.plist",
|
||||
"entitlementsInherit": "./entitlements.mac.plist",
|
||||
"notarize": false,
|
||||
"publish": {
|
||||
"provider": "generic",
|
||||
"url": "https://dist.huly.io",
|
||||
"channel": "qms-latest"
|
||||
}
|
||||
},
|
||||
"win": {
|
||||
"target": [
|
||||
"zip",
|
||||
"nsis"
|
||||
],
|
||||
"artifactName": "TraceX-windows-${version}.${ext}",
|
||||
"verifyUpdateCodeSignature": false,
|
||||
"icon": "./src/AppIcon.ico",
|
||||
"publish": {
|
||||
"provider": "generic",
|
||||
"url": "https://dist.huly.io",
|
||||
"channel": "qms-latest"
|
||||
},
|
||||
"extraResources": [
|
||||
{
|
||||
"from": "./dist/ui/public/icons/",
|
||||
"to": "./icons/",
|
||||
"filter": [
|
||||
"**/*.ico"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"nsis": {
|
||||
"include": "installer.nsh",
|
||||
"installerIcon": "./src/AppIcon.ico",
|
||||
"uninstallerIcon": "./src/AppIcon.ico"
|
||||
},
|
||||
"linux": {
|
||||
"artifactName": "TraceX-linux-${version}.${ext}",
|
||||
"target": [
|
||||
"AppImage",
|
||||
"deb",
|
||||
"zip"
|
||||
],
|
||||
"category": "Utility",
|
||||
"publish": {
|
||||
"provider": "generic",
|
||||
"url": "https://dist.huly.io",
|
||||
"channel": "qms-latest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"electron",
|
||||
"typescript",
|
||||
"svelte"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
## Automatic updates
|
||||
|
||||
All builds are published to R2 storage bucket available at https://dist.huly.io
|
||||
|
||||
To check the latest auto-updatable distributions see
|
||||
|
||||
* MacOS: https://dist.huly.io/qms-latest-mac.yml
|
||||
* Linux: https://dist.huly.io/qms-latest-linux.yml
|
||||
* Windows: https://dist.huly.io/qms-latest.yml
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
SRC_FOLDER=deploy
|
||||
TARGET_FOLDER=$1
|
||||
CHANNEL=qms-latest
|
||||
|
||||
set -e
|
||||
if [ -d "$TARGET_FOLDER" ]; then rm -Rf $TARGET_FOLDER; fi
|
||||
mkdir $TARGET_FOLDER
|
||||
|
||||
cp $SRC_FOLDER/*.blockmap $TARGET_FOLDER
|
||||
cp $SRC_FOLDER/*.dmg $TARGET_FOLDER
|
||||
cp $SRC_FOLDER/*.zip $TARGET_FOLDER
|
||||
cp $SRC_FOLDER/*.AppImage $TARGET_FOLDER
|
||||
cp $SRC_FOLDER/*.deb $TARGET_FOLDER
|
||||
cp $SRC_FOLDER/*.exe $TARGET_FOLDER
|
||||
cp $SRC_FOLDER/$CHANNEL.yml $TARGET_FOLDER
|
||||
cp $SRC_FOLDER/$CHANNEL-mac.yml $TARGET_FOLDER
|
||||
cp $SRC_FOLDER/$CHANNEL-linux.yml $TARGET_FOLDER
|
||||
|
||||
# Create version-specific description files
|
||||
rawVersion=$(node ../common/scripts/show_tag.js)
|
||||
version=${rawVersion:1:${#rawVersion}-2}
|
||||
|
||||
cp $SRC_FOLDER/$CHANNEL.yml $TARGET_FOLDER/qms-${version}.yml
|
||||
cp $SRC_FOLDER/$CHANNEL-mac.yml $TARGET_FOLDER/qms-${version}-mac.yml
|
||||
cp $SRC_FOLDER/$CHANNEL-linux.yml $TARGET_FOLDER/qms-${version}-linux.yml
|
||||
@@ -0,0 +1,41 @@
|
||||
require('dotenv').config();
|
||||
const { notarize } = require('@electron/notarize');
|
||||
|
||||
async function retryNotarize(options, retries = 5, delay = 5000) {
|
||||
for (let i = 0; i < retries; i++) {
|
||||
try {
|
||||
console.log(`Attempt ${i + 1} to notarize...`);
|
||||
await notarize(options);
|
||||
console.log('Notarization successful');
|
||||
return;
|
||||
} catch (error) {
|
||||
console.error(`Notarization attempt ${i + 1} failed:`, error);
|
||||
if (i < retries - 1) {
|
||||
console.log(`Retrying in ${delay / 1000} seconds...`);
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
delay *= 2; // Increase delay for the next retry
|
||||
} else {
|
||||
console.log('All notarization attempts failed...');
|
||||
// Add any necessary teardown logic here
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.default = async function notarizing(context) {
|
||||
const { electronPlatformName, appOutDir } = context;
|
||||
if (electronPlatformName !== 'darwin') {
|
||||
return;
|
||||
}
|
||||
|
||||
const appName = context.packager.appInfo.productFilename;
|
||||
|
||||
console.log('Starting custom notarization process...');
|
||||
await retryNotarize({
|
||||
appPath: `${appOutDir}/${appName}.app`,
|
||||
appleId: process.env.APPLE_ID,
|
||||
appleIdPassword: process.env.APPLE_ID_APP_PASS,
|
||||
teamId: process.env.TEAM_ID
|
||||
});
|
||||
};
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 813 KiB |
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"server": "https://tracex.huly.app",
|
||||
"updatesChannelKey": "tracex"
|
||||
}
|
||||
Reference in New Issue
Block a user