pakyow-ui 1.0.0.rc5 → 1.0.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -22
- data/lib/pakyow/application/behavior/ui/recording.rb +54 -0
- data/lib/pakyow/application/behavior/ui/rendering.rb +123 -0
- data/lib/pakyow/application/behavior/ui/timeouts.rb +25 -0
- data/lib/pakyow/application/helpers/ui.rb +22 -0
- data/lib/pakyow/presenter/renderer/behavior/ui/install_transforms.rb +49 -0
- data/lib/pakyow/ui/framework.rb +10 -10
- metadata +23 -23
- data/lib/pakyow/ui/behavior/recording.rb +0 -52
- data/lib/pakyow/ui/behavior/rendering/install_transforms.rb +0 -47
- data/lib/pakyow/ui/behavior/rendering.rb +0 -117
- data/lib/pakyow/ui/behavior/timeouts.rb +0 -31
- data/lib/pakyow/ui/helpers.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 132a87f510d10785e7bab583dccb03ea1fc1e38a0321d691249715c651b53715
|
4
|
+
data.tar.gz: 19ea083d0b919d532b83f8dddf1fe215c31ec418d34ed7ae290a2a179f00de6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e264cc45b796e94a04b900a1cc4fc2a9958ffb7b3642ab89de5d79dd4d49e8342ed793f73d93d4f87f5e277de9c783d045a5ed4e707c58085d01372dc75ecdc0
|
7
|
+
data.tar.gz: '09b4155d2cc022fa9c2c40c7a8bd5f8f542e5ed07e7cc8e1b1403d3c4256c9d8919ff2170e47d65a0291e51f4270a0cebebdb409755f9a673dbb4cf2091e3700'
|
data/CHANGELOG.md
CHANGED
@@ -1,24 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# UNRELEASED
|
2
2
|
|
3
|
-
|
4
|
-
* Prevent nils from being returned in mutable data
|
3
|
+
# 1.0
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
* Mutators are now evaluated in a proper app context
|
9
|
-
* Helper methods can now be called inside of a mutator
|
10
|
-
* Sessions are now stored with mutations and available when the mutation is invoked after a state change
|
11
|
-
* Registered mutations are now unregistered when the WebSocket shuts down
|
12
|
-
* Qualification values are now typecasted to strings before comparison
|
13
|
-
* Removes code that inserts a node when subscribing an empty view
|
14
|
-
* Automatically returns the mutated view from the mutation
|
15
|
-
* Adds support for view versioning
|
16
|
-
* Allows mutables and mutations to have different scopes
|
17
|
-
* Moves everything into the Pakyow namespace
|
18
|
-
* Now sets `pakyow.socket` on request env when fetching view
|
19
|
-
* Fixes a bug determining qualifiers with non-array data
|
20
|
-
* No longer registers mutations registered on a socket request
|
21
|
-
|
22
|
-
# 0.10.0 / 2015-10-19
|
23
|
-
|
24
|
-
* Initial release
|
5
|
+
* Hello, Web
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/extension"
|
4
|
+
|
5
|
+
require "pakyow/ui/recordable"
|
6
|
+
|
7
|
+
module Pakyow
|
8
|
+
class Application
|
9
|
+
module Behavior
|
10
|
+
module UI
|
11
|
+
module Recording
|
12
|
+
extend Support::Extension
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
def find_ui_presenter_for(presenter_class)
|
16
|
+
if is_a?(Plugin)
|
17
|
+
# Look for the presenter in the plugin first, falling back to the app.
|
18
|
+
#
|
19
|
+
ui_presenter_class = parent.ui_presenters.find { |klass|
|
20
|
+
klass.ancestors.include?(presenter_class)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
ui_presenter_class ||= @ui_presenters.find { |klass|
|
25
|
+
klass.ancestors.include?(presenter_class)
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
apply_extension do
|
30
|
+
# Create subclasses of each presenter, then make the subclasses recordable.
|
31
|
+
# These subclasses will be used when performing a ui presentation instead
|
32
|
+
# of the original presenter, but they'll behave identically!
|
33
|
+
#
|
34
|
+
after "initialize" do
|
35
|
+
@ui_presenters = [isolated(:Presenter)].concat(
|
36
|
+
state(:presenter)
|
37
|
+
).concat(
|
38
|
+
state(:component).map(&:__presenter_class)
|
39
|
+
).map { |presenter_class|
|
40
|
+
Class.new(presenter_class) do
|
41
|
+
include Pakyow::UI::Recordable
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
class_eval do
|
47
|
+
attr_reader :ui_presenters
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
|
5
|
+
require "pakyow/support/deep_dup"
|
6
|
+
require "pakyow/support/extension"
|
7
|
+
require "pakyow/support/inflector"
|
8
|
+
|
9
|
+
require "pakyow/application/helpers/realtime/subscriptions"
|
10
|
+
|
11
|
+
require "pakyow/ui/handler"
|
12
|
+
|
13
|
+
module Pakyow
|
14
|
+
class Application
|
15
|
+
module Behavior
|
16
|
+
module UI
|
17
|
+
module Rendering
|
18
|
+
extend Support::Extension
|
19
|
+
|
20
|
+
apply_extension do
|
21
|
+
isolated :Renderer do
|
22
|
+
include Application::Helpers::Realtime::Subscriptions
|
23
|
+
|
24
|
+
# @api private
|
25
|
+
def socket_client_id
|
26
|
+
presentables[:__socket_client_id]
|
27
|
+
end
|
28
|
+
|
29
|
+
on "render" do
|
30
|
+
unless presentables.include?(:__ui_transform) || subscribables.empty?
|
31
|
+
# To keep up with the node(s) that matter for the transformation, a `data-t` attribute
|
32
|
+
# is added to the node that contains the transformation_id. When the transformation is
|
33
|
+
# triggered in the future, the client knows what node to apply tranformations to.
|
34
|
+
#
|
35
|
+
# Note that when we're presenting an entire view, `data-t` is set on the `html` node.
|
36
|
+
#
|
37
|
+
transformation_target = case @presenter.view.object
|
38
|
+
when StringDoc
|
39
|
+
@presenter.view.object.find_first_significant_node(:html)
|
40
|
+
when StringDoc::Node
|
41
|
+
@presenter.view.object
|
42
|
+
end
|
43
|
+
|
44
|
+
if transformation_target
|
45
|
+
ui_renderer_instance = @app.isolated(:UIRenderer).allocate
|
46
|
+
|
47
|
+
instance_variables.each do |ivar|
|
48
|
+
ui_renderer_instance.instance_variable_set(ivar, instance_variable_get(ivar))
|
49
|
+
end
|
50
|
+
|
51
|
+
metadata = {
|
52
|
+
renderer: ui_renderer_instance
|
53
|
+
}
|
54
|
+
|
55
|
+
@payload = {
|
56
|
+
metadata: Marshal.dump(metadata)
|
57
|
+
}
|
58
|
+
|
59
|
+
# Generate a unique id based on the value of the metadata. This guarantees that the
|
60
|
+
# transformation id will be consistent across subscriptions.
|
61
|
+
#
|
62
|
+
transformation_id = Digest::SHA1.hexdigest(@payload[:metadata])
|
63
|
+
presentables[:__transformation_id] = transformation_id
|
64
|
+
@payload[:transformation_id] = transformation_id
|
65
|
+
@payload[:id] = transformation_id
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
after "render" do
|
71
|
+
if instance_variable_defined?(:@payload)
|
72
|
+
@app.ui_executor.post(self, subscribables, @payload, Pakyow.logger.target) do |context, subscribables, payload, logger|
|
73
|
+
logger.internal {
|
74
|
+
"[ui] subscribing #{@payload[:id]}"
|
75
|
+
}
|
76
|
+
|
77
|
+
# Find every subscribable presentable, creating a data subscription for each.
|
78
|
+
#
|
79
|
+
subscribables.each do |subscribable|
|
80
|
+
subscribable.subscribe(context.socket_client_id, handler: Pakyow::UI::Handler, payload: payload) do |ids|
|
81
|
+
# Subscribe the subscriptions to the "transformation" channel.
|
82
|
+
#
|
83
|
+
context.subscribe(:transformation, *ids.uniq)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Expire subscriptions if the connection is never established.
|
88
|
+
#
|
89
|
+
context.app.data.expire(context.socket_client_id, context.app.config.realtime.timeouts.initial)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
using Support::DeepDup
|
95
|
+
|
96
|
+
private def subscribables
|
97
|
+
@subscribables ||= presentables.reject { |presentable_name, _|
|
98
|
+
presentable_name.to_s.start_with?("__")
|
99
|
+
}.map { |_, value|
|
100
|
+
proxy = if value.is_a?(Pakyow::Data::Proxy)
|
101
|
+
value
|
102
|
+
elsif value.instance_variable_defined?(:@__proxy)
|
103
|
+
value.instance_variable_get(:@__proxy)
|
104
|
+
else
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
|
108
|
+
if proxy && proxy.subscribable?
|
109
|
+
proxy.deep_dup
|
110
|
+
else
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
}.compact.uniq { |subscribable|
|
114
|
+
subscribable.source.__getobj__
|
115
|
+
}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/extension"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
class Application
|
7
|
+
module Behavior
|
8
|
+
module UI
|
9
|
+
module Timeouts
|
10
|
+
extend Support::Extension
|
11
|
+
|
12
|
+
apply_extension do
|
13
|
+
on :join do
|
14
|
+
@connection.app.data.persist(@id)
|
15
|
+
end
|
16
|
+
|
17
|
+
on :leave do
|
18
|
+
@connection.app.data.expire(@id, config.realtime.timeouts.disconnect)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pakyow
|
4
|
+
class Application
|
5
|
+
module Helpers
|
6
|
+
module UI
|
7
|
+
def ui?
|
8
|
+
@connection.request_header?("pw-ui")
|
9
|
+
end
|
10
|
+
|
11
|
+
def ui
|
12
|
+
@connection.request_header("pw-ui")
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
def ui_transform?
|
17
|
+
@connection.set?(:__ui_transform)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/extension"
|
4
|
+
|
5
|
+
require "pakyow/presenter/view"
|
6
|
+
|
7
|
+
module Pakyow
|
8
|
+
module Presenter
|
9
|
+
class Renderer
|
10
|
+
module Behavior
|
11
|
+
module UI
|
12
|
+
module InstallTransforms
|
13
|
+
extend Support::Extension
|
14
|
+
|
15
|
+
apply_extension do
|
16
|
+
attach do |presenter|
|
17
|
+
presenter.render node: -> {
|
18
|
+
nodes = []
|
19
|
+
|
20
|
+
if html_node = object.find_first_significant_node(:html)
|
21
|
+
nodes << Pakyow::Presenter::View.from_object(html_node)
|
22
|
+
end
|
23
|
+
|
24
|
+
if !object.is_a?(StringDoc) && object.significant?(:component)
|
25
|
+
nodes << Pakyow::Presenter::View.from_object(object)
|
26
|
+
end
|
27
|
+
|
28
|
+
object.each_significant_node_without_descending_into_type(:component, descend: true) do |node|
|
29
|
+
if node.label(:components).any? { |c| c[:renderable ] }
|
30
|
+
nodes << Pakyow::Presenter::View.from_object(node)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
nodes
|
35
|
+
} do
|
36
|
+
if transformation_id = presentables[:__transformation_id]
|
37
|
+
# Set the transformation_id on the target node so that transformations can be applied to the right place.
|
38
|
+
#
|
39
|
+
attributes[:"data-t"] = transformation_id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/pakyow/ui/framework.rb
CHANGED
@@ -4,13 +4,13 @@ require "concurrent/executor/thread_pool_executor"
|
|
4
4
|
|
5
5
|
require "pakyow/framework"
|
6
6
|
|
7
|
-
require "pakyow/
|
7
|
+
require "pakyow/application/helpers/ui"
|
8
8
|
|
9
|
-
require "pakyow/
|
10
|
-
require "pakyow/
|
11
|
-
require "pakyow/
|
9
|
+
require "pakyow/application/behavior/ui/recording"
|
10
|
+
require "pakyow/application/behavior/ui/rendering"
|
11
|
+
require "pakyow/application/behavior/ui/timeouts"
|
12
12
|
|
13
|
-
require "pakyow/
|
13
|
+
require "pakyow/presenter/renderer/behavior/ui/install_transforms"
|
14
14
|
|
15
15
|
module Pakyow
|
16
16
|
module UI
|
@@ -33,14 +33,14 @@ module Pakyow
|
|
33
33
|
|
34
34
|
def boot
|
35
35
|
object.class_eval do
|
36
|
-
register_helper :passive, Helpers
|
36
|
+
register_helper :passive, Application::Helpers::UI
|
37
37
|
|
38
|
-
include Behavior::Recording
|
39
|
-
include Behavior::Rendering
|
40
|
-
include Behavior::Timeouts
|
38
|
+
include Application::Behavior::UI::Recording
|
39
|
+
include Application::Behavior::UI::Rendering
|
40
|
+
include Application::Behavior::UI::Timeouts
|
41
41
|
|
42
42
|
isolated :Renderer do
|
43
|
-
include Behavior::
|
43
|
+
include Presenter::Renderer::Behavior::UI::InstallTransforms
|
44
44
|
end
|
45
45
|
|
46
46
|
prepend PresenterForContext
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pakyow-ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bryan Powell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pakyow-core
|
@@ -16,84 +16,84 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.0.0
|
19
|
+
version: 1.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.0.0
|
26
|
+
version: 1.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: pakyow-data
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.0.0
|
33
|
+
version: 1.0.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.0.0
|
40
|
+
version: 1.0.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: pakyow-presenter
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - '='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 1.0.0
|
47
|
+
version: 1.0.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.0.0
|
54
|
+
version: 1.0.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: pakyow-realtime
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.0.0
|
61
|
+
version: 1.0.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - '='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.0.0
|
68
|
+
version: 1.0.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: pakyow-routing
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.0.0
|
75
|
+
version: 1.0.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.0.0
|
82
|
+
version: 1.0.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: pakyow-support
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.0.0
|
89
|
+
version: 1.0.0
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.0.0
|
96
|
+
version: 1.0.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: concurrent-ruby
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '1.1'
|
111
111
|
description: Auto-Updating UIs for Pakyow
|
112
|
-
email: bryan@
|
112
|
+
email: bryan@bryanp.org
|
113
113
|
executables: []
|
114
114
|
extensions: []
|
115
115
|
extra_rdoc_files: []
|
@@ -117,19 +117,19 @@ files:
|
|
117
117
|
- CHANGELOG.md
|
118
118
|
- LICENSE
|
119
119
|
- README.md
|
120
|
+
- lib/pakyow/application/behavior/ui/recording.rb
|
121
|
+
- lib/pakyow/application/behavior/ui/rendering.rb
|
122
|
+
- lib/pakyow/application/behavior/ui/timeouts.rb
|
123
|
+
- lib/pakyow/application/helpers/ui.rb
|
124
|
+
- lib/pakyow/presenter/renderer/behavior/ui/install_transforms.rb
|
120
125
|
- lib/pakyow/ui.rb
|
121
|
-
- lib/pakyow/ui/behavior/recording.rb
|
122
|
-
- lib/pakyow/ui/behavior/rendering.rb
|
123
|
-
- lib/pakyow/ui/behavior/rendering/install_transforms.rb
|
124
|
-
- lib/pakyow/ui/behavior/timeouts.rb
|
125
126
|
- lib/pakyow/ui/framework.rb
|
126
127
|
- lib/pakyow/ui/handler.rb
|
127
|
-
- lib/pakyow/ui/helpers.rb
|
128
128
|
- lib/pakyow/ui/recordable.rb
|
129
129
|
- lib/pakyow/ui/recordable/attribute.rb
|
130
130
|
- lib/pakyow/ui/recordable/attributes.rb
|
131
131
|
- lib/pakyow/ui/recordable/helpers/client_remapping.rb
|
132
|
-
homepage: https://pakyow.
|
132
|
+
homepage: https://pakyow.com
|
133
133
|
licenses:
|
134
134
|
- LGPL-3.0
|
135
135
|
metadata: {}
|
@@ -144,9 +144,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
144
|
version: 2.5.0
|
145
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
146
|
requirements:
|
147
|
-
- - "
|
147
|
+
- - ">="
|
148
148
|
- !ruby/object:Gem::Version
|
149
|
-
version:
|
149
|
+
version: '0'
|
150
150
|
requirements: []
|
151
151
|
rubygems_version: 3.0.3
|
152
152
|
signing_key:
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "pakyow/support/extension"
|
4
|
-
|
5
|
-
require "pakyow/ui/recordable"
|
6
|
-
|
7
|
-
module Pakyow
|
8
|
-
module UI
|
9
|
-
module Behavior
|
10
|
-
module Recording
|
11
|
-
extend Support::Extension
|
12
|
-
|
13
|
-
# @api private
|
14
|
-
def find_ui_presenter_for(presenter_class)
|
15
|
-
if is_a?(Plugin)
|
16
|
-
# Look for the presenter in the plugin first, falling back to the app.
|
17
|
-
#
|
18
|
-
ui_presenter_class = parent.ui_presenters.find { |klass|
|
19
|
-
klass.ancestors.include?(presenter_class)
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
ui_presenter_class ||= @ui_presenters.find { |klass|
|
24
|
-
klass.ancestors.include?(presenter_class)
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
apply_extension do
|
29
|
-
# Create subclasses of each presenter, then make the subclasses recordable.
|
30
|
-
# These subclasses will be used when performing a ui presentation instead
|
31
|
-
# of the original presenter, but they'll behave identically!
|
32
|
-
#
|
33
|
-
after "initialize" do
|
34
|
-
@ui_presenters = [isolated(:Presenter)].concat(
|
35
|
-
state(:presenter)
|
36
|
-
).concat(
|
37
|
-
state(:component).map(&:__presenter_class)
|
38
|
-
).map { |presenter_class|
|
39
|
-
Class.new(presenter_class) do
|
40
|
-
include Recordable
|
41
|
-
end
|
42
|
-
}
|
43
|
-
end
|
44
|
-
|
45
|
-
class_eval do
|
46
|
-
attr_reader :ui_presenters
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "pakyow/support/extension"
|
4
|
-
|
5
|
-
require "pakyow/presenter/view"
|
6
|
-
|
7
|
-
module Pakyow
|
8
|
-
module UI
|
9
|
-
module Behavior
|
10
|
-
module Rendering
|
11
|
-
module InstallTransforms
|
12
|
-
extend Support::Extension
|
13
|
-
|
14
|
-
apply_extension do
|
15
|
-
attach do |presenter|
|
16
|
-
presenter.render node: -> {
|
17
|
-
nodes = []
|
18
|
-
|
19
|
-
if html_node = object.find_first_significant_node(:html)
|
20
|
-
nodes << Pakyow::Presenter::View.from_object(html_node)
|
21
|
-
end
|
22
|
-
|
23
|
-
if !object.is_a?(StringDoc) && object.significant?(:component)
|
24
|
-
nodes << Pakyow::Presenter::View.from_object(object)
|
25
|
-
end
|
26
|
-
|
27
|
-
object.each_significant_node_without_descending_into_type(:component, descend: true) do |node|
|
28
|
-
if node.label(:components).any? { |c| c[:renderable ] }
|
29
|
-
nodes << Pakyow::Presenter::View.from_object(node)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
nodes
|
34
|
-
} do
|
35
|
-
if transformation_id = presentables[:__transformation_id]
|
36
|
-
# Set the transformation_id on the target node so that transformations can be applied to the right place.
|
37
|
-
#
|
38
|
-
attributes[:"data-t"] = transformation_id
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,117 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "securerandom"
|
4
|
-
|
5
|
-
require "pakyow/support/deep_dup"
|
6
|
-
require "pakyow/support/extension"
|
7
|
-
require "pakyow/support/inflector"
|
8
|
-
|
9
|
-
require "pakyow/realtime/helpers/subscriptions"
|
10
|
-
|
11
|
-
require "pakyow/ui/handler"
|
12
|
-
|
13
|
-
module Pakyow
|
14
|
-
module UI
|
15
|
-
module Behavior
|
16
|
-
module Rendering
|
17
|
-
extend Support::Extension
|
18
|
-
|
19
|
-
apply_extension do
|
20
|
-
isolated :Renderer do
|
21
|
-
include Realtime::Helpers::Subscriptions
|
22
|
-
|
23
|
-
# @api private
|
24
|
-
def socket_client_id
|
25
|
-
presentables[:__socket_client_id]
|
26
|
-
end
|
27
|
-
|
28
|
-
on "render" do
|
29
|
-
unless presentables.include?(:__ui_transform) || subscribables.empty?
|
30
|
-
# To keep up with the node(s) that matter for the transformation, a `data-t` attribute
|
31
|
-
# is added to the node that contains the transformation_id. When the transformation is
|
32
|
-
# triggered in the future, the client knows what node to apply tranformations to.
|
33
|
-
#
|
34
|
-
# Note that when we're presenting an entire view, `data-t` is set on the `html` node.
|
35
|
-
#
|
36
|
-
transformation_target = case @presenter.view.object
|
37
|
-
when StringDoc
|
38
|
-
@presenter.view.object.find_first_significant_node(:html)
|
39
|
-
when StringDoc::Node
|
40
|
-
@presenter.view.object
|
41
|
-
end
|
42
|
-
|
43
|
-
if transformation_target
|
44
|
-
ui_renderer_instance = @app.isolated(:UIRenderer).allocate
|
45
|
-
|
46
|
-
instance_variables.each do |ivar|
|
47
|
-
ui_renderer_instance.instance_variable_set(ivar, instance_variable_get(ivar))
|
48
|
-
end
|
49
|
-
|
50
|
-
metadata = {
|
51
|
-
renderer: ui_renderer_instance
|
52
|
-
}
|
53
|
-
|
54
|
-
@payload = {
|
55
|
-
metadata: Marshal.dump(metadata)
|
56
|
-
}
|
57
|
-
|
58
|
-
# Generate a unique id based on the value of the metadata. This guarantees that the
|
59
|
-
# transformation id will be consistent across subscriptions.
|
60
|
-
#
|
61
|
-
transformation_id = Digest::SHA1.hexdigest(@payload[:metadata])
|
62
|
-
presentables[:__transformation_id] = transformation_id
|
63
|
-
@payload[:transformation_id] = transformation_id
|
64
|
-
@payload[:id] = transformation_id
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
after "render" do
|
70
|
-
if instance_variable_defined?(:@payload)
|
71
|
-
@app.ui_executor.post(self, subscribables, @payload, Pakyow.logger.target) do |context, subscribables, payload, logger|
|
72
|
-
logger.internal {
|
73
|
-
"[ui] subscribing #{@payload[:id]}"
|
74
|
-
}
|
75
|
-
|
76
|
-
# Find every subscribable presentable, creating a data subscription for each.
|
77
|
-
#
|
78
|
-
subscribables.each do |subscribable|
|
79
|
-
subscribable.subscribe(context.socket_client_id, handler: Handler, payload: payload) do |ids|
|
80
|
-
# Subscribe the subscriptions to the "transformation" channel.
|
81
|
-
#
|
82
|
-
context.subscribe(:transformation, *ids.uniq)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
using Support::DeepDup
|
90
|
-
|
91
|
-
private def subscribables
|
92
|
-
@subscribables ||= presentables.reject { |presentable_name, _|
|
93
|
-
presentable_name.to_s.start_with?("__")
|
94
|
-
}.map { |_, value|
|
95
|
-
proxy = if value.is_a?(Data::Proxy)
|
96
|
-
value
|
97
|
-
elsif value.instance_variable_defined?(:@__proxy)
|
98
|
-
value.instance_variable_get(:@__proxy)
|
99
|
-
else
|
100
|
-
nil
|
101
|
-
end
|
102
|
-
|
103
|
-
if proxy && proxy.subscribable?
|
104
|
-
proxy.deep_dup
|
105
|
-
else
|
106
|
-
nil
|
107
|
-
end
|
108
|
-
}.compact.uniq { |subscribable|
|
109
|
-
subscribable.source.__getobj__
|
110
|
-
}
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "pakyow/support/extension"
|
4
|
-
|
5
|
-
module Pakyow
|
6
|
-
module UI
|
7
|
-
module Behavior
|
8
|
-
module Timeouts
|
9
|
-
extend Support::Extension
|
10
|
-
|
11
|
-
apply_extension do
|
12
|
-
on :join do
|
13
|
-
@connection.app.data.persist(@id)
|
14
|
-
end
|
15
|
-
|
16
|
-
on :leave do
|
17
|
-
@connection.app.data.expire(@id, config.realtime.timeouts.disconnect)
|
18
|
-
end
|
19
|
-
|
20
|
-
isolated :Renderer do
|
21
|
-
after "render" do
|
22
|
-
# Expire subscriptions if the connection is never established.
|
23
|
-
#
|
24
|
-
@app.data.expire(presentables[:__socket_client_id], @app.config.realtime.timeouts.initial)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/pakyow/ui/helpers.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Pakyow
|
4
|
-
module UI
|
5
|
-
module Helpers
|
6
|
-
def ui?
|
7
|
-
@connection.request_header?("pw-ui")
|
8
|
-
end
|
9
|
-
|
10
|
-
def ui
|
11
|
-
@connection.request_header("pw-ui")
|
12
|
-
end
|
13
|
-
|
14
|
-
# @api private
|
15
|
-
def ui_transform?
|
16
|
-
@connection.set?(:__ui_transform)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|