Add SSH-triggered Eve screenshots

This commit is contained in:
Meta Vens 2026-06-02 16:59:51 +01:00
commit df2953cc7f
3 changed files with 100 additions and 0 deletions

View file

@ -304,6 +304,12 @@ Launch `EveCanvas` from SpringBoard, or over SSH:
uiopen --bundleid org.gamecult.evecanvas
```
Capture the running native renderer over SSH:
```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\capture-eve-screenshot.ps1
```
If OpenGL ES context creation fails on-device, the app stays alive with the
UIKit overlay instead of aborting launch. The render surface can then be fixed
without losing the basic app deployment path.

View file

@ -321,6 +321,69 @@ static NSData *EVEMediaObservation(NSString *observationId,
[self.glView renderAtTime:link.timestamp];
[self updateOverlay];
[self serviceScreenshotRequestIfNeeded];
}
- (void)serviceScreenshotRequestIfNeeded {
NSString *directory = @"/var/mobile/Library/EveCanvas";
NSString *requestPath = [directory stringByAppendingPathComponent:@"capture-request"];
NSFileManager *fileManager = NSFileManager.defaultManager;
if (![fileManager fileExistsAtPath:requestPath]) {
return;
}
[fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:nil];
[fileManager removeItemAtPath:requestPath error:nil];
CGSize size = self.view.bounds.size;
if (size.width <= 0.0 || size.height <= 0.0) {
[@"invalid-view-size" writeToFile:[directory stringByAppendingPathComponent:@"capture-status.txt"]
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
return;
}
UIGraphicsBeginImageContextWithOptions(size, YES, UIScreen.mainScreen.scale);
BOOL rendered = [self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES];
if (!rendered) {
CGContextRef context = UIGraphicsGetCurrentContext();
if (context) {
[self.view.layer renderInContext:context];
rendered = YES;
}
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (!rendered || !image) {
[@"render-failed" writeToFile:[directory stringByAppendingPathComponent:@"capture-status.txt"]
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
return;
}
NSData *png = UIImagePNGRepresentation(image);
if (!png) {
[@"png-encoding-failed" writeToFile:[directory stringByAppendingPathComponent:@"capture-status.txt"]
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
return;
}
NSString *latestPath = [directory stringByAppendingPathComponent:@"latest-screenshot.png"];
if ([png writeToFile:latestPath atomically:YES]) {
[@"ok" writeToFile:[directory stringByAppendingPathComponent:@"capture-status.txt"]
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
} else {
[@"write-failed" writeToFile:[directory stringByAppendingPathComponent:@"capture-status.txt"]
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
}
}
- (void)updateOverlay {

View file

@ -0,0 +1,31 @@
param(
[string] $Target = "eve",
[string] $OutputDirectory = "artifacts\screenshots"
)
$ErrorActionPreference = "Stop"
$projectRoot = Split-Path -Parent $PSScriptRoot
$outputRoot = Join-Path $projectRoot $OutputDirectory
New-Item -ItemType Directory -Force -Path $outputRoot | Out-Null
$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
$localPath = Join-Path $outputRoot "eve-$stamp.png"
$remoteDir = "/var/mobile/Library/EveCanvas"
$remotePath = "$remoteDir/latest-screenshot.png"
$requestPath = "$remoteDir/capture-request"
ssh $Target "mkdir -p '$remoteDir' && chown mobile:mobile '$remoteDir' && rm -f '$remotePath' '$requestPath' && touch '$requestPath' && chown mobile:mobile '$requestPath'"
$deadline = (Get-Date).AddSeconds(10)
do {
Start-Sleep -Milliseconds 250
ssh $Target "test -s '$remotePath'"
if ($LASTEXITCODE -eq 0) {
scp "${Target}:$remotePath" $localPath
Write-Host $localPath
exit 0
}
} while ((Get-Date) -lt $deadline)
throw "Timed out waiting for EveCanvas screenshot at ${Target}:$remotePath"