Store assets: landscape tablet screenshots (iPad, Android 7/10-inch)

Captured from the app's real sidebar shell at 1024x768; adds landscape
compositions to compose.py and the README upload table.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Ayushya Amitabh
2026-10-07 21:46:29 -04:00
co-authored by Claude Sonnet 5.5
parent 11b3d535a9
commit 5837464581
44 changed files with 288 additions and 19 deletions
+52 -3
View File
@@ -31,7 +31,7 @@ STORIES = [
eyebrow='MULTIPLE ACCOUNTS',
lines=('Every cloud,', 'one tap apart.'),
sub='Personal, work and family servers together.'),
dict(key='locks', theme='dark', back='lock', front='security', card_at=.66,
dict(key='locks', theme='dark', back='lock', front='security', card_at=.66, card_at_l=.66,
eyebrow='LOCKS',
lines=('Locks where', 'you want them.'),
sub='Protect opening Noo, switching accounts and hidden files with your device PIN or biometrics.'),
@@ -56,6 +56,10 @@ TARGETS = [
('android/tablet-10in', 'atablet', (1600, 2560), 'tablet'),
('ios/iphone', 'iphone', (1290, 2796), 'phone'),
('ios/ipad', 'ipad', (2064, 2752), 'tablet'),
# Landscape tablets show the app's real sidebar layout.
('android/tablet-7in-landscape', 'atabletl', (1920, 1200), 'landscape'),
('android/tablet-10in-landscape', 'atabletl', (2560, 1600), 'landscape'),
('ios/ipad-landscape', 'ipadl', (2752, 2064), 'landscape'),
]
@@ -127,7 +131,51 @@ def paste_panel(canvas, source, box, radius, t, bleed=False):
return x, y, sw, sh
def landscape_canvas(story, size, device):
"""Text column on the left, the real tablet UI on the right."""
t = THEMES[story['theme']]
w, h = size
im = background(size, t)
d = ImageDraw.Draw(im)
margin = round(h * .07)
colw = round(w * .30)
y = round(h * .27)
spaced(d, (margin, y), story['eyebrow'], font(round(h * .022), 'Bold', 'InstrumentSans'),
t['accent_text'], h * .004)
y += round(h * .06)
head = round(h * .068)
for index, line in enumerate(story['lines']):
fnt, _ = fit(d, line, font, head, colw)
d.text((margin, y), line, font=fnt, fill=t['accent_text'] if index else t['fg'])
y += round(head * 1.12)
y += round(head * .2)
sub_size = round(h * .030)
fnt = body_font(sub_size, 'Regular')
for line in textwrap.wrap(story['sub'], max(16, int(colw / (sub_size * .52)))):
d.text((margin, y), line, font=fnt, fill=t['fg2'])
y += round(sub_size * 1.4)
x0 = margin + colw + round(w * .035)
src = lambda name: OUT / f'source/{device}/{name}.png'
back = Image.open(src(story['back']))
aw, ah = w - x0 - margin, h - margin * 2
factor = min(aw / back.width, ah / back.height)
# Centered vertically; a layered card hangs below the panel's bottom edge.
area = (x0, round((h - back.height * factor) / 2) - (round(h * .03) if story['front'] else 0), aw, ah)
radius = round(h * .03)
bx, by, bw, bh = paste_panel(im, src(story['back']), area, radius, t)
if story['front']:
card = content_crop(src(story['front']))
scale = bw / Image.open(src(story['back'])).width
cw, ch = round(card.width * scale), round(card.height * scale)
cx = bx + round(bw * .40)
cy = by + round(bh * story.get('card_at_l', story['card_at']))
paste_panel(im, card, (cx, cy, cw, ch), round(radius * .6), t)
return im
def story_canvas(story, size, kind, device):
if kind == 'landscape':
return landscape_canvas(story, size, device)
t = THEMES[story['theme']]
w, h = size
im = background(size, t)
@@ -218,11 +266,12 @@ for asset in manifest:
(OUT / 'manifest.json').write_text(json.dumps(manifest, indent=2) + '\n')
# Review materials (not for upload): contact sheet and a gallery page.
contact = Image.new('RGB', (1920, 1500), '#1c1b18')
contact = Image.new('RGB', (1920, 2160), '#1c1b18')
cd = ImageDraw.Draw(contact)
cd.text((32, 20), 'Noo / store listing artwork', font=font(28), fill='#F3EFE6')
rows = [('ANDROID PHONE', 'android/phone'), ('ANDROID 10" TABLET', 'android/tablet-10in'),
('IPHONE', 'ios/iphone'), ('IPAD', 'ios/ipad')]
('IPHONE', 'ios/iphone'), ('IPAD', 'ios/ipad'),
('ANDROID 10" LANDSCAPE', 'android/tablet-10in-landscape'), ('IPAD LANDSCAPE', 'ios/ipad-landscape')]
for row, (label, folder) in enumerate(rows):
cd.text((32, 75 + row * 360), label, font=font(15, 'Bold', 'InstrumentSans'), fill='#CBA5FD')
for col, path in enumerate(sorted((OUT / folder).glob('*.png'))):