-
Notifications
You must be signed in to change notification settings - Fork 0
Basic app #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Basic app #1
Changes from all commits
4f5fcd8
0346c81
7015dc1
57e0bfc
3076b40
571afb3
26f2ed0
392b92d
fbad9e5
67fda53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,5 +57,7 @@ build-iPhoneSimulator/ | |
|
||
*.dll | ||
*.so | ||
*.exp | ||
*.lib | ||
|
||
.vscode |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
@echo off | ||
set RUBY_DLL_PATH=%CD% | ||
echo RUBY_DLL_PATH set to %RUBY_DLL_PATH% | ||
ruby main.rb |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
$env:RUBY_DLL_PATH = Get-Location | ||
Write-Output "RUBY_DLL_PATH set to $env:RUBY_DLL_PATH" | ||
ruby main.rb |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,115 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require 'rx' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require_relative 'theme' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require_relative 'widgetnode' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require 'thread' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require 'concurrent-ruby' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class TodoItem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
attr_accessor :text, :done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def initialize(text, done) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@text = text | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@done = done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class AppState | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
attr_accessor :todo_text, :todo_items | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def initialize(todo_text, todo_items) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@todo_text = todo_text | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@todo_items = todo_items | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$sample_app_state = Rx::BehaviorSubject.new(AppState.new("", [])) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+16
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Encapsulate application state within a service class. Using a global variable ( -$sample_app_state = Rx::BehaviorSubject.new(AppState.new("", []))
+class TodoService
+ def self.instance
+ @instance ||= new
+ end
+
+ def initialize
+ @state = Rx::BehaviorSubject.new(AppState.new("", []))
+ end
+
+ def state
+ @state
+ end
+
+ private_class_method :new
+end This provides better encapsulation and follows the Singleton pattern. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def on_click | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
promise = Concurrent::Promise.execute do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new_todo_item = TodoItem.new("New Todo", false) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
current_state = $sample_app_state.value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
new_state = AppState.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
current_state.todo_text, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
current_state.todo_items + [new_todo_item] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$sample_app_state.on_next(new_state) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
promise.wait | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+27
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve async handling and state management. The current implementation has several issues:
Consider this improved implementation: -def on_click
- promise = Concurrent::Promise.execute do
- new_todo_item = TodoItem.new("New Todo", false)
- current_state = $sample_app_state.value
- new_state = AppState.new(
- current_state.todo_text,
- current_state.todo_items + [new_todo_item]
- )
- $sample_app_state.on_next(new_state)
- end
-
- promise.wait
-end
+def on_click(text = nil)
+ Concurrent::Promise.execute do
+ service = TodoService.instance
+ current_state = service.state.value
+ new_todo_item = TodoItem.new(text || current_state.todo_text || "New Todo", false)
+ new_state = AppState.new(
+ "", # Reset input after adding
+ current_state.todo_items + [new_todo_item]
+ )
+ service.state.on_next(new_state)
+ end
+end 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$text_style = WidgetStyle.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
style: WidgetStyleDef.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
style_rules: StyleRules.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
font: FontDef.new(name: "roboto-regular", size: 32) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$button_style = WidgetStyle.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
style: WidgetStyleDef.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
style_rules: StyleRules.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
font: FontDef.new(name: "roboto-regular", size: 32) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
layout: YogaStyle.new( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
width: "50%", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
padding: {Edge[:Vertical] => 10}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
margin: {Edge[:Left] => 140} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class App < BaseComponent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def initialize | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
super({}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
promise = Concurrent::Promise.execute do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$sample_app_state.subscribe do |latest_app_state| | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
puts "app state changed" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@props.on_next({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"todo_text" => latest_app_state.todo_text, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"todo_items" => latest_app_state.todo_items | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
promise.wait | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@props.on_next({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"todo_text" => "", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"todo_items" => [TodoItem.new("New Todo", false)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def render | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
children = [button("Add todo", Proc.new { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
on_click() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, $button_style)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
promise = Concurrent::Promise.execute do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@props.value["todo_items"].each do |todo_item| | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
text = "#{todo_item.text} (#{todo_item.done ? 'done' : 'to do'})." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
children << unformatted_text(text, $text_style) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
promise.wait | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
node(children) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def dispose | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@app_state_subscription.dispose | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+62
to
+105
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix state management and async rendering issues. Several issues need attention:
Apply these improvements: class App < BaseComponent
def initialize
super({})
- promise = Concurrent::Promise.execute do
- $sample_app_state.subscribe do |latest_app_state|
- puts "app state changed"
+ service = TodoService.instance
+ @app_state_subscription = service.state.subscribe do |latest_app_state|
+ puts "app state changed"
- @props.on_next({
- "todo_text" => latest_app_state.todo_text,
- "todo_items" => latest_app_state.todo_items
- })
- end
+ @props.on_next({
+ "todo_text" => latest_app_state.todo_text,
+ "todo_items" => latest_app_state.todo_items
+ })
end
- promise.wait
-
@props.on_next({
"todo_text" => "",
"todo_items" => [TodoItem.new("New Todo", false)]
})
end
def render
- children = [button("Add todo", Proc.new {
- on_click()
- }, $button_style)]
+ children = [button("Add todo", -> { on_click() }, Theme::Styles.button)]
- promise = Concurrent::Promise.execute do
- @props.value["todo_items"].each do |todo_item|
- text = "#{todo_item.text} (#{todo_item.done ? 'done' : 'to do'})."
- children << unformatted_text(text, $text_style)
- end
+ @props.value["todo_items"].each do |todo_item|
+ text = "#{todo_item.text} (#{todo_item.done ? 'done' : 'to do'})."
+ children << unformatted_text(text, Theme::Styles.text)
end
- promise.wait
-
node(children)
end
def dispose
@app_state_subscription.dispose
end
end 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class Root < BaseComponent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def initialize | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
super({}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def render | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
root_node([App.new]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
require 'json' | ||
require 'rx' | ||
require 'thread' | ||
require_relative 'xframes' | ||
|
||
# $events_subject = Rx::ReplaySubject.new() | ||
|
||
class WidgetRegistrationService | ||
def initialize | ||
@id_generator_lock = Mutex.new | ||
@id_widget_registration_lock = Mutex.new | ||
@id_event_registration_lock = Mutex.new | ||
|
||
|
||
# @events_subject = Rx::ReplaySubject.new() | ||
# @events_subject.debounce(0.001).subscribe(Proc.new { |fn| fn.call }) | ||
# promise = Concurrent::Promise.execute do | ||
# $events_subject.subscribe do |cb| | ||
# puts "yo" | ||
# cb() | ||
# end | ||
# end | ||
# promise.wait | ||
|
||
@widget_registry = {} | ||
@on_click_registry = Rx::BehaviorSubject.new({}) | ||
|
||
@last_widget_id = 0 | ||
@last_component_id = 0 | ||
end | ||
|
||
def get_widget_by_id(widget_id) | ||
@id_widget_registration_lock.synchronize do | ||
@widget_registry[widget_id] | ||
end | ||
end | ||
|
||
def register_widget(widget_id, widget) | ||
@id_widget_registration_lock.synchronize do | ||
@widget_registry[widget_id] = widget | ||
end | ||
end | ||
|
||
def get_next_widget_id | ||
@id_generator_lock.synchronize do | ||
widget_id = @last_widget_id | ||
@last_widget_id += 1 | ||
widget_id | ||
end | ||
end | ||
|
||
def get_next_component_id | ||
@id_generator_lock.synchronize do | ||
component_id = @last_component_id | ||
@last_component_id += 1 | ||
component_id | ||
end | ||
end | ||
|
||
def register_on_click(widget_id, on_click) | ||
@id_event_registration_lock.synchronize do | ||
new_registry = @on_click_registry.value.dup | ||
new_registry[widget_id] = on_click | ||
@on_click_registry.on_next(new_registry) | ||
end | ||
end | ||
|
||
def dispatch_on_click_event(widget_id) | ||
promise = Concurrent::Promise.execute do | ||
on_click = @on_click_registry.value[widget_id] | ||
|
||
if on_click | ||
# promise = Concurrent::Promise.execute do | ||
on_click() | ||
# $events_subject.on_next(on_click) | ||
# end | ||
|
||
|
||
else | ||
puts "Widget with id #{widget_id} has no on_click handler" | ||
end | ||
end | ||
|
||
promise.wait | ||
end | ||
|
||
def create_widget(widget) | ||
widget_json = widget.to_hash.to_json | ||
set_element(widget_json) | ||
end | ||
|
||
def patch_widget(widget_id, widget) | ||
widget_json = widget.to_json | ||
patch_element(widget_id, widget_json) | ||
end | ||
|
||
def link_children(widget_id, child_ids) | ||
children_json = child_ids.to_json | ||
set_children(widget_id, children_json) | ||
end | ||
|
||
def set_data(widget_id, data) | ||
data_json = data.to_json | ||
element_internal_op(widget_id, data_json) | ||
end | ||
|
||
def append_data(widget_id, data) | ||
data_json = data.to_json | ||
element_internal_op(widget_id, data_json) | ||
end | ||
|
||
def reset_data(widget_id) | ||
data_json = "".to_json | ||
element_internal_op(widget_id, data_json) | ||
end | ||
|
||
def append_data_to_plot_line(widget_id, x, y) | ||
plot_data = { x: x, y: y } | ||
element_internal_op(widget_id, plot_data.to_json) | ||
end | ||
|
||
def set_plot_line_axes_decimal_digits(widget_id, x, y) | ||
axes_data = { x: x, y: y } | ||
element_internal_op(widget_id, axes_data.to_json) | ||
end | ||
|
||
def append_text_to_clipped_multi_line_text_renderer(widget_id, text) | ||
extern_append_text(widget_id, text) | ||
end | ||
|
||
def set_input_text_value(widget_id, value) | ||
input_text_data = { value: value } | ||
element_internal_op(widget_id, value) | ||
end | ||
andreamancuso marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def set_combo_selected_index(widget_id, index) | ||
selected_index_data = { index: index } | ||
element_internal_op(widget_id, selected_index_data.to_json) | ||
end | ||
|
||
private | ||
|
||
def set_element(json_data) | ||
XFrames.setElement(json_data) | ||
end | ||
|
||
def patch_element(widget_id, json_data) | ||
# Implement patch logic if needed | ||
end | ||
|
||
def set_children(widget_id, json_data) | ||
XFrames.setChildren(widget_id, json_data) | ||
end | ||
|
||
def element_internal_op(widget_id, json_data) | ||
# Implement internal operation if needed | ||
end | ||
|
||
def extern_append_text(widget_id, text) | ||
# Handle external append text logic | ||
end | ||
Comment on lines
+147
to
+161
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Implement missing private methods. Several private methods are missing implementations:
These missing implementations could lead to runtime errors. Would you like me to help implement these methods or create issues to track their implementation? |
||
end |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,140 @@ | ||||||
require 'rx' | ||||||
require 'json' | ||||||
require_relative 'widgetnode' | ||||||
require_relative 'widgettypes' | ||||||
require_relative 'services' | ||||||
|
||||||
class ShadowNode | ||||||
attr_accessor :id, :renderable, :current_props, :children, :props_change_subscription, :children_change_subscription | ||||||
|
||||||
def initialize(id, renderable) | ||||||
@id = id | ||||||
@renderable = renderable | ||||||
@current_props = {} | ||||||
@children = [] | ||||||
@props_change_subscription = nil | ||||||
@children_change_subscription = nil | ||||||
end | ||||||
|
||||||
def to_hash | ||||||
{ | ||||||
"id" => @id, | ||||||
"current_props" => @current_props, | ||||||
"children" => @children.map(&:to_hash) | ||||||
} | ||||||
end | ||||||
|
||||||
def get_linkable_children | ||||||
out = [] | ||||||
@children.each do |child| | ||||||
next if child.nil? || child.renderable.nil? | ||||||
|
||||||
if child.renderable.is_a?(WidgetNode) | ||||||
out << child | ||||||
elsif !child.children.empty? | ||||||
out.concat(child.get_linkable_children) | ||||||
end | ||||||
end | ||||||
out | ||||||
end | ||||||
end | ||||||
|
||||||
class ShadowNodeTraversalHelper | ||||||
def initialize(widget_registration_service) | ||||||
@widget_registration_service = widget_registration_service | ||||||
end | ||||||
|
||||||
def are_props_equal(props1, props2) | ||||||
props1 == props2 | ||||||
end | ||||||
|
||||||
def subscribe_to_props_helper(shadow_node) | ||||||
if shadow_node.props_change_subscription | ||||||
shadow_node.props_change_subscription.dispose | ||||||
end | ||||||
|
||||||
promise = Concurrent::Promise.execute do | ||||||
|
||||||
if shadow_node.renderable.is_a?(BaseComponent) | ||||||
component = shadow_node.renderable | ||||||
shadow_node.props_change_subscription = component.props.pipe( | ||||||
Rx::Operators.skip(1) | ||||||
).subscribe { |new_props| handle_component_props_change(shadow_node, component, new_props) } | ||||||
elsif shadow_node.renderable.is_a?(WidgetNode) | ||||||
shadow_node.props_change_subscription = shadow_node.renderable.props.pipe( | ||||||
Rx::Operators.skip(1) | ||||||
).subscribe { |new_props| handle_widget_node_props_change(shadow_node, shadow_node.renderable, new_props) } | ||||||
end | ||||||
|
||||||
end | ||||||
|
||||||
promise.wait | ||||||
end | ||||||
|
||||||
def handle_widget_node(widget) | ||||||
if widget.type == WidgetTypes[:Button] | ||||||
on_click = widget.props["on_click"] | ||||||
if on_click | ||||||
@widget_registration_service.register_on_click(widget.id, on_click) | ||||||
else | ||||||
puts "Button widget must have on_click prop" | ||||||
end | ||||||
end | ||||||
end | ||||||
Comment on lines
+74
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Replace puts with proper error handling. Using Apply this diff to improve error handling: def handle_widget_node(widget)
if widget.type == WidgetTypes[:Button]
on_click = widget.props["on_click"]
if on_click
@widget_registration_service.register_on_click(widget.id, on_click)
else
- puts "Button widget must have on_click prop"
+ raise ArgumentError, "Button widget must have on_click prop"
end
end
end |
||||||
|
||||||
def handle_component_props_change(shadow_node, component, new_props) | ||||||
return if are_props_equal(shadow_node.current_props, new_props) | ||||||
|
||||||
shadow_child = component.render | ||||||
shadow_node.children = [traverse_tree(shadow_child)] | ||||||
shadow_node.current_props = new_props | ||||||
|
||||||
linkable_children = shadow_node.get_linkable_children | ||||||
@widget_registration_service.link_children(shadow_node.id, linkable_children.map(&:id)) | ||||||
end | ||||||
|
||||||
def handle_widget_node_props_change(shadow_node, widget_node, new_props) | ||||||
@widget_registration_service.create_widget( | ||||||
WidgetNode.create_raw_childless_widget_node_with_id(shadow_node.id, widget_node) | ||||||
) | ||||||
|
||||||
shadow_children = widget_node.children.map { |child| traverse_tree(child) } | ||||||
shadow_node.children = shadow_children | ||||||
shadow_node.current_props = new_props | ||||||
|
||||||
@widget_registration_service.link_children(shadow_node.id, shadow_node.children.map(&:id)) | ||||||
end | ||||||
|
||||||
def traverse_tree(renderable) | ||||||
if renderable.is_a?(BaseComponent) | ||||||
rendered_child = renderable.render | ||||||
shadow_child = traverse_tree(rendered_child) | ||||||
id = @widget_registration_service.get_next_component_id | ||||||
shadow_node = ShadowNode.new(id, renderable) | ||||||
shadow_node.children = [shadow_child] | ||||||
# shadow_node.current_props = renderable.props.value | ||||||
subscribe_to_props_helper(shadow_node) | ||||||
return shadow_node | ||||||
elsif renderable.is_a?(WidgetNode) | ||||||
id = @widget_registration_service.get_next_widget_id | ||||||
raw_node = create_raw_childless_widget_node_with_id(id, renderable) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix undefined method error. The method Apply this diff to fix the method call: - raw_node = create_raw_childless_widget_node_with_id(id, renderable)
+ raw_node = WidgetNode.create_raw_childless_widget_node_with_id(id, renderable) 📝 Committable suggestion
Suggested change
|
||||||
handle_widget_node(raw_node) | ||||||
@widget_registration_service.create_widget(raw_node) | ||||||
|
||||||
shadow_node = ShadowNode.new(id, renderable) | ||||||
shadow_node.children = renderable.children.value.map { |child| traverse_tree(child) } | ||||||
shadow_node.current_props = renderable.props.value | ||||||
|
||||||
linkable_children = shadow_node.get_linkable_children | ||||||
if !linkable_children.empty? | ||||||
@widget_registration_service.link_children(id, linkable_children.map(&:id)) | ||||||
end | ||||||
|
||||||
subscribe_to_props_helper(shadow_node) | ||||||
|
||||||
return shadow_node | ||||||
else | ||||||
raise 'Unrecognised renderable' | ||||||
end | ||||||
end | ||||||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
require 'rx' | ||
require 'json' | ||
require_relative 'theme' | ||
require_relative 'widgettypes' | ||
|
||
class BaseComponent | ||
def initialize(props) | ||
@props = Rx::BehaviorSubject.new(props) | ||
end | ||
|
||
# Abstract method to be overridden | ||
def render | ||
raise NotImplementedError, 'You must implement the render method' | ||
end | ||
end | ||
|
||
class WidgetNode | ||
attr_accessor :type, :props, :children | ||
|
||
def initialize(type, props = {}, children = []) | ||
@type = type | ||
@props = Rx::BehaviorSubject.new(props) | ||
@children = Rx::BehaviorSubject.new(children) | ||
end | ||
end | ||
|
||
class RawChildlessWidgetNodeWithId | ||
attr_reader :id, :type, :props | ||
|
||
def initialize(id, type, props = {}) | ||
@id = id | ||
@type = type | ||
@props = props | ||
end | ||
|
||
def to_hash | ||
out = { | ||
'id' => @id, | ||
'type' => @type.to_s | ||
} | ||
|
||
@props.each do |key, value| | ||
unless value.is_a?(Proc) | ||
if (value.is_a?(WidgetStyleDef) || value.is_a?(NodeStyleDef)) | ||
out[key] = value.to_hash | ||
else | ||
out[key] = value | ||
end | ||
end | ||
end | ||
|
||
out | ||
end | ||
end | ||
|
||
def widget_node_factory(widget_type, props = {}, children = []) | ||
WidgetNode.new(widget_type, props, children) | ||
end | ||
|
||
def create_raw_childless_widget_node_with_id(id, node) | ||
RawChildlessWidgetNodeWithId.new(id, node.type, node.props.value) | ||
end | ||
|
||
def init_props_with_style(style = nil) | ||
props = {} | ||
|
||
if style | ||
props['style'] = style.style if style.style | ||
props['activeStyle'] = style.active_style if style.active_style | ||
props['hoverStyle'] = style.hover_style if style.hover_style | ||
props['disabledStyle'] = style.disabled_style if style.disabled_style | ||
end | ||
|
||
props | ||
end | ||
|
||
def root_node(children, style = nil) | ||
props = init_props_with_style(style) | ||
props['root'] = true | ||
|
||
widget_node_factory(WidgetTypes[:Node], props, children) | ||
end | ||
|
||
def node(children, style = nil) | ||
props = init_props_with_style(style) | ||
props['root'] = false | ||
|
||
widget_node_factory(WidgetTypes[:Node], props, children) | ||
end | ||
|
||
def unformatted_text(text, style = nil) | ||
props = init_props_with_style(style) | ||
props['text'] = text | ||
|
||
widget_node_factory(WidgetTypes[:UnformattedText], props, []) | ||
end | ||
|
||
def button(label, on_click = nil, style = nil) | ||
raise TypeError, 'on_click must be a callable' if on_click && !on_click.is_a?(Proc) | ||
|
||
props = init_props_with_style(style) | ||
props['label'] = label | ||
props['on_click'] = on_click if on_click | ||
|
||
widget_node_factory(WidgetTypes[:Button], props, []) | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
WidgetTypes = { | ||
Node: 'node', | ||
UnformattedText: 'unformatted-text', | ||
Button: 'di-button' | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
require 'ffi' | ||
|
||
module XFrames | ||
extend FFI::Library | ||
if RUBY_PLATFORM =~ /win32|mingw|cygwin/ | ||
ffi_lib './xframesshared.dll' | ||
else | ||
ffi_lib './libxframesshared.so' | ||
end | ||
|
||
# Define callback types | ||
callback :OnInitCb, [:pointer], :void | ||
callback :OnTextChangedCb, [:int, :string], :void | ||
callback :OnComboChangedCb, [:int, :int], :void | ||
callback :OnNumericValueChangedCb, [:int, :float], :void | ||
callback :OnBooleanValueChangedCb, [:int, :int], :void | ||
callback :OnMultipleNumericValuesChangedCb, [:int, :pointer, :int], :void | ||
callback :OnClickCb, [:int], :void | ||
|
||
attach_function :init, [ | ||
:string, # assetsBasePath | ||
:string, # rawFontDefinitions | ||
:string, # rawStyleOverrideDefinitions | ||
:OnInitCb, | ||
:OnTextChangedCb, | ||
:OnComboChangedCb, | ||
:OnNumericValueChangedCb, | ||
:OnBooleanValueChangedCb, | ||
:OnMultipleNumericValuesChangedCb, | ||
:OnClickCb | ||
], :void | ||
|
||
attach_function :setElement, [:string], :void | ||
|
||
attach_function :setChildren, [:int, :string], :void | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify the dependencies are properly installed.
Please ensure that all required gems are listed in the project's Gemfile:
Run this script to check the dependencies:
🏁 Script executed:
Length of output: 245
Missing Dependency: "rx" gem Not Installed
• The dependency check confirms that "concurrent-ruby" (v1.3.5) is properly installed.
• However, the gem "rx" required by the file (via
require 'rx'
) is missing from the installed gems list.• Please ensure that the project's Gemfile includes
gem 'rx'
(expected latest version "0.0.3") and install it accordingly.