diff --git a/distribution/store-assets/README.md b/distribution/store-assets/README.md index 5e561f3..554d517 100644 --- a/distribution/store-assets/README.md +++ b/distribution/store-assets/README.md @@ -34,8 +34,18 @@ Schibsted Grotesk / Instrument Sans), flat shapes, alternating light and dark. | Google Play 7-inch tablet, landscape | `android/tablet-7in-landscape/` | 1920 × 1200 | | Google Play 10-inch tablet, landscape | `android/tablet-10in-landscape/` | 2560 × 1600 | | App Store iPad screenshots, landscape (13" slot) | `ios/ipad-landscape/` | 2752 × 2064 | +| App Store iPhone 6.1" / 6.3" screenshots | `ios/iphone-6.3in/` | 1206 × 2622 | +| App Store iPhone Duo (foldable), portrait | `ios/iphone-fold-portrait/` | 2007 × 2853 | +| App Store iPhone Duo (foldable), landscape | `ios/iphone-fold-landscape/` | 2853 × 2007 | +| App Store header | `ios/header/` | 5244 × 2950, 3840 × 1646 | +| App Store search results | `ios/search-results/` | 5244 × 2950, 3840 × 2560, 1920 × 1280 | | iOS icon reference | `ios/icon-1024.png` | 1024 × 1024 | +The iPad 13" slot (2064 × 2752 and 2752 × 2064) is covered by `ios/ipad/` and +`ios/ipad-landscape/`. The header and search-results banners are one brand +design (name, tagline, iPad and iPhone) rendered at each size. App previews +(video) are not produced here. + Upload in numeric order. The App Store uses the icon embedded in the uploaded build; `ios/icon-1024.png` is only a reference copy. Screenshots, the feature graphic and the iOS icon are opaque RGB PNGs; the Play icon is 32-bit RGBA. diff --git a/distribution/store-assets/index.html b/distribution/store-assets/index.html index a8c914d..9d1bcb9 100644 --- a/distribution/store-assets/index.html +++ b/distribution/store-assets/index.html @@ -1 +1 @@ -Noo store assets

Noo / store listing assets

English · production Flutter UI · fictional offline demo data.

android/phone/01-accounts.png · 1080 × 1920
android/phone/02-locks.png · 1080 × 1920
android/phone/03-sync.png · 1080 × 1920
android/phone/04-sharing.png · 1080 × 1920
android/phone/05-external.png · 1080 × 1920
android/tablet-7in/01-accounts.png · 1200 × 1920
android/tablet-7in/02-locks.png · 1200 × 1920
android/tablet-7in/03-sync.png · 1200 × 1920
android/tablet-7in/04-sharing.png · 1200 × 1920
android/tablet-7in/05-external.png · 1200 × 1920
android/tablet-10in/01-accounts.png · 1600 × 2560
android/tablet-10in/02-locks.png · 1600 × 2560
android/tablet-10in/03-sync.png · 1600 × 2560
android/tablet-10in/04-sharing.png · 1600 × 2560
android/tablet-10in/05-external.png · 1600 × 2560
ios/iphone/01-accounts.png · 1290 × 2796
ios/iphone/02-locks.png · 1290 × 2796
ios/iphone/03-sync.png · 1290 × 2796
ios/iphone/04-sharing.png · 1290 × 2796
ios/iphone/05-external.png · 1290 × 2796
ios/ipad/01-accounts.png · 2064 × 2752
ios/ipad/02-locks.png · 2064 × 2752
ios/ipad/03-sync.png · 2064 × 2752
ios/ipad/04-sharing.png · 2064 × 2752
ios/ipad/05-external.png · 2064 × 2752
android/tablet-7in-landscape/01-accounts.png · 1920 × 1200
android/tablet-7in-landscape/02-locks.png · 1920 × 1200
android/tablet-7in-landscape/03-sync.png · 1920 × 1200
android/tablet-7in-landscape/04-sharing.png · 1920 × 1200
android/tablet-7in-landscape/05-external.png · 1920 × 1200
android/tablet-10in-landscape/01-accounts.png · 2560 × 1600
android/tablet-10in-landscape/02-locks.png · 2560 × 1600
android/tablet-10in-landscape/03-sync.png · 2560 × 1600
android/tablet-10in-landscape/04-sharing.png · 2560 × 1600
android/tablet-10in-landscape/05-external.png · 2560 × 1600
ios/ipad-landscape/01-accounts.png · 2752 × 2064
ios/ipad-landscape/02-locks.png · 2752 × 2064
ios/ipad-landscape/03-sync.png · 2752 × 2064
ios/ipad-landscape/04-sharing.png · 2752 × 2064
ios/ipad-landscape/05-external.png · 2752 × 2064
android/icon-512.png · 512 × 512
ios/icon-1024.png · 1024 × 1024
android/feature-graphic-1024x500.png · 1024 × 500
\ No newline at end of file +Noo store assets

Noo / store listing assets

English · production Flutter UI · fictional offline demo data.

android/phone/01-accounts.png · 1080 × 1920
android/phone/02-locks.png · 1080 × 1920
android/phone/03-sync.png · 1080 × 1920
android/phone/04-sharing.png · 1080 × 1920
android/phone/05-external.png · 1080 × 1920
android/tablet-7in/01-accounts.png · 1200 × 1920
android/tablet-7in/02-locks.png · 1200 × 1920
android/tablet-7in/03-sync.png · 1200 × 1920
android/tablet-7in/04-sharing.png · 1200 × 1920
android/tablet-7in/05-external.png · 1200 × 1920
android/tablet-10in/01-accounts.png · 1600 × 2560
android/tablet-10in/02-locks.png · 1600 × 2560
android/tablet-10in/03-sync.png · 1600 × 2560
android/tablet-10in/04-sharing.png · 1600 × 2560
android/tablet-10in/05-external.png · 1600 × 2560
ios/iphone/01-accounts.png · 1290 × 2796
ios/iphone/02-locks.png · 1290 × 2796
ios/iphone/03-sync.png · 1290 × 2796
ios/iphone/04-sharing.png · 1290 × 2796
ios/iphone/05-external.png · 1290 × 2796
ios/ipad/01-accounts.png · 2064 × 2752
ios/ipad/02-locks.png · 2064 × 2752
ios/ipad/03-sync.png · 2064 × 2752
ios/ipad/04-sharing.png · 2064 × 2752
ios/ipad/05-external.png · 2064 × 2752
android/tablet-7in-landscape/01-accounts.png · 1920 × 1200
android/tablet-7in-landscape/02-locks.png · 1920 × 1200
android/tablet-7in-landscape/03-sync.png · 1920 × 1200
android/tablet-7in-landscape/04-sharing.png · 1920 × 1200
android/tablet-7in-landscape/05-external.png · 1920 × 1200
android/tablet-10in-landscape/01-accounts.png · 2560 × 1600
android/tablet-10in-landscape/02-locks.png · 2560 × 1600
android/tablet-10in-landscape/03-sync.png · 2560 × 1600
android/tablet-10in-landscape/04-sharing.png · 2560 × 1600
android/tablet-10in-landscape/05-external.png · 2560 × 1600
ios/ipad-landscape/01-accounts.png · 2752 × 2064
ios/ipad-landscape/02-locks.png · 2752 × 2064
ios/ipad-landscape/03-sync.png · 2752 × 2064
ios/ipad-landscape/04-sharing.png · 2752 × 2064
ios/ipad-landscape/05-external.png · 2752 × 2064
ios/iphone-6.3in/01-accounts.png · 1206 × 2622
ios/iphone-6.3in/02-locks.png · 1206 × 2622
ios/iphone-6.3in/03-sync.png · 1206 × 2622
ios/iphone-6.3in/04-sharing.png · 1206 × 2622
ios/iphone-6.3in/05-external.png · 1206 × 2622
ios/iphone-fold-portrait/01-accounts.png · 2007 × 2853
ios/iphone-fold-portrait/02-locks.png · 2007 × 2853
ios/iphone-fold-portrait/03-sync.png · 2007 × 2853
ios/iphone-fold-portrait/04-sharing.png · 2007 × 2853
ios/iphone-fold-portrait/05-external.png · 2007 × 2853
ios/iphone-fold-landscape/01-accounts.png · 2853 × 2007
ios/iphone-fold-landscape/02-locks.png · 2853 × 2007
ios/iphone-fold-landscape/03-sync.png · 2853 × 2007
ios/iphone-fold-landscape/04-sharing.png · 2853 × 2007
ios/iphone-fold-landscape/05-external.png · 2853 × 2007
ios/header/header-5244x2950.png · 5244 × 2950
ios/header/header-3840x1646.png · 3840 × 1646
ios/search-results/search-5244x2950.png · 5244 × 2950
ios/search-results/search-3840x2560.png · 3840 × 2560
ios/search-results/search-1920x1280.png · 1920 × 1280
android/icon-512.png · 512 × 512
ios/icon-1024.png · 1024 × 1024
android/feature-graphic-1024x500.png · 1024 × 500
\ No newline at end of file diff --git a/distribution/store-assets/ios/header/header-3840x1646.png b/distribution/store-assets/ios/header/header-3840x1646.png new file mode 100644 index 0000000..4ace069 Binary files /dev/null and b/distribution/store-assets/ios/header/header-3840x1646.png differ diff --git a/distribution/store-assets/ios/header/header-5244x2950.png b/distribution/store-assets/ios/header/header-5244x2950.png new file mode 100644 index 0000000..d595b3b Binary files /dev/null and b/distribution/store-assets/ios/header/header-5244x2950.png differ diff --git a/distribution/store-assets/ios/iphone-6.3in/01-accounts.png b/distribution/store-assets/ios/iphone-6.3in/01-accounts.png new file mode 100644 index 0000000..8018630 Binary files /dev/null and b/distribution/store-assets/ios/iphone-6.3in/01-accounts.png differ diff --git a/distribution/store-assets/ios/iphone-6.3in/02-locks.png b/distribution/store-assets/ios/iphone-6.3in/02-locks.png new file mode 100644 index 0000000..c659c7e Binary files /dev/null and b/distribution/store-assets/ios/iphone-6.3in/02-locks.png differ diff --git a/distribution/store-assets/ios/iphone-6.3in/03-sync.png b/distribution/store-assets/ios/iphone-6.3in/03-sync.png new file mode 100644 index 0000000..9f163db Binary files /dev/null and b/distribution/store-assets/ios/iphone-6.3in/03-sync.png differ diff --git a/distribution/store-assets/ios/iphone-6.3in/04-sharing.png b/distribution/store-assets/ios/iphone-6.3in/04-sharing.png new file mode 100644 index 0000000..bed7071 Binary files /dev/null and b/distribution/store-assets/ios/iphone-6.3in/04-sharing.png differ diff --git a/distribution/store-assets/ios/iphone-6.3in/05-external.png b/distribution/store-assets/ios/iphone-6.3in/05-external.png new file mode 100644 index 0000000..390c8e9 Binary files /dev/null and b/distribution/store-assets/ios/iphone-6.3in/05-external.png differ diff --git a/distribution/store-assets/ios/iphone-fold-landscape/01-accounts.png b/distribution/store-assets/ios/iphone-fold-landscape/01-accounts.png new file mode 100644 index 0000000..5c20ce4 Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-landscape/01-accounts.png differ diff --git a/distribution/store-assets/ios/iphone-fold-landscape/02-locks.png b/distribution/store-assets/ios/iphone-fold-landscape/02-locks.png new file mode 100644 index 0000000..1700e10 Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-landscape/02-locks.png differ diff --git a/distribution/store-assets/ios/iphone-fold-landscape/03-sync.png b/distribution/store-assets/ios/iphone-fold-landscape/03-sync.png new file mode 100644 index 0000000..5d75ae0 Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-landscape/03-sync.png differ diff --git a/distribution/store-assets/ios/iphone-fold-landscape/04-sharing.png b/distribution/store-assets/ios/iphone-fold-landscape/04-sharing.png new file mode 100644 index 0000000..32afd10 Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-landscape/04-sharing.png differ diff --git a/distribution/store-assets/ios/iphone-fold-landscape/05-external.png b/distribution/store-assets/ios/iphone-fold-landscape/05-external.png new file mode 100644 index 0000000..3c420ec Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-landscape/05-external.png differ diff --git a/distribution/store-assets/ios/iphone-fold-portrait/01-accounts.png b/distribution/store-assets/ios/iphone-fold-portrait/01-accounts.png new file mode 100644 index 0000000..55fb324 Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-portrait/01-accounts.png differ diff --git a/distribution/store-assets/ios/iphone-fold-portrait/02-locks.png b/distribution/store-assets/ios/iphone-fold-portrait/02-locks.png new file mode 100644 index 0000000..8460835 Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-portrait/02-locks.png differ diff --git a/distribution/store-assets/ios/iphone-fold-portrait/03-sync.png b/distribution/store-assets/ios/iphone-fold-portrait/03-sync.png new file mode 100644 index 0000000..7bb3f90 Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-portrait/03-sync.png differ diff --git a/distribution/store-assets/ios/iphone-fold-portrait/04-sharing.png b/distribution/store-assets/ios/iphone-fold-portrait/04-sharing.png new file mode 100644 index 0000000..5276dcf Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-portrait/04-sharing.png differ diff --git a/distribution/store-assets/ios/iphone-fold-portrait/05-external.png b/distribution/store-assets/ios/iphone-fold-portrait/05-external.png new file mode 100644 index 0000000..0818ba1 Binary files /dev/null and b/distribution/store-assets/ios/iphone-fold-portrait/05-external.png differ diff --git a/distribution/store-assets/ios/search-results/search-1920x1280.png b/distribution/store-assets/ios/search-results/search-1920x1280.png new file mode 100644 index 0000000..afecbb7 Binary files /dev/null and b/distribution/store-assets/ios/search-results/search-1920x1280.png differ diff --git a/distribution/store-assets/ios/search-results/search-3840x2560.png b/distribution/store-assets/ios/search-results/search-3840x2560.png new file mode 100644 index 0000000..5969022 Binary files /dev/null and b/distribution/store-assets/ios/search-results/search-3840x2560.png differ diff --git a/distribution/store-assets/ios/search-results/search-5244x2950.png b/distribution/store-assets/ios/search-results/search-5244x2950.png new file mode 100644 index 0000000..d595b3b Binary files /dev/null and b/distribution/store-assets/ios/search-results/search-5244x2950.png differ diff --git a/distribution/store-assets/manifest.json b/distribution/store-assets/manifest.json index fc0386d..3f8120e 100644 --- a/distribution/store-assets/manifest.json +++ b/distribution/store-assets/manifest.json @@ -359,6 +359,186 @@ "mode": "RGB", "story": "external" }, + { + "file": "ios/iphone-6.3in/01-accounts.png", + "size": [ + 1206, + 2622 + ], + "mode": "RGB", + "story": "accounts" + }, + { + "file": "ios/iphone-6.3in/02-locks.png", + "size": [ + 1206, + 2622 + ], + "mode": "RGB", + "story": "locks" + }, + { + "file": "ios/iphone-6.3in/03-sync.png", + "size": [ + 1206, + 2622 + ], + "mode": "RGB", + "story": "sync" + }, + { + "file": "ios/iphone-6.3in/04-sharing.png", + "size": [ + 1206, + 2622 + ], + "mode": "RGB", + "story": "sharing" + }, + { + "file": "ios/iphone-6.3in/05-external.png", + "size": [ + 1206, + 2622 + ], + "mode": "RGB", + "story": "external" + }, + { + "file": "ios/iphone-fold-portrait/01-accounts.png", + "size": [ + 2007, + 2853 + ], + "mode": "RGB", + "story": "accounts" + }, + { + "file": "ios/iphone-fold-portrait/02-locks.png", + "size": [ + 2007, + 2853 + ], + "mode": "RGB", + "story": "locks" + }, + { + "file": "ios/iphone-fold-portrait/03-sync.png", + "size": [ + 2007, + 2853 + ], + "mode": "RGB", + "story": "sync" + }, + { + "file": "ios/iphone-fold-portrait/04-sharing.png", + "size": [ + 2007, + 2853 + ], + "mode": "RGB", + "story": "sharing" + }, + { + "file": "ios/iphone-fold-portrait/05-external.png", + "size": [ + 2007, + 2853 + ], + "mode": "RGB", + "story": "external" + }, + { + "file": "ios/iphone-fold-landscape/01-accounts.png", + "size": [ + 2853, + 2007 + ], + "mode": "RGB", + "story": "accounts" + }, + { + "file": "ios/iphone-fold-landscape/02-locks.png", + "size": [ + 2853, + 2007 + ], + "mode": "RGB", + "story": "locks" + }, + { + "file": "ios/iphone-fold-landscape/03-sync.png", + "size": [ + 2853, + 2007 + ], + "mode": "RGB", + "story": "sync" + }, + { + "file": "ios/iphone-fold-landscape/04-sharing.png", + "size": [ + 2853, + 2007 + ], + "mode": "RGB", + "story": "sharing" + }, + { + "file": "ios/iphone-fold-landscape/05-external.png", + "size": [ + 2853, + 2007 + ], + "mode": "RGB", + "story": "external" + }, + { + "file": "ios/header/header-5244x2950.png", + "size": [ + 5244, + 2950 + ], + "mode": "RGB", + "story": "banner" + }, + { + "file": "ios/header/header-3840x1646.png", + "size": [ + 3840, + 1646 + ], + "mode": "RGB", + "story": "banner" + }, + { + "file": "ios/search-results/search-5244x2950.png", + "size": [ + 5244, + 2950 + ], + "mode": "RGB", + "story": "banner" + }, + { + "file": "ios/search-results/search-3840x2560.png", + "size": [ + 3840, + 2560 + ], + "mode": "RGB", + "story": "banner" + }, + { + "file": "ios/search-results/search-1920x1280.png", + "size": [ + 1920, + 1280 + ], + "mode": "RGB", + "story": "banner" + }, { "file": "android/icon-512.png", "size": [ diff --git a/distribution/store-assets/store-listing-assets.zip b/distribution/store-assets/store-listing-assets.zip index ec8aaa7..90e849d 100644 Binary files a/distribution/store-assets/store-listing-assets.zip and b/distribution/store-assets/store-listing-assets.zip differ diff --git a/distribution/store-assets/tools/compose.py b/distribution/store-assets/tools/compose.py index 2aa2323..8312804 100644 --- a/distribution/store-assets/tools/compose.py +++ b/distribution/store-assets/tools/compose.py @@ -60,6 +60,19 @@ TARGETS = [ ('android/tablet-7in-landscape', 'atabletl', (1920, 1200), 'landscape'), ('android/tablet-10in-landscape', 'atabletl', (2560, 1600), 'landscape'), ('ios/ipad-landscape', 'ipadl', (2752, 2064), 'landscape'), + # Newer App Store slots. iPad 13" (2064x2752, 2752x2064) is the two above. + ('ios/iphone-6.3in', 'iphone', (1206, 2622), 'phone'), + ('ios/iphone-fold-portrait', 'ipad', (2007, 2853), 'tablet'), + ('ios/iphone-fold-landscape', 'ipadl', (2853, 2007), 'landscape'), +] + +# App Store product-page banners: (folder, file name, size). +HEROES = [ + ('ios/header', 'header-5244x2950.png', (5244, 2950)), + ('ios/header', 'header-3840x1646.png', (3840, 1646)), + ('ios/search-results', 'search-5244x2950.png', (5244, 2950)), + ('ios/search-results', 'search-3840x2560.png', (3840, 2560)), + ('ios/search-results', 'search-1920x1280.png', (1920, 1280)), ] @@ -215,6 +228,56 @@ def story_canvas(story, size, kind, device): return im +def hero_canvas(size): + """Brand banner: name and tagline left, iPad (landscape) and iPhone right.""" + t = THEMES['light'] + w, h = size + im = background(size, t) + d = ImageDraw.Draw(im) + margin = round(min(w * .06, h * .13)) + colw = round(w * (.30 if w / h > 2 else .34)) + # Text column, vertically centered as a block. + icon_px = round(h * .105) + head = round(h * .092) + sub_size = round(h * .034) + block = icon_px + round(h * .05) + round(head * 2.35) + round(sub_size * 4.4) + y = (h - block) // 2 + icon = Image.open(ROOT / 'assets/icon/app_icon.png').convert('RGBA').resize((icon_px, icon_px), Image.Resampling.LANCZOS) + im.paste(icon, (margin, y), rounded_mask((icon_px, icon_px), round(icon_px * .24))) + spaced(d, (margin + icon_px + round(h * .025), y + icon_px // 2 - round(h * .02)), 'NOOCLOUD', + font(round(h * .034), 'Bold', 'InstrumentSans'), t['accent_text'], h * .006) + y += icon_px + round(h * .05) + for index, line in enumerate(('The Nextcloud app', 'that just works.')): + 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) + fnt = body_font(sub_size, 'Regular') + chars = max(16, int(colw / (sub_size * .52))) + for line in textwrap.wrap('Multiple accounts, locks, offline sync, sharing and external storage.', chars): + d.text((margin, y), line, font=fnt, fill=t['fg2']) + y += round(sub_size * 1.4) + # Devices: iPad landscape with the iPhone overlapping its bottom-right corner. + x0 = margin + colw + round(w * .03) + region_w = w - x0 - margin + ipad_h = round(h * .72) + ipad_w = round(ipad_h * 4 / 3) + phone_h = round(ipad_h * 1.02) + phone_w = round(phone_h * 0.4614) + total = ipad_w + round(phone_w * .7) + if total > region_w: + k = region_w / total + ipad_h, ipad_w, phone_h, phone_w = (round(v * k) for v in (ipad_h, ipad_w, phone_h, phone_w)) + total = ipad_w + round(phone_w * .7) + x = x0 + (region_w - total) // 2 + top = (h - ipad_h) // 2 - round(h * .03) + paste_panel(im, OUT / 'source/ipadl/external.png', (x, top, ipad_w, ipad_h), round(h * .028), t) + paste_panel(im, OUT / 'source/iphone/offline.png', + (x + ipad_w - round(phone_w * .3), top + ipad_h - phone_h + round(h * .07), phone_w, phone_h), + round(h * .035), t) + return im + + def check(path, size, mode): image = Image.open(path) assert image.size == tuple(size) and image.mode == mode, path @@ -234,6 +297,13 @@ for folder, device, size, kind in TARGETS: manifest.append({'file': str(path.relative_to(OUT)), 'size': list(size), 'mode': 'RGB', 'story': story['key']}) +for folder, name, size in HEROES: + dest = OUT / folder + dest.mkdir(parents=True, exist_ok=True) + path = dest / name + hero_canvas(size).save(path, optimize=True) + manifest.append({'file': str(path.relative_to(OUT)), 'size': list(size), 'mode': 'RGB', 'story': 'banner'}) + # Store icons: Play wants a 512 px PNG, App Store Connect takes the icon from # the uploaded build (this 1024 px copy is only a reference). for platform, px, source in [