diff --git a/android/PLAY.md b/android/PLAY.md index 84b2874..6e4bed1 100644 --- a/android/PLAY.md +++ b/android/PLAY.md @@ -44,8 +44,8 @@ changes that page in the same pull request; it changes the - [ ] **The place-name packs** are live as the `place-packs` release. They are published by the Landmarks workflow, run by hand. - [ ] **Store listing, graphics and screenshots**, as [below](#store-listing). - The icon, the feature graphic and the screenshots, phone, tablet and watch, - are made. + The icon, the feature graphic and the screenshots, phone, 7-inch and 10-inch + tablet, and watch, are made. - [ ] **App content**: the privacy policy, ads, app access, content rating, target audience and Data safety, as [below](#app-content). - [ ] **Form factors.** The watch and the car are opted in separately, under @@ -127,17 +127,20 @@ address the site is run from. | App icon | 512 by 512, 32-bit PNG, at most 1,024 KB | [`web/public/icon-512.png`](../web/public/icon-512.png): a full, opaque square from `design/build-icons.mjs` | | Feature graphic | 1024 by 500, JPEG or 24-bit PNG with no alpha | [`play/feature-graphic.png`](play/feature-graphic.png): the same four bars on the same ground, from the same script, with no words | | Phone screenshots | 2 to 8; the long side at most twice the short; four at 9:16 and 1080 or more to be eligible for promotion | six in [`play/screenshots/phone`](play/screenshots/phone), 1080 by 1920: a place on the map, search by name, the short form anchored to a landmark, saved places, the emergency card and the QR code | -| Tablet screenshots | 4 or more to be shown for tablets, 1080 to 7680 pixels, 16:9 or 9:16 | four in [`play/screenshots/tablet`](play/screenshots/tablet), 1920 by 1080, the wide layout: a place, search by name beside the map, the short form anchored, and the dark theme over its night basemap | +| 7-inch tablet screenshots | 4 or more to be shown for tablets, 1080 to 7680 pixels, 16:9 or 9:16 | four in [`play/screenshots/tablet-7`](play/screenshots/tablet-7), 1920 by 1080 drawn at 1067 by 600 dp, as a 7-inch tablet on its side draws them: the same four screens as the 10-inch set | +| 10-inch tablet screenshots | the same | four in [`play/screenshots/tablet-10`](play/screenshots/tablet-10), 1920 by 1080 drawn at 1280 by 720 dp, the wide layout: a place, search by name beside the map, the short form anchored, and the dark theme over its night basemap | | Wear OS screenshots | at least 384 by 384, square | four in [`play/screenshots/wear`](play/screenshots/wear), 454 by 454: the code where the watch is, saved places, walking to one, and the tile | All are 24-bit PNG with no alpha, as Play asks. A phone that draws at 1080 by 2400, as many do, is more than twice as long as it is wide, and its screenshots -are refused, so these were taken with the screen set to 9:16, and the tablet's -with a 16:9 screen at a tablet's density: +are refused, so these were taken with the screen set to 9:16, and the tablets' +with a 16:9 screen at each size's density, 288 for the 7-inch set and 240 for +the 10-inch, so the app lays itself out at the size it has on each: ``` adb shell wm size 1080x1920 adb shell wm size 1920x1080 +adb shell wm density 288 adb shell wm density 240 ``` diff --git a/android/TESTING.md b/android/TESTING.md index b900147..a7aa6aa 100644 --- a/android/TESTING.md +++ b/android/TESTING.md @@ -13,7 +13,7 @@ world, is set out at the end as a guide to work through before each release. | Accessibility | Google's Accessibility Test Framework over the whole screen after every action and at every screen the device tests reach | the same tests, through `accessibleRule()` | CI, every PR | | Hostile conditions | Turned on its side, the dark theme, the largest text, recreated by the system, location refused, no connection | `ResilienceTest`, `LocationRefusedTest`, `KeyboardAndSearchTest` | CI, every PR | | Static checks | Lint on every module, the notices, the release's merged manifests | Gradle, `gradle/notices.gradle.kts` | CI, every PR | -| Design | Every screen against a reference image: light and dark, a small phone, a phone, a foldable and a tablet, the largest text, a longer language and right to left | `app/src/test/kotlin/com/gridpointcode/screens`, images in `app/src/test/screenshots` | CI, every PR | +| Design | Every screen against a reference image: light and dark, a small phone, a phone, a foldable, and 7-inch and 10-inch tablets, the largest text, a longer language and right to left | `app/src/test/kotlin/com/gridpointcode/screens`, images in `app/src/test/screenshots` | CI, every PR | | Robustness | StrictMode and leak detection around every device test, a seeded stress run of random input, the process ended and the screen put back | `NoStrictModeViolations`, LeakCanary, `RandomInputTest`, `app/src/test/.../ProcessDeathTest.kt` | CI, every PR | | Performance | The baseline profile the release carries, and benchmarks of start-up and frames with it and without it | `benchmark`, `app/src/release/generated/baselineProfiles` | CI checks the profile reaches the release; benchmarks by hand | | The watch and the car | The car's templates and what they hand on; the watch's tile and complication, their timelines and how they draw; the watch's screens on a round face | `car/src/test`, `wear/src/test`, images in `wear/src/test/screenshots` | CI, every PR | diff --git a/android/app/src/main/kotlin/com/gridpointcode/PlaceScreen.kt b/android/app/src/main/kotlin/com/gridpointcode/PlaceScreen.kt index c3253e5..bbae33d 100644 --- a/android/app/src/main/kotlin/com/gridpointcode/PlaceScreen.kt +++ b/android/app/src/main/kotlin/com/gridpointcode/PlaceScreen.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogWindowProvider +import androidx.compose.ui.zIndex import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.luminance import androidx.core.view.WindowCompat @@ -330,7 +331,10 @@ fun PlaceScreen(model: PlaceViewModel, speaker: Speaker) { onSettings = { openSettings(context) }, focus = search, onLeave = { screen.requestFocus() }, + // Over the map's buttons: on a short screen, such as a 7-inch + // tablet on its side, the places a name could mean reach past them. modifier = Modifier + .zIndex(1f) .align(Alignment.TopCenter) .statusBarsPadding() .padding(Space.step2), diff --git a/android/app/src/test/kotlin/com/gridpointcode/screens/Devices.kt b/android/app/src/test/kotlin/com/gridpointcode/screens/Devices.kt index 6a12d48..98cba8d 100644 --- a/android/app/src/test/kotlin/com/gridpointcode/screens/Devices.kt +++ b/android/app/src/test/kotlin/com/gridpointcode/screens/Devices.kt @@ -19,4 +19,7 @@ object Devices { /** A tablet on its side, which takes the wide layout: the panel beside the map. */ const val TABLET = "w1280dp-h800dp-xlarge-long-notround-any-240dpi-keyshidden-nonav" + + /** A 7-inch tablet on its side: the wide layout too, on the least height it is drawn at. */ + const val SMALL_TABLET = "w960dp-h600dp-large-long-notround-any-320dpi-keyshidden-nonav" } diff --git a/android/app/src/test/kotlin/com/gridpointcode/screens/LargeScreensTest.kt b/android/app/src/test/kotlin/com/gridpointcode/screens/LargeScreensTest.kt index bc41822..e94fcb6 100644 --- a/android/app/src/test/kotlin/com/gridpointcode/screens/LargeScreensTest.kt +++ b/android/app/src/test/kotlin/com/gridpointcode/screens/LargeScreensTest.kt @@ -38,6 +38,25 @@ class TabletScreensTest : ScreenTest() { } } +/** A 7-inch tablet on its side, where the wide layout is shortest. */ +@Config(qualifiers = Devices.SMALL_TABLET) +class SmallTabletScreensTest : ScreenTest() { + + @Test + fun aPlaceBesideTheMap() { + open { typed(Places.MARKET) } + record() + } + + /** The list reaches down past the map's buttons, and lies over them. */ + @Test + fun placesANameCouldMean() { + open { threeSaved() } + searchedFor("toronto") + record() + } +} + /** A foldable opened out: nearly square, and just short of the wide layout. */ @Config(qualifiers = Devices.FOLDABLE) class FoldableScreensTest : ScreenTest() { diff --git a/android/app/src/test/kotlin/com/gridpointcode/screens/ScreenTest.kt b/android/app/src/test/kotlin/com/gridpointcode/screens/ScreenTest.kt index 13a170b..f5ea914 100644 --- a/android/app/src/test/kotlin/com/gridpointcode/screens/ScreenTest.kt +++ b/android/app/src/test/kotlin/com/gridpointcode/screens/ScreenTest.kt @@ -26,6 +26,7 @@ import com.github.takahirom.roborazzi.RoborazziOptions import com.github.takahirom.roborazzi.RoborazziRule import com.github.takahirom.roborazzi.captureScreenRoboImage import com.gridpointcode.Anchoring +import com.gridpointcode.Finding import com.gridpointcode.NoConnection import com.gridpointcode.PlaceScreen import com.gridpointcode.PlaceViewModel @@ -37,6 +38,7 @@ import com.gridpointcode.core.Source import com.gridpointcode.core.emergencyOf import com.gridpointcode.core.selectionAt import java.io.File +import java.time.Duration import org.junit.Rule import org.junit.runner.RunWith import org.robolectric.RuntimeEnvironment @@ -129,6 +131,22 @@ abstract class ScreenTest { rule.waitForIdle() } + /** + * Types [text] in the search field and waits for the places it could mean: + * the saved ones at once, then, once the typing has paused, the ones looked + * up, which with no connection are the landmarks on the device. + */ + protected fun searchedFor(text: String) { + rule.waitForIdle() + model.type(text) + rule.waitUntil(SETTLE_MS) { + // The pause is a delay on the main thread, whose clock moves only when told. + shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(100)) + model.found.value.status !in setOf(Finding.Status.IDLE, Finding.Status.LOOKING) + } + rule.waitForIdle() + } + /** Records the whole screen, dialogs included, under the test's own name. */ @OptIn(ExperimentalRoborazziApi::class) protected fun record() { diff --git a/android/app/src/test/screenshots/com.gridpointcode.screens.SmallTabletScreensTest.aPlaceBesideTheMap.png b/android/app/src/test/screenshots/com.gridpointcode.screens.SmallTabletScreensTest.aPlaceBesideTheMap.png new file mode 100644 index 0000000..d8fe085 Binary files /dev/null and b/android/app/src/test/screenshots/com.gridpointcode.screens.SmallTabletScreensTest.aPlaceBesideTheMap.png differ diff --git a/android/app/src/test/screenshots/com.gridpointcode.screens.SmallTabletScreensTest.placesANameCouldMean.png b/android/app/src/test/screenshots/com.gridpointcode.screens.SmallTabletScreensTest.placesANameCouldMean.png new file mode 100644 index 0000000..ef05e9b Binary files /dev/null and b/android/app/src/test/screenshots/com.gridpointcode.screens.SmallTabletScreensTest.placesANameCouldMean.png differ diff --git a/android/play/screenshots/tablet/1-wide.png b/android/play/screenshots/tablet-10/1-wide.png similarity index 100% rename from android/play/screenshots/tablet/1-wide.png rename to android/play/screenshots/tablet-10/1-wide.png diff --git a/android/play/screenshots/tablet/2-search-by-name.png b/android/play/screenshots/tablet-10/2-search-by-name.png similarity index 100% rename from android/play/screenshots/tablet/2-search-by-name.png rename to android/play/screenshots/tablet-10/2-search-by-name.png diff --git a/android/play/screenshots/tablet/3-anchor-the-short-form.png b/android/play/screenshots/tablet-10/3-anchor-the-short-form.png similarity index 100% rename from android/play/screenshots/tablet/3-anchor-the-short-form.png rename to android/play/screenshots/tablet-10/3-anchor-the-short-form.png diff --git a/android/play/screenshots/tablet/4-dark.png b/android/play/screenshots/tablet-10/4-dark.png similarity index 100% rename from android/play/screenshots/tablet/4-dark.png rename to android/play/screenshots/tablet-10/4-dark.png diff --git a/android/play/screenshots/tablet-7/1-wide.png b/android/play/screenshots/tablet-7/1-wide.png new file mode 100644 index 0000000..399080f Binary files /dev/null and b/android/play/screenshots/tablet-7/1-wide.png differ diff --git a/android/play/screenshots/tablet-7/2-search-by-name.png b/android/play/screenshots/tablet-7/2-search-by-name.png new file mode 100644 index 0000000..740a944 Binary files /dev/null and b/android/play/screenshots/tablet-7/2-search-by-name.png differ diff --git a/android/play/screenshots/tablet-7/3-anchor-the-short-form.png b/android/play/screenshots/tablet-7/3-anchor-the-short-form.png new file mode 100644 index 0000000..63eaf3d Binary files /dev/null and b/android/play/screenshots/tablet-7/3-anchor-the-short-form.png differ diff --git a/android/play/screenshots/tablet-7/4-dark.png b/android/play/screenshots/tablet-7/4-dark.png new file mode 100644 index 0000000..b32afe2 Binary files /dev/null and b/android/play/screenshots/tablet-7/4-dark.png differ