electron: external data dir, packaged path fix, footer responsive, test stabilization

- DB + uploads stored outside app bundle (survives updates)
- Router uses DOCUMENT_ROOT instead of __DIR__ (fixes AppImage paths)
- Footer count shifts right below 1250px, min-width 1150px
- Gallery opens gracefully on fetch errors
- Stabilized gallery, export, and find/replace tests with poll loops

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
thandClaude Opus 4.6 committed 2026-04-12 17:24:00 +02:00
1 parent ee192a15e7
commit d3d9355191
9 files changed
+78 -39

No files matched your search

+9 -9
View File
@@ -409,7 +409,7 @@ if (str_starts_with($route, '/api/')) {
// List all upload files
if ($route === '/api/uploads' && $method === 'GET') {
$dir = __DIR__ . '/uploads';
$dir = UPLOAD_DIR;
$files = [];
if (is_dir($dir)) {
foreach (glob($dir . '/*.{png,jpg,gif,webp,mp3,ogg,wav,m4a}', GLOB_BRACE) as $f) {
@@ -424,7 +424,7 @@ if (str_starts_with($route, '/api/')) {
// Delete an upload file
if (preg_match('#^/api/uploads/([a-f0-9]+\.\w+)$#', $route, $m) && $method === 'DELETE') {
$file = __DIR__ . '/uploads/' . basename($m[1]);
$file = UPLOAD_DIR . '/' . basename($m[1]);
if (is_file($file)) {
unlink($file);
echo json_encode(['ok' => true]);
@@ -437,7 +437,7 @@ if (str_starts_with($route, '/api/')) {
// Upload (max 10MB, real MIME check)
if ($route === '/api/upload' && $method === 'POST') {
$uploadDir = __DIR__ . '/uploads';
$uploadDir = UPLOAD_DIR;
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
if (empty($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
@@ -560,7 +560,7 @@ if (str_starts_with($route, '/api/')) {
}
// Copy referenced uploads → attachments/
$uploadDir = __DIR__ . '/uploads';
$uploadDir = UPLOAD_DIR;
if (is_dir($uploadDir)) {
foreach (glob($uploadDir . '/*') as $f) {
$name = basename($f);
@@ -609,7 +609,7 @@ if (str_starts_with($route, '/api/')) {
$zip->addFromString('data.json', json_encode(['version' => 1, 'buckets' => $buckets, 'cards' => $cards, 'selective' => !!$ids], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
// Only include referenced uploads
$uploadDir = __DIR__ . '/uploads';
$uploadDir = UPLOAD_DIR;
$allBodies = implode("\n", array_column($cards, 'body'));
if (is_dir($uploadDir)) {
foreach (glob($uploadDir . '/*') as $f) {
@@ -719,7 +719,7 @@ if (str_starts_with($route, '/api/')) {
}
// Extract uploads
$uploadDir = __DIR__ . '/uploads';
$uploadDir = UPLOAD_DIR;
if (!is_dir($uploadDir)) mkdir($uploadDir, 0777, true);
for ($i = 0; $i < $zip->numFiles; $i++) {
$name = $zip->getNameIndex($i);
@@ -882,7 +882,7 @@ if (str_starts_with($route, '/api/')) {
if ($attStatus === 200) {
$attachments = json_decode($attResponse, true);
$uploadDir = __DIR__ . '/uploads';
$uploadDir = UPLOAD_DIR;
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
foreach ($attachments ?? [] as $att) {
$fn = basename($att['filename']);
@@ -1009,7 +1009,7 @@ if (str_starts_with($route, '/api/')) {
// the sender's secret and re-encrypt with the recipient's secret.
$cardBody = $card['body'] ?? '';
preg_match_all('#uploads/([a-f0-9]+\.\w+)#', $cardBody, $attMatches);
$uploadDir = __DIR__ . '/uploads';
$uploadDir = UPLOAD_DIR;
foreach (array_unique($attMatches[1] ?? []) as $filename) {
$filePath = $uploadDir . '/' . $filename;
if (!file_exists($filePath)) continue;
@@ -1320,7 +1320,7 @@ if (str_starts_with($route, '/api/')) {
<i class="ph ph-gear text-sm"></i><span class="font-pixel text-[10px]">Settings</span>
</button>
</div>
<div id="footer-count" class="font-pixel text-[10px] text-t-dim whitespace-nowrap absolute left-1/2 -translate-x-1/2"></div>
<div id="footer-count" class="font-pixel text-[10px] text-t-dim whitespace-nowrap"></div>
<div class="flex items-center gap-2">
<button id="shortcuts-btn" class="flex items-center gap-1.5 px-2.5 py-1 text-xs border border-t-border text-t-dim hover:border-t-accent hover:text-t-accent transition-colors"><i class="ph ph-keyboard text-sm"></i><span class="font-pixel text-[10px]">Keys</span></button>
<button id="help-btn" class="flex items-center gap-1.5 px-2.5 py-1 text-xs border border-t-border text-t-dim hover:border-t-accent hover:text-t-accent transition-colors"><i class="ph ph-question text-sm"></i><span class="font-pixel text-[10px]">Help</span></button>