Added Photo Collage to Calendar TV View

This commit is contained in:
vrael32 2026-04-04 11:18:28 -04:00
parent dee4567f74
commit 44e6547a0a
14 changed files with 139 additions and 10 deletions

View File

@ -814,8 +814,109 @@ body.calendar-tv-dark {
--secondary-color: #1e293b; --secondary-color: #1e293b;
} }
/* Photo collage behind TV calendar (fixed full viewport) */
.calendar-tv-collage-bg {
position: fixed;
inset: 0;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.calendar-tv-collage-grid {
display: grid;
width: 100%;
height: 100%;
gap: clamp(6px, 1vw, 14px);
padding: clamp(6px, 1vw, 14px);
box-sizing: border-box;
}
.calendar-tv-collage-grid--mosaic {
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(4, 1fr);
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(1) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(2) {
grid-column: 3 / 4;
grid-row: 1 / 2;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(3) {
grid-column: 4 / 5;
grid-row: 1 / 2;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(4) {
grid-column: 5 / 6;
grid-row: 1 / 2;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(5) {
grid-column: 3 / 4;
grid-row: 2 / 3;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(6) {
grid-column: 4 / 5;
grid-row: 2 / 3;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(7) {
grid-column: 5 / 6;
grid-row: 2 / 3;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(8) {
grid-column: 1 / 3;
grid-row: 3 / 5;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(9) {
grid-column: 3 / 5;
grid-row: 3 / 5;
}
.calendar-tv-collage-grid--mosaic .calendar-tv-collage-tile:nth-child(10) {
grid-column: 5 / 6;
grid-row: 3 / 5;
}
.calendar-tv-collage-grid--even .calendar-tv-collage-tile {
min-height: 0;
min-width: 0;
}
.calendar-tv-collage-tile {
min-height: 0;
min-width: 0;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
border-radius: 6px;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.35);
}
.calendar-tv-collage-scrim {
position: absolute;
inset: 0;
background: linear-gradient(
160deg,
rgba(15, 23, 42, 0.78) 0%,
rgba(15, 23, 42, 0.62) 45%,
rgba(15, 23, 42, 0.75) 100%
);
}
body.calendar-tv-dark main { body.calendar-tv-dark main {
background-color: #0f172a; position: relative;
z-index: 1;
background-color: transparent;
} }
body.calendar-tv-dark .calendar-tv-view h2, body.calendar-tv-dark .calendar-tv-view h2,

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
if (empty($isCalendarTvView ?? null)) {
return;
}
$collageDir = dirname(__DIR__) . '/assets/images/calendar-tv-collage';
$files = glob($collageDir . '/collage-*.png') ?: [];
if ($files === []) {
$files = glob($collageDir . '/collage-*.{jpg,jpeg,webp}', GLOB_BRACE) ?: [];
}
natcasesort($files);
$files = array_values($files);
if ($files === []) {
return;
}
$mosaic = count($files) === 10;
$gridClass = $mosaic ? 'calendar-tv-collage-grid calendar-tv-collage-grid--mosaic' : 'calendar-tv-collage-grid calendar-tv-collage-grid--even';
$cols = 5;
$rows = (int) max(1, ceil(count($files) / $cols));
?>
<div class="calendar-tv-collage-bg" aria-hidden="true">
<div class="<?= htmlspecialchars($gridClass, ENT_QUOTES, 'UTF-8') ?>"<?= $mosaic ? '' : ' style="grid-template-columns: repeat(' . (int) $cols . ', 1fr); grid-template-rows: repeat(' . (int) $rows . ', 1fr);"' ?>>
<?php foreach ($files as $absPath): ?>
<?php
$base = basename((string) $absPath);
$url = 'assets/images/calendar-tv-collage/' . $base;
?>
<div class="calendar-tv-collage-tile" style="background-image: url('<?= htmlspecialchars($url, ENT_QUOTES, 'UTF-8') ?>')"></div>
<?php endforeach; ?>
</div>
<div class="calendar-tv-collage-scrim"></div>
</div>

View File

@ -73,6 +73,7 @@
$bodyStyle = implode('; ', $bodyStyleParts) . ';'; $bodyStyle = implode('; ', $bodyStyleParts) . ';';
?> ?>
<body class="family-hub-body <?= htmlspecialchars($headerThemeClass ?? 'header-tone-dark', ENT_QUOTES, 'UTF-8') ?><?= !empty($isCalendarTvView) ? ' calendar-tv-dark' : '' ?>" style="<?= htmlspecialchars($bodyStyle, ENT_QUOTES, 'UTF-8') ?>"> <body class="family-hub-body <?= htmlspecialchars($headerThemeClass ?? 'header-tone-dark', ENT_QUOTES, 'UTF-8') ?><?= !empty($isCalendarTvView) ? ' calendar-tv-dark' : '' ?>" style="<?= htmlspecialchars($bodyStyle, ENT_QUOTES, 'UTF-8') ?>">
<?php include __DIR__ . '/calendar_tv_collage_bg.php'; ?>
<?php $hideTopHeader = !empty($isCalendarTvView); ?> <?php $hideTopHeader = !empty($isCalendarTvView); ?>
<?php if (!$hideTopHeader): ?> <?php if (!$hideTopHeader): ?>
<header class="app-header app-header-with-tabs text-white pt-3 px-3 pb-2 mb-0"> <header class="app-header app-header-with-tabs text-white pt-3 px-3 pb-2 mb-0">

View File

@ -55,7 +55,6 @@ $events = hubCalendarAgendaEvents($rangeStart, $rangeEnd, $people, $familySettin
$todayYmd = familyHubTodayYmdInTz($tzLocal); $todayYmd = familyHubTodayYmdInTz($tzLocal);
$twoWayMerge = !empty($familySettings['calendar_two_way_google']); $twoWayMerge = !empty($familySettings['calendar_two_way_google']);
$isTvView = isset($_GET['view']) && (string) $_GET['view'] === 'tv'; $isTvView = isset($_GET['view']) && (string) $_GET['view'] === 'tv';
$calendarBaseUrl = '?tab=calendar';
$calendarTvUrl = '?tab=calendar&view=tv'; $calendarTvUrl = '?tab=calendar&view=tv';
$eventsByDate = []; $eventsByDate = [];
@ -82,14 +81,7 @@ $iconByType = [
?> ?>
<div id="calendar" class="tab-content<?= $isTvView ? ' calendar-tv-view' : '' ?>"> <div id="calendar" class="tab-content<?= $isTvView ? ' calendar-tv-view' : '' ?>">
<?php if ($isTvView): ?> <?php if (!$isTvView): ?>
<div class="d-flex flex-wrap justify-content-end align-items-center gap-2 mb-2 calendar-tv-toolbar">
<a href="<?= htmlspecialchars($calendarBaseUrl, ENT_QUOTES, 'UTF-8') ?>" class="btn btn-outline-secondary btn-sm" title="Exit TV view">
<i class="fa fa-xmark me-1" aria-hidden="true"></i>
Exit TV view
</a>
</div>
<?php else: ?>
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-2"> <div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-2">
<h2 class="mb-0">Calendar</h2> <h2 class="mb-0">Calendar</h2>
<a href="<?= htmlspecialchars($calendarTvUrl, ENT_QUOTES, 'UTF-8') ?>" class="btn btn-outline-secondary btn-sm" title="Open TV view dashboard"> <a href="<?= htmlspecialchars($calendarTvUrl, ENT_QUOTES, 'UTF-8') ?>" class="btn btn-outline-secondary btn-sm" title="Open TV view dashboard">