twterm 2.3.0 → 2.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -0
  3. data/lib/twterm.rb +4 -4
  4. data/lib/twterm/app.rb +4 -1
  5. data/lib/twterm/direct_message_composer.rb +2 -1
  6. data/lib/twterm/environment.rb +5 -0
  7. data/lib/twterm/event/{base.rb → abstract_event.rb} +1 -1
  8. data/lib/twterm/event/direct_message/fetched.rb +2 -2
  9. data/lib/twterm/event/message/abstract_message.rb +2 -2
  10. data/lib/twterm/event/notification/abstract_notification.rb +2 -2
  11. data/lib/twterm/event/open_photo.rb +13 -0
  12. data/lib/twterm/event/open_uri.rb +2 -2
  13. data/lib/twterm/event/screen/refresh.rb +13 -0
  14. data/lib/twterm/event/screen/resize.rb +2 -2
  15. data/lib/twterm/event/status/{base.rb → abstract_status_event.rb} +2 -2
  16. data/lib/twterm/event/status/delete.rb +2 -2
  17. data/lib/twterm/event/status/mention.rb +2 -2
  18. data/lib/twterm/event/status/timeline.rb +2 -2
  19. data/lib/twterm/event/status_garbage_collected.rb +2 -2
  20. data/lib/twterm/event/user_garbage_collected.rb +2 -2
  21. data/lib/twterm/event_dispatcher.rb +2 -2
  22. data/lib/twterm/photo_viewer.rb +36 -0
  23. data/lib/twterm/photo_viewer_backend/abstract_photo_viewer_backend.rb +46 -0
  24. data/lib/twterm/photo_viewer_backend/browser_backend.rb +16 -0
  25. data/lib/twterm/photo_viewer_backend/imgcat_backend.rb +33 -0
  26. data/lib/twterm/photo_viewer_backend/quick_look_backend.rb +13 -0
  27. data/lib/twterm/preferences.rb +10 -0
  28. data/lib/twterm/publisher.rb +2 -2
  29. data/lib/twterm/rest_client.rb +5 -5
  30. data/lib/twterm/screen.rb +8 -6
  31. data/lib/twterm/status.rb +7 -1
  32. data/lib/twterm/tab/{base.rb → abstract_tab.rb} +1 -1
  33. data/lib/twterm/tab/direct_message/conversation.rb +2 -2
  34. data/lib/twterm/tab/direct_message/conversation_list.rb +2 -2
  35. data/lib/twterm/tab/key_assignments_cheatsheet.rb +2 -2
  36. data/lib/twterm/tab/new/{start.rb → index.rb} +2 -2
  37. data/lib/twterm/tab/new/list.rb +2 -2
  38. data/lib/twterm/tab/new/search.rb +6 -3
  39. data/lib/twterm/tab/new/user.rb +8 -7
  40. data/lib/twterm/tab/preferences/index.rb +9 -3
  41. data/lib/twterm/tab/preferences/notification_backend.rb +2 -2
  42. data/lib/twterm/tab/preferences/photo_viewer_backend.rb +86 -0
  43. data/lib/twterm/tab/rate_limit_status.rb +1 -1
  44. data/lib/twterm/tab/status_tab.rb +4 -3
  45. data/lib/twterm/tab/statuses/{base.rb → abstract_statuses_tab.rb} +2 -2
  46. data/lib/twterm/tab/statuses/conversation.rb +2 -2
  47. data/lib/twterm/tab/statuses/favorites.rb +2 -2
  48. data/lib/twterm/tab/statuses/home.rb +2 -2
  49. data/lib/twterm/tab/statuses/list_timeline.rb +2 -2
  50. data/lib/twterm/tab/statuses/mentions.rb +2 -2
  51. data/lib/twterm/tab/statuses/search.rb +2 -2
  52. data/lib/twterm/tab/statuses/user_timeline.rb +2 -2
  53. data/lib/twterm/tab/user_list_management.rb +1 -1
  54. data/lib/twterm/tab/user_tab.rb +2 -2
  55. data/lib/twterm/tab/users/{base.rb → abstract_users_tab.rb} +2 -2
  56. data/lib/twterm/tab/users/followers.rb +2 -2
  57. data/lib/twterm/tab/users/friends.rb +2 -2
  58. data/lib/twterm/tab_manager.rb +2 -2
  59. data/lib/twterm/tweetbox.rb +20 -16
  60. data/lib/twterm/version.rb +1 -1
  61. data/spec/twterm/event_dispatcher_spec.rb +1 -1
  62. data/twterm.gemspec +1 -1
  63. metadata +20 -13
  64. data/lib/twterm/tab/favorites.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d251a92afa7b450c2da0556f66fe431d6db851633b739601e0c47cb5ad45baa5
4
- data.tar.gz: a014a40ac7b5d15859880b157375ebe372e011a4a76153fc93b66075ad3a594c
3
+ metadata.gz: 3ed5b1fe74b479cd44e106d99f63dcbc348d3f3c67b4f1dd537edd9c8dd9044c
4
+ data.tar.gz: 1969619f0f236f559409b7eaf4f9ac49e8d7226e5068e405ebd18955080b7260
5
5
  SHA512:
6
- metadata.gz: 5dc37cf71fa46b22cb7e69efc5a3ad09c2fd0a65ba8c77869e6d2a494159aace7691653fe0b001952edef57153a39f5be1715ca0447fc1aa04712130aabc40f5
7
- data.tar.gz: de94a92f370e94e509063132cd69a8525df015d9825393e7570ba7d55c99466042aaab7d4261ac1e6559b4518703792ead41433a8c2ad1817115e01a7c3e7da3
6
+ metadata.gz: 2a78e4c7a2b71df77830a3639d16610de65f05ae4ca9d2a56790e7a542eb41b5a476db5e60adc784eb0905649eab2827acfdd2c93111e4d3a49afd5785f51002
7
+ data.tar.gz: d7625b41113573124d36363e5848e794698c17cb332aef8e47bdf9c54548a750ebc8003a92051a72fca8414c9b5393fffbb3b31aaf54c0bed3ce664f78c79263
data/README.md CHANGED
@@ -9,6 +9,7 @@ A full-featured TUI Twitter client
9
9
  - Ruby (>= 2.1, compiled with ncurses and Readline)
10
10
  - ncurses
11
11
  - Readline
12
+ - [GNU Libidn](https://www.gnu.org/software/libidn/)
12
13
 
13
14
  ## Installation
14
15
 
data/lib/twterm.rb CHANGED
@@ -31,16 +31,16 @@ require 'twterm/screen'
31
31
  require 'twterm/scheduler'
32
32
  require 'twterm/status'
33
33
  require 'twterm/tab_manager'
34
- require 'twterm/tab/base'
34
+ require 'twterm/tab/abstract_tab'
35
35
  require 'twterm/tab/dumpable'
36
36
  require 'twterm/tab/exceptions'
37
37
  require 'twterm/tab/scrollable'
38
38
  require 'twterm/tab/key_assignments_cheatsheet'
39
- require 'twterm/tab/new/start'
39
+ require 'twterm/tab/new/index'
40
40
  require 'twterm/tab/new/list'
41
41
  require 'twterm/tab/new/search'
42
42
  require 'twterm/tab/new/user'
43
- require 'twterm/tab/statuses/base'
43
+ require 'twterm/tab/statuses/abstract_statuses_tab'
44
44
  require 'twterm/tab/statuses/conversation'
45
45
  require 'twterm/tab/statuses/favorites'
46
46
  require 'twterm/tab/statuses/home'
@@ -49,7 +49,7 @@ require 'twterm/tab/statuses/mentions'
49
49
  require 'twterm/tab/statuses/search'
50
50
  require 'twterm/tab/statuses/user_timeline'
51
51
  require 'twterm/tab/user_tab'
52
- require 'twterm/tab/users/base'
52
+ require 'twterm/tab/users/abstract_users_tab'
53
53
  require 'twterm/tab/users/followers'
54
54
  require 'twterm/tab/users/friends'
55
55
  require 'twterm/tweetbox'
data/lib/twterm/app.rb CHANGED
@@ -3,11 +3,13 @@ require 'curses'
3
3
  require 'twterm/completion_manager'
4
4
  require 'twterm/direct_message_composer'
5
5
  require 'twterm/environment'
6
+ require 'twterm/event/screen/refresh'
6
7
  require 'twterm/event/screen/resize'
7
8
  require 'twterm/message_window'
8
9
  require 'twterm/notification_dispatcher'
9
10
  require 'twterm/persistable_configuration_proxy'
10
11
  require 'twterm/preferences'
12
+ require 'twterm/photo_viewer'
11
13
  require 'twterm/repository/direct_message_repository'
12
14
  require 'twterm/repository/friendship_repository'
13
15
  require 'twterm/repository/hashtag_repository'
@@ -75,6 +77,7 @@ module Twterm
75
77
  MessageWindow.instance
76
78
 
77
79
  @notification_dispatcher = NotificationDispatcher.new(preferences)
80
+ @photo_viewer = PhotoViewer.new(preferences)
78
81
 
79
82
  timeline = Tab::Statuses::Home.new(self, client)
80
83
  tab_manager.add_and_show(timeline)
@@ -84,7 +87,7 @@ module Twterm
84
87
  tab_manager.add(mentions_tab)
85
88
  tab_manager.recover_tabs
86
89
 
87
- screen.refresh
90
+ publish(Event::Screen::Refresh.new)
88
91
 
89
92
  client.connect_user_stream
90
93
 
@@ -1,3 +1,4 @@
1
+ require 'twterm/event/screen/refresh'
1
2
  require 'twterm/publisher'
2
3
  require 'twterm/user'
3
4
  require 'twterm/utils'
@@ -21,7 +22,7 @@ module Twterm
21
22
  resetter = proc do
22
23
  reset_prog_mode
23
24
  sleep 0.1
24
- app.screen.refresh
25
+ publish(Event::Screen::Refresh.new)
25
26
  end
26
27
 
27
28
  thread = Thread.new do
@@ -7,6 +7,7 @@ module Twterm
7
7
 
8
8
  @terminal_notifier_available = TerminalNotifier.available?
9
9
  @with_eog = system('which eog 2>&1 >/dev/null')
10
+ @with_imgcat = system('which imgcat 2>&1 >/dev/null')
10
11
  @with_tmux = system('which tmux 2>&1 >/dev/null') && !ENV['TMUX'].nil?
11
12
  @with_qlmanage = system('which qlmanage 2>&1 >/dev/null')
12
13
  end
@@ -27,6 +28,10 @@ module Twterm
27
28
  @with_eog
28
29
  end
29
30
 
31
+ def with_imgcat?
32
+ @with_imgcat
33
+ end
34
+
30
35
  def with_qlmanage?
31
36
  @with_qlmanage
32
37
  end
@@ -2,7 +2,7 @@ require 'twterm/utils'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
- class Base
5
+ class AbstractEvent
6
6
  include Utils
7
7
 
8
8
  def initialize(*args)
@@ -1,9 +1,9 @@
1
- require 'twterm/event/base'
1
+ require 'twterm/event/abstract_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
5
  module DirectMessage
6
- class Fetched < Base
6
+ class Fetched < AbstractEvent
7
7
  end
8
8
  end
9
9
  end
@@ -1,9 +1,9 @@
1
- require 'twterm/event/base'
1
+ require 'twterm/event/abstract_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
5
  module Message
6
- class AbstractMessage < Twterm::Event::Base
6
+ class AbstractMessage < AbstractEvent
7
7
  attr_reader :time
8
8
 
9
9
  def initialize(message)
@@ -1,10 +1,10 @@
1
- require 'twterm/event/base'
1
+ require 'twterm/event/abstract_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
5
  module Notification
6
6
  # @abstract
7
- class AbstractNotification < Event::Base
7
+ class AbstractNotification < AbstractEvent
8
8
  # @abstract
9
9
  # @return [String] notification body
10
10
  def body
@@ -0,0 +1,13 @@
1
+ require 'twitter'
2
+
3
+ require 'twterm/event/abstract_event'
4
+
5
+ module Twterm
6
+ module Event
7
+ class OpenPhoto < AbstractEvent
8
+ def fields
9
+ { photo: Twitter::Media::Photo }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,8 +1,8 @@
1
- require 'twterm/event/base'
1
+ require 'twterm/event/abstract_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
- class OpenURI < Base
5
+ class OpenURI < AbstractEvent
6
6
  def fields
7
7
  { uri: Addressable::URI }
8
8
  end
@@ -0,0 +1,13 @@
1
+ require 'twterm/event/abstract_event'
2
+
3
+ module Twterm
4
+ module Event
5
+ module Screen
6
+ class Refresh < AbstractEvent
7
+ def fields
8
+ {}
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,9 +1,9 @@
1
- require 'twterm/event/base'
1
+ require 'twterm/event/abstract_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
5
  module Screen
6
- class Resize < Base
6
+ class Resize < AbstractEvent
7
7
  def fields
8
8
  { lines: Integer, cols: Integer }
9
9
  end
@@ -1,10 +1,10 @@
1
1
  require 'twterm/status'
2
- require 'twterm/event/base'
2
+ require 'twterm/event/abstract_event'
3
3
 
4
4
  module Twterm
5
5
  module Event
6
6
  module Status
7
- class Base < ::Twterm::Event::Base
7
+ class AbstractStatusEvent < AbstractEvent
8
8
  def fields
9
9
  { status: ::Twterm::Status }
10
10
  end
@@ -1,9 +1,9 @@
1
- require 'twterm/event/base'
1
+ require 'twterm/event/abstract_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
5
  module Status
6
- class Delete < Base
6
+ class Delete < AbstractStatusEvent
7
7
  def fields
8
8
  { status_id: Integer }
9
9
  end
@@ -1,9 +1,9 @@
1
- require 'twterm/event/status/base'
1
+ require 'twterm/event/status/abstract_status_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
5
  module Status
6
- class Mention < Base
6
+ class Mention < AbstractStatusEvent
7
7
  end
8
8
  end
9
9
  end
@@ -1,9 +1,9 @@
1
- require 'twterm/event/status/base'
1
+ require 'twterm/event/status/abstract_status_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
5
  module Status
6
- class Timeline < Base
6
+ class Timeline < AbstractStatusEvent
7
7
  end
8
8
  end
9
9
  end
@@ -1,8 +1,8 @@
1
- require 'twterm/event/base'
1
+ require 'twterm/event/abstract_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
- class StatusGarbageCollected < Base
5
+ class StatusGarbageCollected < AbstractEvent
6
6
  def fields
7
7
  {
8
8
  id: Integer
@@ -1,8 +1,8 @@
1
- require 'twterm/event/base'
1
+ require 'twterm/event/abstract_event'
2
2
 
3
3
  module Twterm
4
4
  module Event
5
- class UserGarbageCollected < Base
5
+ class UserGarbageCollected < AbstractEvent
6
6
  def fields
7
7
  {
8
8
  id: Integer
@@ -21,8 +21,8 @@ module Twterm
21
21
 
22
22
  def register_subscription(subscriber_id, event, callback)
23
23
  check_type Class, event
24
- unless event <= Event::Base
25
- raise TypeError, 'the second argument must be a subclass of Twterm::Event::Base'
24
+ unless event <= Event::AbstractEvent
25
+ raise TypeError, 'the second argument must be a subclass of Twterm::Event::AbstractEvent'
26
26
  end
27
27
 
28
28
  @subscriptions << Subscription.new(subscriber_id, event, callback)
@@ -0,0 +1,36 @@
1
+ require 'twterm/event/open_photo'
2
+ require 'twterm/photo_viewer_backend/browser_backend'
3
+ require 'twterm/photo_viewer_backend/imgcat_backend'
4
+ require 'twterm/photo_viewer_backend/quick_look_backend'
5
+ require 'twterm/subscriber'
6
+
7
+ module Twterm
8
+ class PhotoViewer
9
+ include Subscriber
10
+
11
+ # @param preferences [Twterm::Preferences]
12
+ def initialize(preferences)
13
+ @preferences = preferences
14
+
15
+ @backends = {
16
+ browser: PhotoViewerBackend::BrowserBackend.new,
17
+ imgcat: PhotoViewerBackend::ImgcatBackend.new,
18
+ quick_look: PhotoViewerBackend::QuickLookBackend.new,
19
+ }
20
+
21
+ subscribe(Event::OpenPhoto) { |n| view(n.photo) }
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :backends, :preferences
27
+
28
+ # @param photo [Twitter::Media::Photo]
29
+ # @return [void]
30
+ def view(photo)
31
+ backends.each do |key, backend|
32
+ backend.view(photo) if preferences[:photo_viewer_backend, key]
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,46 @@
1
+ require 'concurrent'
2
+
3
+ module Twterm
4
+ module PhotoViewerBackend
5
+ # @abstract
6
+ class AbstractPhotoViewerBackend
7
+ # @abstract
8
+ def view(_photo)
9
+ raise NotImplementedError, '`view` method must be implemented'
10
+ end
11
+
12
+ private
13
+
14
+ def getc
15
+ system('stty raw -echo')
16
+ STDIN.getc
17
+ ensure
18
+ system('stty -raw echo')
19
+ end
20
+
21
+ # @param url [String]
22
+ # @yieldparam file [File]
23
+ def with_downloaded_file(url, &block)
24
+ uri = URI.parse(url)
25
+
26
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
27
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
28
+ res = http.get(uri.path)
29
+
30
+ case res
31
+ when Net::HTTPSuccess
32
+ Tempfile.open(['', '.jpg'], Dir.tmpdir) do |file|
33
+ file.binmode
34
+ file.write(res.body)
35
+ file.flush
36
+
37
+ block.call(file)
38
+ end
39
+ else
40
+ raise res
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,16 @@
1
+ require 'twterm/photo_viewer_backend/abstract_photo_viewer_backend'
2
+ require 'twterm/publisher'
3
+ require 'twterm/event/open_uri'
4
+
5
+ module Twterm
6
+ module PhotoViewerBackend
7
+ class BrowserBackend < AbstractPhotoViewerBackend
8
+ include Publisher
9
+
10
+ def view(photo)
11
+ event = Event::OpenURI.new(photo.media_url_https)
12
+ publish(event)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ require 'curses'
2
+
3
+ require 'twterm/event/screen/refresh'
4
+ require 'twterm/photo_viewer_backend/abstract_photo_viewer_backend'
5
+ require 'twterm/publisher'
6
+
7
+ module Twterm
8
+ module PhotoViewerBackend
9
+ class ImgcatBackend < AbstractPhotoViewerBackend
10
+ include Publisher
11
+
12
+ def view(photo)
13
+ Curses.close_screen unless Curses.closed?
14
+
15
+ puts "\e[H\e[2JDownloading..."
16
+
17
+ with_downloaded_file(photo.media_url_https) do |file|
18
+ begin
19
+ puts "\e[H\e[2JRendering..."
20
+ system "imgcat #{file.path}"
21
+ getc
22
+ ensure
23
+ puts "\e[H\e[2J"
24
+ Curses.reset_prog_mode
25
+ sleep 0.1
26
+ publish(Event::Screen::Refresh.new)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+