Skip to content

Commit 159941b

Browse files
authored
feat: kubo 0.43.0, electron 43 (#3188)
* chore: kubo 0.43.0-rc1 Release candidate, for smoke-testing ahead of the v0.43.0 final. * chore: electron 43.2.0 Brings Chromium 150 and V8 15.0; Node stays on 24.x. None of the Electron 43 breaking changes reach this app: both showOpenDialog call sites already pass an explicit defaultPath, showHiddenFiles is unused, toBitmap is never called, and no window sets titleBarOverlay. The splash is the only frameless window and its artwork clears the new 8 DIP corner clip on Linux, so roundedCorners keeps its default. ensure-electron.js justified its own download path by naming extract-zip, which electron's install.js no longer uses. Reword around the reason that still holds, and drop the version-specific framing so it survives the next bump. * fix: capture screenshots in the main process Electron 17 removed desktopCapturer from the renderer, so the preload has seen it as undefined ever since this app moved to Electron 17 in v0.19.0, and both the tray item and the global shortcut have thrown a TypeError on every use. No webPreferences setting brings it back: sandbox:false and nodeIntegration:true each still leave it undefined. Capture where the API actually lives instead, asking for thumbnails at the display's pixel size so they are full-resolution grabs rather than previews. That drops the renderer round-trip along with getUserMedia, ImageCapture and the canvas data URL. - take-screenshot: captureScreens() over desktopCapturer and screen - webui/screenshot.js and its preload hook are gone - ipc-main-events: nothing sends SCREENSHOT any more An empty thumbnail is how a missing macOS screen-recording grant presents itself, so treat "no usable screen" as an error and raise the existing notification rather than failing silently. Closes #2306 * fix(macos): fetch kubo from github releases kubo 0.43 deprecated distUrl: passing it at all takes the old dist.ipfs.tech code path and prints a deprecation notice on every build. The universal binary step was the last caller still doing that, so move it to releasesUrl, which is where the package already defaults. Matches #3180, which this branch otherwise supersedes by pinning the published kubo release rather than a git revision. * chore: kubo 0.43.0-rc2 * chore: npm audit fix Resolves 15 advisories in transitive dependencies, all within the existing semver ranges, so package.json is unchanged. The 14 remaining need `npm audit fix --force`, which would install ipfsd-ctl@17 as a breaking change. * chore: kubo 0.43.0
1 parent 5cd1123 commit 159941b

8 files changed

Lines changed: 550 additions & 785 deletions

File tree

package-lock.json

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

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"@playwright/test": "^1.50.0",
5454
"cross-env": "^7.0.3",
5555
"dotenv": "^16.0.0",
56-
"electron": "^42.3.3",
56+
"electron": "^43.2.0",
5757
"electron-builder": "26.15.2",
5858
"got": "^12.0.3",
5959
"ipfs-or-gateway": "^4.1.0",
@@ -85,7 +85,7 @@
8585
"ipfs-utils": "^9.0.10",
8686
"ipfsd-ctl": "10.0.6",
8787
"it-last": "^1.0.6",
88-
"kubo": "0.42.0",
88+
"kubo": "0.43.0",
8989
"multiaddr": "10.0.1",
9090
"multiaddr-to-uri": "8.0.0",
9191
"portfinder": "^1.0.32",

pkgs/macos/build-universal-kubo-binary.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const execLog = (cmd) => {
4343
version: kuboVersion,
4444
platform: 'darwin',
4545
arch: arch,
46-
distUrl: 'https://dist.ipfs.tech',
46+
releasesUrl: 'https://github.com/ipfs/kubo/releases',
4747
installPath: archDir
4848
})
4949
console.log(`→ Downloaded ${arch} version to ${archDir}`)

scripts/ensure-electron.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
'use strict'
22

3-
// Electron 42 stopped downloading its binary during `postinstall` (npm
3+
// The electron package does not download its binary during `postinstall` (npm
44
// supply-chain hardening); it is fetched lazily on first run of the electron
55
// bin. Our tests `require('electron')` in a plain Node context, which reads
66
// node_modules/electron/path.txt synchronously, so the binary must be on disk
77
// before the (parallel) Playwright workers start.
88
//
99
// We download via @electron/get (awaited, so a failed fetch is loud) and
10-
// extract with the platform's system unzip. Electron's own install.js, and the
11-
// extract-zip library it uses, extract on an async code path that does not keep
12-
// the Node event loop alive on the CI runners: the process exits mid-extract
13-
// (leaving an empty dist/) or, if held open, hangs. A synchronous, time-bounded
14-
// system extraction avoids both.
10+
// extract with the platform's system unzip. Electron's own install.js extracts
11+
// on an async code path with no lock around node_modules/electron/dist, which
12+
// on the CI runners has exited mid-extract (leaving an empty dist/) or hung. A
13+
// single synchronous, time-bounded system extraction avoids both.
1514

1615
const { execFileSync } = require('child_process')
1716
const fs = require('fs')

src/common/ipc-main-events.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const ipcMainEvents = Object.freeze({
1010
MENUBAR_OPEN: 'menubar-will-open',
1111
UPDATING: 'updating',
1212
UPDATING_ENDED: 'updatingEnded',
13-
SCREENSHOT: 'screenshot',
1413
COUNTLY_ADD_CONSENT: 'countly.addConsent',
1514
COUNTLY_REMOVE_CONSENT: 'countly.removeConsent',
1615
ONLINE_STATUS_CHANGED: 'online-status-changed',

src/take-screenshot.js

Lines changed: 65 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
const i18n = require('i18next')
2-
const { clipboard, nativeImage, ipcMain } = require('electron')
2+
const { clipboard, desktopCapturer, screen } = require('electron')
33
const logger = require('./common/logger')
44
const { IS_MAC } = require('./common/consts')
55
const { notify, notifyError } = require('./common/notify')
66
const { SCREENSHOT_SHORTCUT: CONFIG_KEY } = require('./common/config-keys')
77
const setupGlobalShortcut = require('./utils/setup-global-shortcut')
88
const { analyticsKeys } = require('./analytics/keys')
9-
const ipcMainEvents = require('./common/ipc-main-events')
109
const getCtx = require('./context')
1110

1211
const SHORTCUT = IS_MAC
@@ -49,63 +48,80 @@ function onError (e) {
4948
})
5049
}
5150

52-
function handleScreenshot () {
51+
// Ask for thumbnails at the display's pixel size, which is what makes them
52+
// full-resolution grabs rather than previews. getSources rejects fractional
53+
// dimensions, so round before handing the size over.
54+
async function captureScreens () {
55+
const { size, scaleFactor } = screen.getPrimaryDisplay()
56+
57+
const sources = await desktopCapturer.getSources({
58+
types: ['screen'],
59+
thumbnailSize: {
60+
width: Math.round(size.width * scaleFactor),
61+
height: Math.round(size.height * scaleFactor)
62+
}
63+
})
64+
65+
// An empty thumbnail is how a missing screen-recording grant surfaces on
66+
// macOS: getSources still lists the display, it just hands back nothing.
67+
return sources.filter(({ thumbnail }) => !thumbnail.isEmpty())
68+
}
69+
70+
async function takeScreenshot () {
5371
const ctx = getCtx()
5472
const launchWebUI = ctx.getFn('launchWebUI')
5573
const getIpfsd = ctx.getFn('getIpfsd')
56-
return async (_, output) => {
57-
const ipfsd = await getIpfsd()
74+
const ipfsd = await getIpfsd()
5875

59-
if (!ipfsd) {
60-
return
61-
}
76+
if (!ipfsd) {
77+
return
78+
}
79+
80+
const ipfs = ipfsd.api
81+
82+
if (!ipfs) {
83+
logger.info('[screenshot] daemon not running')
84+
return
85+
}
6286

63-
const ipfs = ipfsd.api
87+
try {
88+
logger.info('[screenshot] taking screenshot')
89+
const screens = await captureScreens()
6490

65-
if (!ipfs) {
66-
logger.info('[screenshot] daemon not running')
67-
return
91+
if (screens.length === 0) {
92+
throw new Error('no screen could be captured, screen recording may not be permitted')
6893
}
6994

70-
try {
71-
await makeScreenshotDir(ipfs)
72-
const isDir = output.length > 1
73-
const d = new Date()
74-
const pad = n => String(n).padStart(2, '0')
75-
const date = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
76-
const time = `${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getMilliseconds())}`
77-
let baseName = `/screenshots/${date}_${time}`
78-
79-
if (isDir) {
80-
baseName += '/'
81-
await ipfs.files.mkdir(baseName, { parents: true })
82-
} else {
83-
baseName += '.png'
84-
}
85-
86-
logger.info(`[screenshot] started: writing screenshots to ${baseName}`, { withAnalytics: analyticsKeys.SCREENSHOT_TAKEN })
87-
let lastImage = null
88-
89-
for (const { name, image } of output) {
90-
const img = nativeImage.createFromDataURL(image)
91-
const path = isDir ? `${baseName}${name}.png` : baseName
92-
const { cid } = await ipfs.add(img.toPNG(), { pin: false }) // no low level pin, presence in MFS will be enough to keep it around
93-
await ipfs.files.cp(cid, path)
94-
lastImage = img
95-
}
96-
97-
logger.info(`[screenshot] completed: writing screenshots to ${baseName}`)
98-
onSuccess(ipfs, launchWebUI, baseName, lastImage)
99-
} catch (e) {
100-
onError(e)
95+
await makeScreenshotDir(ipfs)
96+
const isDir = screens.length > 1
97+
const d = new Date()
98+
const pad = n => String(n).padStart(2, '0')
99+
const date = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
100+
const time = `${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getMilliseconds())}`
101+
let baseName = `/screenshots/${date}_${time}`
102+
103+
if (isDir) {
104+
baseName += '/'
105+
await ipfs.files.mkdir(baseName, { parents: true })
106+
} else {
107+
baseName += '.png'
101108
}
102-
}
103-
}
104109

105-
async function takeScreenshot () {
106-
const webui = await getCtx().getProp('webui')
107-
logger.info('[screenshot] taking screenshot')
108-
webui.webContents.send('screenshot')
110+
logger.info(`[screenshot] started: writing screenshots to ${baseName}`, { withAnalytics: analyticsKeys.SCREENSHOT_TAKEN })
111+
let lastImage = null
112+
113+
for (const { name, thumbnail } of screens) {
114+
const path = isDir ? `${baseName}${name}.png` : baseName
115+
const { cid } = await ipfs.add(thumbnail.toPNG(), { pin: false }) // no low level pin, presence in MFS will be enough to keep it around
116+
await ipfs.files.cp(cid, path)
117+
lastImage = thumbnail
118+
}
119+
120+
logger.info(`[screenshot] completed: writing screenshots to ${baseName}`)
121+
onSuccess(ipfs, launchWebUI, baseName, lastImage)
122+
} catch (e) {
123+
onError(e)
124+
}
109125
}
110126

111127
module.exports = function () {
@@ -120,8 +136,6 @@ module.exports = function () {
120136
takeScreenshot()
121137
}
122138
})
123-
124-
ipcMain.on(ipcMainEvents.SCREENSHOT, handleScreenshot())
125139
}
126140

127141
module.exports.takeScreenshot = takeScreenshot

src/webui/preload.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
// @ts-check
22
const { ipcRenderer, contextBridge } = require('electron')
3-
const screenshotHook = require('./screenshot')
43
const connectionHook = require('./connection-status')
54
const { COUNTLY_KEY, VERSION } = require('../common/consts')
65
const ipcMainEvents = require('../common/ipc-main-events')
76

8-
screenshotHook()
97
connectionHook()
108

119
const urlParams = new URLSearchParams(window.location.search)

src/webui/screenshot.js

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)