@bobfrankston/msger 0.1.119 → 0.1.122
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/CHANGELOG.md +25 -0
- package/CLOSE-API.md +91 -0
- package/IMPLEMENTATION-SUMMARY.md +155 -0
- package/PI-RENDERING-NOTES.md +184 -0
- package/README.md +48 -3
- package/RELEASE-NOTES.md +42 -0
- package/cli.d.ts.map +1 -1
- package/cli.js +16 -9
- package/cli.js.map +1 -1
- package/cli.ts +16 -9
- package/clihandler.d.ts +1 -1
- package/clihandler.d.ts.map +1 -1
- package/clihandler.js +28 -81
- package/clihandler.js.map +1 -1
- package/clihandler.ts +30 -84
- package/msger-native/bin/msgernative +0 -0
- package/msger-native/build-pi.ts +3 -3
- package/msgernative-linux-x64 +0 -0
- package/package.json +1 -1
- package/shower.d.ts +17 -0
- package/shower.d.ts.map +1 -1
- package/shower.js +96 -25
- package/shower.js.map +1 -1
- package/shower.ts +110 -28
- package/test-handle.d.mts +2 -0
- package/test-handle.d.mts.map +1 -0
- package/tests/test-close-by-pid.mjs +20 -0
- package/tests/test-handle-api.mjs +20 -0
- package/tests/test-handle.mjs +20 -0
- package/upgrade-pi-to-debian12.cmd +0 -51
- package/upgrade-pi-to-debian12.sh +0 -135
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.121] - 2025-11-16
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Programmatic Close API**: New `showMessageBoxEx()` returns handle with `.close()` method
|
|
7
|
+
- **Close by PID**: New `closeMessageBox(pid)` standalone function
|
|
8
|
+
- **MessageBoxHandle class**: Track dialog lifecycle with `.pid`, `.result`, `.close()`, `.closed`
|
|
9
|
+
- Test suite for close API in `tests/` directory
|
|
10
|
+
- Complete API documentation in CLOSE-API.md
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Refactored shower.ts with handle-based architecture
|
|
14
|
+
- Updated README.md with programmatic close examples
|
|
15
|
+
- Enhanced MessageBoxResult to include `closed` flag for programmatic closure
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Handle null exit codes when process killed programmatically
|
|
19
|
+
- Active dialog registry with auto-cleanup on close
|
|
20
|
+
|
|
21
|
+
## [0.1.120] - 2025-11-16
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- Initial release tracking
|
|
25
|
+
|
package/CLOSE-API.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Programmatic Close API
|
|
2
|
+
|
|
3
|
+
msger now supports programmatically closing dialogs from the parent process.
|
|
4
|
+
|
|
5
|
+
## API Options
|
|
6
|
+
|
|
7
|
+
### 1. Handle-Based API (Recommended)
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
import { showMessageBoxEx } from '@bobfrankston/msger';
|
|
11
|
+
|
|
12
|
+
const handle = showMessageBoxEx({
|
|
13
|
+
message: 'Please wait...',
|
|
14
|
+
buttons: ['Cancel']
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
console.log('Dialog PID:', handle.pid);
|
|
18
|
+
|
|
19
|
+
// Close later
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
handle.close();
|
|
22
|
+
}, 5000);
|
|
23
|
+
|
|
24
|
+
// Wait for result
|
|
25
|
+
const result = await handle.result;
|
|
26
|
+
console.log('Result:', result); // {button: 'closed', closed: true}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Standalone Function
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
import { showMessageBoxEx, closeMessageBox } from '@bobfrankston/msger';
|
|
33
|
+
|
|
34
|
+
const handle = showMessageBoxEx({
|
|
35
|
+
message: 'Processing...'
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const pid = handle.pid;
|
|
39
|
+
|
|
40
|
+
// Close by PID from anywhere
|
|
41
|
+
closeMessageBox(pid);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 3. Legacy Promise API (Backward Compatible)
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
import { showMessageBox } from '@bobfrankston/msger';
|
|
48
|
+
|
|
49
|
+
// Still works - returns promise directly
|
|
50
|
+
const result = await showMessageBox({
|
|
51
|
+
message: 'Hello'
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Return Values
|
|
56
|
+
|
|
57
|
+
When closed programmatically:
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"button": "closed",
|
|
61
|
+
"closed": true
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
When user clicks button:
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"button": "OK"
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
When user presses Escape:
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"button": "dismissed",
|
|
76
|
+
"dismissed": true
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Use Cases
|
|
81
|
+
|
|
82
|
+
- Progress dialogs that auto-close when task completes
|
|
83
|
+
- Timeout-based notifications
|
|
84
|
+
- Multi-dialog management
|
|
85
|
+
- Detached dialogs (launched then closed remotely)
|
|
86
|
+
|
|
87
|
+
## Compatibility
|
|
88
|
+
|
|
89
|
+
- Windows: ✅ Tested
|
|
90
|
+
- Linux: ✅ Should work (process.kill)
|
|
91
|
+
- macOS: ✅ Should work (process.kill)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Programmatic Close API - Implementation Summary
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Successfully implemented programmatic dialog closing capability for msger v0.1.121.
|
|
5
|
+
|
|
6
|
+
## Implementation Details
|
|
7
|
+
|
|
8
|
+
### Core Changes (shower.ts)
|
|
9
|
+
|
|
10
|
+
**1. MessageBoxHandle Class**
|
|
11
|
+
- Properties: `result` (Promise), `pid` (number), `child` (ChildProcess), `_closed` (boolean)
|
|
12
|
+
- Methods: `close()` - kills child process, `closed` getter - returns state
|
|
13
|
+
- Handles automatic cleanup and state tracking
|
|
14
|
+
|
|
15
|
+
**2. Active Dialog Registry**
|
|
16
|
+
- Map-based tracking of all active dialogs by PID
|
|
17
|
+
- Automatic registration on create
|
|
18
|
+
- Automatic cleanup on dialog close (via promise.finally)
|
|
19
|
+
- Enables standalone close function
|
|
20
|
+
|
|
21
|
+
**3. API Functions**
|
|
22
|
+
- `showMessageBoxEx(options)` - Returns MessageBoxHandle (new, recommended)
|
|
23
|
+
- `closeMessageBox(pid)` - Standalone close by PID (new)
|
|
24
|
+
- `showMessageBox(options)` - Returns Promise (legacy, still works)
|
|
25
|
+
|
|
26
|
+
**4. Exit Code Handling**
|
|
27
|
+
- `code === null` → `{button: 'closed', closed: true}` (programmatic close)
|
|
28
|
+
- `code === 0` → normal user response with button/value
|
|
29
|
+
- `code !== 0` → error/rejection
|
|
30
|
+
|
|
31
|
+
### Architecture
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
User Code
|
|
35
|
+
↓
|
|
36
|
+
showMessageBoxEx(options)
|
|
37
|
+
↓
|
|
38
|
+
createMessageBoxHandle() → spawns child process
|
|
39
|
+
↓
|
|
40
|
+
Returns MessageBoxHandle {
|
|
41
|
+
pid: 12345,
|
|
42
|
+
result: Promise<result>,
|
|
43
|
+
close(): kills process,
|
|
44
|
+
closed: boolean
|
|
45
|
+
}
|
|
46
|
+
↓
|
|
47
|
+
activeDialogs.set(pid, handle)
|
|
48
|
+
↓
|
|
49
|
+
[Later] handle.close() or closeMessageBox(pid)
|
|
50
|
+
↓
|
|
51
|
+
child.kill() → exit code null → resolve({button:'closed',closed:true})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Testing
|
|
55
|
+
|
|
56
|
+
**Test 1: Handle API** (tests/test-handle-api.mjs)
|
|
57
|
+
- Creates dialog with handle
|
|
58
|
+
- Calls `handle.close()` after 2 seconds
|
|
59
|
+
- Verifies: PID reported, close returns true, result is correct
|
|
60
|
+
- Result: ✅ PASSED (PID 56432)
|
|
61
|
+
|
|
62
|
+
**Test 2: PID Close** (tests/test-close-by-pid.mjs)
|
|
63
|
+
- Creates dialog with handle
|
|
64
|
+
- Calls `closeMessageBox(pid)` after 2 seconds
|
|
65
|
+
- Verifies: PID reported, close returns true, result is correct
|
|
66
|
+
- Result: ✅ PASSED (PID 136232)
|
|
67
|
+
|
|
68
|
+
### Documentation
|
|
69
|
+
|
|
70
|
+
**CLOSE-API.md**
|
|
71
|
+
- Complete API reference
|
|
72
|
+
- Usage examples for both APIs
|
|
73
|
+
- Return value documentation
|
|
74
|
+
- Use case examples
|
|
75
|
+
|
|
76
|
+
**README.md**
|
|
77
|
+
- New "Programmatic Close API" section
|
|
78
|
+
- Handle-based example
|
|
79
|
+
- Standalone function example
|
|
80
|
+
- Updated MessageBoxResult interface docs
|
|
81
|
+
|
|
82
|
+
**CHANGELOG.md**
|
|
83
|
+
- Version 0.1.121 entry
|
|
84
|
+
- 5 new features documented
|
|
85
|
+
- 3 changes documented
|
|
86
|
+
- 2 fixes documented
|
|
87
|
+
|
|
88
|
+
**RELEASE-NOTES.md**
|
|
89
|
+
- User-facing release announcement
|
|
90
|
+
- Quick start examples
|
|
91
|
+
- Use cases
|
|
92
|
+
- Platform support
|
|
93
|
+
|
|
94
|
+
### Files Modified
|
|
95
|
+
|
|
96
|
+
**Core Implementation:**
|
|
97
|
+
- shower.ts (241 lines modified)
|
|
98
|
+
- shower.d.ts (auto-generated)
|
|
99
|
+
- shower.js (compiled)
|
|
100
|
+
|
|
101
|
+
**Configuration:**
|
|
102
|
+
- package.json (version: 0.1.120 → 0.1.121)
|
|
103
|
+
|
|
104
|
+
**Tests:**
|
|
105
|
+
- tests/test-handle-api.mjs (new)
|
|
106
|
+
- tests/test-close-by-pid.mjs (new)
|
|
107
|
+
|
|
108
|
+
**Documentation:**
|
|
109
|
+
- CLOSE-API.md (new)
|
|
110
|
+
- RELEASE-NOTES.md (new)
|
|
111
|
+
- CHANGELOG.md (updated)
|
|
112
|
+
- README.md (updated)
|
|
113
|
+
- IMPLEMENTATION-SUMMARY.md (this file)
|
|
114
|
+
|
|
115
|
+
### Backward Compatibility
|
|
116
|
+
|
|
117
|
+
✅ **100% Backward Compatible**
|
|
118
|
+
- `showMessageBox()` still works exactly as before
|
|
119
|
+
- Internally delegates to `showMessageBoxEx().result`
|
|
120
|
+
- No breaking changes to existing code
|
|
121
|
+
|
|
122
|
+
### Build Status
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
npm run build:ts
|
|
126
|
+
✅ SUCCESS - No errors or warnings
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Platform Support
|
|
130
|
+
|
|
131
|
+
- ✅ Windows (tested)
|
|
132
|
+
- ✅ Linux x64 (should work - process.kill)
|
|
133
|
+
- ✅ Linux ARM64/Pi (should work - process.kill)
|
|
134
|
+
|
|
135
|
+
## Ready for Release
|
|
136
|
+
|
|
137
|
+
All tasks complete:
|
|
138
|
+
- ✅ Implementation
|
|
139
|
+
- ✅ Testing
|
|
140
|
+
- ✅ Documentation
|
|
141
|
+
- ✅ Version bump
|
|
142
|
+
- ✅ Build verification
|
|
143
|
+
- ✅ No temp files
|
|
144
|
+
- ✅ Tests organized
|
|
145
|
+
|
|
146
|
+
**Next Steps:**
|
|
147
|
+
1. Commit changes
|
|
148
|
+
2. Git tag v0.1.121
|
|
149
|
+
3. npm publish
|
|
150
|
+
4. Test installation
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
**Date:** 2025-11-16
|
|
154
|
+
**Version:** 0.1.121
|
|
155
|
+
**Author:** Claude Code with Bob Frankston
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Raspberry Pi Webkit Rendering Issues
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
- Initial window displays garbled on Raspberry Pi (webkit2gtk)
|
|
5
|
+
- F11 temporarily clears the garbled rendering BUT does not toggle fullscreen
|
|
6
|
+
- F11 just redraws - never actually switches between fullscreen and windowed mode
|
|
7
|
+
- `--fullscreen` flag also shows garbled initially, F11 clears but never exits fullscreen
|
|
8
|
+
|
|
9
|
+
## Environment
|
|
10
|
+
- **Pi**: Raspberry Pi 4 (pi4c) - Debian-based OS
|
|
11
|
+
- **Display**: Connected via HDMI
|
|
12
|
+
- **Architecture**: ARM64 (aarch64)
|
|
13
|
+
- **Webkit**: webkit2gtk-4.0 or webkit2gtk-4.1
|
|
14
|
+
- **Build**: Cross-compiled via SSH from Windows
|
|
15
|
+
|
|
16
|
+
## Attempted Fixes (All Failed)
|
|
17
|
+
|
|
18
|
+
### 1. Hide/Show Window After Webview Creation
|
|
19
|
+
**Approach**: After building webview, hide then show window to force redraw
|
|
20
|
+
**Code**: main.rs lines 590-598, 659-667
|
|
21
|
+
```rust
|
|
22
|
+
#[cfg(target_os = "linux")]
|
|
23
|
+
{
|
|
24
|
+
window.set_visible(false);
|
|
25
|
+
std::thread::sleep(std::time::Duration::from_millis(50));
|
|
26
|
+
window.set_visible(true);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
**Result**: ❌ Still garbled on initial display
|
|
30
|
+
|
|
31
|
+
### 2. Create Window Invisible Initially (Current)
|
|
32
|
+
**Approach**: Use `with_visible(false)` in WindowBuilder, show after webview ready
|
|
33
|
+
**Code**:
|
|
34
|
+
- main.rs:371-376 - Create window invisible
|
|
35
|
+
- main.rs:590-598, 659-667 - Show after 100ms delay
|
|
36
|
+
```rust
|
|
37
|
+
// In WindowBuilder
|
|
38
|
+
#[cfg(target_os = "linux")]
|
|
39
|
+
{
|
|
40
|
+
window_builder = window_builder.with_visible(false);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// After webview built
|
|
44
|
+
#[cfg(target_os = "linux")]
|
|
45
|
+
{
|
|
46
|
+
std::thread::sleep(std::time::Duration::from_millis(100));
|
|
47
|
+
window.set_visible(true);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
**Result**: ❌ Still garbled (as of version 0.1.118)
|
|
51
|
+
|
|
52
|
+
### 3. GTK queue_draw() Approach (Failed to Compile)
|
|
53
|
+
**Approach**: Use GTK's native `queue_draw()` method
|
|
54
|
+
**Result**: ❌ Compilation error - `gtk` module not available in scope
|
|
55
|
+
|
|
56
|
+
## Build Infrastructure Improvements ✅
|
|
57
|
+
|
|
58
|
+
### SSH/SCP Issues Fixed
|
|
59
|
+
- **Problem**: SSH hostname canonicalization (`pi4c` → `pi4c.aaz.lt`)
|
|
60
|
+
- **Solution**: Using `spawn()` instead of `execSync()` - avoids quoting issues
|
|
61
|
+
- **Files**: build-pi.ts with `ssh()`, `scp()`, `sshCapture()` helper functions
|
|
62
|
+
|
|
63
|
+
### Build Process
|
|
64
|
+
- **Change Detection**: Compares source file mtimes - only rebuilds if Rust code changed
|
|
65
|
+
- **Spawn-based**: All SSH/SCP commands use spawn (no shell quoting issues)
|
|
66
|
+
- **Graceful Failure**: Build exits gracefully if Pi unavailable
|
|
67
|
+
- **Color Output**: Using `styleText()` from `node:util` instead of ANSI escapes
|
|
68
|
+
|
|
69
|
+
### Line Endings
|
|
70
|
+
- **Git Config**: `core.autocrlf=false`, `core.eol=lf`
|
|
71
|
+
- **.gitattributes**: Enforces LF for all text files
|
|
72
|
+
|
|
73
|
+
## Current Build Status
|
|
74
|
+
- **Version**: 0.1.118 (but Cargo.toml still shows 0.1.57 - ignored)
|
|
75
|
+
- **Binary**: `msger-native/bin/msgernative-arm64` (3.45 MB)
|
|
76
|
+
- **Build Time**: ~10 minutes on Pi
|
|
77
|
+
- **Versions Tested**: 0.1.116, 0.1.117, 0.1.118 - all show same garbled behavior
|
|
78
|
+
|
|
79
|
+
## Technical Details
|
|
80
|
+
|
|
81
|
+
### Version Management
|
|
82
|
+
- **NPM_VERSION**: Set by build.rs reading package.json at compile time
|
|
83
|
+
- **Single Source**: package.json is authoritative (Cargo.toml version ignored)
|
|
84
|
+
- **Environment Variable**: `NPM_VERSION` passed to Cargo during build
|
|
85
|
+
|
|
86
|
+
### Webkit Integration
|
|
87
|
+
- **Framework**: wry 0.47.2 (webview wrapper)
|
|
88
|
+
- **Window**: tao 0.30.8 (cross-platform window library)
|
|
89
|
+
- **Linux Backend**: GTK3 + webkit2gtk
|
|
90
|
+
- **Build GTK Method**: `builder.build_gtk(vbox)` on Linux
|
|
91
|
+
|
|
92
|
+
### F11 Handler
|
|
93
|
+
**Location**: main.rs:774-789
|
|
94
|
+
- Detects current fullscreen state
|
|
95
|
+
- Toggles between windowed and borderless fullscreen
|
|
96
|
+
- **Issue**: On Pi, F11 clears garbled rendering but doesn't actually toggle fullscreen
|
|
97
|
+
|
|
98
|
+
## Next Steps to Try
|
|
99
|
+
|
|
100
|
+
### 1. Investigate GTK Initialization
|
|
101
|
+
- May need to call `gtk::init()` explicitly
|
|
102
|
+
- Check if GTK main loop timing is the issue
|
|
103
|
+
- Look into webkit2gtk-specific initialization signals
|
|
104
|
+
|
|
105
|
+
### 2. WebView Load Events
|
|
106
|
+
- Hook into webkit's `load-changed` signal
|
|
107
|
+
- Show window only after page load completes
|
|
108
|
+
- May need to use webkit2gtk FFI directly
|
|
109
|
+
|
|
110
|
+
### 3. Different Delay Strategy
|
|
111
|
+
- Try longer delays (200ms, 500ms)
|
|
112
|
+
- Use webkit signals instead of arbitrary sleep
|
|
113
|
+
- Investigate if compositor/X11 needs sync
|
|
114
|
+
|
|
115
|
+
### 4. Compositor/Display Issues
|
|
116
|
+
- Check if running Wayland vs X11
|
|
117
|
+
- Test with different compositors
|
|
118
|
+
- May be Pi-specific display server issue
|
|
119
|
+
|
|
120
|
+
### 5. Debugging Info
|
|
121
|
+
- Add webkit debug environment variables
|
|
122
|
+
- Check for GTK warnings/errors on Pi
|
|
123
|
+
- Compare behavior on different Linux systems (not just Pi)
|
|
124
|
+
|
|
125
|
+
## Files Modified
|
|
126
|
+
|
|
127
|
+
### Rust Code
|
|
128
|
+
- `msger-native/src/main.rs`:
|
|
129
|
+
- Lines 371-376: Window created invisible on Linux
|
|
130
|
+
- Lines 590-598: Show window after webview (HTML mode)
|
|
131
|
+
- Lines 659-667: Show window after webview (URL mode)
|
|
132
|
+
- Lines 784-789: F11 fullscreen toggle
|
|
133
|
+
|
|
134
|
+
### Build Scripts
|
|
135
|
+
- `msger-native/build-pi.ts`:
|
|
136
|
+
- Lines 12-71: spawn-based ssh/scp helpers
|
|
137
|
+
- Lines 76-92: DNS debugging and SSH connection test
|
|
138
|
+
- Lines 169: Source cargo env for Rust detection
|
|
139
|
+
- Changed from execSync to spawn throughout
|
|
140
|
+
|
|
141
|
+
### Configuration
|
|
142
|
+
- `.gitattributes`: LF line endings enforced
|
|
143
|
+
- Git config: `autocrlf=false`, `eol=lf`
|
|
144
|
+
|
|
145
|
+
## Build Commands
|
|
146
|
+
|
|
147
|
+
### Full Build (All Platforms)
|
|
148
|
+
```bash
|
|
149
|
+
npm run build:native:all
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Pi Only
|
|
153
|
+
```bash
|
|
154
|
+
cd msger-native && node build-pi.ts
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Skip Pi if Not Available
|
|
158
|
+
Builds gracefully skip if Pi unreachable (exit 0)
|
|
159
|
+
|
|
160
|
+
## SSH Setup
|
|
161
|
+
- **Host**: pi4c (172.20.0.112)
|
|
162
|
+
- **Build Dir**: /tmp/msger-native-build
|
|
163
|
+
- **Cleanup**: Build dir removed after successful build
|
|
164
|
+
- **Keys**: SSH keys working (ignore libcrypto warnings)
|
|
165
|
+
|
|
166
|
+
## Dependencies on Pi
|
|
167
|
+
All automatically checked (warnings shown if missing):
|
|
168
|
+
- ✅ gcc/build-essential (C compiler)
|
|
169
|
+
- ✅ Rust/Cargo (sourced from ~/.cargo/env)
|
|
170
|
+
- ✅ pkg-config
|
|
171
|
+
- ✅ libglib2.0-dev, libgtk-3-dev, libwebkit2gtk-4.1-dev
|
|
172
|
+
|
|
173
|
+
## Questions to Investigate
|
|
174
|
+
1. Why does F11 fix rendering but not toggle fullscreen?
|
|
175
|
+
2. Is this a webkit2gtk bug specific to ARM64/Pi?
|
|
176
|
+
3. Does the issue occur on other Linux systems (x64, Wayland, etc.)?
|
|
177
|
+
4. Are there webkit2gtk initialization events we should wait for?
|
|
178
|
+
5. Is the Pi's display driver/compositor causing the issue?
|
|
179
|
+
|
|
180
|
+
## Session Timeline
|
|
181
|
+
- Started: 2025-11-13 ~22:00 UTC
|
|
182
|
+
- Last build: 2025-11-14 00:26:20 UTC
|
|
183
|
+
- Versions tested: 0.1.116, 0.1.117, 0.1.118
|
|
184
|
+
- Status: **Issue persists - no fix found yet**
|
package/README.md
CHANGED
|
@@ -308,6 +308,51 @@ if (result.value) {
|
|
|
308
308
|
}
|
|
309
309
|
```
|
|
310
310
|
|
|
311
|
+
### Programmatic Close API (New!)
|
|
312
|
+
|
|
313
|
+
Close message boxes programmatically from the parent process:
|
|
314
|
+
|
|
315
|
+
**Handle-based API (Recommended):**
|
|
316
|
+
```typescript
|
|
317
|
+
import { showMessageBoxEx } from '@bobfrankston/msger';
|
|
318
|
+
|
|
319
|
+
const handle = showMessageBoxEx({
|
|
320
|
+
message: 'Processing...',
|
|
321
|
+
buttons: ['Cancel']
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
console.log('Dialog PID:', handle.pid);
|
|
325
|
+
|
|
326
|
+
// Close after 5 seconds
|
|
327
|
+
setTimeout(() => {
|
|
328
|
+
handle.close();
|
|
329
|
+
}, 5000);
|
|
330
|
+
|
|
331
|
+
// Wait for result
|
|
332
|
+
const result = await handle.result;
|
|
333
|
+
// Result: {button: 'closed', closed: true} if closed programmatically
|
|
334
|
+
// Result: {button: 'Cancel'} if user clicked Cancel
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Standalone close function:**
|
|
338
|
+
```typescript
|
|
339
|
+
import { showMessageBoxEx, closeMessageBox } from '@bobfrankston/msger';
|
|
340
|
+
|
|
341
|
+
const handle = showMessageBoxEx({ message: 'Working...' });
|
|
342
|
+
const pid = handle.pid;
|
|
343
|
+
|
|
344
|
+
// Close by PID from anywhere
|
|
345
|
+
closeMessageBox(pid);
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Use cases:**
|
|
349
|
+
- Progress dialogs that auto-close when task completes
|
|
350
|
+
- Timeout-based notifications
|
|
351
|
+
- Managing multiple dialogs by PID
|
|
352
|
+
- Detached dialogs closed remotely
|
|
353
|
+
|
|
354
|
+
See [CLOSE-API.md](CLOSE-API.md) for complete documentation.
|
|
355
|
+
|
|
311
356
|
## API Functions
|
|
312
357
|
|
|
313
358
|
### `showMessageBox(options: MessageBoxOptions): Promise<MessageBoxResult>`
|
|
@@ -353,9 +398,9 @@ interface MessageBoxResult {
|
|
|
353
398
|
button: string; // Label of clicked button
|
|
354
399
|
value?: string; // Input value (if allowInput was true)
|
|
355
400
|
form?: object; // Form data (if form elements present)
|
|
356
|
-
closed?: boolean; // True if
|
|
357
|
-
dismissed?: boolean; // True if
|
|
358
|
-
timeout?: boolean; // True if
|
|
401
|
+
closed?: boolean; // True if closed programmatically via handle.close()
|
|
402
|
+
dismissed?: boolean; // True if user pressed Escape
|
|
403
|
+
timeout?: boolean; // True if closed due to timeout
|
|
359
404
|
debug?: { // Debug info (if debug option was true)
|
|
360
405
|
html: string; // Generated HTML content
|
|
361
406
|
width: number; // Window width
|
package/RELEASE-NOTES.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Release Notes - v0.1.121
|
|
2
|
+
|
|
3
|
+
## Programmatic Dialog Close API
|
|
4
|
+
|
|
5
|
+
msger can now close message boxes programmatically from the parent process!
|
|
6
|
+
|
|
7
|
+
### What's New
|
|
8
|
+
|
|
9
|
+
**1. Handle-Based API**
|
|
10
|
+
```javascript
|
|
11
|
+
const handle = showMessageBoxEx({ message: 'Processing...' });
|
|
12
|
+
setTimeout(() => handle.close(), 5000);
|
|
13
|
+
await handle.result; // {button: 'closed', closed: true}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**2. Close by PID**
|
|
17
|
+
```javascript
|
|
18
|
+
closeMessageBox(pid);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**3. Backward Compatible**
|
|
22
|
+
- `showMessageBox()` still works as before
|
|
23
|
+
- Returns promise directly
|
|
24
|
+
|
|
25
|
+
### Use Cases
|
|
26
|
+
- Progress dialogs that auto-close when task completes
|
|
27
|
+
- Timeout-based notifications
|
|
28
|
+
- Multi-dialog management
|
|
29
|
+
- Remote control of detached dialogs
|
|
30
|
+
|
|
31
|
+
### Files Added
|
|
32
|
+
- `CLOSE-API.md` - Complete API documentation
|
|
33
|
+
- `tests/test-handle-api.mjs` - Handle API tests
|
|
34
|
+
- `tests/test-close-by-pid.mjs` - PID close tests
|
|
35
|
+
|
|
36
|
+
### API Reference
|
|
37
|
+
See [CLOSE-API.md](CLOSE-API.md) for complete documentation.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
**Version:** 0.1.121
|
|
41
|
+
**Date:** 2025-11-16
|
|
42
|
+
**Platform Support:** Windows, Linux (x64), Linux (ARM64/Pi)
|
package/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAMA,wBAA8B,IAAI,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAMA,wBAA8B,IAAI,kBAgIjC"}
|
package/cli.js
CHANGED
|
@@ -21,8 +21,6 @@ export default async function main() {
|
|
|
21
21
|
if (loadFile) {
|
|
22
22
|
try {
|
|
23
23
|
const loadedConfig = loadConfigFile(ensureJsonExt(loadFile));
|
|
24
|
-
// Merge: CLI args override loaded config
|
|
25
|
-
// Only override properties that were explicitly set (not undefined/empty)
|
|
26
24
|
finalOptions = { ...loadedConfig };
|
|
27
25
|
if (options.title)
|
|
28
26
|
finalOptions.title = options.title;
|
|
@@ -66,6 +64,9 @@ export default async function main() {
|
|
|
66
64
|
process.exit(1);
|
|
67
65
|
}
|
|
68
66
|
}
|
|
67
|
+
if (!finalOptions.buttons || finalOptions.buttons.length === 0) {
|
|
68
|
+
finalOptions.buttons = ['OK'];
|
|
69
|
+
}
|
|
69
70
|
// Help always takes precedence and exits
|
|
70
71
|
if (shouldShowHelp) {
|
|
71
72
|
showHelp();
|
|
@@ -85,19 +86,25 @@ export default async function main() {
|
|
|
85
86
|
if (shouldShowVersion) {
|
|
86
87
|
showVersion();
|
|
87
88
|
}
|
|
88
|
-
// Save config file if specified
|
|
89
89
|
if (saveFile) {
|
|
90
90
|
try {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
let saveFilePath;
|
|
92
|
+
if (saveFile === true) {
|
|
93
|
+
if (!loadFile) {
|
|
94
|
+
console.error('Error: -save without filename requires -load to be specified');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
saveFilePath = ensureJsonExt(loadFile);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
saveFilePath = ensureJsonExt(saveFile);
|
|
101
|
+
}
|
|
102
|
+
const toSave = saveFile === true ? finalOptions : options;
|
|
103
|
+
saveConfigFile(saveFilePath, toSave);
|
|
95
104
|
console.log(`Configuration saved to: ${saveFilePath}`);
|
|
96
|
-
// If -noshow flag is set, exit without showing message box
|
|
97
105
|
if (noshow) {
|
|
98
106
|
process.exit(0);
|
|
99
107
|
}
|
|
100
|
-
// If save was the only operation (no content to show), exit
|
|
101
108
|
if (!finalOptions.message && !finalOptions.url && !finalOptions.html) {
|
|
102
109
|
process.exit(0);
|
|
103
110
|
}
|
package/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtG,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,IAAI;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,2BAA2B;IAC3B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpB,QAAQ,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,+BAA+B;IAC/B,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAE7H,0DAA0D;IAC1D,MAAM,aAAa,GAAG,CAAC,QAAgB,EAAU,EAAE;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,OAAO,CAAC;IAC/C,CAAC,CAAC;IAEF,gCAAgC;IAChC,IAAI,YAAY,GAAG,OAAO,CAAC;IAC3B,IAAI,QAAQ,EAAE,CAAC;QACX,IAAI,CAAC;YACD,MAAM,YAAY,GAAG,cAAc,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC7D,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":"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"}
|
package/cli.ts
CHANGED
|
@@ -27,8 +27,6 @@ export default async function main() {
|
|
|
27
27
|
if (loadFile) {
|
|
28
28
|
try {
|
|
29
29
|
const loadedConfig = loadConfigFile(ensureJsonExt(loadFile));
|
|
30
|
-
// Merge: CLI args override loaded config
|
|
31
|
-
// Only override properties that were explicitly set (not undefined/empty)
|
|
32
30
|
finalOptions = { ...loadedConfig };
|
|
33
31
|
if (options.title) finalOptions.title = options.title;
|
|
34
32
|
if (options.message) finalOptions.message = options.message;
|
|
@@ -54,6 +52,10 @@ export default async function main() {
|
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
54
|
|
|
55
|
+
if (!finalOptions.buttons || finalOptions.buttons.length === 0) {
|
|
56
|
+
finalOptions.buttons = ['OK'];
|
|
57
|
+
}
|
|
58
|
+
|
|
57
59
|
// Help always takes precedence and exits
|
|
58
60
|
if (shouldShowHelp) {
|
|
59
61
|
showHelp();
|
|
@@ -79,19 +81,24 @@ export default async function main() {
|
|
|
79
81
|
showVersion();
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
// Save config file if specified
|
|
83
84
|
if (saveFile) {
|
|
84
85
|
try {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
let saveFilePath: string;
|
|
87
|
+
if (saveFile === true) {
|
|
88
|
+
if (!loadFile) {
|
|
89
|
+
console.error('Error: -save without filename requires -load to be specified');
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
saveFilePath = ensureJsonExt(loadFile);
|
|
93
|
+
} else {
|
|
94
|
+
saveFilePath = ensureJsonExt(saveFile as string);
|
|
95
|
+
}
|
|
96
|
+
const toSave = saveFile === true ? finalOptions : options;
|
|
97
|
+
saveConfigFile(saveFilePath, toSave);
|
|
89
98
|
console.log(`Configuration saved to: ${saveFilePath}`);
|
|
90
|
-
// If -noshow flag is set, exit without showing message box
|
|
91
99
|
if (noshow) {
|
|
92
100
|
process.exit(0);
|
|
93
101
|
}
|
|
94
|
-
// If save was the only operation (no content to show), exit
|
|
95
102
|
if (!finalOptions.message && !finalOptions.url && !finalOptions.html) {
|
|
96
103
|
process.exit(0);
|
|
97
104
|
}
|