twterm 1.0.12 → 1.1.0.beta1

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/twterm.rb +15 -8
  3. data/lib/twterm/app.rb +2 -3
  4. data/lib/twterm/client.rb +218 -68
  5. data/lib/twterm/filterable_list.rb +2 -1
  6. data/lib/twterm/friendship.rb +124 -0
  7. data/lib/twterm/list.rb +5 -3
  8. data/lib/twterm/promise.rb +143 -0
  9. data/lib/twterm/screen.rb +0 -1
  10. data/lib/twterm/status.rb +15 -14
  11. data/lib/twterm/tab/base.rb +15 -1
  12. data/lib/twterm/tab/key_assignments_cheatsheet.rb +7 -19
  13. data/lib/twterm/tab/new/list.rb +9 -15
  14. data/lib/twterm/tab/new/search.rb +9 -17
  15. data/lib/twterm/tab/new/start.rb +90 -29
  16. data/lib/twterm/tab/new/user.rb +5 -7
  17. data/lib/twterm/tab/scrollable.rb +36 -4
  18. data/lib/twterm/tab/statuses/base.rb +240 -0
  19. data/lib/twterm/tab/statuses/conversation.rb +54 -0
  20. data/lib/twterm/tab/statuses/favorites.rb +45 -0
  21. data/lib/twterm/tab/statuses/home.rb +36 -0
  22. data/lib/twterm/tab/statuses/list_timeline.rb +47 -0
  23. data/lib/twterm/tab/statuses/mentions.rb +40 -0
  24. data/lib/twterm/tab/statuses/search.rb +42 -0
  25. data/lib/twterm/tab/statuses/user_timeline.rb +51 -0
  26. data/lib/twterm/tab/user_tab.rb +288 -19
  27. data/lib/twterm/tab/users/base.rb +90 -0
  28. data/lib/twterm/tab/users/followers.rb +41 -0
  29. data/lib/twterm/tab/users/friends.rb +41 -0
  30. data/lib/twterm/tab_manager.rb +13 -5
  31. data/lib/twterm/user.rb +67 -8
  32. data/lib/twterm/version.rb +1 -1
  33. data/spec/twterm/friendship_spec.rb +104 -0
  34. metadata +18 -11
  35. data/lib/twterm/tab/conversation_tab.rb +0 -49
  36. data/lib/twterm/tab/list_tab.rb +0 -44
  37. data/lib/twterm/tab/mentions_tab.rb +0 -36
  38. data/lib/twterm/tab/search_tab.rb +0 -40
  39. data/lib/twterm/tab/statuses_tab.rb +0 -251
  40. data/lib/twterm/tab/timeline_tab.rb +0 -31
  41. data/lib/twterm/user_window.rb +0 -71
@@ -0,0 +1,90 @@
1
+ module Twterm
2
+ module Tab
3
+ module Users
4
+ module Base
5
+ include Tab::Base
6
+ include FilterableList
7
+ include Scrollable
8
+
9
+ attr_reader :user_ids
10
+
11
+ def drawable_item_count
12
+ (window.maxy - 6).div(3)
13
+ end
14
+
15
+ def close
16
+ @instance_keeper.kill
17
+ super
18
+ end
19
+
20
+ def fetch; end
21
+
22
+ def initialize
23
+ super()
24
+ @user_ids = []
25
+
26
+ @instance_keeper = Scheduler.new(300) { items.each(&:touch!) }
27
+ end
28
+
29
+ def items
30
+ users = user_ids.map { |id| User.find(id) }.reject(&:nil?)
31
+ filter_query.empty? ? users : users.select { |user| user.matches?(filter_query) }
32
+ end
33
+
34
+ def respond_to_key(key)
35
+ return true if scroller.respond_to_key(key)
36
+
37
+ case key
38
+ when 10, ?U
39
+ show_user
40
+ when 18
41
+ fetch
42
+ when ?q
43
+ reset_filter
44
+ when ?/
45
+ filter
46
+ else
47
+ return false
48
+ end
49
+
50
+ true
51
+ end
52
+
53
+ def title
54
+ 'User list'
55
+ end
56
+
57
+ private
58
+
59
+ def show_user
60
+ user = current_item
61
+ tab = Tab::UserTab.new(user.id)
62
+ TabManager.instance.add_and_show(tab)
63
+ end
64
+
65
+ def update
66
+ window.setpos(2, 3)
67
+ window.bold { window.addstr(title) }
68
+
69
+ drawable_items.each.with_index(0) do |user, i|
70
+ window.with_color(:black, :magenta) do
71
+ window.setpos(i * 3 + 5, 3)
72
+ window.addch(' ')
73
+ window.setpos(i * 3 + 6, 3)
74
+ window.addch(' ')
75
+ end if scroller.current_item?(i)
76
+
77
+ window.setpos(i * 3 + 5, 5)
78
+ window.bold { window.with_color(user.color) { window.addstr(user.name) } }
79
+ window.addstr(" (@#{user.screen_name})")
80
+ window.with_color(:yellow) { window.addstr(' [protected]') } if user.protected?
81
+ window.with_color(:cyan) { window.addstr(' [verified]') } if user.verified?
82
+ window.setpos(i * 3 + 6, 7)
83
+ bio_chunks = user.description.gsub(/[\n\r]/, ' ').split_by_width(window.maxx - 10)
84
+ window.addstr(bio_chunks[0] + (bio_chunks[1].nil? ? '' : '...'))
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,41 @@
1
+ module Twterm
2
+ module Tab
3
+ module Users
4
+ class Followers
5
+ include Base
6
+ include Dumpable
7
+
8
+ attr_reader :user_id
9
+
10
+ def dump
11
+ user_id
12
+ end
13
+
14
+ def fetch
15
+ Client.current.followers(user_id) do |users|
16
+ @user_ids.concat(users.map(&:id)).uniq!
17
+ refresh
18
+ end
19
+ end
20
+
21
+ def initialize(user_id)
22
+ super()
23
+
24
+ @user_id = user_id
25
+
26
+ fetch { move_to_top }
27
+ end
28
+
29
+ def title
30
+ user.nil? ? 'Loading...' : "@#{user.screen_name} followers"
31
+ end
32
+
33
+ private
34
+
35
+ def user
36
+ User.find(user_id)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ module Twterm
2
+ module Tab
3
+ module Users
4
+ class Friends
5
+ include Base
6
+ include Dumpable
7
+
8
+ attr_reader :user_id
9
+
10
+ def dump
11
+ user_id
12
+ end
13
+
14
+ def fetch
15
+ Client.current.friends(user_id) do |users|
16
+ @user_ids.concat(users.map(&:id)).uniq!
17
+ refresh
18
+ end
19
+ end
20
+
21
+ def initialize(user_id)
22
+ super()
23
+
24
+ @user_id = user_id
25
+
26
+ fetch { move_to_top }
27
+ end
28
+
29
+ def title
30
+ user.nil? ? 'Loading...' : "@#{user.screen_name} following"
31
+ end
32
+
33
+ private
34
+
35
+ def user
36
+ User.find(user_id)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -66,7 +66,13 @@ module Twterm
66
66
  @index = 0
67
67
  @history = []
68
68
 
69
- @window = stdscr.subwin(3, stdscr.maxx - 30, 0, 0)
69
+ @window = stdscr.subwin(3, stdscr.maxx, 0, 0)
70
+ end
71
+
72
+ def open_my_profile
73
+ current_user_id = Client.current.user_id
74
+ tab = Tab::UserTab.new(current_user_id)
75
+ add_and_show(tab)
70
76
  end
71
77
 
72
78
  def open_new
@@ -112,13 +118,15 @@ module Twterm
112
118
 
113
119
  def respond_to_key(key)
114
120
  case key
115
- when 'h', 2, Key::LEFT
121
+ when ?h, 2, Key::LEFT
116
122
  show_previous
117
- when 'l', 6, Key::RIGHT
123
+ when ?l, 6, Key::RIGHT
118
124
  show_next
119
- when 'N'
125
+ when ?P
126
+ open_my_profile
127
+ when ?N
120
128
  open_new
121
- when 'w'
129
+ when ?w
122
130
  close
123
131
  else
124
132
  return false
data/lib/twterm/user.rb CHANGED
@@ -1,16 +1,40 @@
1
1
  module Twterm
2
2
  class User
3
- attr_reader :id, :name, :screen_name, :description, :location, :website,
4
- :following, :protected, :statuses_count, :friends_count,
5
- :followers_count, :touched_at, :color
6
- alias_method :following?, :following
3
+ attr_reader :color, :description, :favorites_count, :followers_count,
4
+ :friends_count, :id, :location, :name, :protected,
5
+ :screen_name, :statuses_count, :touched_at, :verified, :website
7
6
  alias_method :protected?, :protected
7
+ alias_method :verified?, :verified
8
8
 
9
9
  MAX_CACHED_TIME = 3600
10
10
  COLORS = [:red, :blue, :green, :cyan, :yellow, :magenta]
11
11
 
12
12
  @@instances = {}
13
13
 
14
+ def blocked_by?(user_id)
15
+ Friendship.blocking?(user_id, id)
16
+ end
17
+
18
+ def blocking?(user_id)
19
+ Friendship.blocking?(id, user_id)
20
+ end
21
+
22
+ def followed_by?(user_id)
23
+ Friendship.following?(user_id, id)
24
+ end
25
+
26
+ def following?(user_id)
27
+ Friendship.following?(id, user_id)
28
+ end
29
+
30
+ def following_requested?(user_id)
31
+ Friendship.following_requested?(id, user_id)
32
+ end
33
+
34
+ def following_requested_by?(user_id)
35
+ Friendship.following_requested?(user_id, id)
36
+ end
37
+
14
38
  def initialize(user)
15
39
  @id = user.id
16
40
  update!(user)
@@ -20,6 +44,18 @@ module Twterm
20
44
  @@instances[@id] = self
21
45
  end
22
46
 
47
+ def matches?(query)
48
+ [name, screen_name, description, website].any? { |x| x.to_s.downcase.include? query.downcase }
49
+ end
50
+
51
+ def muted_by?(user_id)
52
+ Friendship.muting?(user_id, id)
53
+ end
54
+
55
+ def muting?(user_id)
56
+ Friendship.muting?(id, user_id)
57
+ end
58
+
23
59
  def touch!
24
60
  @touched_at = Time.now
25
61
  end
@@ -30,11 +66,26 @@ module Twterm
30
66
  @description = user.description || ''
31
67
  @location = user.location.is_a?(Twitter::NullObject) ? '' : user.location
32
68
  @website = user.website
33
- @following = user.following?
34
69
  @protected = user.protected?
35
70
  @statuses_count = user.statuses_count
71
+ @favorites_count = user.favorites_count
36
72
  @friends_count = user.friends_count
37
73
  @followers_count = user.followers_count
74
+ @verified = user.verified?
75
+
76
+ client_id = Client.current.user_id
77
+
78
+ if user.following?
79
+ Friendship.follow(client_id, user.id)
80
+ else
81
+ Friendship.unfollow(client_id, user.id)
82
+ end
83
+
84
+ if user.follow_request_sent?
85
+ Friendship.following_requested(client_id, user.id)
86
+ else
87
+ Friendship.following_not_requested(client_id, user.id)
88
+ end
38
89
 
39
90
  History::ScreenName.instance.add(user.screen_name)
40
91
 
@@ -50,10 +101,14 @@ module Twterm
50
101
  end
51
102
 
52
103
  def self.find_or_fetch(id)
53
- instance = find(id)
54
- (yield(instance) && return) if instance
104
+ Promise.new do |resolve, reject|
105
+ instance = find(id)
106
+ (resolve.(instance) && next) if instance
55
107
 
56
- Client.current.show_user(id) { |user| yield user }
108
+ Client.current.show_user(id).then do |user|
109
+ resolve.(user)
110
+ end
111
+ end
57
112
  end
58
113
 
59
114
  def self.cleanup
@@ -66,6 +121,10 @@ module Twterm
66
121
  @@instances = user_ids.zip(users).to_h
67
122
  end
68
123
 
124
+ def self.ids
125
+ @@instances.keys
126
+ end
127
+
69
128
  def self.new(user)
70
129
  instance = find(user.id)
71
130
  instance.nil? ? super : instance.update!(user)
@@ -1,3 +1,3 @@
1
1
  module Twterm
2
- VERSION = '1.0.12'
2
+ VERSION = '1.1.0.beta1'
3
3
  end
@@ -0,0 +1,104 @@
1
+ describe Twterm::Friendship do
2
+ describe '.already_looked_up?' do
3
+ before do
4
+ described_class.looked_up!(1)
5
+ end
6
+
7
+ it 'returns true when the user is already looked up' do
8
+ expect(described_class.already_looked_up?(1)).to be true
9
+ end
10
+
11
+ it 'returns false when the user is not looked up yet' do
12
+ expect(described_class.already_looked_up?(2)).to be false
13
+ end
14
+ end
15
+
16
+ describe '.blocking?' do
17
+ before do
18
+ described_class.block(1, 2)
19
+ end
20
+
21
+ it 'returns true when user 1 blocks user 2' do
22
+ expect(described_class.blocking?(1, 2)).to be true
23
+ end
24
+
25
+ it 'returns false when user 1 does not block user 2' do
26
+ expect(described_class.blocking?(2, 1)).to be false
27
+ end
28
+ end
29
+
30
+ describe '.following?' do
31
+ before do
32
+ described_class.follow(1, 2)
33
+ end
34
+
35
+ it 'returns true when user 1 follows user 2' do
36
+ expect(described_class.following?(1, 2)).to be true
37
+ end
38
+
39
+ it 'returns false when user 1 does not follow user 2' do
40
+ expect(described_class.following?(2, 1)).to be false
41
+ end
42
+ end
43
+
44
+ describe '.following_requested?' do
45
+ before do
46
+ described_class.following_requested(1, 2)
47
+ end
48
+
49
+ it 'returns true when user 1 have sent following request to user 2' do
50
+ expect(described_class.following_requested?(1, 2)).to be true
51
+ end
52
+
53
+ it 'returns false when user 1 have not sent following request to user 2' do
54
+ expect(described_class.following_requested?(2, 1)).to be false
55
+ end
56
+ end
57
+
58
+ describe '.muting?' do
59
+ before do
60
+ described_class.mute(1, 2)
61
+ end
62
+
63
+ it 'returns true when user 1 mutes user 2' do
64
+ expect(described_class.muting?(1, 2)).to be true
65
+ end
66
+
67
+ it 'returns false when user 1 does not mute user 2' do
68
+ expect(described_class.muting?(2, 1)).to be false
69
+ end
70
+ end
71
+
72
+ describe '.unblock' do
73
+ before do
74
+ described_class.block(1, 2)
75
+ end
76
+
77
+ it 'works' do
78
+ described_class.unblock(1, 2)
79
+ expect(described_class.blocking?(1, 2)).to be false
80
+ end
81
+ end
82
+
83
+ describe '.unfollow' do
84
+ before do
85
+ described_class.follow(1, 2)
86
+ end
87
+
88
+ it 'works' do
89
+ described_class.unfollow(1, 2)
90
+ expect(described_class.following?(1, 2)).to be false
91
+ end
92
+ end
93
+
94
+ describe '.unmute' do
95
+ before do
96
+ described_class.mute(1, 2)
97
+ end
98
+
99
+ it 'works' do
100
+ described_class.unmute(1, 2)
101
+ expect(described_class.muting?(1, 2)).to be false
102
+ end
103
+ end
104
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twterm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.12
4
+ version: 1.1.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryota Kameoka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-09 00:00:00.000000000 Z
11
+ date: 2015-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curses
@@ -164,6 +164,7 @@ files:
164
164
  - lib/twterm/extensions/string.rb
165
165
  - lib/twterm/filter_query_window.rb
166
166
  - lib/twterm/filterable_list.rb
167
+ - lib/twterm/friendship.rb
167
168
  - lib/twterm/history/base.rb
168
169
  - lib/twterm/history/hashtag.rb
169
170
  - lib/twterm/history/screen_name.rb
@@ -172,34 +173,40 @@ files:
172
173
  - lib/twterm/notification/error.rb
173
174
  - lib/twterm/notification/message.rb
174
175
  - lib/twterm/notifier.rb
176
+ - lib/twterm/promise.rb
175
177
  - lib/twterm/scheduler.rb
176
178
  - lib/twterm/screen.rb
177
179
  - lib/twterm/status.rb
178
180
  - lib/twterm/tab/base.rb
179
- - lib/twterm/tab/conversation_tab.rb
180
181
  - lib/twterm/tab/dumpable.rb
181
182
  - lib/twterm/tab/exceptions.rb
182
183
  - lib/twterm/tab/favorites.rb
183
184
  - lib/twterm/tab/key_assignments_cheatsheet.rb
184
- - lib/twterm/tab/list_tab.rb
185
- - lib/twterm/tab/mentions_tab.rb
186
185
  - lib/twterm/tab/new/list.rb
187
186
  - lib/twterm/tab/new/search.rb
188
187
  - lib/twterm/tab/new/start.rb
189
188
  - lib/twterm/tab/new/user.rb
190
189
  - lib/twterm/tab/scrollable.rb
191
- - lib/twterm/tab/search_tab.rb
192
- - lib/twterm/tab/statuses_tab.rb
193
- - lib/twterm/tab/timeline_tab.rb
190
+ - lib/twterm/tab/statuses/base.rb
191
+ - lib/twterm/tab/statuses/conversation.rb
192
+ - lib/twterm/tab/statuses/favorites.rb
193
+ - lib/twterm/tab/statuses/home.rb
194
+ - lib/twterm/tab/statuses/list_timeline.rb
195
+ - lib/twterm/tab/statuses/mentions.rb
196
+ - lib/twterm/tab/statuses/search.rb
197
+ - lib/twterm/tab/statuses/user_timeline.rb
194
198
  - lib/twterm/tab/user_tab.rb
199
+ - lib/twterm/tab/users/base.rb
200
+ - lib/twterm/tab/users/followers.rb
201
+ - lib/twterm/tab/users/friends.rb
195
202
  - lib/twterm/tab_manager.rb
196
203
  - lib/twterm/tweetbox.rb
197
204
  - lib/twterm/user.rb
198
- - lib/twterm/user_window.rb
199
205
  - lib/twterm/version.rb
200
206
  - spec/resources/config
201
207
  - spec/spec_helper.rb
202
208
  - spec/twterm/config_spec.rb
209
+ - spec/twterm/friendship_spec.rb
203
210
  - twterm.gemspec
204
211
  homepage: http://twterm.ryota-ka.me/
205
212
  licenses:
@@ -216,9 +223,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
216
223
  version: 2.1.0
217
224
  required_rubygems_version: !ruby/object:Gem::Requirement
218
225
  requirements:
219
- - - ">="
226
+ - - ">"
220
227
  - !ruby/object:Gem::Version
221
- version: '0'
228
+ version: 1.3.1
222
229
  requirements: []
223
230
  rubyforge_project:
224
231
  rubygems_version: 2.4.7