rm-extensions 0.3.2 → 0.3.3

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
  SHA1:
3
- metadata.gz: 3cf1c7466015bfa9d247a7331ea115b3e2488fe2
4
- data.tar.gz: ab4897b30918931ff43d2f78a753b37f2dcce110
3
+ metadata.gz: 4638058073ecd449cd49a4ae5d0b2c0bcea20304
4
+ data.tar.gz: fda67c1392046c93f1c7de0c6de830cf68cd733b
5
5
  SHA512:
6
- metadata.gz: a1dd632b69fe168f2fa6aea6d46966b4658eae245689037b7b45bb08607266af6eb6bac8fcd0937d6fcd871efc0937cfac74b06758731d23a4a05e1e80c9139c
7
- data.tar.gz: d259f115de70b69418eb5a1b38ff62a33d33600b9613e9223b7e855e7e814dba03a598324aac0c8fc132972f463fe1af26fbe50ef6e1568b092f4f989ff7fc29
6
+ metadata.gz: d78724ff4f31f6014c7dc9732cc3a6a80919f3ccc38c0abc2668f51eb21c822b2eafb3e098488a7c12acbb2d708d6b33fca5662ad253c1034d9f34474052263d
7
+ data.tar.gz: ea9fb77064f3fb6904c8ec56ab0a50fac3f61b23d41dfeeec5d7ee4051442bb869b2c7a53664d0615dbdbe3f2aae6345cea99572b9f8cd4d8de92e16a34f0086
data/lib/motion/util.rb CHANGED
@@ -90,6 +90,124 @@ module RMExtensions
90
90
  true
91
91
  end
92
92
 
93
+ # call the block immediately if called on the main thread,
94
+ # otherwise call it async on the main queue
95
+ def rmext_inline_or_on_main_q(&block)
96
+ if NSThread.currentThread.isMainThread
97
+ block.call
98
+ else
99
+ rmext_on_main_q(&block)
100
+ end
101
+ end
102
+
103
+ # call the block immediately if called on the main thread with the given args,
104
+ # otherwise call it async on the main queue.
105
+ # silently ignores nil blocks to avoid if !block.nil? checks, useful for async callbacks
106
+ # that optionally take a callback
107
+ def rmext_block_on_main_q(block, *args)
108
+ unless block.nil?
109
+ rmext_inline_or_on_main_q do
110
+ block.call(*args)
111
+ end
112
+ end
113
+ end
114
+
115
+ ### EXPERIMENTAL
116
+
117
+ # takes a unique_id, run_immediately bool, and block
118
+ # if run_immediately is true, the block is executed immediately and not counted
119
+ # on the next run loop, the block will be called IF it has been counted at least once.
120
+ # examples:
121
+ #
122
+ # # CALLED will be printed twice. Onces immediately, and once on the next runloop:
123
+ # 10.times do
124
+ # rmext_debounce_on_next_runloop(:my_unique_id, true) do
125
+ # p "CALLED"
126
+ # end
127
+ # end
128
+ #
129
+ # # CALLED will be printed once, on the next runloop:
130
+ # 10.times do
131
+ # rmext_debounce_on_next_runloop(:my_unique_id, false) do
132
+ # p "CALLED"
133
+ # end
134
+ # end
135
+ #
136
+ # useful for queuing up something that should happen on the next runloop,
137
+ # but not every time its called. for example, reloadData. the goal was
138
+ # to get a similar behavior to how setNeedsDisplay/setNeedsLayout scheduled
139
+ # display/layout rendering on the next UI runloop pass
140
+ #
141
+ def rmext_debounce_on_next_runloop(unique_id, run_immediately, &block)
142
+ Thread.current["rmext_debounce_on_next_runloop"] ||= {}
143
+ lookup = Thread.current["rmext_debounce_on_next_runloop"]
144
+ if lookup.key?(unique_id)
145
+ lookup[unique_id][0] += 1
146
+ else
147
+ lookup[unique_id] = [ 0, lambda do
148
+ if (debounced_times = lookup[unique_id][0]) > 0
149
+ # p "we have", debounced_times, "debounced_times queued for unique_id", unique_id
150
+ block.call
151
+ else
152
+ # p "no debounced_times queued for unique_id", unique_id
153
+ end
154
+ lookup.delete(unique_id)
155
+ end ]
156
+ if run_immediately
157
+ block.call
158
+ else
159
+ lookup[unique_id][0] += 1
160
+ end
161
+ # p NSRunLoop.currentRunLoop, NSRunLoop.currentRunLoop.currentMode, lookup[unique_id][1]
162
+ NSRunLoop.currentRunLoop.performSelector('call', target:lookup[unique_id][1], argument:nil, order:0, modes:[NSRunLoop.currentRunLoop.currentMode])
163
+ end
164
+ end
165
+
166
+ def rmext_debounce_selector_on_next_runloop(selector, run_immediately)
167
+ Thread.current["rmext_debounce_selector_on_next_runloop"] ||= {}
168
+ lookup = Thread.current["rmext_debounce_selector_on_next_runloop"]
169
+ if lookup.key?(selector)
170
+ lookup[selector] += 1
171
+ else
172
+ lookup[selector] = 0
173
+ if run_immediately
174
+ send(selector)
175
+ else
176
+ lookup[selector] += 1
177
+ end
178
+ # p NSRunLoop.currentRunLoop, NSRunLoop.currentRunLoop.currentMode, self, selector, lookup[selector]
179
+ block = lambda do
180
+ if (debounced_times = lookup[selector]) > 0
181
+ # p "we have", debounced_times, "debounced_times queued for", self, selector
182
+ send(selector)
183
+ else
184
+ # p "no debounced_times queued for", self, selector
185
+ end
186
+ lookup.delete(selector)
187
+ end
188
+ NSRunLoop.currentRunLoop.performSelector('call', target:block, argument:nil, order:0, modes:[NSRunLoop.currentRunLoop.currentMode])
189
+ end
190
+ end
191
+
192
+ # more typical debouncing behavior
193
+ def rmext_debounced(method_name, seconds, *args)
194
+ new_method_name = "#{method_name}_#{seconds}"
195
+ unless respond_to?(new_method_name)
196
+ self.class.send(:define_method, new_method_name) do |*xargs|
197
+ xargs.unshift(method_name)
198
+ send(*xargs)
199
+ end
200
+ end
201
+ args.unshift(new_method_name)
202
+ NSObject.cancelPreviousPerformRequestsWithTarget(self, selector:"rmext_dispatch__send__", object:args)
203
+ performSelector("rmext_dispatch__send__", withObject:args, afterDelay:seconds)
204
+ end
205
+
206
+ # used internally by `rmext_debounced`
207
+ def rmext_dispatch__send__(*args)
208
+ send(*args)
209
+ end
210
+
93
211
  end
94
212
 
95
213
  end
@@ -1,3 +1,3 @@
1
1
  module RMExtensions
2
- VERSION = "0.3.2"
2
+ VERSION = "0.3.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rm-extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Noon