Repository navigation
fix(hosts): draw Pocket faces and chat widgets the same on iOS and Android - #1447
Conversation
The renderer format left padding against a fixed size, a Box without an alignment, gaps between stack children, Spacer sizing, borders, shaped backgrounds, image sizes and image formats to each host's toolkit, and SwiftUI and Compose disagree on most of them. The docs now say how each is drawn, so both hosts can be held to one answer.
Pocket faces and chat widgets now land where Android puts them: - Padding goes around a fixed size instead of inside it. - A Box, and an Effect, with no alignment place children at the top start. - Rows and columns add no gap between children, and an arrangement only shares out space the stack was given; space-around leaves half a gap at each end. - An Effect is as large as its children and tints them, with the children keeping the layout and the taps. - A border is drawn inside the node. - A button is as wide as its label. - Images: Cover and None are cut to the node, ScaleDown never enlarges, an image with no size takes its natural size, and a missing image leaves its space empty. The devicehood conformance bound moves to 97%: its surface is bars that now touch, as on Android, so it covers most of the card.
Face images go through the SVG processor the app already uses for remote images, and an image that cannot be read is dropped from the cache, so a later draw tries it again rather than drawing nothing for good. FgSuccess mapped to the brand green while its siblings map to their own tokens; it now maps to fgSuccess, the green Android draws.
- A Spacer with no size along its stack takes an equal share of what the stack has left. - A row with no height of its own is as tall as its tallest child, so a child filling the height matches it instead of the space around. - A shaped background clips the content to its shape, leaving the border whole. - A picture's natural size is one image pixel to a dp, as iOS draws one to a point. - The Effect tint sweeps across its children, as the protocol says it is animated.
|
This pull request touches an app, which is not built by default. Add a label for each build you want:
Each starts as soon as it is added and follows the branch from then on. |
Bundle size reportCompared with
WebAssembly modules
Changed files (2)
Commit: 2b7a8ff |
|
CI Status: 25 required jobs green, 22 passed and 3 skipped by path filter. All job results
Signing credentials: valid as of 2026-10-26 Commit |
- iOS: a button given a width fills it; an image with no size is shrunk to fit the space it is given; an image sized on one side takes the other from its proportions instead of growing. - iOS: the Effect tint covers its children's bounds, as on Android, rather than drawing the children a second time as a mask. - iOS: a missing image's VoiceOver label sits on the node's size, so it can be reached. - Android: only an image drawn at its natural size is decoded whole, and a row only measures intrinsic heights when a child fills the height. - Tests poll for a loaded picture instead of waiting a fixed time, and the face conformance check also fails a face left unpainted.
A minimum width or height alone no longer counts as a node's own size: a button, image or stack with only a minimum is as large as its content. A Spacer stays flexible unless it has a fixed size along its stack. Images draw the same on both: one with no size takes its natural size shrunk to fit, one sized on a single side takes the other from its proportions, and None keeps its natural size there. The Android Effect builds its gradient once per size. The test raster draws over magenta, so a dark surface is not mistaken for nothing painted, and keeps one running count and bound per colour. The RFC's other copied doc lines get the rules too.
…r-parity # Conflicts: # hosts/ios/polkadot-appTests/Products/PocketFaceConformanceTests.swift # hosts/ios/polkadot-appTests/Products/WidgetNodeRaster.swift
…otocol docs carry The image sizing rules are one table of cases, the stack gap and arrangement checks one drawing, and the Effect's size and tint one test. The Android picture tests share one helper. Host comments that repeated the rules written in renderer.rs are gone; the ones left say why.
iOS simulator previewBuilt from gh run download 40354547885 --name simulator-preview-2b7a8ffe0
unzip polkadot-app-*.app.zip
xcrun simctl install booted polkadot-app.app
xcrun simctl launch booted io.parity.polkadotapp.developOr download it in a browser, which arrives as a zip wrapping An arm64 simulator slice, so it needs an Apple Silicon Mac and does not |
alexander-lisovyk
left a comment
There was a problem hiding this comment.
Lgtm, please resolve conflicts
…r-parity Keep the loading spinner and missing-image icon from #1496 on Android and draw them on iOS too, centred in the image's own space, in place of the empty space this branch drew. The loaded picture keeps this branch's sizing. The iOS image cache takes the SVG options and the per-source options from #1445.
…ap picture decodes A Spacer is laid out at its own minimum and followed by the space it shares out, so a stack short of room still gives it that minimum, as iOS does. A row or column with only a minimum size keeps its children at the start, as iOS does and the protocol docs say. A picture drawn at its natural size is decoded no larger than the screen and never enlarged. The layout tests now read pictures from PNG files, so they go through the same decoding a product's pictures do.
…size The shared serializer stored a drawn SVG as a PNG at the screen's scale and read it back at scale 1, so the picture came back three times its size. Face images now keep their own bytes on disk and are drawn again from them.
…does Android buttons fill their width since #1480, so iOS does again and the protocol docs say so.
Fixes paritytech/platform-bugs#97.
What
A Pocket face or chat widget now draws the same on iOS and Android. The protocol docs say how each layout question is answered, and both hosts follow them:
Boxwith no alignment places children at the top startSpaceAroundleaves half a gap at each endSpacertakes what its stack has left, and keeps its minimumEffectis as large as its children, placed at the top start, and tints themCoverandNoneimages are cut to the nodeScaleDownnever enlargesNone: its natural size)NoneFill,Cover)FgSuccessis the design system's success greenHow
renderer.rsdocuments each rule. The two lines the RFC copies are updated to match.BoxProps()so the top-start default lives in one place. Rows and columns share oneArrangedChildrenview. The Effect draws its shine over the children's bounds. Face images go through the SVG processor the app already uses for remote images, and an image that cannot be read is dropped from the cache so a later draw retries it.orderedForCompose, after the border. Rows and columns follow an unsizedSpacerwith a weighted one, and a row with no height usesIntrinsicSize.Maxwhen a child fills the height. Images are wrapped in a painter that reports their size in dp, and are decoded no larger than the screen. The Effect tint sweeps across its children.Tests
WidgetNodeLayoutTestsdraws one tree per rule in a window and checks where each colour lands. There are also tests for the Box default, SVG loading, and an unreadable image being retried. Each failed before the fix. The full app test target passes, withIdentityProfileServiceTestsskipped because it hangs on main.JsWidgetLayoutTest(instrumented) covers the Spacer, the row height and the natural image size, andJsModifierOrderTestcovers the background clip. Each failed before the fix. The products, wallet and chats unit tests, the wallet card test and detekt pass.