diff --git a/Gemfile b/Gemfile index 090142a..c78769e 100644 --- a/Gemfile +++ b/Gemfile @@ -9,5 +9,5 @@ gem 'sugarcube', :require => [ 'sugarcube-attributedstring', ] gem "ib" -#gem "kyan_jukebox_websocket_lib", :path => "/Users/duncan/_dev/kyan/gems/kyan_jukebox_websocket_lib" +#gem "kyan_jukebox", :path => "/Users/duncan/_dev/kyan/gems/kyan_jukebox_websocket_lib" gem "kyan_jukebox", :git => 'git@github.com:kyan/kyan_jukebox_websocket_lib.git' diff --git a/Gemfile.lock b/Gemfile.lock index bd5e20b..8fb615a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,8 +1,8 @@ GIT remote: git@github.com:kyan/kyan_jukebox_websocket_lib.git - revision: 60178464e15c2465357326aa40906c1e71377de5 + revision: 8bfe8b70b4ed6fefb491591d9e62279c262ade7d specs: - kyan_jukebox (0.2.0) + kyan_jukebox (0.2.3) GEM remote: https://rubygems.org/ @@ -85,4 +85,4 @@ DEPENDENCIES sugarcube BUNDLED WITH - 1.10.6 + 1.11.2 diff --git a/Rakefile b/Rakefile index 0b885be..feb5d51 100644 --- a/Rakefile +++ b/Rakefile @@ -17,6 +17,7 @@ Motion::Project::App.setup do |app| app.info_plist['NSUIElement'] = 1 app.info_plist['NSHumanReadableCopyright'] = 'Copyright © 2016, Kyan Ltd' + app.info_plist['NSAppTransportSecurity'] = { 'NSAllowsArbitraryLoads' => true } app.pods do pod 'SocketRocket' diff --git a/app/_views/nowplaying_view.rb b/app/_views/nowplaying_view.rb index 41bfdc4..7bef0db 100644 --- a/app/_views/nowplaying_view.rb +++ b/app/_views/nowplaying_view.rb @@ -121,6 +121,7 @@ def update_data! def draw_title_box NSTextField.new.tap do |v| + v.setFont(NSFont.systemFontOfSize(12.0)) v.setEditable(false) v.setBezeled(false) v.setDrawsBackground(false) @@ -130,12 +131,12 @@ def draw_title_box NSLayoutPriorityDefaultLow, forOrientation:NSLayoutConstraintOrientationHorizontal ) - v.cell.setBackgroundStyle(NSBackgroundStyleRaised) end end def draw_artist_box NSTextField.new.tap do |v| + v.setFont(NSFont.systemFontOfSize(10.0)) v.setEditable(false) v.setBezeled(false) v.setDrawsBackground(false) @@ -145,12 +146,12 @@ def draw_artist_box NSLayoutPriorityDefaultLow, forOrientation:NSLayoutConstraintOrientationHorizontal ) - v.cell.setBackgroundStyle(NSBackgroundStyleRaised) end end def draw_album_box NSTextField.new.tap do |v| + v.setFont(NSFont.systemFontOfSize(9.0)) v.setEditable(false) v.setBezeled(false) v.setDrawsBackground(false) @@ -160,7 +161,6 @@ def draw_album_box NSLayoutPriorityDefaultLow, forOrientation:NSLayoutConstraintOrientationHorizontal ) - v.cell.setBackgroundStyle(NSBackgroundStyleRaised) end end @@ -170,6 +170,7 @@ def draw_image_box def draw_addedby_box NSTextField.new.tap do |v| + v.setFont(NSFont.systemFontOfSize(8.0)) v.setEditable(false) v.setBezeled(false) v.setDrawsBackground(false) @@ -179,7 +180,6 @@ def draw_addedby_box NSLayoutPriorityDefaultLow, forOrientation:NSLayoutConstraintOrientationHorizontal ) - v.cell.setBackgroundStyle(NSBackgroundStyleRaised) end end @@ -188,8 +188,6 @@ def update_title paragraph.setLineBreakMode(NSLineBreakByTruncatingTail) txt = track.title.attrd({ - 'NSFont' => NSFont.systemFontOfSize(12.0), - 'NSColor' => NSColor.blackColor, 'NSParagraphStyle' => paragraph }) unless track.title.nil? @title.setAttributedStringValue(txt) @@ -201,8 +199,6 @@ def update_artist paragraph.setLineBreakMode(NSLineBreakByTruncatingTail) txt = track.artist.attrd({ - 'NSFont' => NSFont.systemFontOfSize(10.0), - 'NSColor' => NSColor.blackColor, 'NSParagraphStyle' => paragraph }) unless track.artist.nil? @artist.setAttributedStringValue(txt) @@ -215,8 +211,6 @@ def update_album paragraph.setLineBreakMode(NSLineBreakByTruncatingTail) txt = track.album.attrd({ - 'NSFont' => NSFont.systemFontOfSize(9.0), - 'NSColor' => NSColor.blackColor, 'NSParagraphStyle' => paragraph }) unless track.album.nil? @album.setAttributedStringValue(txt) @@ -229,8 +223,6 @@ def update_addedby paragraph.setLineBreakMode(NSLineBreakByTruncatingTail) txt = "#{CHOSEN_BY_TXT} #{track.added_by}".attrd({ - 'NSFont' => NSFont.systemFontOfSize(8.0), - 'NSColor' => NSColor.blackColor, 'NSParagraphStyle' => paragraph }) unless track.added_by.nil? @addedby.setAttributedStringValue(txt) diff --git a/app/_views/upcoming_table_view.rb b/app/_views/upcoming_table_view.rb new file mode 100644 index 0000000..9f44f82 --- /dev/null +++ b/app/_views/upcoming_table_view.rb @@ -0,0 +1,24 @@ +class UpcomingTableView < NSTableView + + def init + super.tap do |v| + v.translatesAutoresizingMaskIntoConstraints = false + + col2 = NSTableColumn.alloc.initWithIdentifier "col2" + col2.setWidth 20 + col2.identifier = :thumb + v.addTableColumn col2 + + col3 = NSTableColumn.alloc.initWithIdentifier "col3" + col3.setWidth 220 + col3.identifier = :title + v.addTableColumn col3 + + col4 = NSTableColumn.alloc.initWithIdentifier "col4" + col4.setWidth 40 + col4.identifier = :duration + v.addTableColumn col4 + end + end + +end diff --git a/app/config/constants.rb b/app/config/constants.rb index a5ad8ce..657659d 100644 --- a/app/config/constants.rb +++ b/app/config/constants.rb @@ -3,6 +3,8 @@ JUKEBOX_URL = "http://#{WEBSOCKET_HOST}" VOTE_URL = "#{JUKEBOX_URL}/external?" +RECONNECT_TXT = 'If you have any issues with the now playing information not showing, this should fix it.' + DEFAULT_MENU_WIDTH=250.0 MENU_NOWPLAYING=111 @@ -43,4 +45,4 @@ SB_ICON_ACTIVE = "k_logo_col_18x18" SB_ICON_INACTIVE = "k_logo_bw_18x18" -GLOBAL_H_PADDING = 10 \ No newline at end of file +GLOBAL_H_PADDING = 10 diff --git a/app/controllers/upcoming_controller.rb b/app/controllers/upcoming_controller.rb new file mode 100644 index 0000000..52166d2 --- /dev/null +++ b/app/controllers/upcoming_controller.rb @@ -0,0 +1,109 @@ +class UpcomingController < NSViewController + + def init + super.tap do |c| + c.init_data + c.build_view + + @update_observer = App.notification_center.observe JB_UPDATED do |n| + refresh(n.userInfo[:jukebox]) + end + end + end + + def refresh(jukebox) + @jukebox = jukebox + refresh_tracks + @table_view.reloadData + end + + def init_data + @upcoming_tracks = [] + end + + def build_view + @table_view = UpcomingTableView.alloc.init + @table_view.setBoundsOrigin([-10,0]); + @table_view.setBoundsSize([@table_view.bounds.size.width+20, @table_view.bounds.size.height]); + @table_view.delegate = self + @table_view.dataSource = self + self.setView(@table_view) + end + + def numberOfRowsInTableView(table_view) + @upcoming_tracks.count + end + + def tableView(table_view, objectValueForTableColumn:table_column, row:row) + case table_column.identifier.to_sym + when :thumb + if @upcoming_tracks[row].artwork_url.nil? + NSImage.imageNamed("missing_artwork.png") + else + url = NSURL.URLWithString(@upcoming_tracks[row].artwork_url) + NSImage.alloc.initWithContentsOfURL(url) + end + when :title + str = "#{@upcoming_tracks[row].heading} (#{@upcoming_tracks[row].added_by})" + paragraph = NSMutableParagraphStyle.new + paragraph.setLineBreakMode(NSLineBreakByTruncatingTail) + + str.attrd({ + 'NSParagraphStyle' => paragraph + }) + when :duration + @upcoming_tracks[row].eta + end + end + + def tableView(table_view, heightOfRow:row) + 20 + end + + def tableView(table_view, viewForTableColumn:table_column, row:row) + tview = table_view.makeViewWithIdentifier(table_column.identifier, owner:self) + + case table_column.identifier.to_sym + when :thumb + tview = NSImageView.new.tap do |v| + v.setTranslatesAutoresizingMaskIntoConstraints(false) + v.setEditable(false) + v.setImageScaling(NSImageScaleAxesIndependently) + v.identifier = 'thumbid' + end + when :title + tview = NSTextField.new.tap do |v| + v.frame = CGRectZero + v.font = NSFont.systemFontOfSize(12.0) + v.setEditable(false) + v.setBezeled(false) + v.setDrawsBackground(false) + v.setSelectable(false) + v.identifier = 'titleid' + end + else + tview = NSTextField.new.tap do |v| + v.frame = CGRectZero + v.setEditable(false) + v.setBezeled(false) + v.setAlignment(NSRightTextAlignment) + v.setDrawsBackground(false) + v.setSelectable(false) + v.identifier = 'defaultid' + end + end + + tview + end + + private + + def refresh_tracks + @upcoming_tracks = @jukebox.playlist.upcoming_tracks(current_track)[0...5] + end + + def current_track + return @jukebox.track.file if @jukebox.last_change?(:track) + nil + end +end diff --git a/app/menu.rb b/app/menu.rb index fb6d271..170d430 100644 --- a/app/menu.rb +++ b/app/menu.rb @@ -6,6 +6,7 @@ def setup_build_menu @menu.initWithTitle App.name @menu.setMinimumWidth(DEFAULT_MENU_WIDTH) @jukebox_menu ||= NowplayingController.new + @upcoming_tracks ||= UpcomingController.new build_menu(@menu) @@ -22,19 +23,9 @@ def build_menu(menu) menu = setup_build_menu if menu.nil? menu.removeAllItems - flags = (NSEvent.modifierFlags & NSDeviceIndependentModifierFlagsMask) - - # If you hold the ALT key and display the - # menu it will show an extra item that lets - # you refersh your connection to the jukebox - # - if flags == NSAlternateKeyMask - menu.addItem(build_secret_refresh) - add_seperator_for(menu) - end - if jukebox_available? build_now_playing(menu) + build_upcoming_tracks(menu) build_console_status(menu) add_seperator_for(menu) end @@ -43,7 +34,9 @@ def build_menu(menu) m = NSMenuItem.new m.title = data.first m.tag = i - m.setImage( NSImage.imageNamed(data.first.downcase) ) + icon_img = NSImage.imageNamed(data.first.downcase) + icon_img.template = true + m.image = icon_img m.action = 'open_link:' @menu.addItem m end @@ -76,6 +69,13 @@ def build_submenu mi.tag = MENU_ABOUT sub_menu.addItem mi + mi = NSMenuItem.new + mi.title = 'Force reconnect to Jukebox!' + mi.action = 'force_reconnect_to_websocket_server' + mi.tag = MENU_FORCE_REFRESH + mi.toolTip = RECONNECT_TXT + sub_menu.addItem mi + add_seperator_for(sub_menu) mi = NSMenuItem.new @@ -103,14 +103,12 @@ def build_now_playing(menu) add_seperator_for(menu) end - def build_secret_refresh - NSMenuItem.new.tap do |mi| - mi.title = 'Force Refresh!' - mi.action = 'force_reconnect_to_websocket_server' - mi.tag = MENU_FORCE_REFRESH - mi.setKeyEquivalent("r") - mi.setKeyEquivalentModifierMask(NSCommandKeyMask) - end + def build_upcoming_tracks(menu) + jbmi = NSMenuItem.new + jbmi.tag = MENU_NOWPLAYING + jbmi.view = @upcoming_tracks.view + menu.addItem(jbmi) + add_seperator_for(menu) end def build_console_status(menu) @@ -144,7 +142,7 @@ def add_seperator_for(menu) def links [ - ["Timesheet" , "https://gapps.harvestapp.com/gapp_company?domain=kyanmedia.com"], + ["Timesheet" , "https://id.getharvest.com/accounts"], ["Pivotal" , "https://www.pivotaltracker.com/google_domain_openid/redirect_for_auth?domain=kyanmedia.com"], ["Support" , "https://kyan.sirportly.com"], ["Holiday" , "https://app.timetastic.co.uk"],