Added some functionality so we can modify the size of the playing video

This commit is contained in:
2026-08-20 19:50:20 -04:00
parent 5b8bef1451
commit 699ca7d6df
3 changed files with 104 additions and 1 deletions
+21
View File
@@ -47,8 +47,14 @@ DEFAULT_SETTINGS = {
'card_style': 'flat', # 'flat' | 'elevated' | 'bordered'
'corner_radius': 'rounded', # 'sharp' | 'rounded' | 'pill'
'library_path': '', # '' = use COURSES_LIBRARY_PATH/--library-path default
'video_width': '', # '' = responsive full-width; else last dragged size, in px
'video_height': '',
}
# Bounds for the persisted video player size, to reject garbage values
# without capping how big/small someone can reasonably drag it.
VIDEO_SIZE_BOUNDS = {'video_width': (200, 4000), 'video_height': (120, 3000)}
# Allowed values for every setting except accent_color (validated separately
# as a hex string). Anything outside these sets is rejected/ignored on save.
SETTINGS_CHOICES = {
@@ -91,6 +97,9 @@ def load_settings() -> Dict[str, Any]:
# Lenient on load (directory may be transiently
# unavailable at startup) - only validated on save.
settings[key] = value
elif key in VIDEO_SIZE_BOUNDS:
if value == '' or (isinstance(value, int) and not isinstance(value, bool)):
settings[key] = value
elif key in SETTINGS_CHOICES and value in SETTINGS_CHOICES[key]:
settings[key] = value
except (json.JSONDecodeError, OSError) as e:
@@ -109,6 +118,18 @@ def save_settings(new_settings: Dict[str, Any]) -> Dict[str, Any]:
if value and not os.path.isdir(value):
raise ValueError(f"Directory not found: {value}")
current[key] = value
elif key in VIDEO_SIZE_BOUNDS:
if value in (None, ''):
current[key] = ''
continue
try:
num = int(value)
except (TypeError, ValueError):
raise ValueError(f"{key} must be a number")
lo, hi = VIDEO_SIZE_BOUNDS[key]
if not (lo <= num <= hi):
raise ValueError(f"{key} must be between {lo} and {hi}")
current[key] = num
elif key in SETTINGS_CHOICES and value in SETTINGS_CHOICES[key]:
current[key] = value
os.makedirs(DATA_DIR, exist_ok=True)
+54 -1
View File
@@ -130,11 +130,25 @@
}
video, audio {
width: 100%;
max-width: 800px;
max-width: 100%;
border-radius: var(--radius);
display: block;
margin: 0 auto;
}
video {
resize: both;
overflow: hidden;
object-fit: contain;
background: #000;
min-width: 320px;
min-height: 200px;
}
.resize-hint {
text-align: center;
font-size: 0.8em;
color: var(--text-muted);
margin-top: 6px;
}
.content {
margin: 20px 0;
}
@@ -246,6 +260,7 @@
{% endif %}
Your browser does not support the video tag.
</video>
<p class="resize-hint">↘ Drag the bottom-right corner to resize the player</p>
{% endif %}
{% if lesson.audio_file %}
@@ -372,6 +387,44 @@
const activeMedia = video || audio;
let isCompleted = false;
// Restore last-used video player size, and persist future resizes
// (dragging the native corner handle) so it sticks next time.
if (video) {
let applyingStoredSize = true;
let resizeSaveTimeout = null;
fetch('/api/settings')
.then(r => r.json())
.then(data => {
const s = data.settings || {};
if (s.video_width && s.video_height) {
video.style.width = s.video_width + 'px';
video.style.height = s.video_height + 'px';
}
setTimeout(() => { applyingStoredSize = false; }, 300);
})
.catch(() => { applyingStoredSize = false; });
if (window.ResizeObserver) {
const observer = new ResizeObserver(() => {
if (applyingStoredSize) return;
clearTimeout(resizeSaveTimeout);
resizeSaveTimeout = setTimeout(() => {
const rect = video.getBoundingClientRect();
fetch('/api/settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
video_width: Math.round(rect.width),
video_height: Math.round(rect.height)
})
}).catch(() => {});
}, 500);
});
observer.observe(video);
}
}
if (activeMedia) {
let lastSaveTime = 0;
+29
View File
@@ -331,6 +331,22 @@
</div>
</div>
<div class="card">
<h2>Video Player</h2>
<div class="setting-row">
<label>Player size
<span class="setting-desc">
{% if settings.video_width and settings.video_height %}
Remembered at {{ settings.video_width }}×{{ settings.video_height }}px from your last resize
{% else %}
Using default responsive full-width sizing
{% endif %}
</span>
</label>
<button class="btn btn-secondary" onclick="resetVideoSize()">Reset size</button>
</div>
</div>
<div class="actions">
<button class="btn btn-secondary" onclick="resetSettings()">Reset to Defaults</button>
<span id="save-status">✓ Saved</span>
@@ -425,6 +441,19 @@
});
}
function resetVideoSize() {
fetch('/api/settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ video_width: '', video_height: '' })
})
.then(r => r.json())
.then(data => {
if (data.success) location.reload();
})
.catch(err => console.error('Failed to reset video size:', err));
}
function resetSettings() {
fetch('/api/settings/reset', { method: 'POST' })
.then(r => r.json())