Skip to content

Commit 2bc5f01

Browse files
authored
fix: native decoder/method wire-shape and default-value bugs (#1625)
Cross-referenced against the current Lynx engine source (lynx, lynx-stack), including the actual native dispatch code (not just .d.ts type declarations, which are occasionally wrong themselves). - View.Event: animationDecoder read the animation/transition payload from "detail", but real Lynx events carry it under "params" - confirmed both in events.d.ts and directly in the Android dispatch code (TransitionAnimationManager/LynxKeyframeAnimator construct a plain LynxCustomEvent, whose paramsName() is "params", not the LynxDetailEvent subclass used elsewhere). Broke all on(Animation|Transition)(Start|End|Cancel)[Main][With] combinators on native. Also handles Android's legacy (pre-"new animator") transition path, confirmed live in TransitionAnimationManager: it reports animation_type as "transition-<property>" (e.g. "transition-width") and sends neither animation_name nor new_animator at all. Added LegacyTransitionAnimation to AnimationType for this shape and made animationName optional for it. new_animator is only ever sent as an explicit `true` by the new C++ animation engine (animation.cc's CreateEventAndSend sets it unconditionally for both keyframe and transition events); pre-"new animator" engines omit it entirely for keyframe animations too, not just legacy transitions (confirmed in LynxKeyframeAnimator.java and Harmony's ui_base.cc, both of which only ever set animation_type/animation_name). So newAnimator now defaults to False whenever the field is absent, regardless of AnimationType, rather than being keyed off LegacyTransitionAnimation. - Refresh.Event: RefreshStateChangeEvent.state was decoded as MisoString, but the wire sends Lynx's RefreshState enum as a number (0=Idle, 1=OverDragRelease, 2=Refreshing per refresh.d.ts). Broke onRefreshStateChange* on native. - Overlay.Event: touchState was decoded as MisoString, but the wire sends Lynx's OverlayTouchState enum as a number (overlay.d.ts). errorCode was decoded as MisoString, but Android (the only platform implementing binderror) sends a raw Int - confirmed directly in LynxCustomEvent.addDetail(String, Object), which stores it unconverted. This contradicts both overlay.d.ts's own declaration and the public lynxjs.org docs (both say `errorCode: string`), but the dispatch code is the actual wire behavior. Broke onOverlayTouch*/onError* on native. - List.Method: scrollToPosition sent the target index under the key "position". The engine accepts both "position" and "index" as aliases (confirmed in both the Android and Harmony dispatch code), so this was not actually broken - "index" is just the current canonical name per list.d.ts, and this is a forward-compatible rename rather than a functional fix. defaultScrollToPosition and defaultAutoScroll also set stpSmooth/start to True against the engine's documented/actual defaults of false. ScrollView.Method has its own separate AutoScroll type (autoScroll is shared between <list> and <scroll-view> per list.d.ts's ScrollViewParams) with the identical wrong default: defaultAutoScroll set start = True despite its own "sensible defaults (stopped)" doc comment. Fixed the same way. - View.Property: ignoreFocus_ took a MisoString, but the property is boolean on the wire (props.d.ts, confirmed on lynxjs.org) and every sibling boolean property in the file uses Bool/boolProp; its own doc example (ignoreFocus_ True) didn't even typecheck. accessibilityElementsHidden_ and accessibilityExclusiveFocus_'s Haddocks both claimed "Default Value: True" against props.d.ts's documented default of false for both. accessibilityElementsHidden_'s doc example also called the function accessibilityExclusiveHidden_, which doesn't exist. - View.Method: defaultTakeScreenshot set format = ".png" (the engine only accepts the literal strings "jpeg"/"png") and scale = 0.5 against the documented/engine default of 1 (confirmed on lynxjs.org). defaultBoundingClientRect set androidEnableTransformProps = True against the documented/engine default of False (methods.d.ts, confirmed on lynxjs.org).
1 parent ad44bf8 commit 2bc5f01

7 files changed

Lines changed: 82 additions & 26 deletions

File tree

src/Miso/Native/Element/List/Method.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ defaultScrollToPosition
5757
{ stpPosition = 10
5858
, stpOffset = 100
5959
, stpAlignTo = "top"
60-
, stpSmooth = True
60+
, stpSmooth = False
6161
}
6262
-----------------------------------------------------------------------------
6363
instance ToJSVal ScrollToPosition where
6464
toJSVal ScrollToPosition {..} = do
6565
object <- create
66-
set "position" stpPosition object
66+
set "index" stpPosition object
6767
set "offset" stpOffset object
6868
set "alignTo" stpAlignTo object
6969
set "smooth" stpSmooth object
@@ -125,7 +125,7 @@ instance ToJSVal AutoScroll where
125125
defaultAutoScroll :: AutoScroll
126126
defaultAutoScroll = AutoScroll
127127
{ rate = "60"
128-
, start = True
128+
, start = False
129129
, autoStop = True
130130
}
131131
--------------------------------------------------------------------

src/Miso/Native/Element/ScrollView/Method.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ instance ToJSVal AutoScroll where
9999
--
100100
-- @since 1.13.0.0
101101
defaultAutoScroll :: AutoScroll
102-
defaultAutoScroll = AutoScroll 120 True
102+
defaultAutoScroll = AutoScroll 120 False
103103
-----------------------------------------------------------------------------
104104
-- | Invokes the Lynx @autoScroll@ method on a @<scroll-view>@ element.
105105
--

src/Miso/Native/Element/View/Event.hs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ import Control.Applicative (liftA2)
106106
import qualified Data.Map as M
107107
import Miso.Event (on, onMain, Decoder(..), DecodeTarget(..), Events, emptyDecoder, Phase(BUBBLE))
108108
import Miso.JSON
109-
import Miso.String (MisoString)
109+
import Miso.String (MisoString, isPrefixOf)
110110
import Miso.Types (Attribute, EventHandler, DOMRef)
111111
----------------------------------------------------------------------------
112112
-- | The 'Events' map for the Lynx @<view>@ element.
@@ -176,12 +176,18 @@ data AnimationEvent
176176
-- ^ The type of the animation. If it is a keyframe animation,
177177
-- this value is `keyframe-animation`; if it is a transition animation,
178178
-- this value is `transition-animation`.
179-
, animationName :: MisoString
179+
, animationName :: Maybe MisoString
180180
-- ^ The name of the animation. If it is a keyframe animation, it
181181
-- is the name of `@keyframes` in CSS; if it is a transition animation,
182-
-- it is the name of `transition-property` in CSS.
182+
-- it is the name of `transition-property` in CSS. 'Nothing' for
183+
-- 'LegacyTransitionAnimation', whose property name is folded into
184+
-- 'animationType' instead.
183185
, newAnimator :: Bool
184-
-- ^ Default value 'True'
186+
-- ^ 'True' only when the engine's new animator explicitly reports it
187+
-- (always @true@ when present, on both keyframe and transition events);
188+
-- pre-"new animator" engines never send this field at all, for
189+
-- keyframe animations as well as 'LegacyTransitionAnimation', so
190+
-- 'False' whenever the field is absent.
185191
} deriving (Show, Eq)
186192
----------------------------------------------------------------------------
187193
-- | Which animation kind raised the event: a @\@keyframes@ animation or a
@@ -191,25 +197,33 @@ data AnimationEvent
191197
data AnimationType
192198
= KeyFrameAnimation
193199
| TransitionAnimation
200+
| LegacyTransitionAnimation MisoString
201+
-- ^ Pre-"new animator" engines report a CSS transition as
202+
-- @transition-\<property\>@ (e.g. @transition-width@) instead of
203+
-- @transition-animation@, and send no @animation_name@\/@new_animator@
204+
-- alongside it. This carries the raw wire value (e.g. @transition-width@).
194205
deriving (Show, Eq)
195206
----------------------------------------------------------------------------
196207
instance FromJSON AnimationType where
197208
parseJSON = withText "animation-type" $ \case
198209
"keyframe-animation" -> pure KeyFrameAnimation
199210
"transition-animation" -> pure TransitionAnimation
200-
x -> typeMismatch "animation-type" (toJSON x)
211+
x | "transition-" `isPrefixOf` x -> pure (LegacyTransitionAnimation x)
212+
| otherwise -> typeMismatch "animation-type" (toJSON x)
201213
----------------------------------------------------------------------------
202214
-- | Animation decoder for use with events like 'onAnimationStart'
203215
animationDecoder :: Decoder AnimationEvent
204216
animationDecoder = Decoder {..}
205217
where
206218
decodeAt = DecodeTarget mempty
207219
decoder = withObject "animationDecoder" $ \o -> do
208-
d <- o .: "detail"
209-
AnimationEvent
210-
<$> d .: "animation_type"
211-
<*> d .: "animation_name"
212-
<*> d .: "new_animator"
220+
d <- o .: "params"
221+
aType <- d .: "animation_type"
222+
name <- case aType of
223+
LegacyTransitionAnimation _ -> pure Nothing
224+
_ -> Just <$> d .: "animation_name"
225+
newAnim <- d .:? "new_animator" .!= False
226+
pure (AnimationEvent aType name newAnim)
213227
-----------------------------------------------------------------------------
214228
-- | Payload of a @<view>@ layout-change event: the target's id, its new
215229
-- box, and its @dataset@.

src/Miso/Native/Element/View/Method.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ instance ToJSVal BoundingClientRect where
7979
defaultBoundingClientRect :: BoundingClientRect
8080
defaultBoundingClientRect
8181
= BoundingClientRect
82-
{ androidEnableTransformProps = True
82+
{ androidEnableTransformProps = False
8383
, relativeTo = Nothing
8484
}
8585
-----------------------------------------------------------------------------
@@ -168,8 +168,8 @@ takeScreenshot = invokeExec "takeScreenshot"
168168
defaultTakeScreenshot :: TakeScreenshot
169169
defaultTakeScreenshot
170170
= TakeScreenshot
171-
{ scale = 0.5
172-
, format = ".png"
171+
{ scale = 1
172+
, format = "jpeg"
173173
}
174174
-----------------------------------------------------------------------------
175175
-- | https://lynxjs.org/api/elements/built-in/view.html#requestaccessibilityfocus

src/Miso/Native/Element/View/Property.hs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,9 @@ accessibilityElementsA11y_ = textProp "accessibility-elements-a11y"
316316
--
317317
-- Marks the current node and all its child nodes as non-accessible nodes.
318318
--
319-
-- > accessibilityExclusiveHidden_ True
319+
-- > accessibilityElementsHidden_ True
320320
--
321-
-- Default Value: 'True'
321+
-- Default Value: 'False'
322322
--
323323
accessibilityElementsHidden_ :: Bool -> Attribute model action
324324
accessibilityElementsHidden_ = boolProp "accessibility-elements-hidden"
@@ -329,7 +329,7 @@ accessibilityElementsHidden_ = boolProp "accessibility-elements-hidden"
329329
--
330330
-- > accessibilityExclusiveFocus_ True
331331
--
332-
-- Default Value: 'True'
332+
-- Default Value: 'False'
333333
--
334334
accessibilityExclusiveFocus_ :: Bool -> Attribute model action
335335
accessibilityExclusiveFocus_ = boolProp "accessibility-exclusive-focus"
@@ -511,8 +511,8 @@ hitSlop_ = textProp "hit-slop"
511511
--
512512
-- Default Value: 'False
513513
--
514-
ignoreFocus_ :: MisoString -> Attribute model action
515-
ignoreFocus_ = textProp "ignore-focus"
514+
ignoreFocus_ :: Bool -> Attribute model action
515+
ignoreFocus_ = boolProp "ignore-focus"
516516
-----------------------------------------------------------------------------
517517
-- | https://lynxjs.org/api/elements/built-in/view.html#ios-enable-simultaneous-touch
518518
--

src/Miso/Native/X/Element/Overlay/Event.hs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
-----------------------------------------------------------------------------
2+
{-# LANGUAGE LambdaCase #-}
23
{-# LANGUAGE OverloadedStrings #-}
34
-----------------------------------------------------------------------------
45
-- |
@@ -36,6 +37,7 @@ module Miso.Native.X.Element.Overlay.Event
3637
-- *** Types
3738
, OverlayErrorEvent (..)
3839
, OverlayTouchEvent (..)
40+
, OverlayTouchState (..)
3941
-- *** Decoders
4042
, overlayErrorDecoder
4143
, overlayTouchDecoder
@@ -69,16 +71,37 @@ overlayEvents
6971
-- | Payload of the @binderror@ event.
7072
data OverlayErrorEvent
7173
= OverlayErrorEvent
72-
{ errorCode :: MisoString
74+
{ errorCode :: Int
7375
-- ^ The error code
7476
, errorMsg :: MisoString
7577
-- ^ The error message
7678
} deriving (Show, Eq)
7779
-----------------------------------------------------------------------------
80+
-- | Touch phase of a @bindoverlaytouch@ event, mirrored from Lynx's
81+
-- @OverlayTouchState@ enum.
82+
--
83+
-- @since 1.13.0.0
84+
data OverlayTouchState
85+
= OverlayTouchDown
86+
| OverlayTouchMove
87+
| OverlayTouchUp
88+
| OverlayTouchCancel
89+
deriving (Show, Eq)
90+
-----------------------------------------------------------------------------
91+
-- | Numbering matches Lynx's @OverlayTouchState@ enum (@OverlayTouchStateDown
92+
-- = 0@ … @OverlayTouchStateCancel = 3@), the shape the wire actually sends.
93+
instance FromJSON OverlayTouchState where
94+
parseJSON = withNumber "OverlayTouchState" $ \case
95+
0 -> pure OverlayTouchDown
96+
1 -> pure OverlayTouchMove
97+
2 -> pure OverlayTouchUp
98+
3 -> pure OverlayTouchCancel
99+
x -> typeMismatch "OverlayTouchState" (toJSON x)
100+
-----------------------------------------------------------------------------
78101
-- | Payload of the @bindoverlaytouch@ event.
79102
data OverlayTouchEvent
80103
= OverlayTouchEvent
81-
{ touchState :: MisoString
104+
{ touchState :: OverlayTouchState
82105
-- ^ The @OverlayTouchState@
83106
, touchX :: Double
84107
-- ^ The horizontal position of the touch

src/Miso/Native/X/Element/Refresh/Event.hs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
-----------------------------------------------------------------------------
2+
{-# LANGUAGE LambdaCase #-}
23
{-# LANGUAGE OverloadedStrings #-}
34
-----------------------------------------------------------------------------
45
-- |
@@ -28,6 +29,7 @@ module Miso.Native.X.Element.Refresh.Event
2829
-- *** Types
2930
, HeaderOffsetEvent (..)
3031
, RefreshStateChangeEvent (..)
32+
, RefreshState (..)
3133
, StartRefreshEvent (..)
3234
-- *** Decoders
3335
, headerOffsetDecoder
@@ -41,7 +43,6 @@ import qualified Data.Map as M
4143
-----------------------------------------------------------------------------
4244
import Miso.Event
4345
import Miso.JSON
44-
import Miso.String (MisoString)
4546
import Miso.Types (Attribute, EventHandler, DOMRef)
4647
-----------------------------------------------------------------------------
4748
-- | The 'Events' map for the Lynx @<refresh>@ element.
@@ -67,10 +68,28 @@ data HeaderOffsetEvent
6768
-- ^ Ratio of the pull-down distance to the header's own height
6869
} deriving (Show, Eq)
6970
-----------------------------------------------------------------------------
71+
-- | The state of a \<refresh-header\>, mirrored from Lynx's @RefreshState@ enum.
72+
--
73+
-- @since 1.13.0.0
74+
data RefreshState
75+
= Idle
76+
| OverDragRelease
77+
| Refreshing
78+
deriving (Show, Eq)
79+
-----------------------------------------------------------------------------
80+
-- | Numbering matches Lynx's @RefreshState@ enum (@IDLE = 0@ … @REFRESHING
81+
-- = 2@), the shape the wire actually sends.
82+
instance FromJSON RefreshState where
83+
parseJSON = withNumber "RefreshState" $ \case
84+
0 -> pure Idle
85+
1 -> pure OverDragRelease
86+
2 -> pure Refreshing
87+
x -> typeMismatch "RefreshState" (toJSON x)
88+
-----------------------------------------------------------------------------
7089
-- | Payload of the @bindrefreshstatechange@ event.
7190
newtype RefreshStateChangeEvent
7291
= RefreshStateChangeEvent
73-
{ state :: MisoString
92+
{ state :: RefreshState
7493
-- ^ The @RefreshState@ of the \<refresh-header\>
7594
} deriving (Show, Eq)
7695
-----------------------------------------------------------------------------

0 commit comments

Comments
 (0)