1
1
// src/contexts/SwiftUIContext.tsx
2
- import React , { createContext , RefObject , useCallback , useContext , useMemo , useRef , useState } from "react" ;
2
+ import React , {
3
+ createContext ,
4
+ FunctionComponent ,
5
+ PropsWithChildren ,
6
+ RefObject ,
7
+ useCallback ,
8
+ useContext ,
9
+ useMemo ,
10
+ useRef ,
11
+ useState ,
12
+ } from "react" ;
3
13
import type { ViewTreeNode } from "src/types" ;
4
14
import {
5
15
Commands as NativeSwiftUIRootCommands ,
@@ -26,13 +36,27 @@ export type SwiftUIContextValue = {
26
36
27
37
const SwiftUIContext = createContext < SwiftUIContextValue | undefined > ( undefined ) ;
28
38
29
- export const SwiftUIProvider : React . FC < { children : React . ReactNode } > = ( { children } ) => {
39
+ export type SwiftUIProviderProps = {
40
+ id : string ;
41
+ } ;
42
+
43
+ export const SwiftUIProvider : FunctionComponent < PropsWithChildren < SwiftUIProviderProps > > = ( {
44
+ id : rootId ,
45
+ children,
46
+ } ) => {
30
47
const eventRegistry = useRef < EventRegistry > ( new Map ( ) ) ;
31
48
const nodeRegistry = useRef < NodeRegistry > ( new Map ( ) ) ;
32
49
const [ nodeRegistryVersion , setNodeRegistryVersion ] = useState ( 0 ) ;
33
50
const renderSequence = useRef < string [ ] > ( [ ] ) ;
34
51
const nativeRef = useRef < React . ComponentRef < typeof SwiftUIRootNativeComponent > | null > ( null ) ;
35
52
53
+ const log = useCallback (
54
+ ( message : string , ...args : unknown [ ] ) => {
55
+ console . log ( `SwiftUIContext(${ rootId } ) ${ message } ` , ...args ) ;
56
+ } ,
57
+ [ rootId ] ,
58
+ ) ;
59
+
36
60
const nodesKey = useMemo ( ( ) => {
37
61
const keys = Array . from ( nodeRegistry . current . keys ( ) ) ;
38
62
return JSON . stringify ( keys ) ;
@@ -52,13 +76,16 @@ export const SwiftUIProvider: React.FC<{ children: React.ReactNode }> = ({ child
52
76
eventRegistry . current . set ( id , newHandlersForId ) ;
53
77
return newHandlersForId ;
54
78
} ;
55
- const registerEvent = useCallback ( ( id : string , name : string , handler : EventHandler ) => {
56
- const handlersForId = getEventHandlersForId ( id ) ;
57
- if ( handlersForId . has ( name ) ) {
58
- console . log ( `Overwriting existing event handler for ${ id } :${ name } ` ) ;
59
- }
60
- handlersForId . set ( name , handler ) ;
61
- } , [ ] ) ;
79
+ const registerEvent = useCallback (
80
+ ( id : string , name : string , handler : EventHandler ) => {
81
+ const handlersForId = getEventHandlersForId ( id ) ;
82
+ if ( handlersForId . has ( name ) ) {
83
+ log ( `overwriting existing event handler for ${ id } :${ name } ` ) ;
84
+ }
85
+ handlersForId . set ( name , handler ) ;
86
+ } ,
87
+ [ log ] ,
88
+ ) ;
62
89
63
90
const registerEvents = useCallback ( ( id : string , events : Record < string , EventHandler | undefined > ) => {
64
91
const handlersForId = getEventHandlersForId ( id ) ;
@@ -74,18 +101,24 @@ export const SwiftUIProvider: React.FC<{ children: React.ReactNode }> = ({ child
74
101
} ) ;
75
102
} , [ ] ) ;
76
103
77
- const registerNode = useCallback ( ( node : ViewTreeNode , parentId ?: string ) => {
78
- console . log ( `SwiftUIContext registering node with id=${ node . id } ` , { node, parentId } ) ;
79
- nodeRegistry . current . set ( node . id , { node, parentId } ) ;
80
- setNodeRegistryVersion ( ( prev ) => prev + 1 ) ;
81
- } , [ ] ) ;
82
-
83
- const unregisterNode = useCallback ( ( id : string ) => {
84
- console . log ( `SwiftUIContext unregistering node with id=${ id } ` ) ;
85
- nodeRegistry . current . delete ( id ) ;
86
- eventRegistry . current . delete ( id ) ;
87
- setNodeRegistryVersion ( ( prev ) => prev + 1 ) ;
88
- } , [ ] ) ;
104
+ const registerNode = useCallback (
105
+ ( node : ViewTreeNode , parentId ?: string ) => {
106
+ log ( `registering node with id=${ node . id } ` , { node, parentId } ) ;
107
+ nodeRegistry . current . set ( node . id , { node, parentId } ) ;
108
+ setNodeRegistryVersion ( ( prev ) => prev + 1 ) ;
109
+ } ,
110
+ [ log ] ,
111
+ ) ;
112
+
113
+ const unregisterNode = useCallback (
114
+ ( id : string ) => {
115
+ log ( `unregistering node with id=${ id } ` ) ;
116
+ nodeRegistry . current . delete ( id ) ;
117
+ eventRegistry . current . delete ( id ) ;
118
+ setNodeRegistryVersion ( ( prev ) => prev + 1 ) ;
119
+ } ,
120
+ [ log ] ,
121
+ ) ;
89
122
90
123
const getNodes = useCallback ( ( ) => nodeRegistry . current , [ ] ) ;
91
124
@@ -95,20 +128,23 @@ export const SwiftUIProvider: React.FC<{ children: React.ReactNode }> = ({ child
95
128
}
96
129
} , [ ] ) ;
97
130
98
- const updateNodeProps = useCallback ( ( id : string , props : Record < string , unknown > ) => {
99
- if ( ! nativeRef . current ) {
100
- console . warn ( "Native ref not available" ) ;
101
- return ;
102
- }
103
- const node = nodeRegistry . current . get ( id ) ;
104
- if ( ! node ) {
105
- console . warn ( `Node with id=${ id } not found` ) ;
106
- return ;
107
- }
108
- console . log ( `SwiftUIContext updating node with id=${ id } ` , { props } ) ;
109
- node . node . props = { ...node . node . props , ...props } ;
110
- NativeSwiftUIRootCommands . updateChildProps ( nativeRef . current , id , JSON . stringify ( props ) ) ;
111
- } , [ ] ) ;
131
+ const updateNodeProps = useCallback (
132
+ ( id : string , props : Record < string , unknown > ) => {
133
+ if ( ! nativeRef . current ) {
134
+ log ( "[warn] native ref not available" ) ;
135
+ return ;
136
+ }
137
+ const node = nodeRegistry . current . get ( id ) ;
138
+ if ( ! node ) {
139
+ log ( `[warn] node with id=${ id } not found` ) ;
140
+ return ;
141
+ }
142
+ log ( `updating node with id=${ id } ` , { props } ) ;
143
+ node . node . props = { ...node . node . props , ...props } ;
144
+ NativeSwiftUIRootCommands . updateChildProps ( nativeRef . current , id , JSON . stringify ( props ) ) ;
145
+ } ,
146
+ [ log ] ,
147
+ ) ;
112
148
113
149
const context = {
114
150
getEventHandler,
0 commit comments