First commit, imported from the working folder: Android TV app, loopback guide server, design sources and per-release verification notes. Includes the 0.16 tuning screen, built and tested but not yet confirmed on the box. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
40 lines
3.4 KiB
Python
40 lines
3.4 KiB
Python
from pathlib import Path
|
||
from html import escape
|
||
p=Path(__file__).parent
|
||
parts=['<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080">']
|
||
def rect(x,y,w,h,c,stroke=None):
|
||
parts.append(f'<rect x="{x}" y="{y}" width="{w}" height="{h}" fill="{c}"'+(f' stroke="{stroke}" stroke-width="2"' if stroke else '')+'/>')
|
||
def text(x,y,s,size=28,c='#ffffff',bold=False):
|
||
parts.append(f'<text x="{x}" y="{y}" font-family="DejaVu Sans, sans-serif" font-size="{size}" fill="{c}" font-weight="{700 if bold else 400}">{escape(s)}</text>')
|
||
rect(0,0,1920,1080,'#071632')
|
||
parts.append('<circle cx="106" cy="87" r="32" fill="none" stroke="#ffde59" stroke-width="7"/><ellipse cx="106" cy="87" rx="51" ry="14" transform="rotate(-25 106 87)" fill="none" stroke="#ffffff" stroke-width="4"/>')
|
||
text(175,108,'orbit',68,bold=True);text(365,103,'/ Classic',34,'#b7cbe8')
|
||
text(1440,101,'Saturday 31 October',26);text(1770,101,'20:30',28,'#ffde59',True)
|
||
for x,w,label,active in [(64,340,'1 Menu',False),(412,340,'2 TV Guide',True),(760,340,'3 Box Office',False)]:
|
||
rect(x,150,w,64,'#194c91' if active else '#12356b','#38629a');text(x+24,192,label,29,bold=active)
|
||
text(1510,191,'Your media. Your universe.',24,'#b7cbe8')
|
||
rect(64,248,545,300,'#12356b','#38629a')
|
||
parts.append('<circle cx="336" cy="380" r="68" fill="none" stroke="#406ca5" stroke-width="4"/><ellipse cx="336" cy="380" rx="120" ry="27" transform="rotate(-25 336 380)" fill="none" stroke="#ffde59" stroke-width="4"/>')
|
||
rect(64,492,545,56,'#0c244d');text(86,529,'101 Orbit One',24,'#ffffff',True);text(400,529,'Demo signal',20,'#ffde59')
|
||
text(654,276,'Orbit One / 20:30–21:00',24,'#ffde59')
|
||
text(654,338,'The Midnight Observatory',45,bold=True)
|
||
text(654,391,'An astronomer follows a mysterious signal',29,'#b7cbe8')
|
||
text(654,435,'across the night sky.',29,'#b7cbe8')
|
||
text(654,524,'Fictional programmes • Original demo transmission',22,'#b7cbe8')
|
||
rect(64,584,1792,51,'#194c91')
|
||
text(88,619,'Channel',24)
|
||
for x,label in [(430,'20:30'),(910,'21:00'),(1390,'21:30')]:text(x,619,label,24)
|
||
rows=[('101','Orbit One',['The Midnight Observatory','Small Town, Big Orbit','Beyond the Blue']),('202','Orbit Sci-Fi',['Signal from Europa','Starbound Dispatch','Visitors at Dawn']),('401','Orbit Kids',['Moonbug Rangers','The Comet Club','Rocket Pocket'])]
|
||
for i,(num,name,shows) in enumerate(rows):
|
||
y=644+i*100
|
||
rect(64,y,330,92,'#102b57');text(86,y+32,num,22,'#ffde59');text(86,y+68,name,29,bold=True)
|
||
for j,show in enumerate(shows):
|
||
x=402+j*486;focused=i==0 and j==0
|
||
rect(x,y,478,92,'#ffde59' if focused else '#12356b','#ffffff' if focused else '#38629a')
|
||
text(x+20,y+54,show,27,'#071632' if focused else '#ffffff',focused)
|
||
text(66,1009,'Arrows Browse',23,'#b7cbe8');text(430,1009,'OK Watch now / programme information',23,'#b7cbe8');text(1390,1009,'Back Return',23,'#b7cbe8')
|
||
rect(64,1040,1792,2,'#38629a')
|
||
parts.append('</svg>');(p/'orbit-classic-guide.svg').write_text('\n'.join(parts))
|
||
logo='''<svg xmlns="http://www.w3.org/2000/svg" width="640" height="240" viewBox="0 0 640 240"><rect width="640" height="240" fill="#071632"/><circle cx="120" cy="120" r="54" fill="none" stroke="#ffde59" stroke-width="10"/><ellipse cx="120" cy="120" rx="89" ry="22" transform="rotate(-25 120 120)" fill="none" stroke="white" stroke-width="6"/><text x="235" y="153" font-family="DejaVu Sans" font-size="94" font-weight="700" fill="white">orbit</text></svg>'''
|
||
(p/'orbit-wordmark.svg').write_text(logo)
|