@bobfrankston/msger 0.1.107 → 0.1.109
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 +13 -3
- package/SESSION-RESUME-NOTES.md +139 -0
- package/check-pi-debian-version.cmd +25 -0
- package/check-pi-debian-version.sh +53 -0
- package/msger-native/bin/msgernative +0 -0
- package/msger-native/bin/msgernative-arm64 +0 -0
- package/msger-native/bin/msgernative.exe +0 -0
- package/msger-native/build-pi.ts +91 -12
- package/msger-native/package.json +4 -4
- package/msger-native/pi-diagnostics.ts +138 -0
- package/msger-native/src/main.rs +67 -8
- package/msgernative-linux-x64 +0 -0
- package/package.json +2 -3
- package/tests/test-title-change.html +83 -0
- package/upgrade-pi-to-debian12.cmd +51 -0
- package/upgrade-pi-to-debian12.sh +135 -0
package/README.md
CHANGED
|
@@ -79,6 +79,9 @@ msger -message "Second screen" -pos 0,100 -screen 1
|
|
|
79
79
|
# Auto-close timeout
|
|
80
80
|
msger -message "Closing in 5 seconds..." -timeout 5
|
|
81
81
|
|
|
82
|
+
# Open with DevTools for debugging (automatically opens DevTools panel)
|
|
83
|
+
msger -url "https://example.com" -dev
|
|
84
|
+
|
|
82
85
|
# See all options
|
|
83
86
|
msger --help
|
|
84
87
|
```
|
|
@@ -172,7 +175,7 @@ msger -title "Test" -message "Saving config..." -save test.json
|
|
|
172
175
|
| `zoomPercent` | number | 100 | Initial zoom level (100=100%, 150=150%) |
|
|
173
176
|
| `debug` | boolean | false | Return debug info in result |
|
|
174
177
|
| `icon` | string | null | Path to window icon (.png, .ico) |
|
|
175
|
-
| `dev` | boolean | false |
|
|
178
|
+
| `dev` | boolean | false | Open DevTools automatically (for debugging HTML/URL content) |
|
|
176
179
|
|
|
177
180
|
**Content Priority:** Only one content type will be displayed (in order):
|
|
178
181
|
1. `url` - If provided, loads URL (ignores message/html)
|
|
@@ -276,6 +279,7 @@ Notes:
|
|
|
276
279
|
- Press Enter to click last (default) button
|
|
277
280
|
- OK button is green by default
|
|
278
281
|
- URLs default to 1024x768 window size
|
|
282
|
+
- Window title automatically updates from loaded page's <title> tag when using -url
|
|
279
283
|
- Windows auto-size to fit content when size not specified
|
|
280
284
|
- Runtime zoom: Ctrl+Wheel, Ctrl+Plus, Ctrl+Minus
|
|
281
285
|
```
|
|
@@ -441,18 +445,24 @@ echo -e "\x1b[31mError:\x1b[0m Something went wrong" | msger
|
|
|
441
445
|
|
|
442
446
|
```typescript
|
|
443
447
|
// Load external website
|
|
448
|
+
// Note: Window title automatically updates from page's <title> tag
|
|
444
449
|
await showMessageBox({
|
|
445
|
-
title: 'Documentation',
|
|
446
450
|
url: 'https://github.com/BobFrankston/msger',
|
|
447
451
|
size: { width: 1024, height: 768 }
|
|
448
452
|
});
|
|
449
453
|
|
|
450
454
|
// Load local HTML file
|
|
451
455
|
await showMessageBox({
|
|
452
|
-
title: 'Help',
|
|
453
456
|
url: 'file:///path/to/help.html',
|
|
454
457
|
size: { width: 800, height: 600 }
|
|
455
458
|
});
|
|
459
|
+
|
|
460
|
+
// Load with DevTools opened automatically (for debugging)
|
|
461
|
+
await showMessageBox({
|
|
462
|
+
url: 'https://example.com',
|
|
463
|
+
dev: true, // Opens DevTools automatically
|
|
464
|
+
size: { width: 1024, height: 768 }
|
|
465
|
+
});
|
|
456
466
|
```
|
|
457
467
|
|
|
458
468
|
### Auto-Close with Timeout
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Session Resume Notes - 2025-11-13
|
|
2
|
+
|
|
3
|
+
## Where We Left Off
|
|
4
|
+
|
|
5
|
+
Building msger for Raspberry Pi (ARM64) - encountered GLib version incompatibility.
|
|
6
|
+
|
|
7
|
+
## Work Completed This Session
|
|
8
|
+
|
|
9
|
+
### 1. ✅ Added Auto-Title Support
|
|
10
|
+
- Window title automatically updates from document.title in URL mode
|
|
11
|
+
- Uses MutationObserver + periodic polling
|
|
12
|
+
- **Files Modified:** `msger-native/src/main.rs` (lines 470-505)
|
|
13
|
+
|
|
14
|
+
### 2. ✅ Added -dev Flag Support
|
|
15
|
+
- Automatically opens DevTools on startup
|
|
16
|
+
- Simulates F12 keypress via JavaScript
|
|
17
|
+
- **Files Modified:** `msger-native/src/main.rs` (lines 507-532)
|
|
18
|
+
|
|
19
|
+
### 3. ✅ Updated Documentation
|
|
20
|
+
- README.md updated with auto-title and -dev examples
|
|
21
|
+
- **Files Modified:** `README.md`
|
|
22
|
+
|
|
23
|
+
### 4. ✅ Improved Pi Build Script
|
|
24
|
+
- Auto-detects and installs missing dependencies (gcc, rust, pkg-config, glib, gtk, webkit)
|
|
25
|
+
- Smart build detection (skips if binary is up-to-date)
|
|
26
|
+
- Pi availability check with red error banner if unavailable
|
|
27
|
+
- Fixed cargo environment sourcing
|
|
28
|
+
- **Files Modified:** `msger-native/build-pi.ts`
|
|
29
|
+
|
|
30
|
+
### 5. ✅ Created Pi Diagnostics Tool
|
|
31
|
+
- TypeScript script that runs on Pi to check all requirements
|
|
32
|
+
- Identifies exact version mismatches
|
|
33
|
+
- **Files Created:** `msger-native/pi-diagnostics.ts`
|
|
34
|
+
|
|
35
|
+
## Current Issue: GLib Version Incompatibility
|
|
36
|
+
|
|
37
|
+
### Problem Identified
|
|
38
|
+
```
|
|
39
|
+
Raspberry Pi: Debian 11 (Bullseye)
|
|
40
|
+
└─ GLib version: 2.66.8
|
|
41
|
+
|
|
42
|
+
msger (wry 0.47):
|
|
43
|
+
└─ Requires: GLib >= 2.70
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Root Cause
|
|
47
|
+
- wry 0.47 → gtk-rs crates → require glib 2.70+
|
|
48
|
+
- Debian 11 only has glib 2.66
|
|
49
|
+
- Debian 12 (Bookworm) has glib 2.74 ✓
|
|
50
|
+
|
|
51
|
+
## Next Steps (User Chose Option 1: Upgrade Pi OS)
|
|
52
|
+
|
|
53
|
+
### Step 1: Upgrade Pi to Debian 12
|
|
54
|
+
```bash
|
|
55
|
+
# SSH to Pi
|
|
56
|
+
ssh pi4c
|
|
57
|
+
|
|
58
|
+
# Backup important data first!
|
|
59
|
+
sudo apt update
|
|
60
|
+
sudo apt full-upgrade -y
|
|
61
|
+
|
|
62
|
+
# This will take 30-60 minutes
|
|
63
|
+
# May require reboot
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Step 2: Verify GLib Version After Upgrade
|
|
67
|
+
```bash
|
|
68
|
+
# Run diagnostics again
|
|
69
|
+
cd Y:\dev\utils\msger\msger-native
|
|
70
|
+
scp pi-diagnostics.ts pi4c:/tmp/
|
|
71
|
+
ssh pi4c "node /tmp/pi-diagnostics.ts"
|
|
72
|
+
|
|
73
|
+
# Should show: GLib 2.74+ ✓
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Step 3: Build for Pi
|
|
77
|
+
```bash
|
|
78
|
+
cd Y:\dev\utils\msger
|
|
79
|
+
npm run build:native:pi
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Should succeed after OS upgrade!
|
|
83
|
+
|
|
84
|
+
## Alternative (Not Chosen)
|
|
85
|
+
|
|
86
|
+
If upgrade doesn't work, can downgrade wry:
|
|
87
|
+
```toml
|
|
88
|
+
# In msger-native/Cargo.toml
|
|
89
|
+
[dependencies]
|
|
90
|
+
wry = "0.24" # Down from 0.47
|
|
91
|
+
tao = "0.16" # Down from 0.30
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Files Modified This Session
|
|
95
|
+
|
|
96
|
+
1. `msger-native/src/main.rs` - Auto-title + dev flag
|
|
97
|
+
2. `README.md` - Documentation updates
|
|
98
|
+
3. `msger-native/build-pi.ts` - Improved build script
|
|
99
|
+
4. `msger-native/pi-diagnostics.ts` - NEW diagnostic tool
|
|
100
|
+
5. `tests/test-title-change.html` - NEW test file
|
|
101
|
+
6. `.claude/settings.local.json` - Note about experimental-strip-types
|
|
102
|
+
|
|
103
|
+
## Build Status
|
|
104
|
+
|
|
105
|
+
- ✅ Windows x64: Working (v0.1.107)
|
|
106
|
+
- ✅ Linux x64 (WSL): Working
|
|
107
|
+
- ⏳ Linux ARM64 (Pi): Blocked by GLib version (upgrade Pi OS to fix)
|
|
108
|
+
|
|
109
|
+
## Commands Ready to Run After Pi Upgrade
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# 1. Verify Pi is upgraded
|
|
113
|
+
ssh pi4c "cat /etc/os-release" # Should show Debian 12
|
|
114
|
+
|
|
115
|
+
# 2. Check GLib version
|
|
116
|
+
ssh pi4c "pkg-config --modversion glib-2.0" # Should show 2.74+
|
|
117
|
+
|
|
118
|
+
# 3. Build
|
|
119
|
+
npm run build:native:pi
|
|
120
|
+
|
|
121
|
+
# 4. Test
|
|
122
|
+
scp msger-native/bin/msgernative-arm64 pi4c:~/
|
|
123
|
+
ssh pi4c "echo '{\"message\":\"Hello ARM64!\"}' | ./msgernative-arm64"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Background Processes to Clean Up
|
|
127
|
+
|
|
128
|
+
Several test processes may still be running:
|
|
129
|
+
- Bash 6cefc7 - MSGER_DEBUG test with wikipedia
|
|
130
|
+
- Bash 75121d - MSGER_DEBUG test with example.com
|
|
131
|
+
- Bash 939f7a - Pi build attempt
|
|
132
|
+
|
|
133
|
+
Can kill after reboot if needed.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Summary
|
|
138
|
+
|
|
139
|
+
Ready to continue with Pi OS upgrade when you return. All code changes for auto-title and -dev flag are complete and working on Windows/WSL.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
REM Check Pi Debian version from Windows
|
|
3
|
+
|
|
4
|
+
echo ======================================================================
|
|
5
|
+
echo Checking Raspberry Pi Debian Version
|
|
6
|
+
echo ======================================================================
|
|
7
|
+
echo.
|
|
8
|
+
|
|
9
|
+
ssh pi4c "bash -s" < check-pi-debian-version.sh
|
|
10
|
+
|
|
11
|
+
if errorlevel 1 (
|
|
12
|
+
echo.
|
|
13
|
+
echo ======================================================================
|
|
14
|
+
echo ERROR: Cannot connect to pi4c
|
|
15
|
+
echo ======================================================================
|
|
16
|
+
echo.
|
|
17
|
+
echo Troubleshooting:
|
|
18
|
+
echo 1. Check Pi is powered on and connected
|
|
19
|
+
echo 2. Verify SSH access: ssh pi4c
|
|
20
|
+
echo 3. Check hostname in .ssh/config or C:\Windows\System32\drivers\etc\hosts
|
|
21
|
+
echo.
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
echo.
|
|
25
|
+
pause
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Check Raspberry Pi Debian Version (NO UPGRADE)
|
|
4
|
+
# Just checks and warns if not on Debian 12
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
echo "======================================================================"
|
|
8
|
+
echo " Raspberry Pi Debian Version Check"
|
|
9
|
+
echo "======================================================================"
|
|
10
|
+
echo ""
|
|
11
|
+
echo "Current OS version:"
|
|
12
|
+
cat /etc/os-release | grep PRETTY_NAME
|
|
13
|
+
echo ""
|
|
14
|
+
|
|
15
|
+
# Check current version
|
|
16
|
+
CURRENT_VERSION=$(grep VERSION_CODENAME /etc/os-release | cut -d= -f2)
|
|
17
|
+
echo "Detected version: $CURRENT_VERSION"
|
|
18
|
+
echo ""
|
|
19
|
+
|
|
20
|
+
# Check GLib version
|
|
21
|
+
echo "GLib version:"
|
|
22
|
+
GLIB_VERSION=$(pkg-config --modversion glib-2.0 2>/dev/null || echo "not found")
|
|
23
|
+
echo "$GLIB_VERSION"
|
|
24
|
+
echo ""
|
|
25
|
+
|
|
26
|
+
if [[ "$CURRENT_VERSION" == "bookworm" ]]; then
|
|
27
|
+
echo "✅ Running Debian 12 (Bookworm) - compatible with msger"
|
|
28
|
+
|
|
29
|
+
# Check if GLib is sufficient
|
|
30
|
+
GLIB_MAJOR=$(echo $GLIB_VERSION | cut -d. -f1)
|
|
31
|
+
GLIB_MINOR=$(echo $GLIB_VERSION | cut -d. -f2)
|
|
32
|
+
|
|
33
|
+
if [[ $GLIB_MAJOR -ge 2 ]] && [[ $GLIB_MINOR -ge 70 ]]; then
|
|
34
|
+
echo "✅ GLib $GLIB_VERSION >= 2.70 - msger build will work!"
|
|
35
|
+
else
|
|
36
|
+
echo "⚠️ GLib $GLIB_VERSION < 2.70 - msger build may fail"
|
|
37
|
+
echo " (wry 0.47 requires GLib >= 2.70)"
|
|
38
|
+
fi
|
|
39
|
+
elif [[ "$CURRENT_VERSION" == "bullseye" ]]; then
|
|
40
|
+
echo "⚠️ WARNING: Running Debian 11 (Bullseye)"
|
|
41
|
+
echo ""
|
|
42
|
+
echo "❌ GLib $GLIB_VERSION < 2.70 - msger build WILL FAIL"
|
|
43
|
+
echo " wry 0.47 requires GLib >= 2.70"
|
|
44
|
+
echo " Debian 11 only has GLib 2.66"
|
|
45
|
+
echo ""
|
|
46
|
+
echo "Recommended: Fresh install of Raspberry Pi OS based on Debian 12"
|
|
47
|
+
echo "Download: https://www.raspberrypi.com/software/operating-systems/"
|
|
48
|
+
else
|
|
49
|
+
echo "ℹ️ Unknown Debian version: $CURRENT_VERSION"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
echo ""
|
|
53
|
+
echo "======================================================================"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/msger-native/build-pi.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { execSync } from 'child_process';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
|
+
import packageJson from '../package.json' with { type: 'json' };
|
|
5
6
|
|
|
6
7
|
// Configuration - UPDATE THESE VALUES
|
|
7
8
|
const PI_HOST = 'pi4c'; // or 'pi@raspberrypi.local' or 'pi@192.168.1.xxx'
|
|
@@ -13,24 +14,82 @@ console.log(`📍 Target: ${PI_HOST}`);
|
|
|
13
14
|
try {
|
|
14
15
|
// Test SSH connection
|
|
15
16
|
console.log('🔍 Testing SSH connection...');
|
|
16
|
-
execSync(`ssh ${PI_HOST} "echo Connected"`, { stdio: 'pipe' });
|
|
17
|
+
execSync(`ssh ${PI_HOST} "echo Connected"`, { stdio: 'pipe', timeout: 5000 });
|
|
17
18
|
console.log('✅ SSH connection successful');
|
|
18
19
|
} catch (error) {
|
|
19
|
-
|
|
20
|
-
console.
|
|
21
|
-
console.
|
|
22
|
-
|
|
20
|
+
// Yellow/orange banner for warning (not an error)
|
|
21
|
+
console.log('\x1b[93m\x1b[40m'); // Bright yellow on black
|
|
22
|
+
console.log('╔════════════════════════════════════════════════════════════════╗');
|
|
23
|
+
console.log('║ ℹ️ RASPBERRY PI NOT AVAILABLE - SKIPPING ARM64 BUILD ║');
|
|
24
|
+
console.log('╚════════════════════════════════════════════════════════════════╝');
|
|
25
|
+
console.log('\x1b[0m'); // Reset colors
|
|
26
|
+
console.log('');
|
|
27
|
+
console.log(`Cannot connect to Pi: ${PI_HOST}`);
|
|
28
|
+
console.log('To enable Pi builds:');
|
|
29
|
+
console.log(` 1. Ensure Pi is powered on and connected to network`);
|
|
30
|
+
console.log(` 2. Verify SSH access: ssh ${PI_HOST}`);
|
|
31
|
+
console.log(` 3. Set up SSH keys if needed: ssh-copy-id ${PI_HOST}`);
|
|
32
|
+
console.log('');
|
|
33
|
+
console.log('✅ Continuing build without Pi binary...');
|
|
34
|
+
process.exit(0); // Exit gracefully (not an error)
|
|
23
35
|
}
|
|
24
36
|
|
|
25
37
|
// Create build directory on Pi
|
|
26
38
|
console.log('📁 Creating build directory on Pi...');
|
|
27
39
|
execSync(`ssh ${PI_HOST} "mkdir -p ${PI_BUILD_DIR}/src"`, { stdio: 'inherit' });
|
|
28
40
|
|
|
41
|
+
// Check if build is needed (compare source file mtimes with existing binary)
|
|
42
|
+
console.log('🔍 Checking if build is needed...');
|
|
43
|
+
const destPath = path.join(import.meta.dirname, 'bin', 'msgernative-arm64');
|
|
44
|
+
let needsBuild = true;
|
|
45
|
+
|
|
46
|
+
if (fs.existsSync(destPath)) {
|
|
47
|
+
const binaryMtime = fs.statSync(destPath).mtimeMs;
|
|
48
|
+
|
|
49
|
+
// Check if any source files are newer than the binary
|
|
50
|
+
const sourceFiles = [
|
|
51
|
+
path.join(import.meta.dirname, 'Cargo.toml'),
|
|
52
|
+
...fs.readdirSync(path.join(import.meta.dirname, 'src'))
|
|
53
|
+
.map(f => path.join(import.meta.dirname, 'src', f))
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const newerFiles = sourceFiles.filter(f => {
|
|
57
|
+
try {
|
|
58
|
+
return fs.statSync(f).mtimeMs > binaryMtime;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (newerFiles.length === 0) {
|
|
65
|
+
console.log('✅ Binary is up-to-date, skipping build');
|
|
66
|
+
console.log(`📁 Existing binary: ${destPath}`);
|
|
67
|
+
const stats = fs.statSync(destPath);
|
|
68
|
+
const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
|
|
69
|
+
console.log(`📊 Binary size: ${sizeMB} MB`);
|
|
70
|
+
process.exit(0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
console.log(`📝 ${newerFiles.length} source file(s) newer than binary, build needed`);
|
|
74
|
+
needsBuild = true;
|
|
75
|
+
}
|
|
76
|
+
|
|
29
77
|
// Copy source files to Pi
|
|
30
78
|
console.log('📤 Copying source files to Pi...');
|
|
31
79
|
execSync(`scp Cargo.toml ${PI_HOST}:${PI_BUILD_DIR}/`, { stdio: 'inherit', cwd: import.meta.dirname });
|
|
32
80
|
execSync(`scp -r src/* ${PI_HOST}:${PI_BUILD_DIR}/src/`, { stdio: 'inherit', cwd: import.meta.dirname });
|
|
33
81
|
|
|
82
|
+
// Check for C compiler (gcc/cc) on Pi
|
|
83
|
+
console.log('🔍 Checking for C compiler on Pi...');
|
|
84
|
+
try {
|
|
85
|
+
execSync(`ssh ${PI_HOST} "command -v gcc"`, { stdio: 'pipe' });
|
|
86
|
+
console.log('✅ C compiler found');
|
|
87
|
+
} catch {
|
|
88
|
+
console.log('📦 Installing build-essential (C compiler, make, etc.) on Pi...');
|
|
89
|
+
execSync(`ssh ${PI_HOST} "sudo apt-get update && sudo apt-get install -y build-essential"`, { stdio: 'inherit' });
|
|
90
|
+
console.log('✅ build-essential installed');
|
|
91
|
+
}
|
|
92
|
+
|
|
34
93
|
// Check for Rust on Pi
|
|
35
94
|
console.log('🔍 Checking for Rust/Cargo on Pi...');
|
|
36
95
|
try {
|
|
@@ -56,24 +115,45 @@ try {
|
|
|
56
115
|
// Check for build dependencies on Pi
|
|
57
116
|
console.log('🔍 Checking for build dependencies on Pi...');
|
|
58
117
|
try {
|
|
59
|
-
|
|
118
|
+
// Check for all required libraries: glib, gobject, gio, gtk, webkit
|
|
119
|
+
execSync(`ssh ${PI_HOST} "pkg-config --exists glib-2.0 gobject-2.0 gio-2.0 gtk+-3.0 && (pkg-config --exists webkit2gtk-4.1 || pkg-config --exists webkit2gtk-4.0)"`, { stdio: 'pipe' });
|
|
60
120
|
console.log('✅ Build dependencies found');
|
|
61
121
|
} catch {
|
|
62
122
|
console.log('📦 Installing build dependencies on Pi...');
|
|
63
|
-
|
|
64
|
-
|
|
123
|
+
// Install all required development packages
|
|
124
|
+
// Try webkit2gtk-4.1 first (newer), fallback to 4.0 if not available
|
|
125
|
+
try {
|
|
126
|
+
execSync(`ssh ${PI_HOST} "sudo apt-get install -y libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.1-dev"`, { stdio: 'inherit' });
|
|
127
|
+
console.log('✅ Build dependencies installed (webkit2gtk-4.1)');
|
|
128
|
+
} catch {
|
|
129
|
+
console.log('ℹ️ webkit2gtk-4.1 not available, trying 4.0...');
|
|
130
|
+
execSync(`ssh ${PI_HOST} "sudo apt-get install -y libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.0-dev libsoup2.4-dev"`, { stdio: 'inherit' });
|
|
131
|
+
console.log('✅ Build dependencies installed (webkit2gtk-4.0)');
|
|
132
|
+
}
|
|
65
133
|
}
|
|
66
134
|
|
|
135
|
+
// Get NPM version from imported package.json
|
|
136
|
+
const npmVersion = packageJson.version;
|
|
137
|
+
console.log(`📋 Package version: ${npmVersion}`);
|
|
138
|
+
|
|
139
|
+
// Copy package.json to Pi (needed for version)
|
|
140
|
+
console.log('📤 Copying package.json to Pi...');
|
|
141
|
+
execSync(`scp package.json ${PI_HOST}:${PI_BUILD_DIR}/`, { stdio: 'inherit', cwd: import.meta.dirname });
|
|
142
|
+
|
|
67
143
|
// Build on Pi
|
|
68
144
|
console.log('\n📦 Building ARM64 binary on Pi...');
|
|
69
145
|
try {
|
|
70
|
-
|
|
146
|
+
// Source cargo env and build (ensures cargo can find all its dependencies including cc)
|
|
147
|
+
// Export NPM_VERSION for Rust build
|
|
148
|
+
execSync(`ssh ${PI_HOST} "cd ${PI_BUILD_DIR} && source ~/.cargo/env && export PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig && export NPM_VERSION=${npmVersion} && cargo build --release"`, { stdio: 'inherit' });
|
|
71
149
|
console.log('✅ ARM64 build completed');
|
|
72
150
|
} catch (error: any) {
|
|
73
|
-
console.error('❌
|
|
151
|
+
console.error('❌ Pi build failed:');
|
|
74
152
|
console.error(error.stdout?.toString());
|
|
75
153
|
console.error(error.stderr?.toString());
|
|
76
|
-
|
|
154
|
+
console.error('');
|
|
155
|
+
console.error('⚠️ Continuing without Pi binary...');
|
|
156
|
+
process.exit(0); // Exit gracefully to not break overall build
|
|
77
157
|
}
|
|
78
158
|
|
|
79
159
|
// Copy binary back
|
|
@@ -83,7 +163,6 @@ if (!fs.existsSync(destDir)) {
|
|
|
83
163
|
fs.mkdirSync(destDir, { recursive: true });
|
|
84
164
|
}
|
|
85
165
|
|
|
86
|
-
const destPath = path.join(destDir, 'msgernative-arm64');
|
|
87
166
|
execSync(`scp ${PI_HOST}:${PI_BUILD_DIR}/target/release/msgernative ${destPath}`, { stdio: 'inherit' });
|
|
88
167
|
|
|
89
168
|
// Set execute permissions
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"description": "Rust binary for msger - native message box implementation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"build": "node
|
|
8
|
-
"build:wsl": "node
|
|
9
|
-
"build:arm64": "node
|
|
10
|
-
"build:pi": "node
|
|
7
|
+
"build": "node build.ts",
|
|
8
|
+
"build:wsl": "node build-wsl.ts",
|
|
9
|
+
"build:arm64": "node build-arm64.ts",
|
|
10
|
+
"build:pi": "node build-pi.ts"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [
|
|
13
13
|
"message-box",
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Pi Diagnostics Script
|
|
4
|
+
* Runs on the Pi to check build requirements
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
|
|
10
|
+
const COLORS = {
|
|
11
|
+
reset: '\x1b[0m',
|
|
12
|
+
red: '\x1b[31m',
|
|
13
|
+
green: '\x1b[32m',
|
|
14
|
+
yellow: '\x1b[33m',
|
|
15
|
+
blue: '\x1b[34m',
|
|
16
|
+
magenta: '\x1b[35m',
|
|
17
|
+
cyan: '\x1b[36m',
|
|
18
|
+
white: '\x1b[37m',
|
|
19
|
+
bgRed: '\x1b[41m',
|
|
20
|
+
bgGreen: '\x1b[42m',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function log(message: string, color = COLORS.reset) {
|
|
24
|
+
console.log(`${color}${message}${COLORS.reset}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function exec(cmd: string): string {
|
|
28
|
+
try {
|
|
29
|
+
return execSync(cmd, { encoding: 'utf8' });
|
|
30
|
+
} catch {
|
|
31
|
+
return '';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function checkCommand(cmd: string, name: string): boolean {
|
|
36
|
+
const result = exec(`command -v ${cmd}`).trim();
|
|
37
|
+
if (result) {
|
|
38
|
+
log(`✅ ${name} found: ${result}`, COLORS.green);
|
|
39
|
+
return true;
|
|
40
|
+
} else {
|
|
41
|
+
log(`❌ ${name} NOT found`, COLORS.red);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function checkPkgConfig(pkg: string, minVersion?: string): { found: boolean; version: string } {
|
|
47
|
+
const version = exec(`pkg-config --modversion ${pkg} 2>/dev/null`).trim();
|
|
48
|
+
if (!version) {
|
|
49
|
+
log(`❌ ${pkg} NOT found via pkg-config`, COLORS.red);
|
|
50
|
+
return { found: false, version: '' };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (minVersion) {
|
|
54
|
+
const versionParts = version.split('.').map(Number);
|
|
55
|
+
const minParts = minVersion.split('.').map(Number);
|
|
56
|
+
const isOldEnough = versionParts[0] > minParts[0] ||
|
|
57
|
+
(versionParts[0] === minParts[0] && versionParts[1] >= minParts[1]);
|
|
58
|
+
|
|
59
|
+
if (isOldEnough) {
|
|
60
|
+
log(`✅ ${pkg} version ${version} (>= ${minVersion})`, COLORS.green);
|
|
61
|
+
return { found: true, version };
|
|
62
|
+
} else {
|
|
63
|
+
log(`⚠️ ${pkg} version ${version} (need >= ${minVersion})`, COLORS.yellow);
|
|
64
|
+
return { found: true, version };
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
log(`✅ ${pkg} version ${version}`, COLORS.green);
|
|
68
|
+
return { found: true, version };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
log('\n🔍 Raspberry Pi Build Requirements Diagnostic\n', COLORS.cyan);
|
|
73
|
+
|
|
74
|
+
// Check OS
|
|
75
|
+
log('📋 OS Information:', COLORS.blue);
|
|
76
|
+
const osRelease = exec('cat /etc/os-release');
|
|
77
|
+
const osName = osRelease.match(/PRETTY_NAME="([^"]+)"/)?.[1] || 'Unknown';
|
|
78
|
+
const osVersion = osRelease.match(/VERSION_ID="([^"]+)"/)?.[1] || 'Unknown';
|
|
79
|
+
log(` ${osName}`, COLORS.white);
|
|
80
|
+
|
|
81
|
+
// Check architecture
|
|
82
|
+
const arch = exec('uname -m').trim();
|
|
83
|
+
log(` Architecture: ${arch}\n`, COLORS.white);
|
|
84
|
+
|
|
85
|
+
// Check build tools
|
|
86
|
+
log('🔧 Build Tools:', COLORS.blue);
|
|
87
|
+
const hasGcc = checkCommand('gcc', 'C Compiler (gcc)');
|
|
88
|
+
const hasMake = checkCommand('make', 'Make');
|
|
89
|
+
const hasCargo = checkCommand('cargo', 'Rust/Cargo');
|
|
90
|
+
const hasPkgConfig = checkCommand('pkg-config', 'pkg-config');
|
|
91
|
+
|
|
92
|
+
// Check libraries
|
|
93
|
+
log('\n📚 Required Libraries:', COLORS.blue);
|
|
94
|
+
const glib = checkPkgConfig('glib-2.0', '2.70');
|
|
95
|
+
const gobject = checkPkgConfig('gobject-2.0', '2.70');
|
|
96
|
+
const gio = checkPkgConfig('gio-2.0', '2.70');
|
|
97
|
+
const gtk = checkPkgConfig('gtk+-3.0');
|
|
98
|
+
const webkit4_1 = checkPkgConfig('webkit2gtk-4.1');
|
|
99
|
+
const webkit4_0 = checkPkgConfig('webkit2gtk-4.0');
|
|
100
|
+
|
|
101
|
+
// Summary
|
|
102
|
+
log('\n📊 Summary:', COLORS.blue);
|
|
103
|
+
|
|
104
|
+
const allToolsReady = hasGcc && hasMake && hasCargo && hasPkgConfig;
|
|
105
|
+
const glibOk = glib.found && parseFloat(glib.version) >= 2.70;
|
|
106
|
+
const allLibsReady = glib.found && gobject.found && gio.found && gtk.found && (webkit4_1.found || webkit4_0.found);
|
|
107
|
+
|
|
108
|
+
if (allToolsReady && glibOk && allLibsReady) {
|
|
109
|
+
log('✅ All requirements met! Ready to build.', COLORS.green);
|
|
110
|
+
} else {
|
|
111
|
+
log('❌ Some requirements missing or outdated', COLORS.red);
|
|
112
|
+
|
|
113
|
+
if (!glibOk && glib.found) {
|
|
114
|
+
log('\n⚠️ CRITICAL ISSUE:', COLORS.bgRed + COLORS.white);
|
|
115
|
+
log(` GLib version ${glib.version} is too old (need >= 2.70)`, COLORS.yellow);
|
|
116
|
+
log(` Your OS: ${osName}`, COLORS.white);
|
|
117
|
+
log(`\n Solutions:`, COLORS.cyan);
|
|
118
|
+
log(` 1. Upgrade to Debian 12 (Bookworm) or later:`, COLORS.white);
|
|
119
|
+
log(` sudo apt update && sudo apt full-upgrade`, COLORS.white);
|
|
120
|
+
log(` 2. Or use wry 0.24 which supports glib 2.56+`, COLORS.white);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!allToolsReady) {
|
|
124
|
+
log('\n💡 Missing tools - install with:', COLORS.cyan);
|
|
125
|
+
if (!hasGcc || !hasMake) log(' sudo apt install build-essential', COLORS.white);
|
|
126
|
+
if (!hasCargo) log(' curl --proto \'=https\' --tlsv1.2 -sSf https://sh.rustup.rs | sh', COLORS.white);
|
|
127
|
+
if (!hasPkgConfig) log(' sudo apt install pkg-config', COLORS.white);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (!allLibsReady) {
|
|
131
|
+
log('\n💡 Missing libraries - install with:', COLORS.cyan);
|
|
132
|
+
log(' sudo apt install libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.1-dev', COLORS.white);
|
|
133
|
+
log(' OR (if 4.1 unavailable):', COLORS.white);
|
|
134
|
+
log(' sudo apt install libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.0-dev', COLORS.white);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
log('', COLORS.reset);
|
package/msger-native/src/main.rs
CHANGED
|
@@ -460,13 +460,77 @@ fn main() {
|
|
|
460
460
|
#[cfg_attr(not(windows), allow(unused_variables))]
|
|
461
461
|
let webview = if let Some(ref url) = options.url {
|
|
462
462
|
// Create initialization script with config + msger API
|
|
463
|
-
let init_script = format!(
|
|
463
|
+
let mut init_script = format!(
|
|
464
464
|
"window.msgerConfig = {{ escapeCloses: {}, reset: {} }};\n{}",
|
|
465
465
|
if options.escape_closes { "true" } else { "false" },
|
|
466
466
|
if options.reset { "true" } else { "false" },
|
|
467
467
|
MSGER_JS_API
|
|
468
468
|
);
|
|
469
469
|
|
|
470
|
+
// Add auto-title monitoring for URL mode
|
|
471
|
+
init_script.push_str(r#"
|
|
472
|
+
// Auto-update window title from document.title
|
|
473
|
+
(function() {
|
|
474
|
+
let lastTitle = '';
|
|
475
|
+
function updateTitle() {
|
|
476
|
+
const currentTitle = document.title;
|
|
477
|
+
if (currentTitle && currentTitle !== lastTitle) {
|
|
478
|
+
lastTitle = currentTitle;
|
|
479
|
+
if (window.ipc && window.ipc.postMessage) {
|
|
480
|
+
window.ipc.postMessage(JSON.stringify({
|
|
481
|
+
_action: 'setTitle',
|
|
482
|
+
title: currentTitle
|
|
483
|
+
}));
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Check on load
|
|
489
|
+
if (document.readyState === 'loading') {
|
|
490
|
+
document.addEventListener('DOMContentLoaded', updateTitle);
|
|
491
|
+
} else {
|
|
492
|
+
updateTitle();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Monitor for title changes (SPAs, dynamic pages)
|
|
496
|
+
const observer = new MutationObserver(updateTitle);
|
|
497
|
+
const titleEl = document.querySelector('title');
|
|
498
|
+
if (titleEl) {
|
|
499
|
+
observer.observe(titleEl, { childList: true });
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Also check periodically as fallback
|
|
503
|
+
setInterval(updateTitle, 1000);
|
|
504
|
+
})();
|
|
505
|
+
"#);
|
|
506
|
+
|
|
507
|
+
// Add DevTools opener if -dev flag is set
|
|
508
|
+
if options.dev {
|
|
509
|
+
init_script.push_str(r#"
|
|
510
|
+
// Open DevTools automatically when -dev flag is set
|
|
511
|
+
(function() {
|
|
512
|
+
function openDevTools() {
|
|
513
|
+
// Simulate F12 key press to open DevTools
|
|
514
|
+
const event = new KeyboardEvent('keydown', {
|
|
515
|
+
key: 'F12',
|
|
516
|
+
code: 'F12',
|
|
517
|
+
keyCode: 123,
|
|
518
|
+
which: 123,
|
|
519
|
+
bubbles: true,
|
|
520
|
+
cancelable: true
|
|
521
|
+
});
|
|
522
|
+
document.dispatchEvent(event);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (document.readyState === 'loading') {
|
|
526
|
+
document.addEventListener('DOMContentLoaded', () => setTimeout(openDevTools, 100));
|
|
527
|
+
} else {
|
|
528
|
+
setTimeout(openDevTools, 100);
|
|
529
|
+
}
|
|
530
|
+
})();
|
|
531
|
+
"#);
|
|
532
|
+
}
|
|
533
|
+
|
|
470
534
|
// Load URL with msger API injected
|
|
471
535
|
let builder = WebViewBuilder::with_web_context(&mut web_context)
|
|
472
536
|
.with_url(url)
|
|
@@ -583,13 +647,8 @@ fn main() {
|
|
|
583
647
|
webview
|
|
584
648
|
};
|
|
585
649
|
|
|
586
|
-
//
|
|
587
|
-
|
|
588
|
-
// TODO: open_devtools() method not available in wry 0.47.2
|
|
589
|
-
// webview.open_devtools();
|
|
590
|
-
eprintln!("Warning: -dev flag specified but open_devtools() not available in wry 0.47.2");
|
|
591
|
-
eprintln!("DevTools are enabled - press F12 to open manually");
|
|
592
|
-
}
|
|
650
|
+
// DevTools handling is done via JavaScript injection in init_script above
|
|
651
|
+
// No additional action needed here
|
|
593
652
|
|
|
594
653
|
// Run event loop
|
|
595
654
|
event_loop.run(move |event, _,control_flow| {
|
package/msgernative-linux-x64
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/msger",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.109",
|
|
4
4
|
"description": "Fast, lightweight, cross-platform message box - Rust-powered alternative to msgview",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -19,8 +19,7 @@
|
|
|
19
19
|
"build:native:wsl": "cd msger-native && npm run build:wsl",
|
|
20
20
|
"build:native:arm64": "cd msger-native && npm run build:arm64",
|
|
21
21
|
"build:native:pi": "cd msger-native && npm run build:pi",
|
|
22
|
-
"build:native:all": "npm run build:native && npm run build:native:wsl",
|
|
23
|
-
"build:native:allpiignored": "npm run build:native:pi",
|
|
22
|
+
"build:native:all": "npm run build:native && npm run build:native:wsl && (npm run build:native:pi || true)",
|
|
24
23
|
"setup:arm64": "wsl bash msger-native/setup-arm64-toolchain.sh",
|
|
25
24
|
"build:ts": "tsc",
|
|
26
25
|
"watch": "tsc -w",
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Initial Title - Should Update</title>
|
|
5
|
+
<style>
|
|
6
|
+
body {
|
|
7
|
+
font-family: Arial, sans-serif;
|
|
8
|
+
padding: 40px;
|
|
9
|
+
max-width: 600px;
|
|
10
|
+
margin: 0 auto;
|
|
11
|
+
}
|
|
12
|
+
button {
|
|
13
|
+
padding: 10px 20px;
|
|
14
|
+
margin: 10px;
|
|
15
|
+
font-size: 16px;
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
}
|
|
18
|
+
.info {
|
|
19
|
+
background: #e3f2fd;
|
|
20
|
+
padding: 15px;
|
|
21
|
+
border-radius: 5px;
|
|
22
|
+
margin: 20px 0;
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
<h1>Title Auto-Update Test</h1>
|
|
28
|
+
|
|
29
|
+
<div class="info">
|
|
30
|
+
<strong>Window title should automatically update from document.title!</strong>
|
|
31
|
+
<p>Current title: <span id="currentTitle"></span></p>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<p>Click buttons to change the document title:</p>
|
|
35
|
+
|
|
36
|
+
<button onclick="changeTitle('Hello World!')">Set Title: Hello World!</button>
|
|
37
|
+
<button onclick="changeTitle('Test Title 123')">Set Title: Test Title 123</button>
|
|
38
|
+
<button onclick="changeTitle('Dynamic Update Works!')">Set Title: Dynamic Update Works!</button>
|
|
39
|
+
<button onclick="dynamicTitles()">Auto-Change Every Second</button>
|
|
40
|
+
|
|
41
|
+
<script>
|
|
42
|
+
function updateDisplay() {
|
|
43
|
+
document.getElementById('currentTitle').textContent = document.title;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function changeTitle(newTitle) {
|
|
47
|
+
document.title = newTitle;
|
|
48
|
+
updateDisplay();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let interval;
|
|
52
|
+
function dynamicTitles() {
|
|
53
|
+
if (interval) {
|
|
54
|
+
clearInterval(interval);
|
|
55
|
+
interval = null;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const titles = [
|
|
60
|
+
'Title 1 - Auto Update!',
|
|
61
|
+
'Title 2 - See it change?',
|
|
62
|
+
'Title 3 - Window title updates!',
|
|
63
|
+
'Title 4 - Amazing!'
|
|
64
|
+
];
|
|
65
|
+
let i = 0;
|
|
66
|
+
|
|
67
|
+
interval = setInterval(() => {
|
|
68
|
+
document.title = titles[i];
|
|
69
|
+
updateDisplay();
|
|
70
|
+
i = (i + 1) % titles.length;
|
|
71
|
+
}, 1000);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Update display on load
|
|
75
|
+
updateDisplay();
|
|
76
|
+
|
|
77
|
+
// Change title after 1 second to test auto-update
|
|
78
|
+
setTimeout(() => {
|
|
79
|
+
changeTitle('Auto-Changed After 1 Second!');
|
|
80
|
+
}, 1000);
|
|
81
|
+
</script>
|
|
82
|
+
</body>
|
|
83
|
+
</html>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
REM Windows batch file to upgrade Raspberry Pi via SSH
|
|
3
|
+
REM Runs the upgrade script remotely on the Pi
|
|
4
|
+
|
|
5
|
+
echo ======================================================================
|
|
6
|
+
echo Raspberry Pi OS Upgrade: Debian 11 -^> Debian 12
|
|
7
|
+
echo (Remote execution from Windows via SSH)
|
|
8
|
+
echo ======================================================================
|
|
9
|
+
echo.
|
|
10
|
+
echo This will:
|
|
11
|
+
echo 1. SSH to pi4c
|
|
12
|
+
echo 2. Run the upgrade script
|
|
13
|
+
echo 3. Upgrade from Debian 11 (Bullseye) to Debian 12 (Bookworm)
|
|
14
|
+
echo.
|
|
15
|
+
echo Estimated time: 30-60 minutes
|
|
16
|
+
echo.
|
|
17
|
+
|
|
18
|
+
set /p CONFIRM="Continue with upgrade? (yes/no): "
|
|
19
|
+
if /i not "%CONFIRM%"=="yes" (
|
|
20
|
+
echo Upgrade cancelled.
|
|
21
|
+
exit /b 0
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
echo.
|
|
25
|
+
echo ======================================================================
|
|
26
|
+
echo Copying upgrade script to Pi...
|
|
27
|
+
echo ======================================================================
|
|
28
|
+
scp upgrade-pi-to-debian12.sh pi4c:/tmp/
|
|
29
|
+
|
|
30
|
+
echo.
|
|
31
|
+
echo ======================================================================
|
|
32
|
+
echo Running upgrade on Pi (this will take 30-60 minutes)...
|
|
33
|
+
echo ======================================================================
|
|
34
|
+
ssh -t pi4c "bash /tmp/upgrade-pi-to-debian12.sh"
|
|
35
|
+
|
|
36
|
+
echo.
|
|
37
|
+
echo ======================================================================
|
|
38
|
+
echo Cleaning up...
|
|
39
|
+
echo ======================================================================
|
|
40
|
+
ssh pi4c "rm /tmp/upgrade-pi-to-debian12.sh"
|
|
41
|
+
|
|
42
|
+
echo.
|
|
43
|
+
echo ======================================================================
|
|
44
|
+
echo Done! Pi should reboot automatically.
|
|
45
|
+
echo ======================================================================
|
|
46
|
+
echo.
|
|
47
|
+
echo After reboot, verify with:
|
|
48
|
+
echo ssh pi4c "cat /etc/os-release ^| grep PRETTY_NAME"
|
|
49
|
+
echo ssh pi4c "pkg-config --modversion glib-2.0"
|
|
50
|
+
echo.
|
|
51
|
+
pause
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Raspberry Pi OS Upgrade Script: Debian 11 (Bullseye) → Debian 12 (Bookworm)
|
|
4
|
+
#
|
|
5
|
+
# This script upgrades Raspberry Pi OS from Debian 11 to Debian 12.
|
|
6
|
+
# Estimated time: 30-60 minutes
|
|
7
|
+
#
|
|
8
|
+
# Run on Pi: ssh pi4c < upgrade-pi-to-debian12.sh
|
|
9
|
+
# Or copy to Pi and run: bash upgrade-pi-to-debian12.sh
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
set -e # Exit on error
|
|
13
|
+
|
|
14
|
+
echo "======================================================================"
|
|
15
|
+
echo " Raspberry Pi OS Upgrade: Debian 11 → Debian 12"
|
|
16
|
+
echo "======================================================================"
|
|
17
|
+
echo ""
|
|
18
|
+
echo "Current OS version:"
|
|
19
|
+
cat /etc/os-release | grep PRETTY_NAME
|
|
20
|
+
echo ""
|
|
21
|
+
|
|
22
|
+
# Check current version
|
|
23
|
+
CURRENT_VERSION=$(grep VERSION_CODENAME /etc/os-release | cut -d= -f2)
|
|
24
|
+
echo "Detected version: $CURRENT_VERSION"
|
|
25
|
+
echo ""
|
|
26
|
+
|
|
27
|
+
if [[ "$CURRENT_VERSION" == "bookworm" ]]; then
|
|
28
|
+
echo "✅ Already running Debian 12 (Bookworm) - no upgrade needed!"
|
|
29
|
+
echo ""
|
|
30
|
+
echo "GLib version:"
|
|
31
|
+
pkg-config --modversion glib-2.0
|
|
32
|
+
echo ""
|
|
33
|
+
echo "System is up to date."
|
|
34
|
+
exit 0
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if [[ "$CURRENT_VERSION" != "bullseye" ]]; then
|
|
38
|
+
echo "⚠️ WARNING: Unexpected Debian version: $CURRENT_VERSION"
|
|
39
|
+
echo "This script is designed for Bullseye → Bookworm upgrade only."
|
|
40
|
+
echo ""
|
|
41
|
+
read -p "Continue anyway? (yes/no): " -r
|
|
42
|
+
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
|
43
|
+
echo "Upgrade cancelled."
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
echo "⚠️ WARNING: This will upgrade your Pi OS to Debian 12 (Bookworm)"
|
|
49
|
+
echo "⚠️ Estimated time: 30-60 minutes"
|
|
50
|
+
echo "⚠️ Internet connection required"
|
|
51
|
+
echo ""
|
|
52
|
+
|
|
53
|
+
# Confirm
|
|
54
|
+
read -p "Continue with upgrade? (yes/no): " -r
|
|
55
|
+
if [[ ! $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
|
56
|
+
echo "Upgrade cancelled."
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
echo ""
|
|
61
|
+
echo "======================================================================"
|
|
62
|
+
echo "STEP 1/6: Updating current packages"
|
|
63
|
+
echo "======================================================================"
|
|
64
|
+
sudo apt update
|
|
65
|
+
sudo apt upgrade -y
|
|
66
|
+
sudo apt full-upgrade -y
|
|
67
|
+
|
|
68
|
+
echo ""
|
|
69
|
+
echo "======================================================================"
|
|
70
|
+
echo "STEP 2/6: Updating package sources to Debian 12 (Bookworm)"
|
|
71
|
+
echo "======================================================================"
|
|
72
|
+
|
|
73
|
+
# Backup original sources
|
|
74
|
+
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak.$(date +%Y%m%d)
|
|
75
|
+
echo "✅ Backed up: /etc/apt/sources.list.bak.$(date +%Y%m%d)"
|
|
76
|
+
|
|
77
|
+
# Update sources.list
|
|
78
|
+
sudo sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list
|
|
79
|
+
|
|
80
|
+
# Update Raspberry Pi specific sources if they exist
|
|
81
|
+
if [ -f /etc/apt/sources.list.d/raspi.list ]; then
|
|
82
|
+
sudo cp /etc/apt/sources.list.d/raspi.list /etc/apt/sources.list.d/raspi.list.bak.$(date +%Y%m%d)
|
|
83
|
+
sudo sed -i 's/bullseye/bookworm/g' /etc/apt/sources.list.d/raspi.list
|
|
84
|
+
echo "✅ Backed up: /etc/apt/sources.list.d/raspi.list.bak.$(date +%Y%m%d)"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
echo "✅ Package sources updated to Bookworm"
|
|
88
|
+
echo ""
|
|
89
|
+
echo "New sources.list:"
|
|
90
|
+
cat /etc/apt/sources.list
|
|
91
|
+
|
|
92
|
+
echo ""
|
|
93
|
+
echo "======================================================================"
|
|
94
|
+
echo "STEP 3/6: Updating package lists"
|
|
95
|
+
echo "======================================================================"
|
|
96
|
+
sudo apt update
|
|
97
|
+
|
|
98
|
+
echo ""
|
|
99
|
+
echo "======================================================================"
|
|
100
|
+
echo "STEP 4/6: Performing distribution upgrade (this takes 20-40 minutes)"
|
|
101
|
+
echo "======================================================================"
|
|
102
|
+
sudo DEBIAN_FRONTEND=noninteractive apt dist-upgrade -y
|
|
103
|
+
|
|
104
|
+
echo ""
|
|
105
|
+
echo "======================================================================"
|
|
106
|
+
echo "STEP 5/6: Cleaning up old packages"
|
|
107
|
+
echo "======================================================================"
|
|
108
|
+
sudo apt autoremove -y
|
|
109
|
+
sudo apt clean
|
|
110
|
+
|
|
111
|
+
echo ""
|
|
112
|
+
echo "======================================================================"
|
|
113
|
+
echo "STEP 6/6: Verifying upgrade"
|
|
114
|
+
echo "======================================================================"
|
|
115
|
+
echo "New OS version:"
|
|
116
|
+
cat /etc/os-release | grep PRETTY_NAME
|
|
117
|
+
echo ""
|
|
118
|
+
echo "GLib version:"
|
|
119
|
+
pkg-config --modversion glib-2.0
|
|
120
|
+
echo ""
|
|
121
|
+
|
|
122
|
+
echo "======================================================================"
|
|
123
|
+
echo "✅ UPGRADE COMPLETE!"
|
|
124
|
+
echo "======================================================================"
|
|
125
|
+
echo ""
|
|
126
|
+
echo "🔄 REBOOT REQUIRED to complete upgrade"
|
|
127
|
+
echo ""
|
|
128
|
+
read -p "Reboot now? (yes/no): " -r
|
|
129
|
+
if [[ $REPLY =~ ^[Yy][Ee][Ss]$ ]]; then
|
|
130
|
+
echo "Rebooting in 5 seconds..."
|
|
131
|
+
sleep 5
|
|
132
|
+
sudo reboot
|
|
133
|
+
else
|
|
134
|
+
echo "Please reboot manually: sudo reboot"
|
|
135
|
+
fi
|