git.iko.soy/rowtype-yoga/purescript-yoga-react-native
on main help sign in
Add native video player (AVPlayerView) and animated image (GIF) components
commit4fff510be1f19137e032fb3547d5ad05ea2ea0f3 authorMark <mark.eibes@gmail.com> dateSat 14 Feb 2026, 08:51 (8 months ago) parent36c9c92
1 file changed+52−22
example-macos/src/Main.purs+52−22
example-macos/src/Main.purs+52−22
@@ -605,7 +605,7 @@ type ChatProps =
605605type Message =
606606 { sender :: String
607607 , body :: String
608− , isSticker :: Boolean
608+ , kind :: String -- "text" | "sticker" | "gif" | "video"
609609 }
610610
611611type Contact =
@@ -625,27 +625,33 @@ contacts =
625625initialMessages :: String -> Array Message
626626initialMessages name = case name of
627627 "Alice" ->
628− [ { sender: "Alice", body: "Hey! Have you seen the new Rive stickers?", isSticker: false }
629− , { sender: "You", body: "Not yet, show me!", isSticker: false }
630− , { sender: "Alice", body: "cat_following_mouse", isSticker: true }
631− , { sender: "You", body: "That's amazing! The cat follows your mouse!", isSticker: false }
632− , { sender: "You", body: "😍", isSticker: false }
633− , { sender: "Alice", body: "Right? Check out this one too", isSticker: false }
634− , { sender: "Alice", body: "rating_animation", isSticker: true }
628+ [ { sender: "Alice", body: "Hey! Have you seen the new Rive stickers?", kind: "text" }
629+ , { sender: "You", body: "Not yet, show me!", kind: "text" }
630+ , { sender: "Alice", body: "cat_following_mouse", kind: "sticker" }
631+ , { sender: "You", body: "That's amazing! The cat follows your mouse!", kind: "text" }
632+ , { sender: "You", body: "😍", kind: "text" }
633+ , { sender: "Alice", body: "Right? Check out this one too", kind: "text" }
634+ , { sender: "Alice", body: "rating_animation", kind: "sticker" }
635+ , { sender: "Alice", body: "Look at this cute cat!", kind: "text" }
636+ , { sender: "Alice", body: "https://media.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif", kind: "gif" }
635637 ]
636638 "Bob" ->
637− [ { sender: "Bob", body: "Hey, how's the app going?", isSticker: false }
638− , { sender: "You", body: "Great! Just added native macOS controls", isSticker: false }
639− , { sender: "Bob", body: "Nice! Toolbar, sidebar, the works?", isSticker: false }
640− , { sender: "You", body: "Yep, plus visual effects and context menus", isSticker: false }
641− , { sender: "Bob", body: "🔥", isSticker: false }
642− , { sender: "Bob", body: "switch_event_example", isSticker: true }
639+ [ { sender: "Bob", body: "Hey, how's the app going?", kind: "text" }
640+ , { sender: "You", body: "Great! Just added native macOS controls", kind: "text" }
641+ , { sender: "Bob", body: "Nice! Toolbar, sidebar, the works?", kind: "text" }
642+ , { sender: "You", body: "Yep, plus visual effects and context menus", kind: "text" }
643+ , { sender: "Bob", body: "🔥", kind: "text" }
644+ , { sender: "Bob", body: "switch_event_example", kind: "sticker" }
645+ , { sender: "Bob", body: "Check out this video", kind: "text" }
646+ , { sender: "Bob", body: "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", kind: "video" }
643647 ]
644648 "Carol" ->
645− [ { sender: "Carol", body: "Love the new UI", isSticker: false }
646− , { sender: "You", body: "Thanks! It's all PureScript + native macOS views", isSticker: false }
647− , { sender: "Carol", body: "The frosted glass sidebar is chef's kiss", isSticker: false }
648− , { sender: "Carol", body: "windy_tree", isSticker: true }
649+ [ { sender: "Carol", body: "Love the new UI", kind: "text" }
650+ , { sender: "You", body: "Thanks! It's all PureScript + native macOS views", kind: "text" }
651+ , { sender: "Carol", body: "The frosted glass sidebar is chef's kiss", kind: "text" }
652+ , { sender: "Carol", body: "windy_tree", kind: "sticker" }
653+ , { sender: "You", body: "https://media.giphy.com/media/13CoXDiaCcCoyk/giphy.gif", kind: "gif" }
654+ , { sender: "Carol", body: "Haha love it!", kind: "text" }
649655 ]
650656 _ -> []
651657
@@ -658,14 +664,14 @@ chatTab = component "ChatTab" \p -> React.do
658664 sendMessage msg = do
659665 if msg == "" then pure unit
660666 else do
661− setMessages (snoc messages { sender: "You", body: msg, isSticker: false })
667+ setMessages (snoc messages { sender: "You", body: msg, kind: "text" })
662668 setInputText ""
663669 switchContact name = do
664670 setActiveContact name
665671 setMessages (initialMessages name)
666672 setInputText ""
667673 sendSticker stickerName = do
668− setMessages (snoc messages { sender: "You", body: stickerName, isSticker: true })
674+ setMessages (snoc messages { sender: "You", body: stickerName, kind: "sticker" })
669675 setInputText ""
670676 allStickers = [ "cat_following_mouse", "rating_animation", "switch_event_example", "windy_tree" ]
671677 query = colonQuery inputText
@@ -704,7 +710,7 @@ chatTab = component "ChatTab" \p -> React.do
704710 messageBubble _ msg = do
705711 let isMine = msg.sender == "You"
706712 let align = if isMine then "flex-end" else "flex-start"
707− let bigEmoji = isSingleEmoji msg.body
713+ let bigEmoji = msg.kind == "text" && isSingleEmoji msg.body
708714 nativeContextMenu
709715 { items:
710716 [ { id: "copy", title: "Copy", sfSymbol: "doc.on.doc" }
@@ -715,7 +721,7 @@ chatTab = component "ChatTab" \p -> React.do
715721 , onSelectItem: handler_ (pure unit)
716722 , style: tw "px-3 mb-1"
717723 }
718− ( if msg.isSticker then
724+ ( if msg.kind == "sticker" then
719725 view
720726 { style: Style.style { alignSelf: align, width: 120.0, height: 120.0 } }
721727 [ nativeRiveView_
@@ -725,6 +731,30 @@ chatTab = component "ChatTab" \p -> React.do
725731 , style: Style.style { width: 120.0, height: 120.0 }
726732 }
727733 ]
734+ else if msg.kind == "gif" then
735+ view
736+ { style: tw "rounded-2xl overflow-hidden"
737+ <> Style.style { alignSelf: align, maxWidth: 240.0 }
738+ }
739+ [ nativeAnimatedImage
740+ { source: msg.body
741+ , animating: true
742+ , style: Style.style { width: 240.0, height: 180.0 }
743+ }
744+ ]
745+ else if msg.kind == "video" then
746+ view
747+ { style: tw "rounded-2xl overflow-hidden"
748+ <> Style.style { alignSelf: align, maxWidth: 280.0 }
749+ }
750+ [ nativeVideoPlayer
751+ { source: msg.body
752+ , playing: false
753+ , looping: true
754+ , muted: false
755+ , style: Style.style { width: 280.0, height: 180.0 }
756+ }
757+ ]
728758 else if bigEmoji then
729759 text
730760 { style: Style.style { alignSelf: align, fontSize: 64.0, lineHeight: 72.0 } }