redpotion 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -11
- data/bin/potion +51 -43
- data/lib/project/ext/object.rb +4 -0
- data/lib/project/ext/ui_collection_view_cell.rb +17 -0
- data/lib/project/ext/ui_color.rb +4 -8
- data/lib/project/ext/ui_table_view_cell.rb +8 -0
- data/lib/project/pro_motion/data_table.rb +193 -0
- data/lib/project/pro_motion/data_table_screen.rb +15 -26
- data/lib/project/pro_motion/data_table_search_delegate.rb +15 -0
- data/lib/project/pro_motion/data_table_searchable.rb +89 -0
- data/lib/project/ruby_motion_query/app.rb +4 -0
- data/lib/project/version.rb +1 -1
- data/lib/redpotion.rb +1 -1
- data/templates/collection_view_screen/app/screens/name_screen.rb +1 -1
- data/templates/collection_view_screen/app/views/name_cell.rb +0 -8
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d02a5ebf83ee813131955bcb138df65d3c0d46df
|
4
|
+
data.tar.gz: 14409d48ae7de7f9a20cdd14205f0e3acc84f5bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdd6442f259a64cdc1a948dab9039d31378b0a264aaf532c663eddd9545ae869ba9ee8e95393bdf4263dad7244ef5fe05fa02e1ddf97b245cfae224237a1e487
|
7
|
+
data.tar.gz: 3e8249d43d27b7af83dab08bcd0941f4f5aacb925d12fa73f54eb5cb5522146dc2a34e3b6d804103585686d7378a37fe36faa4015e27a6c43fae130a677f8ac8
|
data/README.md
CHANGED
@@ -60,17 +60,6 @@ add it to your `Gemfile`:
|
|
60
60
|
|
61
61
|
- `gem 'redpotion'`
|
62
62
|
|
63
|
-
|
64
|
-
## Contributing
|
65
|
-
|
66
|
-
0. Create an issue in GitHub to make sure your PR will be accepted.
|
67
|
-
1. Fork it
|
68
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
69
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
70
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
71
|
-
5. Create new Pull Request
|
72
|
-
|
73
|
-
|
74
63
|
<br />
|
75
64
|
|
76
65
|
## Read the documentation at [docs.redpotion.org](http://docs.redpotion.org)
|
data/bin/potion
CHANGED
@@ -3,32 +3,31 @@
|
|
3
3
|
require "erb"
|
4
4
|
require "rubygems"
|
5
5
|
require 'open-uri'
|
6
|
-
|
7
|
-
$:.unshift(File.join(File.dirname(__FILE__), "/../lib/project"))
|
8
|
-
require "version"
|
6
|
+
require_relative "../lib/project/version"
|
9
7
|
|
10
8
|
class PotionCommandLine
|
11
9
|
HELP_TEXT = %{ potion version #{RedPotion::VERSION}
|
12
10
|
|
13
11
|
Some things you can do with the potion command:
|
14
12
|
|
15
|
-
> potion
|
16
|
-
> potion
|
13
|
+
> potion new my_new_app
|
14
|
+
> potion new my_new_app --skip-cdq # Setup application without CDQ
|
15
|
+
> potion new my_new_app --skip-afmotion # Setup application without afmotion
|
17
16
|
|
18
|
-
> potion
|
19
|
-
> potion
|
20
|
-
> potion
|
21
|
-
> potion
|
22
|
-
> potion
|
23
|
-
> potion
|
24
|
-
> potion
|
25
|
-
> potion
|
26
|
-
> potion
|
17
|
+
> potion g model foo
|
18
|
+
> potion g screen foo
|
19
|
+
> potion g table_screen foo
|
20
|
+
> potion g table_screen_cell bar_cell
|
21
|
+
> potion g metal_table_screen foo
|
22
|
+
> potion g collection_view_screen
|
23
|
+
> potion g view bar
|
24
|
+
> potion g shared some_class_used_app_wide
|
25
|
+
> potion g lib some_class_used_by_multiple_apps
|
27
26
|
|
28
27
|
You can still create controllers, but you should create screens instead
|
29
|
-
> potion
|
30
|
-
> potion
|
31
|
-
> potion
|
28
|
+
> potion g controller foos
|
29
|
+
> potion g collection_view_controller foos
|
30
|
+
> potion g table_view_controller bars
|
32
31
|
|
33
32
|
You can remove CDQ or afmotion if your project does not use it
|
34
33
|
> potion remove cdq
|
@@ -59,50 +58,53 @@ class PotionCommandLine
|
|
59
58
|
:table_view_controller
|
60
59
|
]
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
puts "potion - Invalid command, try adding an application name or template name."
|
61
|
+
def new(app_name, *options)
|
62
|
+
if app_name.nil?
|
63
|
+
puts "potion - Invalid command, try adding an application name. (ex: potion new my_app)\n"
|
66
64
|
return
|
67
65
|
end
|
68
66
|
|
69
67
|
options.compact!
|
68
|
+
#ensure_template_dir
|
69
|
+
create_app(app_name, options)
|
70
|
+
end
|
71
|
+
|
72
|
+
def generate(template, *options)
|
73
|
+
name = options.slice!(0)
|
74
|
+
if VALID_CREATE_TYPES.include?(template.to_sym)
|
75
|
+
insert_from_template(template, name)
|
76
|
+
else
|
77
|
+
puts "potion - Invalid command, do something like this: potion g controller my_controller\n"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def create(template_or_app_name, *options)
|
70
82
|
# Dry Run option - TODO - change this to --dry_run to streamline
|
71
83
|
if options.first == 'dry_run'
|
72
84
|
@dry_run = true
|
73
85
|
options.slice!(0)
|
74
86
|
end
|
75
87
|
|
76
|
-
if options.
|
77
|
-
|
78
|
-
name = options.slice!(0)
|
79
|
-
unless VALID_CREATE_TYPES.include?(template_or_app_name.to_sym)
|
80
|
-
puts "potion - Invalid command, do something like this: potion create controller my_controller\n"
|
81
|
-
return
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
if name
|
87
|
-
insert_from_template(template_or_app_name, name)
|
88
|
+
if options.first && options.first.include?('--')
|
89
|
+
new(template_or_app_name, *options)
|
88
90
|
else
|
89
|
-
|
90
|
-
create_app(template_or_app_name)
|
91
|
-
options.each do |option|
|
92
|
-
if SKIP_FLAGS.include?(option)
|
93
|
-
Dir.chdir("./#{template_or_app_name}")
|
94
|
-
remove(option.split('-').last, true)
|
95
|
-
Dir.chdir('..')
|
96
|
-
end
|
97
|
-
end
|
91
|
+
generate(template_or_app_name, *options)
|
98
92
|
end
|
99
93
|
end
|
100
94
|
|
101
|
-
def create_app(app_name)
|
95
|
+
def create_app(app_name, options)
|
102
96
|
puts ' Creating app'
|
103
97
|
|
104
98
|
`motion create --template=https://github.com/infinitered/redpotion-template.git #{app_name}`
|
105
99
|
|
100
|
+
options.each do |option|
|
101
|
+
if SKIP_FLAGS.include?(option)
|
102
|
+
Dir.chdir("./#{app_name}")
|
103
|
+
remove(option.split('-').last, true)
|
104
|
+
Dir.chdir('..')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
106
108
|
["bundle", "rake pod:install"].each do |command|
|
107
109
|
puts "Running #{command}..."
|
108
110
|
|
@@ -230,6 +232,7 @@ class PotionCommandLine
|
|
230
232
|
remove_lines('Rakefile', /schema:build/, show_output)
|
231
233
|
File.delete('schemas/0001_initial.rb') if File.exists?('schemas/0001_initial.rb')
|
232
234
|
File.delete('resources/cdq.yml') if File.exists?('resources/cdq.yml')
|
235
|
+
File.delete('spec/helpers/cdq.rb') if File.exists?('spec/helpers/cdq.rb')
|
233
236
|
Dir.delete('schemas') if Dir.exists?('schemas')
|
234
237
|
when 'afmotion'
|
235
238
|
remove_lines('Gemfile', /gem ('|")afmotion('|")/, show_output)
|
@@ -269,7 +272,12 @@ action = ARGV[0]
|
|
269
272
|
query = ARGV[1]
|
270
273
|
|
271
274
|
case action
|
275
|
+
when 'new'
|
276
|
+
PotionCommandLine.new(ARGV[1], ARGV[2], ARGV[3])
|
277
|
+
when 'g', 'generate'
|
278
|
+
PotionCommandLine.generate(ARGV[1], ARGV[2], ARGV[3])
|
272
279
|
when 'create'
|
280
|
+
# create provided as an alias for backwards compatibility
|
273
281
|
PotionCommandLine.create(ARGV[1], ARGV[2], ARGV[3])
|
274
282
|
when 'rmq_docs'
|
275
283
|
if query
|
data/lib/project/ext/object.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
class UICollectionViewCell
|
2
|
+
# You can use either rmq_build or on_load, not both. If you have both, on_load will be ignored,
|
3
|
+
# you can however call it from rmq_build. They are the same, on_load follows the ProMotion style
|
4
|
+
# and is recommended.
|
5
|
+
def rmq_build
|
6
|
+
self.on_load
|
7
|
+
end
|
8
|
+
|
9
|
+
def reused
|
10
|
+
@reused
|
11
|
+
end
|
12
|
+
|
13
|
+
def prepareForReuse
|
14
|
+
super
|
15
|
+
@reused = true
|
16
|
+
end
|
17
|
+
end
|
data/lib/project/ext/ui_color.rb
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
class UIColor
|
2
2
|
def with(options)
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
r, g, b, a = Pointer.new('f'), Pointer.new('f'), Pointer.new('f'), Pointer.new('f')
|
8
|
-
self.getRed(r, green: g, blue: b, alpha: a)
|
9
|
-
end
|
10
|
-
|
3
|
+
type = CGSize.type[/(f|d)/]
|
4
|
+
r, g, b, a = Pointer.new(type), Pointer.new(type), Pointer.new(type), Pointer.new(type)
|
5
|
+
self.getRed(r, green: g, blue: b, alpha: a)
|
6
|
+
|
11
7
|
r = options[:r] || options[:red] || r.value
|
12
8
|
g = options[:g] || options[:green] || g.value
|
13
9
|
b = options[:b] || options[:blue] || b.value
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class UITableViewCell
|
2
|
+
# You can use either rmq_build or on_load, not both. If you have both, on_load will be ignored,
|
3
|
+
# you can however call it from rmq_build. They are the same, on_load follows the ProMotion style
|
4
|
+
# and is recommended.
|
5
|
+
def rmq_build
|
6
|
+
self.on_load
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
module ProMotion
|
2
|
+
module DataTable
|
3
|
+
include TableClassMethods
|
4
|
+
include ProMotion::Styling
|
5
|
+
include ProMotion::Table
|
6
|
+
include ProMotion::TableBuilder
|
7
|
+
include ProMotion::TableDataBuilder
|
8
|
+
include ProMotion::Table::Utils
|
9
|
+
|
10
|
+
include ProMotion::Table::Searchable
|
11
|
+
include ProMotion::Table::Refreshable
|
12
|
+
include ProMotion::Table::Indexable
|
13
|
+
include ProMotion::Table::Longpressable
|
14
|
+
|
15
|
+
def table_view
|
16
|
+
self.view
|
17
|
+
end
|
18
|
+
|
19
|
+
# This has to be defined in order to inherit everything from TableScreen
|
20
|
+
def table_data
|
21
|
+
[{cells:[]}]
|
22
|
+
end
|
23
|
+
|
24
|
+
def screen_setup
|
25
|
+
set_up_fetch_controller
|
26
|
+
|
27
|
+
set_up_header_footer_views
|
28
|
+
set_up_searchable
|
29
|
+
set_up_refreshable
|
30
|
+
set_up_longpressable
|
31
|
+
set_up_row_height
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_up_fetch_controller
|
35
|
+
error_ptr = Pointer.new(:object)
|
36
|
+
fetch_controller.delegate = self
|
37
|
+
|
38
|
+
unless fetch_controller.performFetch(error_ptr)
|
39
|
+
raise "Error performing fetch: #{error_ptr[2].description}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def update_table_data(notification = nil)
|
44
|
+
if notification.nil?
|
45
|
+
table_view.reloadData
|
46
|
+
else
|
47
|
+
Dispatch::Queue.main.async do
|
48
|
+
fetch_controller.managedObjectContext.mergeChangesFromContextDidSaveNotification(notification)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def fetch_scope
|
54
|
+
@_fetch_scope ||= begin
|
55
|
+
if respond_to?(:model_query)
|
56
|
+
data_with_scope = model_query
|
57
|
+
else
|
58
|
+
data_with_scope = data_model.send(data_scope)
|
59
|
+
end
|
60
|
+
|
61
|
+
if data_with_scope.sort_descriptors.empty?
|
62
|
+
# Try to be smart about how we sort things if a sort descriptor doesn't exist
|
63
|
+
attributes = data_model.send(:attribute_names)
|
64
|
+
sort_attribute = nil
|
65
|
+
[:updated_at, :created_at, :id].each do |att|
|
66
|
+
sort_attribute ||= att if attributes.include?(att.to_s)
|
67
|
+
end
|
68
|
+
|
69
|
+
if sort_attribute
|
70
|
+
mp "The `#{data_model}` model scope `#{data_scope}` needs a sort descriptor. Add sort_by(:property) to your scope. Currently sorting by :#{sort_attribute}.", force_color: :yellow
|
71
|
+
data_model.send(data_scope).sort_by(sort_attribute)
|
72
|
+
else
|
73
|
+
# This is where the application says goodbye and dies in a fiery crash.
|
74
|
+
mp "The `#{data_model}` model scope `#{data_scope}` needs a sort descriptor. Add sort_by(:property) to your scope.", force_color: :yellow
|
75
|
+
end
|
76
|
+
else
|
77
|
+
data_with_scope
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def fetch_controller
|
83
|
+
if searching?
|
84
|
+
search_fetch_controller
|
85
|
+
else
|
86
|
+
@fetch_controller ||= NSFetchedResultsController.alloc.initWithFetchRequest(
|
87
|
+
fetch_scope.fetch_request,
|
88
|
+
managedObjectContext: fetch_scope.context,
|
89
|
+
sectionNameKeyPath: nil,
|
90
|
+
cacheName: nil
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def on_cell_created(cell, data)
|
96
|
+
# Do not call super here
|
97
|
+
self.rmq.build(cell)
|
98
|
+
end
|
99
|
+
|
100
|
+
def cell_at(args = {})
|
101
|
+
index_path = args.is_a?(Hash) ? args[:index_path] : args
|
102
|
+
c = object_at_index(index_path).cell
|
103
|
+
set_data_cell_defaults(c)
|
104
|
+
end
|
105
|
+
|
106
|
+
def object_at_index(i)
|
107
|
+
fetch_controller.objectAtIndexPath(i)
|
108
|
+
end
|
109
|
+
|
110
|
+
def data_model
|
111
|
+
self.class.data_model
|
112
|
+
end
|
113
|
+
|
114
|
+
def data_scope
|
115
|
+
self.class.data_scope
|
116
|
+
end
|
117
|
+
|
118
|
+
def searching?
|
119
|
+
@_data_table_searching || false
|
120
|
+
end
|
121
|
+
|
122
|
+
def search_string
|
123
|
+
@_data_table_search_string
|
124
|
+
end
|
125
|
+
|
126
|
+
def original_search_string
|
127
|
+
search_string
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.included(base)
|
131
|
+
base.extend(TableClassMethods)
|
132
|
+
end
|
133
|
+
|
134
|
+
# UITableViewDelegate methods
|
135
|
+
def numberOfSectionsInTableView(_)
|
136
|
+
fetch_controller.sections.count
|
137
|
+
end
|
138
|
+
|
139
|
+
def tableView(table_view, numberOfRowsInSection: section)
|
140
|
+
fetch_controller.sections[section].numberOfObjects
|
141
|
+
end
|
142
|
+
|
143
|
+
def tableView(table_view, didSelectRowAtIndexPath: index_path)
|
144
|
+
data_cell = cell_at(index_path: index_path)
|
145
|
+
table_view.deselectRowAtIndexPath(index_path, animated: true) unless data_cell[:keep_selection] == true
|
146
|
+
trigger_action(data_cell[:action], data_cell[:arguments], index_path) if data_cell[:action]
|
147
|
+
end
|
148
|
+
|
149
|
+
def tableView(_, cellForRowAtIndexPath: index_path)
|
150
|
+
params = index_path_to_section_index(index_path: index_path)
|
151
|
+
data_cell = cell_at(index_path: index_path)
|
152
|
+
return self.rmq.create(UITableViewCell) unless data_cell
|
153
|
+
|
154
|
+
create_table_cell(data_cell)
|
155
|
+
end
|
156
|
+
|
157
|
+
def tableView(_, willDisplayCell: table_cell, forRowAtIndexPath: index_path)
|
158
|
+
data_cell = cell_at(index_path: index_path)
|
159
|
+
table_cell.send(:will_display) if table_cell.respond_to?(:will_display)
|
160
|
+
table_cell.send(:restyle!) if table_cell.respond_to?(:restyle!) # Teacup compatibility
|
161
|
+
end
|
162
|
+
|
163
|
+
def tableView(table_view, heightForRowAtIndexPath: index_path)
|
164
|
+
(object_at_index(index_path).cell[:height] || table_view.rowHeight).to_f
|
165
|
+
end
|
166
|
+
|
167
|
+
def controllerWillChangeContent(controller)
|
168
|
+
# TODO - we should update the search results table when a new record is added
|
169
|
+
# or deleted or changed. For now, when the data changes, the search doesn't
|
170
|
+
# update. Closing the search will update the data and then searching again
|
171
|
+
# will show the new or changed content.
|
172
|
+
table_view.beginUpdates unless searching?
|
173
|
+
end
|
174
|
+
|
175
|
+
def controller(controller, didChangeObject: task, atIndexPath: index_path, forChangeType: change_type, newIndexPath: new_index_path)
|
176
|
+
unless searching?
|
177
|
+
case change_type
|
178
|
+
when NSFetchedResultsChangeInsert
|
179
|
+
table_view.insertRowsAtIndexPaths([new_index_path], withRowAnimation: UITableViewRowAnimationAutomatic)
|
180
|
+
when NSFetchedResultsChangeDelete
|
181
|
+
table_view.deleteRowsAtIndexPaths([index_path], withRowAnimation: UITableViewRowAnimationAutomatic)
|
182
|
+
when NSFetchedResultsChangeUpdate
|
183
|
+
table_view.reloadRowsAtIndexPaths([index_path], withRowAnimation: UITableViewRowAnimationAutomatic)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def controllerDidChangeContent(controller)
|
189
|
+
table_view.endUpdates unless searching?
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
end
|
@@ -1,39 +1,28 @@
|
|
1
1
|
module ProMotion
|
2
|
-
class DataTableScreen <
|
2
|
+
class DataTableScreen < TableViewController
|
3
|
+
include ProMotion::ScreenModule
|
4
|
+
include ProMotion::DataTable
|
5
|
+
|
3
6
|
class << self
|
4
|
-
def model(value,
|
7
|
+
def model(value, opts = {})
|
5
8
|
if value.method_defined?(:cell)
|
6
|
-
@
|
7
|
-
|
9
|
+
@opts = {
|
10
|
+
model: value,
|
11
|
+
scope: :all,
|
12
|
+
}.merge(opts)
|
8
13
|
else
|
9
14
|
raise "#{value} must define the cell method"
|
10
15
|
end
|
11
16
|
end
|
12
17
|
|
13
|
-
def data_model
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def table_data
|
18
|
-
[{
|
19
|
-
cells: cell_data
|
20
|
-
}]
|
21
|
-
end
|
22
|
-
|
23
|
-
def cell_data
|
24
|
-
return [] if data_model.nil?
|
25
|
-
|
26
|
-
data_model.send(data_scope).collect(&:cell)
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
18
|
+
def data_model
|
19
|
+
@opts[:model]
|
20
|
+
end
|
30
21
|
|
31
|
-
|
32
|
-
|
22
|
+
def data_scope
|
23
|
+
@opts[:scope]
|
24
|
+
end
|
33
25
|
end
|
34
26
|
|
35
|
-
def data_scope
|
36
|
-
self.class.data_scope
|
37
|
-
end
|
38
27
|
end
|
39
28
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class DataTableSeachDelegate
|
2
|
+
attr_accessor :parent
|
3
|
+
|
4
|
+
def searchDisplayController(controller, shouldReloadTableForSearchString:search_string)
|
5
|
+
parent.dt_searchDisplayController(controller, shouldReloadTableForSearchString:search_string)
|
6
|
+
end
|
7
|
+
|
8
|
+
def searchDisplayControllerWillEndSearch(controller)
|
9
|
+
parent.dt_searchDisplayControllerWillEndSearch(controller)
|
10
|
+
end
|
11
|
+
|
12
|
+
def searchDisplayControllerWillBeginSearch(controller)
|
13
|
+
parent.dt_searchDisplayControllerWillBeginSearch(controller)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module ProMotion
|
2
|
+
module Table
|
3
|
+
module Searchable
|
4
|
+
|
5
|
+
# Replace this method so that we can gather the predicate fields for DataTableScreen searchable
|
6
|
+
alias_method :old_set_searchable_param_defaults, :set_searchable_param_defaults
|
7
|
+
def set_searchable_param_defaults(params)
|
8
|
+
all_params = old_set_searchable_param_defaults(params)
|
9
|
+
|
10
|
+
if self.is_a?(ProMotion::DataTableScreen)
|
11
|
+
if params[:search_bar][:fields].nil?
|
12
|
+
raise "ERROR: You must specify fields:[:example] for your searchable DataTableScreen. It should be an array of fields you want searched in CDQ."
|
13
|
+
else
|
14
|
+
@data_table_predicate_fields = all_params[:search_bar][:fields]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
all_params[:delegate] = search_delegate
|
19
|
+
all_params
|
20
|
+
end
|
21
|
+
|
22
|
+
def search_fetch_controller
|
23
|
+
@_search_fetch_controller ||= new_frc_with_search(search_string)
|
24
|
+
end
|
25
|
+
|
26
|
+
def new_frc_with_search(search_string)
|
27
|
+
# Create the predicate from the predetermined fetch scope.
|
28
|
+
where = @data_table_predicate_fields.map{|f| "#{f} CONTAINS[cd] \"#{search_string}\"" }.join(" OR ")
|
29
|
+
search_scope = fetch_scope.where(where)
|
30
|
+
|
31
|
+
# Create the search FRC with the predicate and set delegate
|
32
|
+
search = NSFetchedResultsController.alloc.initWithFetchRequest(
|
33
|
+
search_scope.fetch_request,
|
34
|
+
managedObjectContext: search_scope.context,
|
35
|
+
sectionNameKeyPath: nil,
|
36
|
+
cacheName: nil
|
37
|
+
)
|
38
|
+
search.delegate = search_delegate
|
39
|
+
|
40
|
+
# Perform the fetch
|
41
|
+
error_ptr = Pointer.new(:object)
|
42
|
+
unless search.performFetch(error_ptr)
|
43
|
+
raise "Error performing fetch: #{error_ptr[2].description}"
|
44
|
+
end
|
45
|
+
|
46
|
+
search
|
47
|
+
end
|
48
|
+
|
49
|
+
def reset_search_frc
|
50
|
+
# Update the filter, in this case just blow away the FRC and let
|
51
|
+
# lazy evaluation create another with the relevant search info
|
52
|
+
@_search_fetch_controller.delegate = nil unless @_search_fetch_controller.nil?
|
53
|
+
@_search_fetch_controller = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def search_delegate
|
57
|
+
@_search_delegate ||= begin
|
58
|
+
d = DataTableSeachDelegate.new
|
59
|
+
d.parent = WeakRef.new(self)
|
60
|
+
d
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
######### iOS methods, headless camel case #######
|
65
|
+
|
66
|
+
def dt_searchDisplayController(controller, shouldReloadTableForSearchString:search_string)
|
67
|
+
@_data_table_search_string = search_string
|
68
|
+
reset_search_frc
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
def dt_searchDisplayControllerWillEndSearch(controller)
|
73
|
+
@_data_table_searching = false
|
74
|
+
@_search_fetch_controller.delegate = nil unless @_search_fetch_controller.nil?
|
75
|
+
@_search_fetch_controller = nil
|
76
|
+
@_data_table_search_string = nil
|
77
|
+
self.table_view.setScrollEnabled true
|
78
|
+
@table_search_display_controller.delegate.will_end_search if @table_search_display_controller.delegate.respond_to? "will_end_search"
|
79
|
+
update_table_data
|
80
|
+
end
|
81
|
+
|
82
|
+
def dt_searchDisplayControllerWillBeginSearch(controller)
|
83
|
+
@_data_table_searching = true
|
84
|
+
self.table_view.setScrollEnabled false
|
85
|
+
@table_search_display_controller.delegate.will_begin_search if @table_search_display_controller.delegate.respond_to? "will_begin_search"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/project/version.rb
CHANGED
data/lib/redpotion.rb
CHANGED
@@ -35,7 +35,7 @@ class <%= @name_camel_case %>Screen < UICollectionViewController
|
|
35
35
|
|
36
36
|
def collectionView(view, cellForItemAtIndexPath: index_path)
|
37
37
|
view.dequeueReusableCellWithReuseIdentifier(<%= @name.upcase %>_CELL_ID, forIndexPath: index_path).tap do |cell|
|
38
|
-
build(cell) unless cell.reused
|
38
|
+
self.rmq.build(cell) unless cell.reused
|
39
39
|
|
40
40
|
# Update cell's data here
|
41
41
|
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
class <%= @name_camel_case %>Cell < UICollectionViewCell
|
2
|
-
attr_reader :reused
|
3
|
-
|
4
2
|
def on_load
|
5
3
|
find(self).apply_style :<%= @name %>_cell
|
6
4
|
|
@@ -8,10 +6,4 @@ class <%= @name_camel_case %>Cell < UICollectionViewCell
|
|
8
6
|
# Add your subviews, init stuff here
|
9
7
|
# @foo = q.append!(UILabel, :foo)
|
10
8
|
end
|
11
|
-
|
12
|
-
def prepareForReuse
|
13
|
-
super
|
14
|
-
@reused = true
|
15
|
-
end
|
16
|
-
|
17
9
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redpotion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- InfiniteRed
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-07-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ruby_motion_query
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 1.
|
20
|
+
version: 1.6.1
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 1.
|
27
|
+
version: 1.6.1
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: ProMotion
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,11 +123,16 @@ files:
|
|
123
123
|
- lib/project/ext/kernel.rb
|
124
124
|
- lib/project/ext/object.rb
|
125
125
|
- lib/project/ext/pm_delegate.rb
|
126
|
+
- lib/project/ext/ui_collection_view_cell.rb
|
126
127
|
- lib/project/ext/ui_color.rb
|
127
128
|
- lib/project/ext/ui_image_view.rb
|
129
|
+
- lib/project/ext/ui_table_view_cell.rb
|
128
130
|
- lib/project/ext/ui_view.rb
|
129
131
|
- lib/project/ext/ui_view_controller.rb
|
132
|
+
- lib/project/pro_motion/data_table.rb
|
130
133
|
- lib/project/pro_motion/data_table_screen.rb
|
134
|
+
- lib/project/pro_motion/data_table_search_delegate.rb
|
135
|
+
- lib/project/pro_motion/data_table_searchable.rb
|
131
136
|
- lib/project/pro_motion/screen.rb
|
132
137
|
- lib/project/pro_motion/support.rb
|
133
138
|
- lib/project/pro_motion/table.rb
|