redpotion 1.3.0 → 1.4.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/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
|