Log and always regenerate MVLog maps on save
This commit is contained in:
parent
37e43b6bca
commit
6ba4050d9a
2 changed files with 50 additions and 26 deletions
74
new.php
74
new.php
|
|
@ -75,14 +75,14 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
|
|||
$text = $normalize($text);
|
||||
return $text === '' ? '' : wordwrap($text, $width, "\n", false);
|
||||
};
|
||||
$clampWrappedText = static function ($text, int $width, int $maxLines) use ($normalize): string {
|
||||
$clampWrappedText = static function ($text, int $width, int $maxLines, bool $cutLongWords = false) use ($normalize): string {
|
||||
$text = $normalize($text);
|
||||
if ($text === '') return '';
|
||||
$words = preg_split('/\s+/u', $text, -1, PREG_SPLIT_NO_EMPTY) ?: [];
|
||||
if (!$words) return '';
|
||||
$candidate = implode(' ', $words);
|
||||
while (true) {
|
||||
$wrapped = wordwrap($candidate, $width, "\n", false);
|
||||
$wrapped = wordwrap($candidate, $width, "\n", $cutLongWords);
|
||||
$lineCount = substr_count($wrapped, "\n") + 1;
|
||||
if ($lineCount <= $maxLines || count($words) <= 1) return $wrapped;
|
||||
array_pop($words);
|
||||
|
|
@ -94,8 +94,8 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
|
|||
$bestSize = 95;
|
||||
$bestWidth = 28;
|
||||
$bestLines = 1;
|
||||
for ($size = 94; $size >= 60; $size -= 4) {
|
||||
$width = max(16, min(46, (int)round(24 + (94 - $size) / 2.7)));
|
||||
for ($size = 84; $size >= 54; $size -= 4) {
|
||||
$width = max(16, min(46, (int)round(23 + (84 - $size) / 2.7)));
|
||||
$candidate = $wrapText($text, $width);
|
||||
$lines = substr_count($candidate, "\n") + 1;
|
||||
$bestText = $candidate;
|
||||
|
|
@ -108,14 +108,14 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
|
|||
};
|
||||
|
||||
[$titleText, $titleFontSize, $titleWrapWidth, $titleLines] = $fitTitleText($title);
|
||||
$teaserText = $clampWrappedText($teaser, 38, 6);
|
||||
$teaserText = $clampWrappedText($teaser, 34, 6, true);
|
||||
$teaserLines = max(1, substr_count($teaserText, "\n") + 1);
|
||||
|
||||
// Move the whole block a bit right while keeping left-aligned text.
|
||||
$left = max(18, (int)round($imgW * 0.055));
|
||||
$titleY = max(24, (int)round($imgH * 0.06));
|
||||
// Move the whole block a bit left and higher while keeping left-aligned text.
|
||||
$left = max(14, (int)round($imgW * 0.046));
|
||||
$titleY = max(20, (int)round($imgH * 0.062));
|
||||
$titleLineStep = max(68, (int)round($imgH * 0.043));
|
||||
$teaserY = max((int)round($imgH * 0.25), $titleY + ($titleLines * $titleLineStep) + max(56, (int)round($imgH * 0.03)));
|
||||
$teaserY = max((int)round($imgH * 0.235), $titleY + ($titleLines * $titleLineStep) + max(54, (int)round($imgH * 0.03)));
|
||||
|
||||
$overlayBase = tempnam(sys_get_temp_dir(), 'thumb_overlay_');
|
||||
$outputPath = dirname($imagePath) . '/' . basename($imagePath) . '.tmp.' . uniqid('', true) . '.jpg';
|
||||
|
|
@ -158,7 +158,7 @@ function apply_thumbnail_overlay($imagePath, $title, $teaser) {
|
|||
foreach ($qualities as $quality) {
|
||||
$attemptPath = dirname($imagePath) . '/' . basename($imagePath) . '.tmp.' . uniqid('', true) . '.jpg';
|
||||
$cmd2 = sprintf(
|
||||
'/usr/bin/convert -filter Lanczos -define filter:blur=0.85 %s -resize %dx%d^ -gravity center -extent %dx%d -modulate 62,76 %s -composite -strip -interlace Plane -sampling-factor 4:2:0 -quality %d %s 2>&1',
|
||||
'/usr/bin/convert -filter Lanczos -define filter:blur=0.85 %s -resize %dx%d^ -gravity center -extent %dx%d -modulate 70,82 %s -composite -strip -interlace Plane -sampling-factor 4:2:0 -quality %d %s 2>&1',
|
||||
escapeshellarg($imagePath),
|
||||
$imgW,
|
||||
$imgH,
|
||||
|
|
@ -813,9 +813,13 @@ function input_dir_output($dir){
|
|||
return basename((string)($state['output'] ?? ''));
|
||||
}
|
||||
function regenerate_input_dir_maps($dir, $config){
|
||||
$logFile = '/var/log/mvlog_map.log';
|
||||
$python = trim((string)shell_exec('command -v python3 2>/dev/null'));
|
||||
$script = __DIR__ . '/bin/gpsmap.py';
|
||||
if ($python === '' || !is_file($script)) return;
|
||||
if ($python === '' || !is_file($script)) {
|
||||
file_put_contents($logFile, '[mvlog] map regenerate skipped for ' . basename((string)$dir) . ' (python=' . ($python !== '' ? 'yes' : 'no') . ', script=' . (is_file($script) ? 'yes' : 'no') . ")\n", FILE_APPEND);
|
||||
return;
|
||||
}
|
||||
|
||||
$state = input_dir_state($dir);
|
||||
$targets = [];
|
||||
|
|
@ -831,14 +835,19 @@ function regenerate_input_dir_maps($dir, $config){
|
|||
}
|
||||
|
||||
$targets = array_values(array_unique($targets));
|
||||
file_put_contents($logFile, '[mvlog] map regenerate requested for ' . basename((string)$dir) . ' targets=' . implode(', ', array_map('basename', $targets)) . "\n", FILE_APPEND);
|
||||
|
||||
foreach ($targets as $outPng) {
|
||||
file_put_contents($logFile, '[mvlog] map regenerate start for ' . basename((string)$dir) . ' target=' . basename((string)$outPng) . "\n", FILE_APPEND);
|
||||
$cmd = escapeshellarg($python) . ' ' . escapeshellarg($script) . ' ' . escapeshellarg($dir) . ' ' . escapeshellarg($outPng) . ' 2>&1';
|
||||
$output = (string)shell_exec($cmd);
|
||||
if (is_file($outPng)) {
|
||||
@chmod($outPng, 0664);
|
||||
clearstatcache(true, $outPng);
|
||||
$size = @filesize($outPng);
|
||||
file_put_contents($logFile, '[mvlog] map regenerate done for ' . basename((string)$dir) . ' target=' . basename((string)$outPng) . ' bytes=' . ($size !== false ? $size : 'unknown') . "\n", FILE_APPEND);
|
||||
} else {
|
||||
error_log('[mvlog] map regenerate failed for '.basename((string)$dir).' target='.basename((string)$outPng).' output='.trim($output)."\n", 3, '/var/log/mvlog_map.log');
|
||||
file_put_contents($logFile, '[mvlog] map regenerate failed for ' . basename((string)$dir) . ' target=' . basename((string)$outPng) . ' output=' . trim($output) . "\n", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1099,11 +1108,15 @@ try {
|
|||
$dir = resolve_input_dir_from_request($config['uploads_dir'], $_POST['id'] ?? '', $_POST['dir'] ?? '', $articleIndex);
|
||||
$articleId = ensure_state_article_id($dir);
|
||||
if (input_dir_running($dir)) throw new RuntimeException('This input directory is being rendered. Editing is disabled until the job completes.');
|
||||
write_data($dir, $_POST);
|
||||
save_uploads('media', $dir, $allowedMedia);
|
||||
save_uploads('audio', $dir, $allowedAudio);
|
||||
// Always regenerate map image(s) on Save changes.
|
||||
regenerate_input_dir_maps($dir, $config);
|
||||
file_put_contents('/var/log/mvlog_map.log', '[mvlog] save changes pressed for ' . basename($dir) . ' id=' . $articleId . "\n", FILE_APPEND);
|
||||
try {
|
||||
write_data($dir, $_POST);
|
||||
save_uploads('media', $dir, $allowedMedia);
|
||||
save_uploads('audio', $dir, $allowedAudio);
|
||||
} finally {
|
||||
// Always regenerate map image(s) whenever Save changes is pressed.
|
||||
regenerate_input_dir_maps($dir, $config);
|
||||
}
|
||||
if (!empty($_POST['ajax'])) ajax_json(['ok'=>true, 'message'=>'Updated input directory: in-dir/' . basename($dir), 'dir'=>basename($dir), 'id'=>$articleId]);
|
||||
header('Location: new.php?tab=edit');
|
||||
exit;
|
||||
|
|
@ -1368,9 +1381,11 @@ function setThumbButtonsDisabled(disabled){
|
|||
buttons[i].classList.toggle('is-busy-target', disabled);
|
||||
}
|
||||
}
|
||||
function showThumbBusy(){
|
||||
function showThumbBusy(label){
|
||||
var overlay = ensureThumbBusyOverlay();
|
||||
setThumbButtonsDisabled(true);
|
||||
var text = overlay.querySelector('.label');
|
||||
if(text && label) text.textContent = label;
|
||||
overlay.classList.add('show');
|
||||
}
|
||||
function hideThumbBusy(){
|
||||
|
|
@ -1380,7 +1395,7 @@ function hideThumbBusy(){
|
|||
function setThumb(name){
|
||||
var ctx = getEditDirContext();
|
||||
if(!ctx.dir){ showToast('Internal error: missing input dir', false); return; }
|
||||
showThumbBusy();
|
||||
showThumbBusy('Creating thumbnail…');
|
||||
var body = 'action=set_video_thumb&dir=' + encodeURIComponent(ctx.dir) + '&id=' + encodeURIComponent(ctx.id) + '&file=' + encodeURIComponent(name) + '&ajax=1';
|
||||
fetch('new.php', {
|
||||
method: 'POST',
|
||||
|
|
@ -1617,7 +1632,7 @@ function handleAjaxFormSubmit(form, redirectTab) {
|
|||
data.set('ajax', '1');
|
||||
|
||||
const action = String(data.get('action') || '');
|
||||
const verb = action === 'update' ? 'Saving'
|
||||
const verb = action === 'update' ? 'Saving changes…'
|
||||
: action === 'delete_video' ? 'Deleting'
|
||||
: action === 'delete_dir' ? 'Deleting'
|
||||
: action === 'delete_file' ? 'Deleting'
|
||||
|
|
@ -1626,18 +1641,22 @@ function handleAjaxFormSubmit(form, redirectTab) {
|
|||
|
||||
let timer = 0;
|
||||
let success = false;
|
||||
const useBusyOverlay = action === 'update';
|
||||
if (submit) {
|
||||
submit.dataset.label = submit.dataset.label || submit.textContent.trim() || 'Submit';
|
||||
submit.disabled = true;
|
||||
submit.style.opacity = '0.78';
|
||||
submit.style.cursor = 'wait';
|
||||
let dots = 0;
|
||||
submit.textContent = verb;
|
||||
timer = window.setInterval(function(){
|
||||
dots = (dots + 1) % 4;
|
||||
submit.textContent = verb + '.'.repeat(dots);
|
||||
}, 320);
|
||||
if (!useBusyOverlay) {
|
||||
let dots = 0;
|
||||
submit.textContent = verb;
|
||||
timer = window.setInterval(function(){
|
||||
dots = (dots + 1) % 4;
|
||||
submit.textContent = verb + '.'.repeat(dots);
|
||||
}, 320);
|
||||
}
|
||||
}
|
||||
if (useBusyOverlay) showThumbBusy('Saving changes…');
|
||||
|
||||
try{
|
||||
const res = await fetch('new.php', { method: 'POST', body: data, credentials: 'same-origin', headers: { 'Accept': 'application/json' }});
|
||||
|
|
@ -1645,9 +1664,11 @@ function handleAjaxFormSubmit(form, redirectTab) {
|
|||
if(!res.ok || !json.ok) throw new Error(json.error || 'Operation failed');
|
||||
success = true;
|
||||
showToast(json.message || 'Operation successful', true);
|
||||
if (useBusyOverlay) setTimeout(hideThumbBusy, 120);
|
||||
setTimeout(() => { window.location.href = 'new.php?tab=' + (json.tab || redirectTab); }, 450);
|
||||
} catch(e) {
|
||||
showToast(e.message || 'Operation failed', false);
|
||||
if (useBusyOverlay) setTimeout(hideThumbBusy, 120);
|
||||
} finally {
|
||||
if (timer) window.clearInterval(timer);
|
||||
if(submit && !success) {
|
||||
|
|
@ -1656,6 +1677,7 @@ function handleAjaxFormSubmit(form, redirectTab) {
|
|||
submit.style.cursor = '';
|
||||
submit.textContent = submit.dataset.label || 'Submit';
|
||||
}
|
||||
if (useBusyOverlay && !success) hideThumbBusy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue