7 Commits
Author SHA1 Message Date
Ayushya AmitabhandClaude Sonnet 5.5 660d0bc869 Store assets: App Store header, search results, iPhone 6.3 and foldable sizes
Check PR / check (pull_request) Successful in 59s
Adds ios/header, ios/search-results, ios/iphone-6.3in and ios/iphone-fold-*
to compose.py and the README upload table.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 22:58:49 -04:00
Ayushya AmitabhandClaude Sonnet 5.5 5837464581 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>
2026-10-07 21:46:29 -04:00
Ayushya AmitabhandClaude Sonnet 5.5 11b3d535a9 Store listing assets for the five website features (accounts, locks, offline sync, sharing, external storage)
iPhone, iPad, Android phone and 7/10-inch tablet screenshots, Play feature
graphic and icon, and draft listing copy, generated from real app widgets.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 21:32:01 -04:00
Ayushya Amitabh d92bf04a7d Add action bar preview and all swipe actions; rename App lock 2026-10-07 21:04:50 -04:00
Ayushya AmitabhandClaude Sonnet 5.5 86e5e599b6 CI: pin iOS signing certificate by SHA-1 and log CI keychain identities
Build iOS / build (push) Successful in 4m0s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:36:29 -04:00
Ayushya AmitabhandClaude Sonnet 5.5 0ea98363de CI: split release tags - RC-Android-* (APK), RC-iOS-* (iOS), Release-* (both)
Build iOS / build (push) Failing after 1m55s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:15:29 -04:00
Ayushya AmitabhandClaude Sonnet 5.5 ca4afb2ed7 CI: signed iOS build and TestFlight upload on Release tags
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 19:04:39 -04:00
130 changed files with 2105 additions and 92 deletions
@@ -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.
**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.
- 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
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 |
| 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. |
| Biometric label | "Lock with Face ID" | "Lock with fingerprint" |
| App lock label | "App lock" | "App lock" |
### 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,
share, download, delete, copy, move, rename, sync, details) - the
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
Mobile is a two-level menu, the way native iOS/Android Settings apps
+5 -3
View File
@@ -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
CI env vars (`RELEASE_KEYSTORE_PATH`/`_PASSWORD`, `RELEASE_KEY_ALIAS`/
`_PASSWORD`, set from the same repo secrets by both `.gitea/workflows/
build.yml`, triggered by `RC*` tags and producing a sideloadable APK, and
`.gitea/workflows/release.yml`, triggered by `Release-*` tags and producing
the `.aab` Play Console wants), then falls back to the debug key if neither
build.yml`, triggered by `RC-Android-*` tags and producing a sideloadable
APK, and `.gitea/workflows/release.yml`, triggered by `Release-*` tags and
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
`key.properties` locally and the Gitea secrets, local release builds and
CI-built release APKs share one signature, so `adb install -r` works
+11
View File
@@ -111,6 +111,17 @@ Gotchas:
in one gesture, it's not tap-only anymore.
- Window chrome (macOS traffic lights, the Windows 40px title bar) isn't
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
`Theme.of(context).colorScheme` - the latter is Flutter's own Material 3
scheme, reseeded by the user's accent color choice (`AppTheme.light`/
+31
View File
@@ -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
+6 -5
View File
@@ -1,12 +1,13 @@
name: Build APK
# Deliberately not "on every push" - only when a release-candidate tag
# (RC1, RC2, RC2026.1, ...) is pushed. Tag the commit you want built:
# git tag RC1 && git push origin RC1
# Deliberately not "on every push" - only when an Android release-candidate
# tag (RC-Android-1, RC-Android-2, ...) is pushed. Tag the commit you want built:
# 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:
push:
tags:
- "RC*"
- "RC-Android-*"
jobs:
build:
@@ -72,7 +73,7 @@ jobs:
# talks to this same Gitea instance automatically via the
# `github.token`/`github.server_url` context Gitea Actions
# 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
with:
files: ${{ env.APK_PATH }}
+103
View File
@@ -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"
+2 -2
View File
@@ -3,7 +3,7 @@ name: Build App Bundle
# 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:
# 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.
on:
push:
@@ -56,7 +56,7 @@ jobs:
run: flutter analyze
- 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
# android/app/build.gradle.kts.
run: echo "$RELEASE_KEYSTORE_BASE64" | base64 -d > "${{ runner.temp }}/release-keystore.jks"
+87
View File
@@ -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.
Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 455 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

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."
}
}
+566
View File
@@ -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"
}
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Some files were not shown because too many files have changed in this diff Show More