opencube 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/main.js +76 -14
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -16,6 +16,7 @@ const ICON_PATH = process.env.OPENCODE_PET_ICON || path.join(__dirname, "..", "a
|
|
|
16
16
|
const MAX_EVENTS = 100
|
|
17
17
|
const MAX_INTERACTION_EVENTS = 80
|
|
18
18
|
const IDLE_TTL_MS = 5 * 60 * 1000
|
|
19
|
+
const PET_WINDOW_SIZE = 120
|
|
19
20
|
|
|
20
21
|
let petWindow = null
|
|
21
22
|
let panelWindow = null
|
|
@@ -31,17 +32,68 @@ let pendingQuestionsByRequest = new Map()
|
|
|
31
32
|
let cleanupTimer = null
|
|
32
33
|
let dragState = null
|
|
33
34
|
|
|
35
|
+
function normalizeDragPoint(point) {
|
|
36
|
+
const screenX = Number(point?.screenX)
|
|
37
|
+
const screenY = Number(point?.screenY)
|
|
38
|
+
if (!Number.isFinite(screenX) || !Number.isFinite(screenY)) return null
|
|
39
|
+
return { screenX, screenY }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function clamp(value, min, max) {
|
|
43
|
+
return Math.max(min, Math.min(max, value))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getVirtualWorkArea() {
|
|
47
|
+
const displays = screen.getAllDisplays()
|
|
48
|
+
if (!displays.length) return screen.getPrimaryDisplay().workArea
|
|
49
|
+
|
|
50
|
+
return displays.reduce((area, display) => {
|
|
51
|
+
const next = display.workArea
|
|
52
|
+
const left = Math.min(area.x, next.x)
|
|
53
|
+
const top = Math.min(area.y, next.y)
|
|
54
|
+
const right = Math.max(area.x + area.width, next.x + next.width)
|
|
55
|
+
const bottom = Math.max(area.y + area.height, next.y + next.height)
|
|
56
|
+
return { x: left, y: top, width: right - left, height: bottom - top }
|
|
57
|
+
}, displays[0].workArea)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function normalizeWindowPosition(x, y, win) {
|
|
61
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || !win || win.isDestroyed()) return null
|
|
62
|
+
|
|
63
|
+
const bounds = win.getBounds()
|
|
64
|
+
const area = getVirtualWorkArea()
|
|
65
|
+
const minX = area.x
|
|
66
|
+
const minY = area.y
|
|
67
|
+
const maxX = area.x + area.width - Math.max(1, bounds.width)
|
|
68
|
+
const maxY = area.y + area.height - Math.max(1, bounds.height)
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
x: Math.round(clamp(x, Math.min(minX, maxX), Math.max(minX, maxX))),
|
|
72
|
+
y: Math.round(clamp(y, Math.min(minY, maxY), Math.max(minY, maxY))),
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
34
76
|
ipcMain.on("opencube-drag-start", (event, point) => {
|
|
35
77
|
if (!petWindow || petWindow.isDestroyed()) return
|
|
78
|
+
const dragPoint = normalizeDragPoint(point)
|
|
79
|
+
if (!dragPoint) return
|
|
36
80
|
const [x, y] = petWindow.getPosition()
|
|
37
|
-
dragState = { windowX: x, windowY: y, screenX:
|
|
81
|
+
dragState = { windowX: x, windowY: y, screenX: dragPoint.screenX, screenY: dragPoint.screenY }
|
|
38
82
|
})
|
|
39
83
|
|
|
40
84
|
ipcMain.on("opencube-drag-move", (event, point) => {
|
|
41
85
|
if (!petWindow || petWindow.isDestroyed() || !dragState) return
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
86
|
+
const dragPoint = normalizeDragPoint(point)
|
|
87
|
+
if (!dragPoint) return
|
|
88
|
+
const nextX = Math.round(dragState.windowX + dragPoint.screenX - dragState.screenX)
|
|
89
|
+
const nextY = Math.round(dragState.windowY + dragPoint.screenY - dragState.screenY)
|
|
90
|
+
const nextPosition = normalizeWindowPosition(nextX, nextY, petWindow)
|
|
91
|
+
if (!nextPosition) return
|
|
92
|
+
try {
|
|
93
|
+
petWindow.setPosition(nextPosition.x, nextPosition.y, false)
|
|
94
|
+
} catch {
|
|
95
|
+
dragState = null
|
|
96
|
+
}
|
|
45
97
|
})
|
|
46
98
|
|
|
47
99
|
ipcMain.on("opencube-drag-end", () => {
|
|
@@ -680,6 +732,7 @@ function petHtml3D() {
|
|
|
680
732
|
const initialStateJson = JSON.stringify(getPetState()).replaceAll("<", "\\u003c")
|
|
681
733
|
const iconUrl = createIconDataUrl()
|
|
682
734
|
const threeCjsPath = JSON.stringify(path.join(path.dirname(require.resolve("three")), "three.cjs"))
|
|
735
|
+
const renderSize = PET_WINDOW_SIZE
|
|
683
736
|
return `<!doctype html>
|
|
684
737
|
<html>
|
|
685
738
|
<head>
|
|
@@ -704,8 +757,8 @@ function petHtml3D() {
|
|
|
704
757
|
#scene {
|
|
705
758
|
position: absolute;
|
|
706
759
|
inset: 0;
|
|
707
|
-
width:
|
|
708
|
-
height:
|
|
760
|
+
width: ${renderSize}px;
|
|
761
|
+
height: ${renderSize}px;
|
|
709
762
|
pointer-events: none;
|
|
710
763
|
}
|
|
711
764
|
#hit-layer {
|
|
@@ -734,6 +787,7 @@ function petHtml3D() {
|
|
|
734
787
|
const THREE = require(${threeCjsPath})
|
|
735
788
|
const { ipcRenderer } = require("electron")
|
|
736
789
|
|
|
790
|
+
const PET_RENDER_SIZE = ${renderSize}
|
|
737
791
|
window.__PET_STATE = ${initialStateJson}
|
|
738
792
|
const stage = document.querySelector(".stage")
|
|
739
793
|
const hitLayer = document.getElementById("hit-layer")
|
|
@@ -765,7 +819,7 @@ function petHtml3D() {
|
|
|
765
819
|
camera.position.set(0, 0.04, 3.25)
|
|
766
820
|
const renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true })
|
|
767
821
|
renderer.setClearColor(0x000000, 0)
|
|
768
|
-
renderer.setPixelRatio(Math.min(
|
|
822
|
+
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2))
|
|
769
823
|
renderer.outputColorSpace = THREE.SRGBColorSpace
|
|
770
824
|
|
|
771
825
|
const cubeGroup = new THREE.Group()
|
|
@@ -1093,10 +1147,8 @@ function petHtml3D() {
|
|
|
1093
1147
|
}
|
|
1094
1148
|
|
|
1095
1149
|
function resize() {
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
renderer.setSize(width, height, false)
|
|
1099
|
-
camera.aspect = width / height
|
|
1150
|
+
renderer.setSize(PET_RENDER_SIZE, PET_RENDER_SIZE, false)
|
|
1151
|
+
camera.aspect = 1
|
|
1100
1152
|
camera.updateProjectionMatrix()
|
|
1101
1153
|
}
|
|
1102
1154
|
window.addEventListener("resize", resize)
|
|
@@ -1631,6 +1683,16 @@ function petHtml3D() {
|
|
|
1631
1683
|
busyFaces,
|
|
1632
1684
|
helloFlashes,
|
|
1633
1685
|
permissionGlows,
|
|
1686
|
+
renderSize: {
|
|
1687
|
+
fixed: PET_RENDER_SIZE,
|
|
1688
|
+
innerWidth: window.innerWidth,
|
|
1689
|
+
innerHeight: window.innerHeight,
|
|
1690
|
+
devicePixelRatio: window.devicePixelRatio || 1,
|
|
1691
|
+
canvasWidth: canvas.width,
|
|
1692
|
+
canvasHeight: canvas.height,
|
|
1693
|
+
canvasClientWidth: canvas.clientWidth,
|
|
1694
|
+
canvasClientHeight: canvas.clientHeight,
|
|
1695
|
+
},
|
|
1634
1696
|
}
|
|
1635
1697
|
requestAnimationFrame(tick)
|
|
1636
1698
|
}
|
|
@@ -1658,7 +1720,7 @@ function restorePosition(win) {
|
|
|
1658
1720
|
try {
|
|
1659
1721
|
const raw = fs.readFileSync(STATE_FILE, "utf8")
|
|
1660
1722
|
const state = JSON.parse(raw)
|
|
1661
|
-
if (
|
|
1723
|
+
if (Number.isFinite(state.x) && Number.isFinite(state.y)) {
|
|
1662
1724
|
win.setPosition(state.x, state.y, false)
|
|
1663
1725
|
return
|
|
1664
1726
|
}
|
|
@@ -1676,8 +1738,8 @@ function restorePosition(win) {
|
|
|
1676
1738
|
function createPetWindow() {
|
|
1677
1739
|
if (petWindow && !petWindow.isDestroyed()) return petWindow
|
|
1678
1740
|
petWindow = new BrowserWindow({
|
|
1679
|
-
width:
|
|
1680
|
-
height:
|
|
1741
|
+
width: PET_WINDOW_SIZE,
|
|
1742
|
+
height: PET_WINDOW_SIZE,
|
|
1681
1743
|
show: false,
|
|
1682
1744
|
frame: false,
|
|
1683
1745
|
resizable: false,
|