rotor-framework 0.4.2 β†’ 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -96,7 +96,7 @@ You can find [🌱](./docs/ai/readme.opt.yaml) symbols in all documentation page
96
96
 
97
97
  ## πŸ“š Learn More
98
98
 
99
- ![Version](https://img.shields.io/badge/version-v0.4.2-blue?label=Documents%20TAG)
99
+ ![Version](https://img.shields.io/badge/version-v0.4.4-blue?label=Documents%20TAG)
100
100
 
101
101
  ### Framework Core
102
102
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rotor-framework",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Roku toolkit library providing a ViewBuilder, full UI lifecycle with focus handling and many core features, plus MVI-based state management.",
5
5
  "author": "BalΓ‘zs MolnΓ‘r",
6
6
  "license": "MIT",
@@ -4,7 +4,7 @@
4
4
  ' β–β–›β–€β–šβ––β–β–Œ β–β–Œ β–ˆ β–β–Œ β–β–Œβ–β–›β–€β–šβ–– β–β–›β–€β–€β–˜β–β–›β–€β–šβ––β–β–›β–€β–œβ–Œβ–β–Œ β–β–Œβ–β–›β–€β–€β–˜β–β–Œ β–β–Œβ–β–Œ β–β–Œβ–β–›β–€β–šβ––β–β–›β–šβ––
5
5
  ' β–β–Œ β–β–Œβ–β–šβ–„β–žβ–˜ β–ˆ β–β–šβ–„β–žβ–˜β–β–Œ β–β–Œ β–β–Œ β–β–Œ β–β–Œβ–β–Œ β–β–Œβ–β–Œ β–β–Œβ–β–™β–„β–„β––β–β–™β–ˆβ–Ÿβ–Œβ–β–šβ–„β–žβ–˜β–β–Œ β–β–Œβ–β–Œ β–β–Œ
6
6
  ' Rotor Frameworkβ„’
7
- ' Version 0.4.2
7
+ ' Version 0.4.4
8
8
  ' Β© 2025 BalΓ‘zs MolnΓ‘r β€” MIT License
9
9
  ' =========================================================================
10
10
 
@@ -85,7 +85,7 @@ namespace Rotor
85
85
  class Framework
86
86
 
87
87
  name = "Rotor Framework"
88
- version = "0.4.2"
88
+ version = "0.4.4"
89
89
 
90
90
  config = {
91
91
  tasks: invalid, ' @array (optional)
@@ -4,7 +4,7 @@
4
4
  ' β–β–›β–€β–šβ––β–β–Œ β–β–Œ β–ˆ β–β–Œ β–β–Œβ–β–›β–€β–šβ–– β–β–›β–€β–€β–˜β–β–›β–€β–šβ––β–β–›β–€β–œβ–Œβ–β–Œ β–β–Œβ–β–›β–€β–€β–˜β–β–Œ β–β–Œβ–β–Œ β–β–Œβ–β–›β–€β–šβ––β–β–›β–šβ––
5
5
  ' β–β–Œ β–β–Œβ–β–šβ–„β–žβ–˜ β–ˆ β–β–šβ–„β–žβ–˜β–β–Œ β–β–Œ β–β–Œ β–β–Œ β–β–Œβ–β–Œ β–β–Œβ–β–Œ β–β–Œβ–β–™β–„β–„β––β–β–™β–ˆβ–Ÿβ–Œβ–β–šβ–„β–žβ–˜β–β–Œ β–β–Œβ–β–Œ β–β–Œ
6
6
  ' Rotor Frameworkβ„’
7
- ' Version 0.4.2
7
+ ' Version 0.4.4
8
8
  ' Β© 2025 BalΓ‘zs MolnΓ‘r β€” MIT License
9
9
  ' =========================================================================
10
10
 
@@ -70,7 +70,7 @@ namespace Rotor
70
70
  class FrameworkTask
71
71
 
72
72
  name = "Rotor Framework"
73
- version = "0.4.2"
73
+ version = "0.4.4"
74
74
 
75
75
  config = {
76
76
  tasks: invalid, ' optional
@@ -86,6 +86,7 @@ namespace Rotor
86
86
  taskNode as object
87
87
  dispatcherProvider as object
88
88
  port as object
89
+ asyncTransferRegistry = {} ' transferId -> { dispatcherId, context }
89
90
 
90
91
  ' ---------------------------------------------------------------------
91
92
  ' new - Initializes the FrameworkTask instance
@@ -128,6 +129,24 @@ namespace Rotor
128
129
  return m.dispatcherProvider.getFacade(dispatcherId, GetGlobalAA())
129
130
  end function
130
131
 
132
+ ' ---------------------------------------------------------------------
133
+ ' registerAsyncTransfer - Registers an async transfer with dispatcher context
134
+ '
135
+ ' This method associates a roUrlTransfer identity with a dispatcher ID and
136
+ ' optional context data. When the transfer completes and sends a roUrlEvent,
137
+ ' the framework will route it to the correct dispatcher's asyncReducerCallback.
138
+ '
139
+ ' @param {string} transferId - The transfer.GetIdentity().ToStr() value
140
+ ' @param {string} dispatcherId - Dispatcher ID that initiated the transfer
141
+ ' @param {object} context - Optional user data to pass back in callback
142
+ '
143
+ public sub registerAsyncTransfer(transferId as string, dispatcherId as string, context = invalid as dynamic)
144
+ m.asyncTransferRegistry[transferId] = {
145
+ dispatcherId: dispatcherId,
146
+ context: context
147
+ }
148
+ end sub
149
+
131
150
  ' ---------------------------------------------------------------------
132
151
  ' sync - Starts the message loop for cross-thread communication
133
152
  '
@@ -194,6 +213,27 @@ namespace Rotor
194
213
  end if
195
214
 
196
215
  end if
216
+ else if msgType = "roUrlEvent"
217
+ ' Handle async transfer responses
218
+ transferId = msg.GetSourceIdentity().ToStr()
219
+
220
+ if m.asyncTransferRegistry.DoesExist(transferId)
221
+ transferData = m.asyncTransferRegistry[transferId]
222
+ dispatcherId = transferData.dispatcherId
223
+
224
+ dispatcherInstance = m.dispatcherProvider.get(dispatcherId)
225
+ if dispatcherInstance <> invalid
226
+ ' Route to dispatcher with wrapped message
227
+ dispatcherInstance.asyncReducerCallback({
228
+ type: "roUrlEvent",
229
+ event: msg,
230
+ context: transferData.context
231
+ })
232
+ end if
233
+
234
+ ' Cleanup registry entry
235
+ m.asyncTransferRegistry.delete(transferId)
236
+ end if
197
237
  end if
198
238
  end if
199
239
  end while
@@ -259,6 +299,7 @@ namespace Rotor
259
299
  ' Destroys dispatcher provider and clears global framework helper.
260
300
  '
261
301
  public sub destroy()
302
+ m.asyncTransferRegistry.clear()
262
303
  m.dispatcherProvider.destroy()
263
304
 
264
305
  globalScope = GetGlobalAA()
@@ -23,12 +23,12 @@ namespace Rotor
23
23
  ' MEMBER VARIABLES
24
24
  ' =============================================================
25
25
 
26
- model as object ' Reference to Model holding state
27
26
  middlewares = [] as function[] ' Middleware function array
28
27
  port as object ' Framework port for async operations
29
28
 
30
29
  ' Dispatcher integration
31
30
  getDispatcher as function ' Get dispatcher facade by ID
31
+ getState as function ' Get dispatcher's model state
32
32
  dispatch as function ' Dispatch intent to owner dispatcher
33
33
  ownerDispatcher as object ' Owning dispatcher instance
34
34
  ownerDispatcherId as string ' Owning dispatcher ID
@@ -52,10 +52,15 @@ namespace Rotor
52
52
  return GetGlobalAA().rotor_framework_helper.frameworkInstance.dispatcherProvider.getFacade(dispatcherId, m)
53
53
  end function
54
54
 
55
- ' Inject dispatch method for self-dispatching
55
+ ' Inject dispatch method for dispatching intents
56
56
  m.dispatch = sub(intent as object)
57
57
  m.ownerDispatcher.dispatch(intent)
58
58
  end sub
59
+
60
+ ' Inject getState method for accessing current state
61
+ m.getState = function() as Rotor.Model
62
+ return m.ownerDispatcher.getState()
63
+ end function
59
64
  end sub
60
65
 
61
66
  ' =============================================================
@@ -154,6 +159,37 @@ namespace Rotor
154
159
  return newState
155
160
  end function
156
161
 
162
+ ' =============================================================
163
+ ' ASYNC TRANSFER SUPPORT
164
+ ' =============================================================
165
+
166
+ ' ---------------------------------------------------------------------
167
+ ' registerAsyncTransfer - Registers a roUrlTransfer with the framework
168
+ '
169
+ ' Helper method to simplify async HTTP request tracking. Call this after
170
+ ' creating a roUrlTransfer but BEFORE calling AsyncGetToString() or other
171
+ ' async methods.
172
+ '
173
+ ' @param {object} transfer - The roUrlTransfer object
174
+ ' @param {object} context - Optional data to receive in asyncReducerCallback
175
+ '
176
+ ' Example:
177
+ ' transfer = CreateObject("roUrlTransfer")
178
+ ' transfer.SetUrl("https://api.example.com/data")
179
+ ' transfer.SetMessagePort(m.port)
180
+ ' m.registerAsyncTransfer(transfer, { userId: 123 })
181
+ ' transfer.AsyncGetToString()
182
+ '
183
+ sub registerAsyncTransfer(transfer as object, context = invalid as dynamic)
184
+ frameworkInstance = GetGlobalAA().rotor_framework_helper.frameworkInstance
185
+ transferId = transfer.GetIdentity().ToStr()
186
+
187
+ ' Only call if the method exists (task thread only)
188
+ if Rotor.Utils.isFunction(frameworkInstance?.registerAsyncTransfer)
189
+ frameworkInstance.registerAsyncTransfer(transferId, m.ownerDispatcherId, context)
190
+ end if
191
+ end sub
192
+
157
193
  ' =============================================================
158
194
  ' ASYNC CALLBACK
159
195
  ' =============================================================
@@ -44,9 +44,9 @@ namespace Rotor
44
44
  ' LIFECYCLE CALLBACKS
45
45
  ' =============================================================
46
46
 
47
- onMountWidget as Function ' Called after widget is mounted
48
- onUpdateWidget as Function ' Called before widget updates
49
- onDestroyWidget as Function ' Called before widget is destroyed
47
+ onMountWidget as function ' Called after widget is mounted
48
+ onUpdateWidget as function ' Called before widget updates
49
+ onDestroyWidget as function ' Called before widget is destroyed
50
50
 
51
51
  ' =============================================================
52
52
  ' DECORATED METHODS
@@ -54,31 +54,32 @@ namespace Rotor
54
54
  ' These methods are injected by WidgetCreate.bs
55
55
 
56
56
  ' Tree Navigation
57
- getWidget as Function ' Find widget by ID or path (any depth)
58
- findWidgets as Function ' Find widgets by glob pattern
59
- getChildrenWidgets as Function ' Get direct children (optionally filtered)
60
- getSiblingWidget as Function ' Get sibling widget by ID
61
- getSubtreeClone as Function ' Clone widget subtree
57
+ getWidget as function ' Find widget by ID or path (any depth)
58
+ findWidgets as function ' Find widgets by glob pattern
59
+ getChildrenWidgets as function ' Get direct children (optionally filtered)
60
+ getSiblingWidget as function ' Get sibling widget by ID
61
+ getSubtreeClone as function ' Clone widget subtree
62
62
 
63
63
  ' ViewModel Access
64
- getParentViewModel as Function ' Get parent ViewModel
65
- getViewModel as Function ' Get owning ViewModel
66
- getRootWidget as Function ' Get root widget (HID "0")
64
+ getParentViewModel as function ' Get parent ViewModel
65
+ getViewModel as function ' Get owning ViewModel
66
+ getRootWidget as function ' Get root widget (HID "0")
67
67
 
68
68
  ' Rendering
69
- render as Function ' Render widget updates
70
- refresh as Function ' Refresh specific properties by key paths
71
- erase as Function ' Remove widget(s) from tree
69
+ render as function ' Render widget updates
70
+ refresh as function ' Refresh specific properties by key paths
71
+ erase as function ' Remove widget(s) from tree
72
72
 
73
73
  ' Framework Integration
74
- getFrameworkInstance as Function ' Get framework instance
75
- getDispatcher as Function ' Get dispatcher facade by ID
76
- createDispatcher as Function ' Create dispatcher
77
- animator as Function ' Get animator factory
74
+ getFrameworkInstance as function ' Get framework instance
75
+ getDispatcher as function ' Get dispatcher facade by ID
76
+ dispatchTo as function ' Dispatch intent to dispatcher by ID
77
+ getStateFrom as function ' Get state from dispatcher by ID
78
+ animator as function ' Get animator factory
78
79
 
79
80
  ' i18n Integration
80
- getLocale as String ' Get locale e.g: "en_US"
81
- isRTL as Boolean ' Indicates whether the current locale uses right-to-left text
81
+ getLocale as function ' Get locale e.g: "en_US"
82
+ isRTL as function ' Indicates whether the current locale uses right-to-left text
82
83
 
83
84
  ' =============================================================
84
85
  ' PLUGIN METHODS
@@ -152,9 +152,9 @@ namespace Rotor.ViewBuilder
152
152
  end sub
153
153
 
154
154
  ' Listen shortcut - Listen to specific dispatcher'
155
- widget.getStateFrom = function(dispatcherId as string)
155
+ widget.getStateFrom = function(dispatcherId as string, mapStateToProps = invalid as dynamic)
156
156
  dispatcherFaced = m.getDispatcher(dispatcherId)
157
- return dispatcherFaced.getState()
157
+ return dispatcherFaced.getState(mapStateToProps)
158
158
  end function
159
159
 
160
160
  ' animator - Gets animator factory by ID *'