cubism 0.1.0.pre11 → 0.1.0.pre12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf5d9eed6d97039688a2f51dd5ddab248619879ad47d50abbf37bab73d7f7d56
4
- data.tar.gz: 8120474f22abf5ee4b9bc2497e91ef2e68f41aea79f59fde4ae1c9e577a75dd7
3
+ metadata.gz: 8cd7c7ee681cabc05fd5329e7e6c17fd030d037beb100440faf1ef190a614ddf
4
+ data.tar.gz: a772708b9dc6a32c5a37766d203ea6a4b119eac57368378121e6b4da9f2b50f6
5
5
  SHA512:
6
- metadata.gz: fe7a0bca6d22807e0eb6b81e612ee8d435f67380a5aec20df253a86a92606642f907a67341b845159b2ae498dfcc0d7c56c1f49fb3425e1470789140adf4939e
7
- data.tar.gz: dd6925f36a82fcfab2de5a888b1d974b151fb9a14a7c4cf76cab9f3ffde28b865790c09dd4b97b19a8284192cef644847a3c944b06e53dd2d690ef8da2a7245e
6
+ metadata.gz: b47525bcc5545b289624615b66215b68467c2a2ba35a7b5335c944bdfacc68d0c6d60c430c93ad1b18470db7e7d3a58313f232b35bc32a34b21847f4a28f086b
7
+ data.tar.gz: 4595ebf829643d556613ebc5ca03e19f35cc6601a8c435f0dfea3c4e9cc7c08966c94ae69996e87d0e8c572d1d0decc8e6bd1cfa9ee7840a7abad29909f3ab7f
data/README.md CHANGED
@@ -96,9 +96,10 @@ CableReady.initialize({ consumer });
96
96
 
97
97
  The `cubicle_for` helper accepts the following options as keyword arguments:
98
98
 
99
+ - `scope`: declare a scope in which presence indicators should appear. For example, if you want to divide between index and show views, do `scope: :index` and `scope: :show` respectively (default: `""`).
99
100
  - `exclude_current_user (true|false)`: Whether or not to exclude the current user from the list of present users broadcasted to the view. Useful e.g. for "typing..." indicators (default: `true`).
100
- - `appear_trigger`: JavaScript event names (e.g. `["focus", "debounced:input]`) to use. (Can also be a singular string, which will be converted to an array). The default is `:connect`, i.e. register a user as "appeared"/"present" when the element connects to the DOM.
101
- - `disappear_trigger`: a JavaScript event name (e.g. `:blur`) to use. (Can also be a singular string, which will be converted to an array). The default is `:disconnect`, i.e. remove a user form the present users list when the element disconnects from the DOM.
101
+ - `appear_trigger`: JavaScript event names (e.g. `["focus", "debounced:input]`) to use. (Can also be a singular string, which will be converted to an array). The default is `:connect`, i.e. register a user as "appeared"/"present" when the element connects to the DOM. Another special value is `:intersect`, which fires when the `trigger_root` comes into the viewport.
102
+ - `disappear_trigger`: a JavaScript event name (e.g. `:blur`) to use. (Can also be a singular string, which will be converted to an array). The default is `:disconnect`, i.e. remove a user form the present users list when the element disconnects from the DOM. Analoguous to above, `:intersect` means that `disappear` will fire when the `trigger_root` is scrolled out of the viewport.
102
103
  - `trigger_root`: a CSS selector to attach the appear/disappear events to. Defaults to the `cubicle-element` itself.
103
104
  - `html_options` are passed to the TagBuilder.
104
105
 
@@ -3,7 +3,7 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
3
3
 
4
4
  def subscribed
5
5
  if resource.present?
6
- stream_from params[:element_id]
6
+ stream_from element_id
7
7
  resource.cubicle_element_ids << element_id
8
8
  resource.excluded_user_id_for_element_id[element_id] = user.id if exclude_current_user?
9
9
  else
@@ -20,11 +20,11 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
20
20
  end
21
21
 
22
22
  def appear
23
- resource.present_users.add(user.id)
23
+ resource.set_present_users_for_scope(resource.present_users_for_scope(scope).add(user.id), scope) if scope
24
24
  end
25
25
 
26
26
  def disappear
27
- resource.present_users.remove(user.id)
27
+ resource.set_present_users_for_scope(resource.present_users_for_scope(scope).delete(user.id), scope) if scope
28
28
  end
29
29
 
30
30
  private
@@ -35,7 +35,15 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
35
35
  end
36
36
 
37
37
  def user
38
- GlobalID::Locator.locate_signed(params[:user])
38
+ block_container&.user
39
+ end
40
+
41
+ def scope
42
+ block_container&.scope
43
+ end
44
+
45
+ def block_container
46
+ Cubism.block_store[element_id]
39
47
  end
40
48
 
41
49
  def exclude_current_user?
@@ -43,7 +51,8 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
43
51
  end
44
52
 
45
53
  def element_id
46
- params[:element_id]
54
+ /cubicle-(?<element_id>.+)/ =~ params[:element_id]
55
+ element_id
47
56
  end
48
57
 
49
58
  def url
@@ -3,7 +3,7 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
3
3
 
4
4
  def subscribed
5
5
  if resource.present?
6
- stream_from params[:element_id]
6
+ stream_from element_id
7
7
  resource.cubicle_element_ids << element_id
8
8
  resource.excluded_user_id_for_element_id[element_id] = user.id if exclude_current_user?
9
9
  else
@@ -20,11 +20,11 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
20
20
  end
21
21
 
22
22
  def appear
23
- resource.present_users.add(user.id)
23
+ resource.set_present_users_for_scope(resource.present_users_for_scope(scope).add(user.id), scope)
24
24
  end
25
25
 
26
26
  def disappear
27
- resource.present_users.remove(user.id)
27
+ resource.set_present_users_for_scope(resource.present_users_for_scope(scope).delete(user.id), scope)
28
28
  end
29
29
 
30
30
  private
@@ -35,7 +35,15 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
35
35
  end
36
36
 
37
37
  def user
38
- GlobalID::Locator.locate_signed(params[:user])
38
+ block_container.user
39
+ end
40
+
41
+ def scope
42
+ block_container.scope
43
+ end
44
+
45
+ def block_container
46
+ Cubism.block_store[element_id]
39
47
  end
40
48
 
41
49
  def exclude_current_user?
@@ -43,7 +51,8 @@ class Cubism::PresenceChannel < ActionCable::Channel::Base
43
51
  end
44
52
 
45
53
  def element_id
46
- params[:element_id]
54
+ /cubicle-(?<element_id>.+)/ =~ params[:element_id]
55
+ element_id
47
56
  end
48
57
 
49
58
  def url
@@ -1,7 +1,7 @@
1
1
  module CubismHelper
2
2
  include CableReady::StreamIdentifier
3
3
 
4
- def cubicle_for(resource, user, html_options: {}, appear_trigger: :connect, disappear_trigger: nil, trigger_root: nil, exclude_current_user: true, &block)
4
+ def cubicle_for(resource, user, scope: "", html_options: {}, appear_trigger: :connect, disappear_trigger: nil, trigger_root: nil, exclude_current_user: true, &block)
5
5
  block_location = block.source_location.join(":")
6
6
  block_source = Cubism::BlockSource.find_or_create(
7
7
  location: block_location,
@@ -14,7 +14,8 @@ module CubismHelper
14
14
  block_location: block_location,
15
15
  block_source: block_source,
16
16
  resource_gid: resource_gid,
17
- user_gid: user.to_gid.to_s
17
+ user_gid: user.to_gid.to_s,
18
+ scope: scope
18
19
  )
19
20
 
20
21
  digested_block_key = block_container.digest
@@ -23,7 +24,6 @@ module CubismHelper
23
24
 
24
25
  tag.cubicle_element(
25
26
  identifier: signed_stream_identifier(resource_gid),
26
- user: user.to_sgid.to_s,
27
27
  "appear-trigger": Array(appear_trigger).join(","),
28
28
  "disappear-trigger": disappear_trigger,
29
29
  "trigger-root": trigger_root,
@@ -1,30 +1,33 @@
1
1
  module CubismHelper
2
2
  include CableReady::StreamIdentifier
3
3
 
4
- def cubicle_for(resource, user, html_options: {}, appear_trigger: :connect, disappear_trigger: nil, trigger_root: nil, exclude_current_user: true, &block)
4
+ def cubicle_for(resource, user, scope: "", html_options: {}, appear_trigger: :connect, disappear_trigger: nil, trigger_root: nil, exclude_current_user: true, &block)
5
5
  block_location = block.source_location.join(":")
6
+ block_source = Cubism::BlockSource.find_or_create(
7
+ location: block_location,
8
+ view_context: self
9
+ )
6
10
 
7
11
  resource_gid = resource.to_gid.to_s
8
12
 
9
- store_item = Cubism::BlockStoreItem.new(
13
+ block_container = Cubism::BlockContainer.new(
10
14
  block_location: block_location,
15
+ block_source: block_source,
11
16
  resource_gid: resource_gid,
12
17
  user_gid: user.to_gid.to_s,
13
- view_context: self
18
+ scope: scope
14
19
  )
15
20
 
16
- digested_block_key = store_item.digest
17
-
18
- store_item.parse!
21
+ digested_block_key = block_container.digest
19
22
 
20
- Cubism.block_store[digested_block_key] = store_item
23
+ Cubism.block_store.fetch(digested_block_key, block_container)
21
24
 
22
25
  tag.cubicle_element(
23
26
  identifier: signed_stream_identifier(resource_gid),
24
- user: user.to_sgid.to_s,
25
27
  "appear-trigger": Array(appear_trigger).join(","),
26
28
  "disappear-trigger": disappear_trigger,
27
29
  "trigger-root": trigger_root,
30
+ scope: scope,
28
31
  id: "cubicle-#{digested_block_key}",
29
32
  "exclude-current-user": exclude_current_user,
30
33
  **html_options
@@ -2,7 +2,7 @@ module Cubism::Presence
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
- kredis_set :present_users, after_change: :stream_presence
5
+ kredis_hash :present_users, after_change: :stream_presence
6
6
  kredis_set :cubicle_element_ids
7
7
  kredis_hash :excluded_user_id_for_element_id
8
8
  end
@@ -11,8 +11,16 @@ module Cubism::Presence
11
11
  Cubism::Broadcaster.new(resource: self).broadcast
12
12
  end
13
13
 
14
- def present_users_for_element_id(element_id)
15
- users = Cubism.user_class.find(present_users.members)
14
+ def present_users_for_scope(scope = "")
15
+ present_users[scope].present? ? Marshal.load(present_users[scope]) : Set.new
16
+ end
17
+
18
+ def set_present_users_for_scope(user_ids, scope = "")
19
+ present_users[scope] = Marshal.dump(Set.new(user_ids))
20
+ end
21
+
22
+ def present_users_for_element_id_and_scope(element_id, scope = "")
23
+ users = Cubism.user_class.find(present_users_for_scope(scope).to_a)
16
24
  users.reject! { |user| user.id == excluded_user_id_for_element_id[element_id].to_i }
17
25
 
18
26
  users
@@ -13,20 +13,25 @@ module Cubism
13
13
 
14
14
  def broadcast
15
15
  resource.cubicle_element_ids.to_a.each do |element_id|
16
- /cubicle-(?<block_key>.+)/ =~ element_id
17
- block_container = Cubism.block_store[block_key]
16
+ block_container = Cubism.block_store[element_id]
18
17
 
19
18
  next if block_container.blank?
20
19
 
20
+ present_users = resource.present_users_for_element_id_and_scope(element_id, block_container.scope)
21
+
21
22
  block_source = block_container.block_source
22
23
 
23
- html = ApplicationController.render(inline: block_source.source, locals: {"#{block_source.variable_name}": resource.present_users_for_element_id(element_id)})
24
+ html = ApplicationController.render(inline: block_source.source, locals: {"#{block_source.variable_name}": present_users})
25
+
26
+ selector = "cubicle-element#cubicle-#{element_id}[identifier='#{signed_stream_identifier(resource.to_global_id.to_s)}']"
24
27
 
25
28
  cable_ready[element_id].inner_html(
26
- selector: "cubicle-element##{element_id}[identifier='#{signed_stream_identifier(resource.to_global_id.to_s)}']",
29
+ selector: selector,
27
30
  html: html
28
- ).broadcast
31
+ )
29
32
  end
33
+
34
+ cable_ready.broadcast
30
35
  end
31
36
  end
32
37
  end
@@ -13,18 +13,25 @@ module Cubism
13
13
 
14
14
  def broadcast
15
15
  resource.cubicle_element_ids.to_a.each do |element_id|
16
- /cubicle-(?<block_key>.+)/ =~ element_id
17
- store_item = Cubism.block_store[block_key]
16
+ block_container = Cubism.block_store[element_id]
18
17
 
19
- next if store_item.blank?
18
+ next if block_container.blank?
20
19
 
21
- html = ApplicationController.render(inline: store_item.block_source, locals: {"#{store_item.block_variable_name}": resource.present_users_for_element_id(element_id)})
20
+ present_users = resource.present_users_for_element_id_and_scope(element_id, block_container.scope)
21
+
22
+ block_source = block_container.block_source
23
+
24
+ html = ApplicationController.render(inline: block_source.source, locals: {"#{block_source.variable_name}": present_users})
25
+
26
+ selector = "cubicle-element#cubicle-#{element_id}[identifier='#{signed_stream_identifier(resource.to_global_id.to_s)}'][scope='#{block_container.scope}']"
22
27
 
23
28
  cable_ready[element_id].inner_html(
24
- selector: "cubicle-element##{element_id}[identifier='#{signed_stream_identifier(resource.to_global_id.to_s)}']",
29
+ selector: selector,
25
30
  html: html
26
- ).broadcast
31
+ )
27
32
  end
33
+
34
+ cable_ready.broadcast
28
35
  end
29
36
  end
30
37
  end
@@ -49,6 +49,7 @@ module Cubism
49
49
  :block_source,
50
50
  :user_gid,
51
51
  :resource_gid,
52
+ :scope,
52
53
  keyword_init: true
53
54
  ) do
54
55
  def initialize(*args)
@@ -65,8 +66,12 @@ module Cubism
65
66
  GlobalID::Locator.locate self[:resource_gid]
66
67
  end
67
68
 
69
+ def scope
70
+ self[:scope] || ""
71
+ end
72
+
68
73
  def digest
69
- resource_user_key = [resource_gid, user_gid].join(":")
74
+ resource_user_key = [resource_gid, user_gid, scope].join(":")
70
75
 
71
76
  ActiveSupport::Digest.hexdigest("#{block_location}:#{File.read(@filename)}:#{resource_user_key}")
72
77
  end
@@ -44,11 +44,12 @@ module Cubism
44
44
  end
45
45
 
46
46
  # Container for cubicle blocks
47
- BlockStoreItem = Struct.new(
47
+ BlockContainer = Struct.new(
48
48
  :block_location,
49
49
  :block_source,
50
50
  :user_gid,
51
51
  :resource_gid,
52
+ :scope,
52
53
  keyword_init: true
53
54
  ) do
54
55
  def initialize(*args)
@@ -65,6 +66,10 @@ module Cubism
65
66
  GlobalID::Locator.locate self[:resource_gid]
66
67
  end
67
68
 
69
+ def scope
70
+ self[:scope] || ""
71
+ end
72
+
68
73
  def digest
69
74
  resource_user_key = [resource_gid, user_gid].join(":")
70
75
 
@@ -72,7 +77,7 @@ module Cubism
72
77
  end
73
78
 
74
79
  def marshal_dump
75
- to_h.reverse_merge(block_source: block_source.digest)
80
+ to_h.merge(block_source: block_source.digest)
76
81
  end
77
82
 
78
83
  def marshal_load(serialized_item)
@@ -80,7 +85,7 @@ module Cubism
80
85
  send("#{arg}=", serialized_item[arg])
81
86
  end
82
87
 
83
- self.block_source = Cubism.source_store(serialized_item[:block_source])
88
+ self.block_source = Cubism.source_store[serialized_item[:block_source]]
84
89
  end
85
90
  end
86
91
 
@@ -1,3 +1,3 @@
1
1
  module Cubism
2
- VERSION = "0.1.0.pre11"
2
+ VERSION = "0.1.0.pre12"
3
3
  end
@@ -1,3 +1,3 @@
1
1
  module Cubism
2
- VERSION = "0.1.0.pre9"
2
+ VERSION = "0.1.0.pre11"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cubism
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre11
4
+ version: 0.1.0.pre12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Rubisch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-16 00:00:00.000000000 Z
11
+ date: 2022-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails