option to use gradient backgrounds

This commit is contained in:
j 2025-02-15 00:24:00 +01:00
commit c7ce34b0da
8 changed files with 214 additions and 1 deletions

View file

@ -0,0 +1,23 @@
# Generated by Django 5.1.5 on 2025-02-13 15:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("item", "0010_week_break_notice_week_is_break"),
]
operations = [
migrations.AddField(
model_name="week",
name="use_hue",
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name="week",
name="break_notice",
field=models.TextField(blank=True, default=""),
),
]

View file

@ -1,3 +1,4 @@
import urllib.parse
from django.utils.timezone import datetime, timedelta
from django.utils import timezone
import json
@ -11,6 +12,8 @@ from django.db.models.functions import ExtractWeek, ExtractYear
from django.urls import reverse
from django.utils.timesince import timesince
import ox
User = get_user_model()
@ -27,7 +30,6 @@ class Item(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
title = models.CharField(max_length=1024)
url = models.CharField(max_length=1024, unique=True)
description = models.TextField(default="", blank=True, editable=False)
@ -40,6 +42,10 @@ class Item(models.Model):
#if self.url and not self.data.get("url") == self.url:
if self.url:
self.update_data()
if self.use_hue:
if "hue" in self.data:
del self.data["hue"]
self.get_hue()
super().save(*args, **kwargs)
def __str__(self):
@ -104,6 +110,14 @@ class Item(models.Model):
d = '%s-W%s' % (self.get_year(), self.get_week())
return datetime.strptime(d + '-1', "%Y-W%W-%w").strftime('%Y-%m-%d')
@property
def use_hue(self):
monday = self.get_monday()
week = Week.objects.filter(monday=monday).first()
if week:
return week.use_hue
return False
def get_absolute_url(self):
return reverse('item', kwargs={'id': self.id})
@ -112,6 +126,8 @@ class Item(models.Model):
def update_data(self):
self.data.update(self.parse_url())
if "hue" in self.data:
del self.data["hue"]
def parse_url(self):
content = requests.get(self.url).text
@ -133,6 +149,84 @@ class Item(models.Model):
data["thumbnail"] = data["thumbnail"].replace('/512p', '/1024p')
return data
def get_hue(self, update=False):
if "hue" in self.data:
return self.data["hue"]
if update:
self.save()
return self.data.get("hue")
hue = None
parts = self.url.split('/')
url = '/'.join(parts[:3]) + '/api/'
if parts[4] == 'edits':
edit = urllib.parse.unquote(parts[5]).replace('_', ' ')
request = {
"action": "getEdit",
"data": {
"id": edit,
"keys": []
}
}
response = requests.post(url, json=request).json()
clips = response["data"]["clips"]
if clips:
hue = clips[int(len(clips)/2)]['hue']
else:
item = parts[4]
parts = parts[5:]
if parts and parts[0] in ("editor", "player"):
parts = parts[1:]
args = {}
if parts and "?" in parts[-1]:
part, arguments = parts[-1].split('?')
parts[-1] = part
args = dict(
kv.split('=', 1)
for kv in urllib.parse.unquote(arguments).split("&")
)
if ',' in parts[0]:
start, end = [ox.parse_timecode(p) for p in parts[0].split(',')]
request = {
"action": "findClips",
"data": {
"query": {
"conditions": [
{"key": "out", "value": start, "operator": ">"},
{"key": "in", "value": end, "operator": "<"},
]
},
"itemsQuery": {
"conditions": [{"key": "id", "value": item, "operator": "=="}]
},
"keys": ["id", "in", "out", "hue"],
"range": [0, 5000],
"sort": [
{"key": "in", "operator": "+"},
{"key": "out", "operator": "+"},
]
}
}
response = requests.post(url, json=request).json()
items = response["data"]["items"]
if items:
hue = items[int(len(items)/2)]["hue"]
else:
annotation = '%s/%s' % (item, parts[0])
request = {
"action": "getAnnotation",
"data": {
"id": annotation,
"keys": ["hue"]
}
}
response = requests.post(url, json=request).json()
hue = response["data"]["hue"]
if hue is not None:
self.data["hue"] = hue
return hue
class Comment(models.Model):
created = models.DateTimeField(auto_now_add=True)
@ -198,8 +292,30 @@ class Week(models.Model):
title = models.CharField(max_length=2048, blank=True, default="")
byline = models.CharField(max_length=2048, blank=True, default="")
published = models.DateTimeField(null=True, default=None, blank=True, editable=False)
use_hue = models.BooleanField(default=False)
is_break = models.BooleanField(default=False)
break_notice = models.TextField(default="", blank=True)
def __str__(self):
return "%s (%s)" % (self.title, self.monday)
def items(self):
from datetime import date
monday = timezone.make_aware(datetime.combine(self.monday, datetime.min.time()), timezone.get_default_timezone())
monday += timedelta(days=7)
items, _ = Item.public(monday)
return items.order_by('published')
@property
def background(self):
if self.use_hue:
colors = []
for item in self.items():
color = item.get_hue(update=True)
if color:
if not colors:
colors.append(f'hsl({color}, 100%, 15%, 0.8)')
else:
colors.append(f'hsl({color}, 60%, 15%, 0.8)')
return 'linear-gradient(to bottom, %s)' % ', '.join(colors)
return ''

View file

@ -109,6 +109,7 @@ def archive(request, year=None, month=None, day=None, week=None):
if extra:
context['week_title'] = extra.title
context['week_byline'] = extra.byline
context['week_background'] = extra.background
elif week:
week = int(week)
year = int(year)

View file

@ -6,6 +6,12 @@
--title: rgb(240, 240, 240);
}
html, body {
overscroll-behavior: none;
background-color: var(--bg);
}
@font-face {
font-family: "wrong font";
src: url("https://files.pad.ma/ttf/wrongfont.woff") format("woff");

View file

@ -190,6 +190,15 @@ async function loadEdit(id, args) {
previous = annotation
})
}
if (window.useHue && data.edit.clips && data.edit.clips.length) {
const color1 = data.edit.clips[0].hue
const color2 = data.edit.clips[parseInt(data.edit.clips.length/2)].hue
const color3 = data.edit.clips[data.edit.clips.length-1].hue
document.documentElement.style.setProperty('--color1', `hsl(${color1}, 100%, 15%, 0.8)`);
document.documentElement.style.setProperty('--color2', `hsl(${color2}, 60%, 15%, 0.8)`);
document.documentElement.style.setProperty('--color3', `hsl(${color3}, 60%, 15%, 0.8)`);
}
var value = []
pandora.layerKeys.forEach(layer => {
if (!data.layers[layer]) {

View file

@ -14,6 +14,7 @@ async function loadData(id, args) {
"date",
"source",
"summary",
"hue",
"streams",
"duration",
"durations",
@ -30,6 +31,8 @@ async function loadData(id, args) {
}
}
data.item = response['data']
if (data.item.rightslevel > pandora.site.capabilities.canPlayClips['guest']) {
return {
site: data.site,
@ -79,6 +82,35 @@ async function loadData(id, args) {
data['in'] = data.annotation['in']
data.out = data.annotation['out']
}
if (window.useHue) {
var clips = await pandoraAPI('findClips', {
"query": {
"conditions": [
{"key": "out", "value": data["in"], "operator": ">"},
{"key": "in", "value": data["out"], "operator": "<"},
]
},
"itemsQuery": {
"conditions": [{"key": "id", "value": data.id.split('/')[0], "operator": "=="}]
},
"keys":["id", "in", "out", "hue"],
"range": [0, 5000],
"sort": [
{"key": "in", "operator": "+"},
{"key": "out", "operator": "+"},
]
})
clips = clips.data?.items
if (clips && clips.length) {
const color1 = clips[0].hue
const color2 = clips[parseInt(clips.length/2)].hue
const color3 = clips[clips.length-1].hue
document.documentElement.style.setProperty('--color1', `hsl(${color1}, 100%, 15%, 0.8)`);
document.documentElement.style.setProperty('--color2', `hsl(${color2}, 60%, 15%, 0.8)`);
document.documentElement.style.setProperty('--color3', `hsl(${color3}, 60%, 15%, 0.8)`);
}
}
data.layers = {}

View file

@ -1,6 +1,16 @@
{% extends "base.html" %}
{% block head %}
<title>{{ settings.SITENAME }}</title>
{% if week_background %}
<style>
body {
background: {{ week_background }};
}
</style>
<script>
window.useHue = true;
</script>
{% endif %}
{% endblock %}
{% block content %}
<div class="index archive">

View file

@ -13,6 +13,22 @@
<meta property="og:url" content="{{ url }}"/>
{% endif %}
<meta property="og:site_name" content="{{ settings.SITENAME }}"/>
{% if item.use_hue %}
<style>
:root {
--color1: var(--bg);
--color2: var(--bg);
--color3: var(--bg);
}
body {
background: linear-gradient(to bottom, var(--color1), var(--color2), var(--color3));
}
</style>
<script>
window.useHue = true;
</script>
{% endif %}
{% endblock %}
{% block main %}
<div class="content">