twittermotion 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .repl_history
2
+ build
3
+ resources/*.nib
4
+ resources/*.momd
5
+ resources/*.storyboardc
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'bubble-wrap', ">=1.1.2"
4
+ gem 'geomotion'
5
+
6
+ # Specify your gem's dependencies in Routable.gemspec
7
+ gemspec
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # TwitterMotion, a RubyMotion Wrapper
2
+
3
+ ## Usage
4
+
5
+ Sign in:
6
+
7
+ ```ruby
8
+ Twitter.sign_in do |granted, ns_error|
9
+ # have fun
10
+ end
11
+ ```
12
+
13
+ See accounts:
14
+
15
+ ```ruby
16
+ > Twitter.accounts
17
+ => [#<Twitter::User>]
18
+ > Twitter.accounts[0].username
19
+ => "clayallsopp"
20
+ ```
21
+
22
+ Compose a tweet:
23
+
24
+ ```ruby
25
+ Twitter.accounts[0].compose(tweet: 'Hello RubyMotion!',
26
+ images: [ui_image], urls: ["http://clayallsopp.com"]) do |composer|
27
+ if composer.error
28
+ # check error.invalid_tweet/images/urls
29
+ elsif composer.cancelled?
30
+ # user didnt sent the tweet
31
+ elsif composer.done?
32
+ # user sent the tweet
33
+ end
34
+ end
35
+ ```
36
+
37
+ or without a user:
38
+
39
+ ```ruby
40
+ composer = Twitter::Composer.new
41
+ composer.compose(tweet: 'Hello RubyMotion!',
42
+ images: [ui_image], urls: ["http://clayallsopp.com"]) do |composer|
43
+ ...
44
+ end
45
+ ```
46
+
47
+ Grab a user's timeline:
48
+
49
+ ```ruby
50
+ user.get_timeline do |hash, ns_error|
51
+ p "Timeline #{hash}"
52
+ # => [{\"coordinates\"=>nil, \"truncated\"=>false.....}, ....]
53
+ end
54
+ ```
55
+
56
+ ## Installation
57
+
58
+ 1. `gem install twittermotion`
59
+
60
+ 2. Add `require 'twittermotion'` to your `Rakefile`
61
+
62
+ ## Pull Requests
63
+
64
+ It would be really cool if this was a fully-compatible Twitter API wrapper, so add whatever functionality you think helps!
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ $:.unshift("/Library/RubyMotion/lib")
2
+ require 'motion/project'
3
+ require "bundler/gem_tasks"
4
+
5
+ $:.unshift("./lib/")
6
+ require './lib/twittermotion'
7
+
8
+ Motion::Project::App.setup do |app|
9
+ # Use `rake config' to see complete project settings.
10
+ app.name = 'TwitterMotion'
11
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/twittermotion/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "twittermotion"
6
+ s.version = Twitter::VERSION
7
+ s.authors = ["Clay Allsopp"]
8
+ s.email = ["clay.allsopp@gmail.com"]
9
+ s.homepage = "https://github.com/clayallsopp/twittermotion"
10
+ s.summary = "A RubyMotion Twitter Wrapper"
11
+ s.description = "A RubyMotion Twitter Wrapper"
12
+
13
+ s.files = `git ls-files`.split($\)
14
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency "bubble-wrap", ">= 1.1.2"
18
+ s.add_development_dependency 'geomotion'
19
+ s.add_development_dependency 'rake'
20
+ end
@@ -0,0 +1,47 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
4
+ @controller = UIViewController.alloc.initWithNibName(nil, bundle:nil)
5
+ @window.rootViewController = @controller
6
+ @window.makeKeyAndVisible
7
+
8
+ Twitter.sign_in do |granted, error|
9
+ if granted
10
+ compose = UIButton.buttonWithType(UIButtonTypeRoundedRect)
11
+ compose.setTitle("Compose", forState:UIControlStateNormal)
12
+ compose.sizeToFit
13
+ @controller.view.addSubview(compose)
14
+ compose.when UIControlEventTouchUpInside do
15
+ account = Twitter.accounts[0]
16
+ account.compose(tweet: "Hello World!", urls: ["http://clayallsopp.com"]) do |composer|
17
+ p "Done? #{composer.done?}"
18
+ p "Cancelled? #{composer.cancelled?}"
19
+ p "Error #{composer.error.inspect}"
20
+ end
21
+ end
22
+
23
+ timeline = UIButton.buttonWithType(UIButtonTypeRoundedRect)
24
+ timeline.setTitle("Timeline", forState:UIControlStateNormal)
25
+ timeline.setTitle("Loading", forState:UIControlStateDisabled)
26
+ timeline.sizeToFit
27
+ timeline.frame = compose.frame.below(10)
28
+ @controller.view.addSubview(timeline)
29
+ timeline.when UIControlEventTouchUpInside do
30
+ timeline.enabled = false
31
+ account = Twitter.accounts[0]
32
+ account.get_timeline do |hash, error|
33
+ timeline.enabled = true
34
+ p "Timeline #{hash}"
35
+ end
36
+ end
37
+ else
38
+ label = UILabel.alloc.initWithFrame(CGRectZero)
39
+ label.text = "Denied :("
40
+ label.sizeToFit
41
+ label.center = @controller.view.frame.center
42
+ @controller.view.addSubview(label)
43
+ end
44
+ end
45
+ true
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ require "twittermotion/version"
2
+
3
+ unless defined?(Motion::Project::Config)
4
+ raise "This file must be required within a RubyMotion project Rakefile."
5
+ end
6
+
7
+ require 'bubble-wrap'
8
+ require 'geomotion'
9
+
10
+ Motion::Project::App.setup do |app|
11
+ Dir.glob(File.join(File.dirname(__FILE__), 'twittermotion/*.rb')).each do |file|
12
+ app.files.unshift(file)
13
+ end
14
+ app.frameworks += ["Twitter", "Accounts"]
15
+ end
@@ -0,0 +1,117 @@
1
+ module Twitter
2
+ class ComposerError
3
+ attr_accessor :invalid_tweet
4
+ attr_accessor :invalid_images
5
+ attr_accessor :invalid_urls
6
+
7
+ def initialize(tweet = nil, images = nil, urls = nil)
8
+ self.invalid_tweet = tweet
9
+ self.invalid_images = images
10
+ self.invalid_urls = urls
11
+ end
12
+ end
13
+
14
+ class Composer
15
+ def self.available?
16
+ TWTweetComposeViewController.canSendTweet
17
+ end
18
+
19
+ attr_accessor :compose_controller
20
+ attr_accessor :callback
21
+ attr_accessor :error, :result
22
+ attr_accessor :images, :urls, :tweet
23
+
24
+ def compose_controller
25
+ @compose_controller ||= TWTweetComposeViewController.new
26
+ end
27
+
28
+ def done?
29
+ @result == TWTweetComposeViewControllerResultDone
30
+ end
31
+
32
+ def cancelled?
33
+ @result == TWTweetComposeViewControllerResultCancelled
34
+ end
35
+
36
+ def urls=(urls)
37
+ self.compose_controller.removeAllURLs
38
+
39
+ invalid_urls = []
40
+ urls ||= []
41
+
42
+ urls.each do |url|
43
+ _url = url
44
+ if _url.is_a? NSString
45
+ _url = NSURL.URLWithString(url)
46
+ end
47
+ if !self.compose_controller.addURL(_url)
48
+ invalid_urls << url
49
+ end
50
+ end
51
+
52
+ if invalid_urls.length > 0
53
+ self.error ||= Twitter::ComposerError.new
54
+ self.error.invalid_urls = invalid_urls
55
+ end
56
+
57
+ @urls = urls
58
+ end
59
+
60
+ def images=(images)
61
+ self.compose_controller.removeAllImages
62
+
63
+ invalid_images = []
64
+ images ||= []
65
+ images.each do |ui_image|
66
+ if !self.compose_controller.addImage(ui_image)
67
+ invalid_images << ui_image
68
+ end
69
+ end
70
+
71
+ if invalid_images.length > 0
72
+ self.error ||= Twitter::ComposerError.new
73
+ self.error.invalid_images = invalid_images
74
+ end
75
+
76
+ @images = images
77
+ end
78
+
79
+ def tweet=(tweet)
80
+ if !self.compose_controller.setInitialText(tweet)
81
+ self.error ||= Twitter::ComposerError.new
82
+ self.error.invalid_tweet = tweet
83
+ end
84
+
85
+ @tweet = tweet
86
+ end
87
+
88
+ def compose(options = {}, &compose_callback)
89
+ self.error = nil
90
+
91
+ self.tweet = options[:tweet] || self.tweet
92
+ self.images = options[:images] || self.images
93
+ self.urls = options[:urls] || self.urls
94
+
95
+ if self.error
96
+ Dispatch::Queue.main.async {
97
+ compose_callback.call(self)
98
+ }
99
+ return
100
+ end
101
+
102
+ options[:animated] = true if !options.has_key? :animated
103
+ options[:presenting_controller] ||= UIWindow.keyWindow.rootViewController
104
+
105
+ self.callback ||= lambda { |composer|
106
+ self.compose_controller.dismissModalViewControllerAnimated(true)
107
+ compose_callback.call(self)
108
+ }
109
+ self.compose_controller.completionHandler = lambda { |result|
110
+ self.result = result
111
+ self.callback.call(self)
112
+ }
113
+
114
+ options[:presenting_controller].presentModalViewController(self.compose_controller, animated: options[:animated])
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,9 @@
1
+ class ACAccountType
2
+ alias_method :granted?, :accessGranted
3
+ alias_method :description, :accountTypeDescription
4
+ end
5
+
6
+ class ACAccount
7
+ alias_method :account_description, :accountDescription
8
+ alias_method :account_type, :accountType
9
+ end
@@ -0,0 +1,28 @@
1
+ module Twitter
2
+ module_function
3
+ def account_store
4
+ @account_store ||= ACAccountStore.new
5
+ end
6
+
7
+ def account_type
8
+ @account_type ||= self.account_store.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
9
+ end
10
+
11
+ def accounts
12
+ @accounts ||= self.account_store.accountsWithAccountType(account_type).collect do |ac_account|
13
+ Twitter::User.new(ac_account)
14
+ end
15
+ end
16
+
17
+ def sign_in(&block)
18
+ @sign_in_callback = block
19
+ self.account_store.requestAccessToAccountsWithType(self.account_type,
20
+ withCompletionHandler:lambda { |granted, error|
21
+ # Reset accounts
22
+ @accounts = nil
23
+ Dispatch::Queue.main.sync {
24
+ @sign_in_callback.call(granted, error)
25
+ }
26
+ })
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ module Twitter
2
+ class User
3
+ attr_accessor :ac_account
4
+
5
+ def initialize(ac_account)
6
+ self.ac_account = ac_account
7
+ end
8
+
9
+ def username
10
+ self.ac_account.username
11
+ end
12
+
13
+ # user.compose(tweet: 'initial tweet', images: [ui_image, ui_image],
14
+ # urls: ["http://", ns_url, ...]) do |composer|
15
+ #
16
+ # end
17
+ def compose(options = {}, &block)
18
+ @composer = Twitter::Composer.new
19
+ @composer.compose(options) do |composer|
20
+ block.call(composer)
21
+ end
22
+ end
23
+
24
+ # user.get_timeline(include_entities: 1) do |hash, ns_error|
25
+ # end
26
+ def get_timeline(options = {}, &block)
27
+ url = NSURL.URLWithString("http://api.twitter.com/1/statuses/home_timeline.json")
28
+ request = TWRequest.alloc.initWithURL(url, parameters:options, requestMethod:TWRequestMethodGET)
29
+ request.account = self.ac_account
30
+ request.performRequestWithHandler(lambda {|response_data, url_response, error|
31
+ if !response_data
32
+ block.call(nil, error)
33
+ else
34
+ block.call(BubbleWrap::JSON.parse(response_data), nil)
35
+ end
36
+ })
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module Twitter
2
+ VERSION = "0.0.1"
3
+ end
data/spec/main_spec.rb ADDED
@@ -0,0 +1,9 @@
1
+ describe "Application 'TwitterMotion'" do
2
+ before do
3
+ @app = UIApplication.sharedApplication
4
+ end
5
+
6
+ it "has one window" do
7
+ @app.windows.size.should == 1
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: twittermotion
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Clay Allsopp
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bubble-wrap
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.1.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: geomotion
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: A RubyMotion Twitter Wrapper
63
+ email:
64
+ - clay.allsopp@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - README.md
72
+ - Rakefile
73
+ - TwitterMotion.gemspec
74
+ - app/app_delegate.rb
75
+ - lib/twittermotion.rb
76
+ - lib/twittermotion/composer.rb
77
+ - lib/twittermotion/pollute.rb
78
+ - lib/twittermotion/twitter.rb
79
+ - lib/twittermotion/user.rb
80
+ - lib/twittermotion/version.rb
81
+ - spec/main_spec.rb
82
+ homepage: https://github.com/clayallsopp/twittermotion
83
+ licenses: []
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 1.8.23
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: A RubyMotion Twitter Wrapper
106
+ test_files:
107
+ - spec/main_spec.rb