Skip to content

Commit

Permalink
Merge pull request #349 from colinta/network_indicator
Browse files Browse the repository at this point in the history
adds 'BW::NetworkIndicator'
  • Loading branch information
clayallsopp committed Mar 10, 2014
2 parents a7e69a1 + a53a35c commit bec9c64
Show file tree
Hide file tree
Showing 9 changed files with 330 additions and 22 deletions.
37 changes: 36 additions & 1 deletion README.md
Expand Up @@ -93,6 +93,12 @@ If you wish to only include the `SMS` wrapper:
require 'bubble-wrap/sms'
```

If you wish to only include the `NetworkIndicator` wrapper:

```ruby
require 'bubble-wrap/network-indicator'
```

If you want to include everything (ie kitchen sink mode) you can save time and do:

```ruby
Expand Down Expand Up @@ -452,7 +458,36 @@ Wrapper for showing an in-app message (SMS) composer view.
result.canceled? # => boolean
result.failed? # => boolean
error # => NSError
}
}
```

## NetworkIndicator

Wrapper for showing and hiding the network indicator (the status bar spinner).

```ruby
BW::NetworkIndicator.show # starts the spinner
BW::NetworkIndicator.hide # stops it

# the nice thing is if you call 'show' multiple times, the 'hide' method will
# not have any effect until you've called it the same number of times.
BW::NetworkIndicator.show
# ...somewhere else
BW::NetworkIndicator.show

# ...down the line
BW::NetworkIndicator.hide
# indicator is still visible

BW::NetworkIndicator.hide
# NOW the indicator is hidden!

# If you *really* want to hide the indicator immediately, you can call `reset!`
# but this is in no way encouraged.
BW::NetworkIndicator.reset!

# and for completeness, a check to see if the indicator is visible
BW::NetworkIndicator.visible?
```

## UI
Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Expand Up @@ -28,7 +28,7 @@ Motion::Project::App.setup do |app|
app.spec_files
if Motion::Project::App.osx?
app.spec_files -= Dir.glob("./spec/motion/**/ios/**.rb")
["font", "location", "media", "ui", "mail", "sms"].each do |package|
["font", "location", "media", "ui", "mail", "sms", "network-indicator"].each do |package|
app.spec_files -= Dir.glob("./spec/motion/#{package}/**/*.rb")
end
else
Expand Down
2 changes: 1 addition & 1 deletion lib/bubble-wrap/all.rb
@@ -1,4 +1,4 @@
require File.expand_path('../loader', __FILE__)
['core', 'http', 'reactor', 'rss_parser', 'ui', 'location', 'media', 'font', 'mail','sms'].each { |sub|
['core', 'http', 'reactor', 'rss_parser', 'ui', 'location', 'media', 'font', 'mail','sms', 'network-indicator'].each { |sub|
require File.expand_path("../#{sub}", __FILE__)
}
1 change: 1 addition & 0 deletions lib/bubble-wrap/http.rb
@@ -1,5 +1,6 @@
require 'bubble-wrap/version' unless defined?(BubbleWrap::VERSION)
require 'bubble-wrap/loader'
require 'bubble-wrap/network-indicator'
BubbleWrap.require('motion/core/ns_url_request.rb')
BubbleWrap.require('motion/core.rb')
BubbleWrap.require('motion/http.rb')
Expand Down
6 changes: 6 additions & 0 deletions lib/bubble-wrap/network-indicator.rb
@@ -0,0 +1,6 @@
require 'bubble-wrap/loader'

BubbleWrap.require_ios("network-indicator") do
BubbleWrap.require('motion/core/app.rb')
BubbleWrap.require('motion/network-indicator/**/*.rb')
end
33 changes: 24 additions & 9 deletions motion/http/query.rb
Expand Up @@ -69,6 +69,10 @@ def to_s
end
alias description to_s

def done?
@did_fail_error || @did_finish_loading || @canceled
end

def connection(connection, didReceiveResponse:response)
# On OSX, if using an FTP connection, this method will fire *immediately* after creating an
# NSURLConnection, even if the connection has not yet started. The `response`
Expand Down Expand Up @@ -99,13 +103,10 @@ def connection(connection, willSendRequest:request, redirectResponse:redirect_re
log "##{@redirect_count} HTTP redirect_count: #{request.inspect} - #{self.description}"

if @redirect_count >= 30
@response.error = NSError.errorWithDomain('BubbleWrap::HTTP', code:NSURLErrorHTTPTooManyRedirects,
error = NSError.errorWithDomain('BubbleWrap::HTTP', code:NSURLErrorHTTPTooManyRedirects,
userInfo:NSDictionary.dictionaryWithObject("Too many redirections",
forKey: NSLocalizedDescriptionKey))
@response.error_message = @response.error.localizedDescription
show_status_indicator false
@request.done_loading!
call_delegator_with_response
self.connection(connection, didFailWithError: error)
nil
else
@url = request.URL if @follow_urls
Expand All @@ -114,6 +115,9 @@ def connection(connection, willSendRequest:request, redirectResponse:redirect_re
end

def connection(connection, didFailWithError: error)
return if done?

@did_fail_error = error
log "HTTP Connection to #{@url.absoluteString} failed #{error.localizedDescription}"
show_status_indicator false
@request.done_loading!
Expand All @@ -129,6 +133,9 @@ def connection(connection, didSendBodyData:sending, totalBytesWritten:written, t
end

def connectionDidFinishLoading(connection)
return if done?
@did_finish_loading = true

show_status_indicator false
@request.done_loading!
response_body = NSData.dataWithData(@received_data) if @received_data
Expand Down Expand Up @@ -156,6 +163,9 @@ def connection(connection, didReceiveAuthenticationChallenge:challenge)
end

def cancel
return if done?
@canceled = true

@connection.cancel
show_status_indicator false
@request.done_loading!
Expand All @@ -170,8 +180,13 @@ def did_receive_response(response)
end

def show_status_indicator(show)
if App.ios?
UIApplication.sharedApplication.networkActivityIndicatorVisible = show
if App.ios? && (@status.nil? || @status != !!show)
@status = !!show
if show
BW::NetworkIndicator.show
else
BW::NetworkIndicator.hide
end
end
end

Expand Down Expand Up @@ -276,8 +291,8 @@ def append_auth_header
def parse_file(key, value)
value = {data: value} unless value.is_a?(Hash)
raise(InvalidFileError, "You need to supply a `:data` entry in #{value} for file '#{key}' in your HTTP `:files`") if value[:data].nil?
{
data: value[:data],
{
data: value[:data],
filename: value.fetch(:filename, key),
content_type: value.fetch(:content_type, "application/octet-stream")
}
Expand Down
67 changes: 67 additions & 0 deletions motion/network-indicator/network-indicator.rb
@@ -0,0 +1,67 @@
module BubbleWrap
module NetworkIndicator
DELAY = 0.2

module_function

def counter
@counter ||= 0
end

def show
if Dispatch::Queue.current.to_s == 'com.apple.main-thread'
@counter = self.counter + 1
self.update_spinner
else
Dispatch::Queue.main.async do
self.show
end
end
end

def hide
if Dispatch::Queue.current.to_s == 'com.apple.main-thread'
@counter = [self.counter - 1, 0].max
if self.counter == 0
if @hide_indicator_timer
@hide_indicator_timer.invalidate
end
@hide_indicator_timer = NSTimer.timerWithTimeInterval(DELAY - 0.01, target: self, selector: :update_spinner_timer, userInfo: nil, repeats: false)
NSRunLoop.mainRunLoop.addTimer(@hide_indicator_timer, forMode:NSRunLoopCommonModes)
end
else
Dispatch::Queue.main.async do
self.hide
end
end
end

def update_spinner_timer
update_spinner
end

def update_spinner
if Dispatch::Queue.current.to_s == 'com.apple.main-thread'
if @hide_indicator_timer
@hide_indicator_timer.invalidate
@hide_indicator_timer = nil
end
UIApplication.sharedApplication.networkActivityIndicatorVisible = (@counter > 0)
else
Dispatch::Queue.main.async do
self.update_spinner
end
end
end

def visible?
UIApplication.sharedApplication.networkActivityIndicatorVisible?
end

def reset!
@counter = 0
self.update_spinner
end

end
end

0 comments on commit bec9c64

Please sign in to comment.