@bobfrankston/msger 0.1.422 → 0.1.423
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/README.md +21 -2
- package/cli.js +11 -1
- package/msger-native/bin/msgernative-darwin-arm64 +0 -0
- package/msger-native/bin/msgernative.exe +0 -0
- package/msger-native/builder/postinstall.js +33 -3
- package/package.json +1 -1
- package/prep-mac-source.js +29 -0
- package/shower.d.ts +4 -1
- package/shower.js +5 -2
package/README.md
CHANGED
|
@@ -80,9 +80,20 @@ msger -url "https://example.com" -detach
|
|
|
80
80
|
# Fullscreen mode
|
|
81
81
|
msger -fullscreen -url "https://example.com"
|
|
82
82
|
|
|
83
|
-
# Multi-monitor
|
|
83
|
+
# Multi-monitor - show on second screen
|
|
84
84
|
msger -message "Second screen" -pos 0,100 -screen 1
|
|
85
85
|
|
|
86
|
+
# What displays are there? (JSON, no window; indices match -screen)
|
|
87
|
+
msger -list
|
|
88
|
+
|
|
89
|
+
# Transparent click-through overlay on screen 1, gone after 3 seconds
|
|
90
|
+
msger -overlay -fullscreen -screen 1 -timeout 3 "1"
|
|
91
|
+
|
|
92
|
+
# Number every screen, the way the display settings "Identify" button does
|
|
93
|
+
msger -list | ConvertFrom-Json | ForEach-Object { $_.monitors } | ForEach-Object {
|
|
94
|
+
Start-Process msger -ArgumentList "-overlay -fullscreen -screen $($_.index) -timeout 3 `"$($_.index + 1)`""
|
|
95
|
+
}
|
|
96
|
+
|
|
86
97
|
# Auto-close timeout
|
|
87
98
|
msger -message "Closing in 5 seconds..." -timeout 5
|
|
88
99
|
|
|
@@ -239,6 +250,9 @@ msger -title "Test" -message "Saving config..." -save test.json
|
|
|
239
250
|
| `autoSize` | boolean | true when no size | Auto-resize window to fit content |
|
|
240
251
|
| `alwaysOnTop` | boolean | false | Keep window on top |
|
|
241
252
|
| `fullscreen` | boolean | false | Start in fullscreen mode |
|
|
253
|
+
| `screen` | number | null | Monitor index (0-based) for `fullscreen`, and the fallback for `pos.screen`. The portable way to target a display — Wayland refuses client-set window coordinates but honors fullscreen on a chosen output |
|
|
254
|
+
| `overlay` | boolean | false | Frameless, transparent, click-through, always-on-top window drawn over the desktop, kept out of the taskbar and never taking focus. Pair with `timeout` — it has no close button and passes clicks through, so nothing in it can be operated. With `url`/`rawHtml` the page must set its own transparent background; the built-in template already does. Each overlay gets its own WebView2 profile (keyed by screen) so a set of them can start in parallel |
|
|
255
|
+
| `listMonitors` | boolean | false | Print the monitor layout as JSON and exit without opening a window: `{"monitors":[{index,name,x,y,width,height,scale,primary}]}` |
|
|
242
256
|
| `zoom` | number | 100 | Initial zoom level (100=100%, 150=150%). Applies in every mode — message, HTML and URL |
|
|
243
257
|
| `newWindow` | string | `"browser"` | Where "open in new window" / `target=_blank` links go: `"browser"` (system browser) or `"msger"` (spawns another msger window) |
|
|
244
258
|
| `contextMenu` | string | `"page"` | `"always"` forces the native right-click menu everywhere, even where the page suppresses it with its own `contextmenu` handler |
|
|
@@ -320,7 +334,9 @@ Options:
|
|
|
320
334
|
-default, --default <text> Default value for input field
|
|
321
335
|
-size, --size <width,height> Window size (e.g., -size 800,600)
|
|
322
336
|
-pos, --pos <x,y> Window position (e.g., -pos 100,200)
|
|
323
|
-
-screen, --screen <number>
|
|
337
|
+
-screen, --screen <number> Screen index (0=primary, 1=second, etc.). Offsets -pos into
|
|
338
|
+
that screen, and picks which screen -fullscreen covers.
|
|
339
|
+
-list, --list Print the monitor layout as JSON and exit (no window)
|
|
324
340
|
-zoom, --zoom <percent> Zoom level as percentage (e.g., -zoom 150 for 150%).
|
|
325
341
|
Works in message, HTML and URL modes alike.
|
|
326
342
|
-newwindow, --newwindow <where> Where "open in new window" links go:
|
|
@@ -329,6 +345,9 @@ Options:
|
|
|
329
345
|
-ontop, --ontop Keep window always on top
|
|
330
346
|
-detach, --detach Launch window independently (parent returns immediately)
|
|
331
347
|
-fullscreen, --fullscreen Start window in fullscreen mode (F11 to toggle, Escape to exit)
|
|
348
|
+
-overlay, --overlay Frameless, transparent, click-through window over the desktop.
|
|
349
|
+
Always on top, no taskbar slot, never takes focus. Pair with
|
|
350
|
+
-timeout; combine with -fullscreen -screen <n> per display.
|
|
332
351
|
-raw, --raw With -html: load HTML as-is, no msger template/buttons (alias: -full)
|
|
333
352
|
-debug, --debug Return debug info (HTML, size, autoSize) in result
|
|
334
353
|
-render, --render [file] Render the page to a bitmap instead of displaying it.
|
package/cli.js
CHANGED
|
@@ -46,11 +46,21 @@ Options:
|
|
|
46
46
|
-size <width,height> Set window size (e.g., -size 800,600)
|
|
47
47
|
-zoom <percent> Set zoom level as percentage (e.g., -zoom 150 for 150%)
|
|
48
48
|
-pos <x,y> Set window position (e.g., -pos 100,200)
|
|
49
|
-
-screen <number>
|
|
49
|
+
-screen <number> Screen index for multi-monitor (0=primary, 1=second, etc.). Offsets
|
|
50
|
+
-pos into that screen, and picks which screen -fullscreen covers.
|
|
51
|
+
-list Print the monitor layout as JSON and exit (no window). Indices
|
|
52
|
+
match -screen: {"monitors":[{index,name,x,y,width,height,scale,primary}]}
|
|
50
53
|
-icon <path> Set window icon (PNG file). Default: icon.png in current directory
|
|
51
54
|
-timeout <seconds> Auto-close after specified seconds
|
|
52
55
|
-detach Leave window open after app exits (parent process returns immediately)
|
|
53
56
|
-fullscreen Start window in fullscreen mode (F11 to toggle, Escape to exit)
|
|
57
|
+
-overlay Frameless, transparent, click-through window drawn over the
|
|
58
|
+
desktop. Always on top, no taskbar slot, never takes focus.
|
|
59
|
+
Pair with -timeout: it has no close button and passes clicks
|
|
60
|
+
through, so the timeout is how it goes away. Combine with
|
|
61
|
+
-fullscreen -screen <n> to cover one display, e.g.
|
|
62
|
+
msger -overlay -fullscreen -screen 1 -timeout 3 "2"
|
|
63
|
+
With -url/-raw the page must set its own transparent background.
|
|
54
64
|
-no-escape-closes Prevent Escape key from closing window (still exits fullscreen)
|
|
55
65
|
-reset Clear localStorage on startup (useful for resetting web content state)
|
|
56
66
|
-ontop Keep window always on top of other windows
|
|
Binary file
|
|
Binary file
|
|
@@ -54,18 +54,48 @@ function getUserBinDir() {
|
|
|
54
54
|
|
|
55
55
|
const userBinDir = getUserBinDir();
|
|
56
56
|
|
|
57
|
-
// Step 1: Copy from target/release/ → bin/ if build output is newer
|
|
57
|
+
// Step 1: Copy from target/release/ → bin/ if build output is newer.
|
|
58
|
+
//
|
|
59
|
+
// A plain copy here fails whenever a msger window is running from bin/ —
|
|
60
|
+
// Windows refuses to overwrite a running exe — and the old behavior was to
|
|
61
|
+
// shrug and keep shipping the STALE binary, which is how a fresh build can
|
|
62
|
+
// silently not reach the package. Use the same rename-aside trick step 2b
|
|
63
|
+
// uses: renaming a running exe is permitted, so retire the locked file and
|
|
64
|
+
// drop the new one into the freed path. The running process keeps executing
|
|
65
|
+
// from the retired name.
|
|
66
|
+
//
|
|
67
|
+
// Retired copies go to msger-native/.old/ rather than beside the binary,
|
|
68
|
+
// because package.json ships `msger-native/bin/` — an `.old-*` file left in
|
|
69
|
+
// bin/ would be published as a stray multi-MB binary. Same volume, so the
|
|
70
|
+
// rename stays a rename (a cross-device move degrades to copy+delete, which
|
|
71
|
+
// is exactly what a running exe forbids).
|
|
58
72
|
if (fs.existsSync(buildBinary)) {
|
|
59
73
|
const buildTime = fs.statSync(buildBinary).mtimeMs;
|
|
60
74
|
const srcTime = fs.existsSync(srcBinary) ? fs.statSync(srcBinary).mtimeMs : 0;
|
|
61
75
|
if (buildTime > srcTime) {
|
|
76
|
+
const retireDir = path.join(nativeDir, ".old");
|
|
62
77
|
try {
|
|
63
78
|
fs.copyFileSync(buildBinary, srcBinary);
|
|
64
79
|
console.log(` msger: updated ${baseName}${ext} from build`);
|
|
65
80
|
} catch (e) {
|
|
66
|
-
|
|
67
|
-
|
|
81
|
+
try {
|
|
82
|
+
fs.mkdirSync(retireDir, { recursive: true });
|
|
83
|
+
const retired = path.join(retireDir, `${baseName}${ext}.old-${Date.now()}`);
|
|
84
|
+
fs.renameSync(srcBinary, retired);
|
|
85
|
+
fs.copyFileSync(buildBinary, srcBinary);
|
|
86
|
+
console.log(` msger: updated ${baseName}${ext} from build (retired the running copy aside)`);
|
|
87
|
+
} catch (e2) {
|
|
88
|
+
console.error(` msger: could not update ${baseName}${ext}: ${e2.message}`);
|
|
89
|
+
console.error(` msger: the package would ship a STALE binary — close any running msger and rebuild.`);
|
|
90
|
+
}
|
|
68
91
|
}
|
|
92
|
+
// Sweep retired copies whose process has since exited. Still-locked
|
|
93
|
+
// ones stay for the next run; that's expected, not an error.
|
|
94
|
+
try {
|
|
95
|
+
for (const f of fs.readdirSync(retireDir)) {
|
|
96
|
+
try { fs.unlinkSync(path.join(retireDir, f)); } catch { /* still running */ }
|
|
97
|
+
}
|
|
98
|
+
} catch { /* no retire dir — nothing was ever locked */ }
|
|
69
99
|
}
|
|
70
100
|
}
|
|
71
101
|
|
package/package.json
CHANGED
package/prep-mac-source.js
CHANGED
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Excludes `target/` (build output, gigabytes), `pibuild/` (Pi-specific),
|
|
11
11
|
* and the existing `bin/` (Linux/Windows binaries — Mac doesn't need them).
|
|
12
|
+
*
|
|
13
|
+
* EXCEPT the image assets in `bin/`: `main.rs` pulls `../bin/msger.png` in with
|
|
14
|
+
* `include_bytes!`, so it is a compile-time input, not build output. Skipping
|
|
15
|
+
* the whole of `bin/` silently broke the Mac build the moment that include
|
|
16
|
+
* landed ("couldn't read `src/../bin/msger.png`"), which is why Mac binaries
|
|
17
|
+
* went stale. The binaries themselves are still excluded — only the small
|
|
18
|
+
* icon files come across.
|
|
12
19
|
*/
|
|
13
20
|
import fs from "fs";
|
|
14
21
|
import path from "path";
|
|
@@ -55,6 +62,28 @@ function copyDir(src, dst) {
|
|
|
55
62
|
|
|
56
63
|
copyDir(srcDir, dstDir);
|
|
57
64
|
|
|
65
|
+
// bin/ is skipped wholesale above (it holds tens of MB of other platforms'
|
|
66
|
+
// binaries), but the icon assets in it are `include_bytes!` inputs the Rust
|
|
67
|
+
// build needs. Copy just those.
|
|
68
|
+
const binSrc = path.join(srcDir, "bin");
|
|
69
|
+
const binDst = path.join(dstDir, "bin");
|
|
70
|
+
if (fs.existsSync(binSrc)) {
|
|
71
|
+
fs.mkdirSync(binDst, { recursive: true });
|
|
72
|
+
for (const name of fs.readdirSync(binSrc)) {
|
|
73
|
+
if (!/\.(png|ico)$/i.test(name)) continue;
|
|
74
|
+
const s = path.join(binSrc, name);
|
|
75
|
+
const d = path.join(binDst, name);
|
|
76
|
+
if (!fs.statSync(s).isFile()) continue;
|
|
77
|
+
const dMtime = fs.existsSync(d) ? fs.statSync(d).mtimeMs : 0;
|
|
78
|
+
if (dMtime >= fs.statSync(s).mtimeMs) {
|
|
79
|
+
skipped++;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
fs.copyFileSync(s, d);
|
|
83
|
+
copied++;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
58
87
|
console.log(` msger: prep:mac — ${copied} file(s) copied, ${skipped} unchanged`);
|
|
59
88
|
console.log(` msger: source staged at mac/msger-native/. OneDrive will sync to the Mac;`);
|
|
60
89
|
console.log(` msger: then run \`./build-mac.sh\` from the OneDrive folder on the Mac.`);
|
package/shower.d.ts
CHANGED
|
@@ -23,8 +23,11 @@ export interface MessageBoxOptions {
|
|
|
23
23
|
pos?: {
|
|
24
24
|
x: number; /** Window X position in pixels */
|
|
25
25
|
y: number; /** Window Y position in pixels */
|
|
26
|
-
screen?: number; /** Optional screen index (0-based
|
|
26
|
+
screen?: number; /** Optional screen index (0-based). Offsets x/y into that monitor. Was Windows-only; now applied on Mac and X11 too. Wayland ignores client-set window positions entirely — use `fullscreen` + `screen` there. */
|
|
27
27
|
};
|
|
28
|
+
screen?: number; /** Monitor index (0-based) for `fullscreen`, and the fallback for `pos.screen`. The portable way to target a display: Wayland refuses client-set coordinates but honors fullscreen-on-a-given-output. */
|
|
29
|
+
overlay?: boolean; /** Frameless, transparent, click-through, always-on-top window drawn over the desktop — transient notices, e.g. per-monitor identification. Combine with `fullscreen` + `screen` to cover one display and `timeout` to dismiss it; an overlay has no close button and passes clicks through, so nothing in it can be operated. With `url` / `rawHtml` the page must set its own transparent background (the built-in template already does). */
|
|
30
|
+
listMonitors?: boolean; /** Print the monitor layout as JSON (`{monitors:[{index,name,x,y,width,height,scale,primary}]}`) and exit without opening a window. Indices match `screen`. */
|
|
28
31
|
zoom?: number; /** Initial zoom level as percentage (100=100%, 150=150%, 50=50%, etc.) */
|
|
29
32
|
autoSize?: boolean; /** Automatically resize window to fit content (default: false) */
|
|
30
33
|
alwaysOnTop?: boolean; /** Keep window on top of other windows (default: false) */
|
package/shower.js
CHANGED
|
@@ -637,9 +637,12 @@ function createMessageBoxHandle(options) {
|
|
|
637
637
|
});
|
|
638
638
|
// Send options to stdin
|
|
639
639
|
try {
|
|
640
|
-
// If autoSize is not explicitly set, enable it when no size is specified
|
|
640
|
+
// If autoSize is not explicitly set, enable it when no size is specified.
|
|
641
|
+
// Not for overlays: auto-sizing shrinks the window to its content,
|
|
642
|
+
// which for a full-screen overlay collapses the very area it is
|
|
643
|
+
// meant to cover. The caller's geometry (or fullscreen) wins there.
|
|
641
644
|
const optionsToSend = { ...options };
|
|
642
|
-
if (optionsToSend.autoSize === undefined && !optionsToSend.size) {
|
|
645
|
+
if (optionsToSend.autoSize === undefined && !optionsToSend.size && !optionsToSend.overlay) {
|
|
643
646
|
optionsToSend.autoSize = true;
|
|
644
647
|
}
|
|
645
648
|
// Render mode: Rust wants a bare boolean plus a format string; the
|