Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
660d0bc869 | ||
|
|
5837464581 | ||
|
|
11b3d535a9 | ||
|
|
d92bf04a7d | ||
|
|
86e5e599b6 | ||
|
|
0ea98363de | ||
|
|
ca4afb2ed7 |
@@ -168,10 +168,10 @@ Use **Lucide** (pinned to `lucide-static@0.460.0`) at a 1.8 stroke. Sizes are 14
|
|||||||
- Shared: `users` in fg-3.
|
- Shared: `users` in fg-3.
|
||||||
|
|
||||||
**Swipe action**
|
**Swipe action**
|
||||||
- The row slides and uncovers a 96px action block. Delete is white on danger-fill; Favorite is white on accent.
|
- The row slides and uncovers a 96px action block. Delete is white on danger-fill; all other actions are white on accent.
|
||||||
- The block has a 20px icon above a 12/600 label.
|
- The block has a 20px icon above a 12/600 label.
|
||||||
- Releasing past half the block snaps it open; dragging further still (past 1.8× the block's width, a haptic tick marks the crossing and the icon bumps up 15%) arms the action, and releasing while armed fires it immediately - one swipe-through gesture instead of open-then-tap. The block grows to fill however far it's dragged, so there's never a gap behind it.
|
- Releasing past half the block snaps it open; dragging further still (past 1.8× the block's width, a haptic tick marks the crossing and the icon bumps up 15%) arms the action, and releasing while armed fires it immediately - one swipe-through gesture instead of open-then-tap. The block grows to fill however far it's dragged, so there's never a gap behind it.
|
||||||
- Swipe actions are set in Settings → Swipe on a file.
|
- Swipe actions are set in Settings → Swipe on a file. Both directions offer None and every action-bar action: Favorite, Share, Download, Delete, Copy, Move, Rename, Sync to device, Details. They use the same single-item handlers; Delete still asks for confirmation.
|
||||||
|
|
||||||
**Selection action bar** (Files, Photos, Favorites - anywhere with
|
**Selection action bar** (Files, Photos, Favorites - anywhere with
|
||||||
multi-select)
|
multi-select)
|
||||||
@@ -289,7 +289,7 @@ Mobile always has **5 pinned tabs in the bottom bar**. The rest go in the drawer
|
|||||||
| Upload | `plus` in the nav bar | Extended FAB - fully round (pill) when the bottom bar is floating, rounded square (`card` radius) when it's attached |
|
| Upload | `plus` in the nav bar | Extended FAB - fully round (pill) when the bottom bar is floating, rounded square (`card` radius) when it's attached |
|
||||||
| Overflow icon | `ellipsis` | `ellipsis-vertical` |
|
| Overflow icon | `ellipsis` | `ellipsis-vertical` |
|
||||||
| Settings | Pushed screen with a "‹ Files" back button and a large title. No bottom bar. | Pushed screen with a back arrow and a title. No bottom bar. |
|
| Settings | Pushed screen with a "‹ Files" back button and a large title. No bottom bar. | Pushed screen with a back arrow and a title. No bottom bar. |
|
||||||
| Biometric label | "Lock with Face ID" | "Lock with fingerprint" |
|
| App lock label | "App lock" | "App lock" |
|
||||||
|
|
||||||
### Desktop
|
### Desktop
|
||||||
|
|
||||||
@@ -366,7 +366,9 @@ Sidebar items are 38px tall with radius 12, an 18px icon and a 14/500 label. The
|
|||||||
priority order for the Selection action bar's bulk actions (favorite,
|
priority order for the Selection action bar's bulk actions (favorite,
|
||||||
share, download, delete, copy, move, rename, sync, details) - the
|
share, download, delete, copy, move, rename, sync, details) - the
|
||||||
first few (3 mobile / 4 desktop) land in the bar's fixed inline
|
first few (3 mobile / 4 desktop) land in the bar's fixed inline
|
||||||
slots, the rest sit behind "More". See §2 "Selection action bar".
|
slots, the rest sit behind "More". A live preview above the list uses
|
||||||
|
the actual bar and updates on reorder, including its More sheet. Preview
|
||||||
|
actions show feedback without touching files. See §2 "Selection action bar".
|
||||||
9. Swipe on a file
|
9. Swipe on a file
|
||||||
|
|
||||||
Mobile is a two-level menu, the way native iOS/Android Settings apps
|
Mobile is a two-level menu, the way native iOS/Android Settings apps
|
||||||
|
|||||||
@@ -113,9 +113,11 @@ in this order: a local `android/key.properties` (gitignored — points at a
|
|||||||
gitignored keystore file, e.g. `android/app/release-keystore.jks`), then
|
gitignored keystore file, e.g. `android/app/release-keystore.jks`), then
|
||||||
CI env vars (`RELEASE_KEYSTORE_PATH`/`_PASSWORD`, `RELEASE_KEY_ALIAS`/
|
CI env vars (`RELEASE_KEYSTORE_PATH`/`_PASSWORD`, `RELEASE_KEY_ALIAS`/
|
||||||
`_PASSWORD`, set from the same repo secrets by both `.gitea/workflows/
|
`_PASSWORD`, set from the same repo secrets by both `.gitea/workflows/
|
||||||
build.yml`, triggered by `RC*` tags and producing a sideloadable APK, and
|
build.yml`, triggered by `RC-Android-*` tags and producing a sideloadable
|
||||||
`.gitea/workflows/release.yml`, triggered by `Release-*` tags and producing
|
APK, and `.gitea/workflows/release.yml`, triggered by `Release-*` tags and
|
||||||
the `.aab` Play Console wants), then falls back to the debug key if neither
|
producing the `.aab` Play Console wants; `.gitea/workflows/ios.yml` builds
|
||||||
|
and uploads the signed iOS app to TestFlight on `RC-iOS-*` and `Release-*`
|
||||||
|
tags, on a self-hosted macOS runner), then falls back to the debug key if neither
|
||||||
is configured. As long as the same dedicated release keystore backs both
|
is configured. As long as the same dedicated release keystore backs both
|
||||||
`key.properties` locally and the Gitea secrets, local release builds and
|
`key.properties` locally and the Gitea secrets, local release builds and
|
||||||
CI-built release APKs share one signature, so `adb install -r` works
|
CI-built release APKs share one signature, so `adb install -r` works
|
||||||
|
|||||||
@@ -111,6 +111,17 @@ Gotchas:
|
|||||||
in one gesture, it's not tap-only anymore.
|
in one gesture, it's not tap-only anymore.
|
||||||
- Window chrome (macOS traffic lights, the Windows 40px title bar) isn't
|
- Window chrome (macOS traffic lights, the Windows 40px title bar) isn't
|
||||||
built yet. `NooSidebar.windowControls` is the slot for it.
|
built yet. `NooSidebar.windowControls` is the slot for it.
|
||||||
|
- Swipe settings offer every `SelectionActionKind` plus None. `SwipeAction`
|
||||||
|
persists the existing enum names and maps to that shared action catalog;
|
||||||
|
`FilesView` uses the single-item action-bar handlers, with the existing
|
||||||
|
delete confirmation retained. Labels/icons update for favorited and synced
|
||||||
|
items. Swipes remain disabled during selection, picking, and offline browsing.
|
||||||
|
- Settings → Action bar shows the real `NooSelectionBar` above its reorder
|
||||||
|
list. It updates immediately and supports the same More sheet; preview
|
||||||
|
actions only show feedback, never operate on files. The bar scales down
|
||||||
|
inside Settings' narrower column while keeping the mobile/tablet split.
|
||||||
|
- The Security setting is labelled **App lock** on every platform; its
|
||||||
|
subtitle still explains device PIN or biometric authentication.
|
||||||
- Always read colors through `context.nooColors`, never
|
- Always read colors through `context.nooColors`, never
|
||||||
`Theme.of(context).colorScheme` - the latter is Flutter's own Material 3
|
`Theme.of(context).colorScheme` - the latter is Flutter's own Material 3
|
||||||
scheme, reseeded by the user's accent color choice (`AppTheme.light`/
|
scheme, reseeded by the user's accent color choice (`AppTheme.light`/
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# CI-only: switches the Release configuration of the Runner and ShareExtension
|
||||||
|
# targets to manual signing with the App Store profiles. The committed project
|
||||||
|
# stays on Automatic signing so local development is unaffected; this edit
|
||||||
|
# happens only inside the CI checkout. Run from the repo root:
|
||||||
|
# ruby .gitea/scripts/ios_ci_signing.rb
|
||||||
|
require "xcodeproj"
|
||||||
|
|
||||||
|
TEAM = "Q3JLTAG9PV"
|
||||||
|
# Pinned by SHA-1, not by the "Apple Distribution" name: a runner that also
|
||||||
|
# holds other same-named distribution certs (e.g. a dev Mac's login keychain)
|
||||||
|
# would otherwise let Xcode pick one the profiles don't include. Update this
|
||||||
|
# (and ios/ExportOptions.plist) when the certificate is renewed.
|
||||||
|
CERT_SHA1 = "2527806871D806E8E27221B15CA8A1938CF216F2"
|
||||||
|
PROFILES = {
|
||||||
|
"Runner" => "NooProfile",
|
||||||
|
"ShareExtension" => "NooShareSheetProfile",
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
project = Xcodeproj::Project.open("ios/Runner.xcodeproj")
|
||||||
|
PROFILES.each do |target_name, profile|
|
||||||
|
target = project.targets.find { |t| t.name == target_name } or abort("no target #{target_name}")
|
||||||
|
target.build_configurations.select { |c| c.name == "Release" }.each do |config|
|
||||||
|
settings = config.build_settings
|
||||||
|
settings["CODE_SIGN_STYLE"] = "Manual"
|
||||||
|
settings["DEVELOPMENT_TEAM"] = TEAM
|
||||||
|
settings["CODE_SIGN_IDENTITY"] = CERT_SHA1
|
||||||
|
settings["CODE_SIGN_IDENTITY[sdk=iphoneos*]"] = CERT_SHA1
|
||||||
|
settings["PROVISIONING_PROFILE_SPECIFIER"] = profile
|
||||||
|
end
|
||||||
|
end
|
||||||
|
project.save
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
name: Build APK
|
name: Build APK
|
||||||
|
|
||||||
# Deliberately not "on every push" - only when a release-candidate tag
|
# Deliberately not "on every push" - only when an Android release-candidate
|
||||||
# (RC1, RC2, RC2026.1, ...) is pushed. Tag the commit you want built:
|
# tag (RC-Android-1, RC-Android-2, ...) is pushed. Tag the commit you want built:
|
||||||
# git tag RC1 && git push origin RC1
|
# git tag RC-Android-1 && git push origin RC-Android-1
|
||||||
|
# iOS has its own RC-iOS-* tags (ios.yml); Release-* builds both platforms.
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "RC*"
|
- "RC-Android-*"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -72,7 +73,7 @@ jobs:
|
|||||||
# talks to this same Gitea instance automatically via the
|
# talks to this same Gitea instance automatically via the
|
||||||
# `github.token`/`github.server_url` context Gitea Actions
|
# `github.token`/`github.server_url` context Gitea Actions
|
||||||
# provides for compatibility. Release is named/tagged after
|
# provides for compatibility. Release is named/tagged after
|
||||||
# whatever tag triggered this run (e.g. "RC1").
|
# whatever tag triggered this run (e.g. "RC-Android-1").
|
||||||
uses: akkuman/gitea-release-action@v1
|
uses: akkuman/gitea-release-action@v1
|
||||||
with:
|
with:
|
||||||
files: ${{ env.APK_PATH }}
|
files: ${{ env.APK_PATH }}
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
name: Build iOS
|
||||||
|
|
||||||
|
# Tag scheme (shared with the Android workflows):
|
||||||
|
# Release-<version> -> release.yml (Play bundle) AND this workflow
|
||||||
|
# RC-Android-<n> -> build.yml (APK) only
|
||||||
|
# RC-iOS-<n> -> this workflow only
|
||||||
|
# git tag RC-iOS-1 && git push origin RC-iOS-1
|
||||||
|
# Builds a signed .ipa and uploads it to TestFlight. Needs a Mac runner
|
||||||
|
# registered with the `macos` label (gitea-runner in host mode) with Xcode
|
||||||
|
# installed; Linux runners cannot build iOS.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "Release-*"
|
||||||
|
- "RC-iOS-*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: macos
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Flutter
|
||||||
|
uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
|
||||||
|
- name: Check tag matches pubspec version
|
||||||
|
# Only Release-* tags carry a version; RC-iOS-* tags are free-form.
|
||||||
|
if: startsWith(github.ref_name, 'Release-')
|
||||||
|
run: |
|
||||||
|
VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //' | cut -d'+' -f1)
|
||||||
|
if [ "${GITHUB_REF_NAME}" != "Release-${VERSION}" ]; then
|
||||||
|
echo "Tag ${GITHUB_REF_NAME} does not match pubspec version ${VERSION}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: flutter pub get
|
||||||
|
|
||||||
|
- name: Analyze
|
||||||
|
run: flutter analyze
|
||||||
|
|
||||||
|
- name: Install signing certificate and profiles
|
||||||
|
# A throwaway keychain keeps the distribution key off the runner's
|
||||||
|
# login keychain; it is deleted again in the cleanup step.
|
||||||
|
env:
|
||||||
|
CERT_P12_BASE64: ${{ secrets.IOS_DIST_CERT_P12_BASE64 }}
|
||||||
|
CERT_PASSWORD: ${{ secrets.IOS_DIST_CERT_PASSWORD }}
|
||||||
|
APP_PROFILE_BASE64: ${{ secrets.IOS_APP_PROFILE_BASE64 }}
|
||||||
|
EXT_PROFILE_BASE64: ${{ secrets.IOS_EXT_PROFILE_BASE64 }}
|
||||||
|
run: |
|
||||||
|
KEYCHAIN="${{ runner.temp }}/ci-signing.keychain-db"
|
||||||
|
KEYCHAIN_PASSWORD=$(uuidgen)
|
||||||
|
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
|
||||||
|
security set-keychain-settings -lut 21600 "$KEYCHAIN"
|
||||||
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
|
||||||
|
echo "$CERT_P12_BASE64" | base64 -d > "${{ runner.temp }}/dist.p12"
|
||||||
|
security import "${{ runner.temp }}/dist.p12" -P "$CERT_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN"
|
||||||
|
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
|
||||||
|
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"')
|
||||||
|
rm -f "${{ runner.temp }}/dist.p12"
|
||||||
|
# Must list 2527806871D8... (the cert the profiles embed); if it
|
||||||
|
# doesn't, IOS_DIST_CERT_P12_BASE64 holds the wrong certificate.
|
||||||
|
security find-identity -v -p codesigning "$KEYCHAIN"
|
||||||
|
|
||||||
|
PROFILES_DIR="$HOME/Library/MobileDevice/Provisioning Profiles"
|
||||||
|
mkdir -p "$PROFILES_DIR"
|
||||||
|
echo "$APP_PROFILE_BASE64" | base64 -d > "$PROFILES_DIR/NooProfile.mobileprovision"
|
||||||
|
echo "$EXT_PROFILE_BASE64" | base64 -d > "$PROFILES_DIR/NooShareSheetProfile.mobileprovision"
|
||||||
|
|
||||||
|
- name: Switch Release config to manual signing
|
||||||
|
run: ruby .gitea/scripts/ios_ci_signing.rb
|
||||||
|
|
||||||
|
- name: Build signed IPA
|
||||||
|
run: flutter build ipa --release --export-options-plist=ios/ExportOptions.plist
|
||||||
|
|
||||||
|
- name: Rename IPA to Noo-<version>.ipa
|
||||||
|
run: |
|
||||||
|
VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //' | cut -d'+' -f1)
|
||||||
|
mkdir -p release
|
||||||
|
cp build/ios/ipa/*.ipa "release/Noo-${VERSION}.ipa"
|
||||||
|
echo "IPA_PATH=release/Noo-${VERSION}.ipa" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Upload to TestFlight
|
||||||
|
env:
|
||||||
|
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
|
||||||
|
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
|
||||||
|
ASC_KEY_P8_BASE64: ${{ secrets.ASC_KEY_P8_BASE64 }}
|
||||||
|
run: |
|
||||||
|
mkdir -p "$HOME/.appstoreconnect/private_keys"
|
||||||
|
echo "$ASC_KEY_P8_BASE64" | base64 -d > "$HOME/.appstoreconnect/private_keys/AuthKey_${ASC_KEY_ID}.p8"
|
||||||
|
xcrun altool --upload-app -f "$IPA_PATH" -t ios \
|
||||||
|
--apiKey "$ASC_KEY_ID" --apiIssuer "$ASC_ISSUER_ID"
|
||||||
|
|
||||||
|
- name: Cleanup signing material
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
security delete-keychain "${{ runner.temp }}/ci-signing.keychain-db" || true
|
||||||
|
rm -f "$HOME/Library/MobileDevice/Provisioning Profiles/NooProfile.mobileprovision" \
|
||||||
|
"$HOME/Library/MobileDevice/Provisioning Profiles/NooShareSheetProfile.mobileprovision"
|
||||||
|
rm -rf "$HOME/.appstoreconnect/private_keys"
|
||||||
@@ -3,7 +3,7 @@ name: Build App Bundle
|
|||||||
# Deliberately not "on every push" - only when a real release tag (Release-1.0.0,
|
# Deliberately not "on every push" - only when a real release tag (Release-1.0.0,
|
||||||
# Release-1.2.3, ...) is pushed. Tag the commit you want built:
|
# Release-1.2.3, ...) is pushed. Tag the commit you want built:
|
||||||
# git tag Release-1.0.0 && git push origin Release-1.0.0
|
# git tag Release-1.0.0 && git push origin Release-1.0.0
|
||||||
# Unlike the RC* flow (build.yml), this builds the .aab Play Console wants,
|
# Unlike the RC-Android-* flow (build.yml), this builds the .aab Play Console wants,
|
||||||
# not a sideloadable .apk.
|
# not a sideloadable .apk.
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -56,7 +56,7 @@ jobs:
|
|||||||
run: flutter analyze
|
run: flutter analyze
|
||||||
|
|
||||||
- name: Decode release keystore
|
- name: Decode release keystore
|
||||||
# Same key as the RC* APK builds, so a Play Store upload's signature
|
# Same key as the RC-Android-* APK builds, so a Play Store upload's signature
|
||||||
# matches anything sideloaded from a release build. See
|
# matches anything sideloaded from a release build. See
|
||||||
# android/app/build.gradle.kts.
|
# android/app/build.gradle.kts.
|
||||||
run: echo "$RELEASE_KEYSTORE_BASE64" | base64 -d > "${{ runner.temp }}/release-keystore.jks"
|
run: echo "$RELEASE_KEYSTORE_BASE64" | base64 -d > "${{ runner.temp }}/release-keystore.jks"
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
# Noo store listing assets
|
||||||
|
|
||||||
|
English artwork for the App Store and Google Play, built from Noo's
|
||||||
|
production Flutter widgets with fictional data (example.com servers, made-up
|
||||||
|
people and files). No real accounts, credentials or network requests are
|
||||||
|
involved. The five screenshots follow the Features section of the website
|
||||||
|
(`noo.ayushya.dev`), in the same order:
|
||||||
|
|
||||||
|
1. Multiple accounts: the account switcher
|
||||||
|
2. Locks: the lock screen with the Security card over it
|
||||||
|
3. Offline sync: the Offline tab with the File sync card over it
|
||||||
|
4. Sharing: the Share sheet (people, groups, public link)
|
||||||
|
5. External storage: Files with the mounted-storage section
|
||||||
|
|
||||||
|
The landscape tablet sets show the app's real tablet layout (sidebar and
|
||||||
|
toolbar), captured from the actual shell widget. Portrait and landscape tablet
|
||||||
|
screenshots go in the same store slot; upload whichever orientation you want
|
||||||
|
to show, or both.
|
||||||
|
|
||||||
|
Look: the app's own design tokens (warm neutrals, one violet accent,
|
||||||
|
Schibsted Grotesk / Instrument Sans), flat shapes, alternating light and dark.
|
||||||
|
|
||||||
|
## Upload files
|
||||||
|
|
||||||
|
| Store slot | Location | Dimensions |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Google Play app icon | `android/icon-512.png` | 512 × 512 |
|
||||||
|
| Google Play feature graphic | `android/feature-graphic-1024x500.png` | 1024 × 500 |
|
||||||
|
| Google Play phone screenshots | `android/phone/01-*.png` … `05-*.png` | 1080 × 1920 |
|
||||||
|
| Google Play 7-inch tablet screenshots | `android/tablet-7in/` | 1200 × 1920 |
|
||||||
|
| Google Play 10-inch tablet screenshots | `android/tablet-10in/` | 1600 × 2560 |
|
||||||
|
| App Store iPhone screenshots (6.9" / 6.7" slot) | `ios/iphone/` | 1290 × 2796 |
|
||||||
|
| App Store iPad screenshots (13" slot) | `ios/ipad/` | 2064 × 2752 |
|
||||||
|
| 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.
|
||||||
|
`manifest.json` records each file's exact size and mode. `index.html` and
|
||||||
|
`contact-sheet.jpg` are review materials, not store uploads.
|
||||||
|
`store-listing-assets.zip` holds the upload files, this guide, the manifest
|
||||||
|
and the draft listing text.
|
||||||
|
|
||||||
|
`listing-copy.json` has draft text for both stores, written around the same
|
||||||
|
five features. The App Store name is `NooCloud` (the plain name was taken);
|
||||||
|
the home-screen name stays `Noo` via `CFBundleDisplayName`. Character limits
|
||||||
|
are checked by `tools/compose.py`.
|
||||||
|
|
||||||
|
Dimensions checked against the official requirements on October 7, 2026:
|
||||||
|
|
||||||
|
- [Google Play preview assets](https://support.google.com/googleplay/android-developer/answer/9866151?hl=en)
|
||||||
|
- [Apple screenshot specifications](https://developer.apple.com/help/app-store-connect/reference/app-information/screenshot-specifications)
|
||||||
|
|
||||||
|
## Reproduce and edit
|
||||||
|
|
||||||
|
The app needs a current stable Flutter (Dart ^3.12). From the repository root:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
flutter test --no-pub distribution/store-assets/tools/capture_test.dart
|
||||||
|
python3 -m venv /tmp/noo-store-assets-venv
|
||||||
|
/tmp/noo-store-assets-venv/bin/pip install Pillow
|
||||||
|
/tmp/noo-store-assets-venv/bin/python distribution/store-assets/tools/compose.py
|
||||||
|
```
|
||||||
|
|
||||||
|
`capture_test.dart` lives outside `test/` so normal test runs never rewrite
|
||||||
|
marketing assets. It renders the real widgets (account switcher, lock screen,
|
||||||
|
Security and File sync sections, Offline tab, Share sheet, Files with
|
||||||
|
external storage) at phone and tablet sizes into `source/`, using demo
|
||||||
|
subclasses of the session, files, sync and item-operation controllers.
|
||||||
|
`compose.py` lays headlines, colors and device panels around those captures;
|
||||||
|
change copy, colors or output sizes there.
|
||||||
|
|
||||||
|
Review the output before uploading, and re-capture after UI changes.
|
||||||
|
These files are prepared locally; no store listing has been changed.
|
||||||
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 184 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 280 KiB |
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 190 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 209 KiB |
|
After Width: | Height: | Size: 342 KiB |
|
After Width: | Height: | Size: 290 KiB |
|
After Width: | Height: | Size: 238 KiB |
|
After Width: | Height: | Size: 277 KiB |
|
After Width: | Height: | Size: 188 KiB |
|
After Width: | Height: | Size: 294 KiB |
|
After Width: | Height: | Size: 307 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 239 KiB |
|
After Width: | Height: | Size: 205 KiB |
|
After Width: | Height: | Size: 168 KiB |
|
After Width: | Height: | Size: 194 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 216 KiB |
|
After Width: | Height: | Size: 154 KiB |
|
After Width: | Height: | Size: 455 KiB |
|
After Width: | Height: | Size: 431 KiB |
|
After Width: | Height: | Size: 684 KiB |
|
After Width: | Height: | Size: 143 KiB |
|
After Width: | Height: | Size: 249 KiB |
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 385 KiB |
|
After Width: | Height: | Size: 318 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 397 KiB |
|
After Width: | Height: | Size: 339 KiB |
|
After Width: | Height: | Size: 265 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 350 KiB |
|
After Width: | Height: | Size: 291 KiB |
|
After Width: | Height: | Size: 248 KiB |
|
After Width: | Height: | Size: 259 KiB |
|
After Width: | Height: | Size: 248 KiB |
|
After Width: | Height: | Size: 397 KiB |
|
After Width: | Height: | Size: 333 KiB |
|
After Width: | Height: | Size: 279 KiB |
|
After Width: | Height: | Size: 319 KiB |
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 392 KiB |
|
After Width: | Height: | Size: 354 KiB |
|
After Width: | Height: | Size: 272 KiB |
|
After Width: | Height: | Size: 289 KiB |
|
After Width: | Height: | Size: 236 KiB |
|
After Width: | Height: | Size: 377 KiB |
|
After Width: | Height: | Size: 314 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 489 KiB |
|
After Width: | Height: | Size: 684 KiB |
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"locale": "en-US",
|
||||||
|
"google_play": {
|
||||||
|
"title": "Noo - Nextcloud",
|
||||||
|
"short_description": "The Nextcloud app that just works: accounts, locks, offline sync, sharing.",
|
||||||
|
"description": "Noo is a simple, dependable client for your own Nextcloud server. You host it; Noo makes it effortless for everyone who uses it.\n\nMULTIPLE ACCOUNTS\nKeep your personal server, your work instance and the family box signed in at once and switch in one tap. Each account keeps its own sync scope, cache and favorites.\n\nLOCKS WHERE YOU WANT THEM\nProtect opening the app, switching accounts and revealing hidden files with your device's own PIN, pattern or biometric. Noo never stores or sees your PIN.\n\nOFFLINE AND BACKGROUND SYNC\nMirror a few folders, or the whole account, to your device and keep reading and previewing with no connection. Background sync tops them up, on Wi-Fi only unless you say otherwise, and tells you when something conflicts.\n\nSHARING THAT FEELS LIKE NEXTCLOUD\nInvite people or groups with a permission pill, switch a public link on and copy it, or send the file itself straight to another app.\n\nEXTERNAL STORAGE, BUILT IN\nFolders your admin mounts through Nextcloud's External storage app (SMB, S3, SFTP and more) appear in Files like any other folder.\n\nMAKE IT YOURS\nPin your favorite tabs, order the action bar, choose swipe actions, and adjust the theme and navigation around how you use your cloud.\n\nPRIVATE BY DESIGN\nNoo never asks for your password: sign-in uses your server's own login page (Login Flow v2) and a revocable app token. The app talks only to your server. No analytics, no trackers, no ads.\n\nRequires a Nextcloud server. Noo is an independent, unofficial client; Nextcloud is a trademark of Nextcloud GmbH."
|
||||||
|
},
|
||||||
|
"app_store": {
|
||||||
|
"name": "NooCloud",
|
||||||
|
"subtitle": "The Nextcloud app that works",
|
||||||
|
"promotional_text": "Multiple accounts, app locks, offline sync, sharing and external storage for your own Nextcloud. No analytics, no trackers.",
|
||||||
|
"keywords": "nextcloud,files,photos,offline,sync,self-hosted,storage,cloud,share,webdav",
|
||||||
|
"description": "Noo is a simple, dependable client for your own Nextcloud server. You host it; Noo makes it effortless for everyone who uses it, on iPhone and iPad.\n\nMULTIPLE ACCOUNTS\nKeep your personal server, your work instance and the family box signed in at once and switch in one tap. Each account keeps its own sync scope, cache and favorites.\n\nLOCKS WHERE YOU WANT THEM\nProtect opening the app, switching accounts and revealing hidden files with Face ID, Touch ID or your device passcode. Noo never stores or sees your passcode.\n\nOFFLINE AND BACKGROUND SYNC\nMirror a few folders, or the whole account, to your device and keep opening and previewing files with no connection. iOS decides when background sync can run, so timing is opportunistic rather than on a fixed schedule. Noo tells you when something conflicts.\n\nSHARING THAT FEELS LIKE NEXTCLOUD\nInvite people or groups with a permission pill, switch a public link on and copy it, or send the file itself straight to another app.\n\nEXTERNAL STORAGE, BUILT IN\nFolders your admin mounts through Nextcloud's External storage app (SMB, S3, SFTP and more) appear in Files like any other folder.\n\nMAKE IT YOURS\nPin your favorite tabs, order the action bar, choose swipe actions, and adjust the theme and navigation around how you use your cloud.\n\nPRIVATE BY DESIGN\nNoo never asks for your password: sign-in uses your server's own login page (Login Flow v2) and a revocable app token. The app talks only to your server. No analytics, no trackers, no ads.\n\nRequires a Nextcloud server. Noo is an independent, unofficial client; Nextcloud is a trademark of Nextcloud GmbH."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,566 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"file": "android/phone/01-accounts.png",
|
||||||
|
"size": [
|
||||||
|
1080,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/phone/02-locks.png",
|
||||||
|
"size": [
|
||||||
|
1080,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "locks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/phone/03-sync.png",
|
||||||
|
"size": [
|
||||||
|
1080,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/phone/04-sharing.png",
|
||||||
|
"size": [
|
||||||
|
1080,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/phone/05-external.png",
|
||||||
|
"size": [
|
||||||
|
1080,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "external"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in/01-accounts.png",
|
||||||
|
"size": [
|
||||||
|
1200,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in/02-locks.png",
|
||||||
|
"size": [
|
||||||
|
1200,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "locks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in/03-sync.png",
|
||||||
|
"size": [
|
||||||
|
1200,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in/04-sharing.png",
|
||||||
|
"size": [
|
||||||
|
1200,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in/05-external.png",
|
||||||
|
"size": [
|
||||||
|
1200,
|
||||||
|
1920
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "external"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in/01-accounts.png",
|
||||||
|
"size": [
|
||||||
|
1600,
|
||||||
|
2560
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in/02-locks.png",
|
||||||
|
"size": [
|
||||||
|
1600,
|
||||||
|
2560
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "locks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in/03-sync.png",
|
||||||
|
"size": [
|
||||||
|
1600,
|
||||||
|
2560
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in/04-sharing.png",
|
||||||
|
"size": [
|
||||||
|
1600,
|
||||||
|
2560
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in/05-external.png",
|
||||||
|
"size": [
|
||||||
|
1600,
|
||||||
|
2560
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "external"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/iphone/01-accounts.png",
|
||||||
|
"size": [
|
||||||
|
1290,
|
||||||
|
2796
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/iphone/02-locks.png",
|
||||||
|
"size": [
|
||||||
|
1290,
|
||||||
|
2796
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "locks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/iphone/03-sync.png",
|
||||||
|
"size": [
|
||||||
|
1290,
|
||||||
|
2796
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/iphone/04-sharing.png",
|
||||||
|
"size": [
|
||||||
|
1290,
|
||||||
|
2796
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/iphone/05-external.png",
|
||||||
|
"size": [
|
||||||
|
1290,
|
||||||
|
2796
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "external"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad/01-accounts.png",
|
||||||
|
"size": [
|
||||||
|
2064,
|
||||||
|
2752
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad/02-locks.png",
|
||||||
|
"size": [
|
||||||
|
2064,
|
||||||
|
2752
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "locks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad/03-sync.png",
|
||||||
|
"size": [
|
||||||
|
2064,
|
||||||
|
2752
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad/04-sharing.png",
|
||||||
|
"size": [
|
||||||
|
2064,
|
||||||
|
2752
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad/05-external.png",
|
||||||
|
"size": [
|
||||||
|
2064,
|
||||||
|
2752
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "external"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in-landscape/01-accounts.png",
|
||||||
|
"size": [
|
||||||
|
1920,
|
||||||
|
1200
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in-landscape/02-locks.png",
|
||||||
|
"size": [
|
||||||
|
1920,
|
||||||
|
1200
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "locks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in-landscape/03-sync.png",
|
||||||
|
"size": [
|
||||||
|
1920,
|
||||||
|
1200
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in-landscape/04-sharing.png",
|
||||||
|
"size": [
|
||||||
|
1920,
|
||||||
|
1200
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-7in-landscape/05-external.png",
|
||||||
|
"size": [
|
||||||
|
1920,
|
||||||
|
1200
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "external"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in-landscape/01-accounts.png",
|
||||||
|
"size": [
|
||||||
|
2560,
|
||||||
|
1600
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in-landscape/02-locks.png",
|
||||||
|
"size": [
|
||||||
|
2560,
|
||||||
|
1600
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "locks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in-landscape/03-sync.png",
|
||||||
|
"size": [
|
||||||
|
2560,
|
||||||
|
1600
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in-landscape/04-sharing.png",
|
||||||
|
"size": [
|
||||||
|
2560,
|
||||||
|
1600
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/tablet-10in-landscape/05-external.png",
|
||||||
|
"size": [
|
||||||
|
2560,
|
||||||
|
1600
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "external"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad-landscape/01-accounts.png",
|
||||||
|
"size": [
|
||||||
|
2752,
|
||||||
|
2064
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad-landscape/02-locks.png",
|
||||||
|
"size": [
|
||||||
|
2752,
|
||||||
|
2064
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "locks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad-landscape/03-sync.png",
|
||||||
|
"size": [
|
||||||
|
2752,
|
||||||
|
2064
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad-landscape/04-sharing.png",
|
||||||
|
"size": [
|
||||||
|
2752,
|
||||||
|
2064
|
||||||
|
],
|
||||||
|
"mode": "RGB",
|
||||||
|
"story": "sharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/ipad-landscape/05-external.png",
|
||||||
|
"size": [
|
||||||
|
2752,
|
||||||
|
2064
|
||||||
|
],
|
||||||
|
"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": [
|
||||||
|
512,
|
||||||
|
512
|
||||||
|
],
|
||||||
|
"mode": "RGBA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ios/icon-1024.png",
|
||||||
|
"size": [
|
||||||
|
1024,
|
||||||
|
1024
|
||||||
|
],
|
||||||
|
"mode": "RGB"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "android/feature-graphic-1024x500.png",
|
||||||
|
"size": [
|
||||||
|
1024,
|
||||||
|
500
|
||||||
|
],
|
||||||
|
"mode": "RGB"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
After Width: | Height: | Size: 172 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 194 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 192 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 274 KiB |
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 289 KiB |
|
After Width: | Height: | Size: 149 KiB |
|
After Width: | Height: | Size: 252 KiB |
|
After Width: | Height: | Size: 255 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 320 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 222 KiB |