diff --git a/distribution/store-assets/README.md b/distribution/store-assets/README.md
index 5c0f5e9..5e561f3 100644
--- a/distribution/store-assets/README.md
+++ b/distribution/store-assets/README.md
@@ -12,6 +12,11 @@ involved. The five screenshots follow the Features section of the website
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.
@@ -26,6 +31,9 @@ Schibsted Grotesk / Instrument Sans), flat shapes, alternating light and dark.
| 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 |
| iOS icon reference | `ios/icon-1024.png` | 1024 × 1024 |
Upload in numeric order. The App Store uses the icon embedded in the uploaded
diff --git a/distribution/store-assets/android/tablet-10in-landscape/01-accounts.png b/distribution/store-assets/android/tablet-10in-landscape/01-accounts.png
new file mode 100644
index 0000000..66259fe
Binary files /dev/null and b/distribution/store-assets/android/tablet-10in-landscape/01-accounts.png differ
diff --git a/distribution/store-assets/android/tablet-10in-landscape/02-locks.png b/distribution/store-assets/android/tablet-10in-landscape/02-locks.png
new file mode 100644
index 0000000..3a15b1f
Binary files /dev/null and b/distribution/store-assets/android/tablet-10in-landscape/02-locks.png differ
diff --git a/distribution/store-assets/android/tablet-10in-landscape/03-sync.png b/distribution/store-assets/android/tablet-10in-landscape/03-sync.png
new file mode 100644
index 0000000..2165003
Binary files /dev/null and b/distribution/store-assets/android/tablet-10in-landscape/03-sync.png differ
diff --git a/distribution/store-assets/android/tablet-10in-landscape/04-sharing.png b/distribution/store-assets/android/tablet-10in-landscape/04-sharing.png
new file mode 100644
index 0000000..6fa0c79
Binary files /dev/null and b/distribution/store-assets/android/tablet-10in-landscape/04-sharing.png differ
diff --git a/distribution/store-assets/android/tablet-10in-landscape/05-external.png b/distribution/store-assets/android/tablet-10in-landscape/05-external.png
new file mode 100644
index 0000000..e213a27
Binary files /dev/null and b/distribution/store-assets/android/tablet-10in-landscape/05-external.png differ
diff --git a/distribution/store-assets/android/tablet-7in-landscape/01-accounts.png b/distribution/store-assets/android/tablet-7in-landscape/01-accounts.png
new file mode 100644
index 0000000..caa456d
Binary files /dev/null and b/distribution/store-assets/android/tablet-7in-landscape/01-accounts.png differ
diff --git a/distribution/store-assets/android/tablet-7in-landscape/02-locks.png b/distribution/store-assets/android/tablet-7in-landscape/02-locks.png
new file mode 100644
index 0000000..4c6fe2d
Binary files /dev/null and b/distribution/store-assets/android/tablet-7in-landscape/02-locks.png differ
diff --git a/distribution/store-assets/android/tablet-7in-landscape/03-sync.png b/distribution/store-assets/android/tablet-7in-landscape/03-sync.png
new file mode 100644
index 0000000..1003540
Binary files /dev/null and b/distribution/store-assets/android/tablet-7in-landscape/03-sync.png differ
diff --git a/distribution/store-assets/android/tablet-7in-landscape/04-sharing.png b/distribution/store-assets/android/tablet-7in-landscape/04-sharing.png
new file mode 100644
index 0000000..05bcf27
Binary files /dev/null and b/distribution/store-assets/android/tablet-7in-landscape/04-sharing.png differ
diff --git a/distribution/store-assets/android/tablet-7in-landscape/05-external.png b/distribution/store-assets/android/tablet-7in-landscape/05-external.png
new file mode 100644
index 0000000..3ac06fb
Binary files /dev/null and b/distribution/store-assets/android/tablet-7in-landscape/05-external.png differ
diff --git a/distribution/store-assets/contact-sheet.jpg b/distribution/store-assets/contact-sheet.jpg
index 6ec37a8..de18163 100644
Binary files a/distribution/store-assets/contact-sheet.jpg and b/distribution/store-assets/contact-sheet.jpg differ
diff --git a/distribution/store-assets/index.html b/distribution/store-assets/index.html
index 75f9d4f..a8c914d 100644
--- a/distribution/store-assets/index.html
+++ b/distribution/store-assets/index.html
@@ -1 +1 @@
-
Noo store assetsNoo / 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/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 assetsNoo / 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
diff --git a/distribution/store-assets/ios/ipad-landscape/01-accounts.png b/distribution/store-assets/ios/ipad-landscape/01-accounts.png
new file mode 100644
index 0000000..5bf177b
Binary files /dev/null and b/distribution/store-assets/ios/ipad-landscape/01-accounts.png differ
diff --git a/distribution/store-assets/ios/ipad-landscape/02-locks.png b/distribution/store-assets/ios/ipad-landscape/02-locks.png
new file mode 100644
index 0000000..17d2f2e
Binary files /dev/null and b/distribution/store-assets/ios/ipad-landscape/02-locks.png differ
diff --git a/distribution/store-assets/ios/ipad-landscape/03-sync.png b/distribution/store-assets/ios/ipad-landscape/03-sync.png
new file mode 100644
index 0000000..48a180a
Binary files /dev/null and b/distribution/store-assets/ios/ipad-landscape/03-sync.png differ
diff --git a/distribution/store-assets/ios/ipad-landscape/04-sharing.png b/distribution/store-assets/ios/ipad-landscape/04-sharing.png
new file mode 100644
index 0000000..7fd2b70
Binary files /dev/null and b/distribution/store-assets/ios/ipad-landscape/04-sharing.png differ
diff --git a/distribution/store-assets/ios/ipad-landscape/05-external.png b/distribution/store-assets/ios/ipad-landscape/05-external.png
new file mode 100644
index 0000000..d830d16
Binary files /dev/null and b/distribution/store-assets/ios/ipad-landscape/05-external.png differ
diff --git a/distribution/store-assets/manifest.json b/distribution/store-assets/manifest.json
index 8ce3fc0..fc0386d 100644
--- a/distribution/store-assets/manifest.json
+++ b/distribution/store-assets/manifest.json
@@ -224,6 +224,141 @@
"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": "android/icon-512.png",
"size": [
diff --git a/distribution/store-assets/source/android/security.png b/distribution/store-assets/source/android/security.png
index b946aa2..5dba3d1 100644
Binary files a/distribution/store-assets/source/android/security.png and b/distribution/store-assets/source/android/security.png differ
diff --git a/distribution/store-assets/source/android/sync.png b/distribution/store-assets/source/android/sync.png
index 203202d..58bdff6 100644
Binary files a/distribution/store-assets/source/android/sync.png and b/distribution/store-assets/source/android/sync.png differ
diff --git a/distribution/store-assets/source/atablet/security.png b/distribution/store-assets/source/atablet/security.png
index 4131ed9..53a3965 100644
Binary files a/distribution/store-assets/source/atablet/security.png and b/distribution/store-assets/source/atablet/security.png differ
diff --git a/distribution/store-assets/source/atablet/sync.png b/distribution/store-assets/source/atablet/sync.png
index f116677..a3895b9 100644
Binary files a/distribution/store-assets/source/atablet/sync.png and b/distribution/store-assets/source/atablet/sync.png differ
diff --git a/distribution/store-assets/source/atabletl/accounts.png b/distribution/store-assets/source/atabletl/accounts.png
new file mode 100644
index 0000000..8f5241d
Binary files /dev/null and b/distribution/store-assets/source/atabletl/accounts.png differ
diff --git a/distribution/store-assets/source/atabletl/external.png b/distribution/store-assets/source/atabletl/external.png
new file mode 100644
index 0000000..6698f32
Binary files /dev/null and b/distribution/store-assets/source/atabletl/external.png differ
diff --git a/distribution/store-assets/source/atabletl/lock.png b/distribution/store-assets/source/atabletl/lock.png
new file mode 100644
index 0000000..3930f4c
Binary files /dev/null and b/distribution/store-assets/source/atabletl/lock.png differ
diff --git a/distribution/store-assets/source/atabletl/offline.png b/distribution/store-assets/source/atabletl/offline.png
new file mode 100644
index 0000000..46f3094
Binary files /dev/null and b/distribution/store-assets/source/atabletl/offline.png differ
diff --git a/distribution/store-assets/source/atabletl/security.png b/distribution/store-assets/source/atabletl/security.png
new file mode 100644
index 0000000..99b3cc7
Binary files /dev/null and b/distribution/store-assets/source/atabletl/security.png differ
diff --git a/distribution/store-assets/source/atabletl/sharing.png b/distribution/store-assets/source/atabletl/sharing.png
new file mode 100644
index 0000000..0d0d911
Binary files /dev/null and b/distribution/store-assets/source/atabletl/sharing.png differ
diff --git a/distribution/store-assets/source/atabletl/sync.png b/distribution/store-assets/source/atabletl/sync.png
new file mode 100644
index 0000000..0d8d1dd
Binary files /dev/null and b/distribution/store-assets/source/atabletl/sync.png differ
diff --git a/distribution/store-assets/source/ipad/security.png b/distribution/store-assets/source/ipad/security.png
index 4131ed9..53a3965 100644
Binary files a/distribution/store-assets/source/ipad/security.png and b/distribution/store-assets/source/ipad/security.png differ
diff --git a/distribution/store-assets/source/ipad/sync.png b/distribution/store-assets/source/ipad/sync.png
index f116677..a3895b9 100644
Binary files a/distribution/store-assets/source/ipad/sync.png and b/distribution/store-assets/source/ipad/sync.png differ
diff --git a/distribution/store-assets/source/ipadl/accounts.png b/distribution/store-assets/source/ipadl/accounts.png
new file mode 100644
index 0000000..4fe808e
Binary files /dev/null and b/distribution/store-assets/source/ipadl/accounts.png differ
diff --git a/distribution/store-assets/source/ipadl/external.png b/distribution/store-assets/source/ipadl/external.png
new file mode 100644
index 0000000..2bb4026
Binary files /dev/null and b/distribution/store-assets/source/ipadl/external.png differ
diff --git a/distribution/store-assets/source/ipadl/lock.png b/distribution/store-assets/source/ipadl/lock.png
new file mode 100644
index 0000000..3930f4c
Binary files /dev/null and b/distribution/store-assets/source/ipadl/lock.png differ
diff --git a/distribution/store-assets/source/ipadl/offline.png b/distribution/store-assets/source/ipadl/offline.png
new file mode 100644
index 0000000..46f3094
Binary files /dev/null and b/distribution/store-assets/source/ipadl/offline.png differ
diff --git a/distribution/store-assets/source/ipadl/security.png b/distribution/store-assets/source/ipadl/security.png
new file mode 100644
index 0000000..99b3cc7
Binary files /dev/null and b/distribution/store-assets/source/ipadl/security.png differ
diff --git a/distribution/store-assets/source/ipadl/sharing.png b/distribution/store-assets/source/ipadl/sharing.png
new file mode 100644
index 0000000..0184f70
Binary files /dev/null and b/distribution/store-assets/source/ipadl/sharing.png differ
diff --git a/distribution/store-assets/source/ipadl/sync.png b/distribution/store-assets/source/ipadl/sync.png
new file mode 100644
index 0000000..0d8d1dd
Binary files /dev/null and b/distribution/store-assets/source/ipadl/sync.png differ
diff --git a/distribution/store-assets/source/iphone/security.png b/distribution/store-assets/source/iphone/security.png
index bea1042..5dba3d1 100644
Binary files a/distribution/store-assets/source/iphone/security.png and b/distribution/store-assets/source/iphone/security.png differ
diff --git a/distribution/store-assets/source/iphone/sync.png b/distribution/store-assets/source/iphone/sync.png
index 757ca6a..58bdff6 100644
Binary files a/distribution/store-assets/source/iphone/sync.png and b/distribution/store-assets/source/iphone/sync.png differ
diff --git a/distribution/store-assets/store-listing-assets.zip b/distribution/store-assets/store-listing-assets.zip
index 8530a63..ec8aaa7 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/capture_test.dart b/distribution/store-assets/tools/capture_test.dart
index ac51c95..baa8062 100644
--- a/distribution/store-assets/tools/capture_test.dart
+++ b/distribution/store-assets/tools/capture_test.dart
@@ -11,6 +11,10 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
+import 'package:noo/main.dart' show MainShellView;
+import 'package:noo/providers/recent_controller.dart';
+import 'package:noo/providers/shares_controller.dart';
+import 'package:noo/providers/trash_controller.dart';
import 'package:noo/models/app_tab.dart';
import 'package:noo/theme/design_tokens.dart';
import 'package:noo/views/lock_screen_view.dart';
@@ -169,10 +173,26 @@ class DemoOps extends ItemOperations {
Future> searchSharees(String query) async => [];
}
+/// The shell collapses to the Offline tab alone when it thinks there is no
+/// network, so the landscape (full shell) captures report an online device.
+class DemoConnectivity extends ConnectivityController {
+ @override
+ bool get isOffline => false;
+}
+
class DemoFiles extends FilesController {
DemoFiles(super.session, {this.external = false});
final bool external;
@override
+ NextcloudUserQuota? get quota => const NextcloudUserQuota(
+ usedBytes: 46000000000,
+ totalBytes: 107374182400,
+ usagePercentage: 0.43,
+ userName: 'alex',
+ email: 'alex@cloud.example.com',
+ serverVersion: '31.0.0',
+ );
+ @override
StorageScope get storageScope =>
external ? StorageScope.all : StorageScope.cloud;
@override
@@ -329,12 +349,31 @@ void main() {
MockStreamHandler.inline(onListen: (arguments, events) {}),
);
}
+ // The shell listens for share/pick intents; none ever arrive here.
+ for (final name in [
+ 'dev.ayushya.noo/share_intent/new',
+ 'dev.ayushya.noo/pick_intent/new',
+ ]) {
+ messenger.setMockStreamHandler(
+ EventChannel(name),
+ MockStreamHandler.inline(onListen: (arguments, events) {}),
+ );
+ }
messenger.setMockStreamHandler(
const EventChannel('dev.fluttercommunity.plus/connectivity_status'),
MockStreamHandler.inline(onListen: (arguments, events) {}),
);
});
- for (final device in ['android', 'atablet', 'iphone', 'ipad']) {
+ // `ipadl` / `atabletl` are the landscape tablet captures, which render the
+ // app's real shell (sidebar + toolbar) instead of the single-screen widgets.
+ for (final device in [
+ 'android',
+ 'atablet',
+ 'atabletl',
+ 'iphone',
+ 'ipad',
+ 'ipadl',
+ ]) {
for (final screen in [
'accounts',
'lock',
@@ -353,17 +392,27 @@ void main() {
'ui_lock_account_switching': true,
'ui_lock_hidden_files': true,
'ui_use_dynamic_color': false,
+ // Skips the shell's one-time notification-permission prompt.
+ 'notification_permission_asked': true,
});
- final tablet = device == 'ipad' || device == 'atablet';
- final android = device == 'android' || device == 'atablet';
- final size = tablet
+ final landscape = device == 'ipadl' || device == 'atabletl';
+ final tablet = landscape || device == 'ipad' || device == 'atablet';
+ final android =
+ device == 'android' ||
+ device == 'atablet' ||
+ device == 'atabletl';
+ final size = landscape
+ ? const Size(1024, 768)
+ : tablet
? const Size(768, 1024)
: (android ? const Size(430, 800) : const Size(430, 932));
tester.view.devicePixelRatio = 1;
tester.view.physicalSize = size;
await tester.binding.setSurfaceSize(size);
final key = GlobalKey();
- final connectivity = ConnectivityController();
+ final connectivity = landscape
+ ? DemoConnectivity()
+ : ConnectivityController();
final session = DemoSession(connectivity);
final files = DemoFiles(session, external: screen == 'external');
final settings = SettingsController();
@@ -378,6 +427,12 @@ void main() {
photos: photos,
favorites: favorites,
);
+ final trash = TrashController(session);
+ final shares = SharesController(session);
+ final recent = RecentController(session);
+ if (landscape && screen == 'offline') {
+ settings.requestTab(AppTab.offline);
+ }
final scroll = ScrollController();
final style = android ? NooNavStyle.android : NooNavStyle.ios;
final browsing = const {
@@ -412,6 +467,12 @@ void main() {
ChangeNotifierProvider.value(value: offline),
ChangeNotifierProvider.value(value: pick),
ChangeNotifierProvider.value(value: photos),
+ ChangeNotifierProvider.value(
+ value: favorites,
+ ),
+ ChangeNotifierProvider.value(value: trash),
+ ChangeNotifierProvider.value(value: shares),
+ ChangeNotifierProvider.value(value: recent),
Provider.value(value: ops),
],
child: MaterialApp(
@@ -423,6 +484,8 @@ void main() {
card ? child! : RepaintBoundary(key: key, child: child),
home: screen == 'lock'
? const LockScreenView()
+ : landscape && browsing
+ ? const MainShellView()
: Scaffold(
body: browsing
? FilesView(
@@ -438,16 +501,27 @@ void main() {
)
: Align(
alignment: Alignment.topCenter,
- child: Builder(
- builder: (context) => RepaintBoundary(
- key: key,
- child: ColoredBox(
- color: context.nooColors.bg,
- child: Padding(
- padding: const EdgeInsets.all(12),
- child: screen == 'security'
- ? const SettingsSecuritySection()
- : const SettingsFileSyncSection(),
+ child: ConstrainedBox(
+ // Landscape tablets would stretch the card
+ // across the whole window; keep it phone-like.
+ constraints: BoxConstraints(
+ maxWidth: landscape ? 520 : double.infinity,
+ ),
+ child: Builder(
+ builder: (context) => RepaintBoundary(
+ key: key,
+ child: ColoredBox(
+ color: context.nooColors.bg,
+ child: Padding(
+ padding: const EdgeInsets.all(12),
+ // The desktop-style card fills its
+ // height, so size it to its content.
+ child: IntrinsicHeight(
+ child: screen == 'security'
+ ? const SettingsSecuritySection()
+ : const SettingsFileSyncSection(),
+ ),
+ ),
),
),
),
@@ -514,6 +588,9 @@ void main() {
});
await tester.pumpWidget(const SizedBox.shrink());
scroll.dispose();
+ trash.dispose();
+ shares.dispose();
+ recent.dispose();
pick.dispose();
offline.dispose();
sync.dispose();
diff --git a/distribution/store-assets/tools/compose.py b/distribution/store-assets/tools/compose.py
index 6601cb3..2aa2323 100644
--- a/distribution/store-assets/tools/compose.py
+++ b/distribution/store-assets/tools/compose.py
@@ -31,7 +31,7 @@ STORIES = [
eyebrow='MULTIPLE ACCOUNTS',
lines=('Every cloud,', 'one tap apart.'),
sub='Personal, work and family servers together.'),
- dict(key='locks', theme='dark', back='lock', front='security', card_at=.66,
+ dict(key='locks', theme='dark', back='lock', front='security', card_at=.66, card_at_l=.66,
eyebrow='LOCKS',
lines=('Locks where', 'you want them.'),
sub='Protect opening Noo, switching accounts and hidden files with your device PIN or biometrics.'),
@@ -56,6 +56,10 @@ TARGETS = [
('android/tablet-10in', 'atablet', (1600, 2560), 'tablet'),
('ios/iphone', 'iphone', (1290, 2796), 'phone'),
('ios/ipad', 'ipad', (2064, 2752), 'tablet'),
+ # Landscape tablets show the app's real sidebar layout.
+ ('android/tablet-7in-landscape', 'atabletl', (1920, 1200), 'landscape'),
+ ('android/tablet-10in-landscape', 'atabletl', (2560, 1600), 'landscape'),
+ ('ios/ipad-landscape', 'ipadl', (2752, 2064), 'landscape'),
]
@@ -127,7 +131,51 @@ def paste_panel(canvas, source, box, radius, t, bleed=False):
return x, y, sw, sh
+def landscape_canvas(story, size, device):
+ """Text column on the left, the real tablet UI on the right."""
+ t = THEMES[story['theme']]
+ w, h = size
+ im = background(size, t)
+ d = ImageDraw.Draw(im)
+ margin = round(h * .07)
+ colw = round(w * .30)
+ y = round(h * .27)
+ spaced(d, (margin, y), story['eyebrow'], font(round(h * .022), 'Bold', 'InstrumentSans'),
+ t['accent_text'], h * .004)
+ y += round(h * .06)
+ head = round(h * .068)
+ for index, line in enumerate(story['lines']):
+ fnt, _ = fit(d, line, font, head, colw)
+ d.text((margin, y), line, font=fnt, fill=t['accent_text'] if index else t['fg'])
+ y += round(head * 1.12)
+ y += round(head * .2)
+ sub_size = round(h * .030)
+ fnt = body_font(sub_size, 'Regular')
+ for line in textwrap.wrap(story['sub'], max(16, int(colw / (sub_size * .52)))):
+ d.text((margin, y), line, font=fnt, fill=t['fg2'])
+ y += round(sub_size * 1.4)
+ x0 = margin + colw + round(w * .035)
+ src = lambda name: OUT / f'source/{device}/{name}.png'
+ back = Image.open(src(story['back']))
+ aw, ah = w - x0 - margin, h - margin * 2
+ factor = min(aw / back.width, ah / back.height)
+ # Centered vertically; a layered card hangs below the panel's bottom edge.
+ area = (x0, round((h - back.height * factor) / 2) - (round(h * .03) if story['front'] else 0), aw, ah)
+ radius = round(h * .03)
+ bx, by, bw, bh = paste_panel(im, src(story['back']), area, radius, t)
+ if story['front']:
+ card = content_crop(src(story['front']))
+ scale = bw / Image.open(src(story['back'])).width
+ cw, ch = round(card.width * scale), round(card.height * scale)
+ cx = bx + round(bw * .40)
+ cy = by + round(bh * story.get('card_at_l', story['card_at']))
+ paste_panel(im, card, (cx, cy, cw, ch), round(radius * .6), t)
+ return im
+
+
def story_canvas(story, size, kind, device):
+ if kind == 'landscape':
+ return landscape_canvas(story, size, device)
t = THEMES[story['theme']]
w, h = size
im = background(size, t)
@@ -218,11 +266,12 @@ for asset in manifest:
(OUT / 'manifest.json').write_text(json.dumps(manifest, indent=2) + '\n')
# Review materials (not for upload): contact sheet and a gallery page.
-contact = Image.new('RGB', (1920, 1500), '#1c1b18')
+contact = Image.new('RGB', (1920, 2160), '#1c1b18')
cd = ImageDraw.Draw(contact)
cd.text((32, 20), 'Noo / store listing artwork', font=font(28), fill='#F3EFE6')
rows = [('ANDROID PHONE', 'android/phone'), ('ANDROID 10" TABLET', 'android/tablet-10in'),
- ('IPHONE', 'ios/iphone'), ('IPAD', 'ios/ipad')]
+ ('IPHONE', 'ios/iphone'), ('IPAD', 'ios/ipad'),
+ ('ANDROID 10" LANDSCAPE', 'android/tablet-10in-landscape'), ('IPAD LANDSCAPE', 'ios/ipad-landscape')]
for row, (label, folder) in enumerate(rows):
cd.text((32, 75 + row * 360), label, font=font(15, 'Bold', 'InstrumentSans'), fill='#CBA5FD')
for col, path in enumerate(sorted((OUT / folder).glob('*.png'))):