* working on generic recording widget logic
This commit is contained in:
parent
e7c1a791a7
commit
b7a1e06889
|
|
@ -61,7 +61,7 @@ module JamRuby
|
|||
|
||||
|
||||
def has_mix?
|
||||
recording.mixes.length > 0 && recording.mixes.first.completed
|
||||
recording.has_mix?
|
||||
end
|
||||
|
||||
def can_download?(some_user)
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ module JamRuby
|
|||
self.comments.size
|
||||
end
|
||||
|
||||
def has_mix?
|
||||
self.mixes.length > 0 && self.mixes.first.completed
|
||||
end
|
||||
|
||||
# this can probably be done more efficiently, but David needs this asap for a video
|
||||
def grouped_tracks
|
||||
tracks = []
|
||||
|
|
|
|||
|
|
@ -6,14 +6,46 @@
|
|||
context.JK.FeedItemRecording = function($parentElement, options){
|
||||
|
||||
var $feedItem = $parentElement;
|
||||
var $description = $('.description', $feedItem)
|
||||
var $musicians = $('.musician-detail', $feedItem)
|
||||
var $description = $('.description', $feedItem);
|
||||
var $musicians = $('.musician-detail', $feedItem);
|
||||
var $controls = $('.recording-controls', $feedItem);
|
||||
var playing = false;
|
||||
|
||||
var toggledOpen = false;
|
||||
if(!$feedItem.is('.feed-entry')) {
|
||||
throw "$parentElement must be a .feed-entry"
|
||||
}
|
||||
|
||||
function startPlay() {
|
||||
var img = $('.play-icon', $feedItem);
|
||||
img.attr('src', '/assets/content/icon_pausebutton.png');
|
||||
$controls.trigger('play.listenRecording');
|
||||
playing = true;
|
||||
}
|
||||
|
||||
function stopPlay() {
|
||||
var img = $('.play-icon', $feedItem);
|
||||
img.attr('src', '/assets/content/icon_playbutton.png');
|
||||
$controls.trigger('pause.listenRecording');
|
||||
playing = false;
|
||||
}
|
||||
|
||||
function togglePlay() {
|
||||
|
||||
if(playing) {
|
||||
stopPlay();
|
||||
}
|
||||
else {
|
||||
startPlay();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function stateChange(e, data) {
|
||||
if(data.isEnd) stopPlay();
|
||||
}
|
||||
|
||||
function toggleDetails() {
|
||||
if(toggledOpen) {
|
||||
$feedItem.css('height', $feedItem.height() + 'px')
|
||||
|
|
@ -40,11 +72,14 @@
|
|||
function events() {
|
||||
$('.details', $feedItem).click(toggleDetails);
|
||||
$('.details-arrow', $feedItem).click(toggleDetails);
|
||||
$('.play-button', $feedItem).click(togglePlay);
|
||||
$controls.bind('statechange.listenRecording', stateChange);
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
$('.timeago', $feedItem).timeago();
|
||||
$('.dotdotdot', $feedItem).dotdotdot();
|
||||
$controls.listenRecording({sliderSelector:'.recording-slider', sliderBarSelector: '.recording-playback', currentTimeSelector:'.recording-current'});
|
||||
context.JK.prettyPrintElements($('time.duration', $feedItem));
|
||||
context.JK.setInstrumentAssetPath($('.instrument-icon', $feedItem));
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
$controls.trigger('pause.listenBroadcast');
|
||||
playing = false;
|
||||
}
|
||||
|
||||
function togglePlay() {
|
||||
if(playing) {
|
||||
$status.text('SESSION IN PROGRESS');
|
||||
|
|
@ -83,7 +84,6 @@
|
|||
$('.details', $feedItem).click(toggleDetails);
|
||||
$('.details-arrow', $feedItem).click(toggleDetails);
|
||||
$('.play-button', $feedItem).click(togglePlay);
|
||||
|
||||
$controls.bind('statechange.listenBroadcast', stateChange);
|
||||
}
|
||||
|
||||
|
|
@ -91,29 +91,12 @@
|
|||
$('.timeago', $feedItem).timeago();
|
||||
$('.dotdotdot', $feedItem).dotdotdot();
|
||||
$controls.listenBroadcast();
|
||||
|
||||
context.JK.prettyPrintElements($('time.duration', $feedItem));
|
||||
context.JK.prettyPrintElements($('time.duration', $feedItem).show());
|
||||
context.JK.setInstrumentAssetPath($('.instrument-icon', $feedItem));
|
||||
|
||||
$feedItem.data('original-max-height', $feedItem.css('height'));
|
||||
|
||||
events();
|
||||
|
||||
|
||||
// this is a bit lame, because this is a singleton.
|
||||
// the idea is, if there are any session widgets on the page, then we start ticking time
|
||||
if(!context.JK.FeedItemSessionTimer) {
|
||||
context.JK.FeedItemSessionTimer = setInterval(function() {
|
||||
$.each($('.feed-entry.music-session-history-entry .inprogress .session-duration'), function(index, item) {
|
||||
var $duration = $(item);
|
||||
|
||||
var createdAt = new Date(Number($duration.attr('data-created-at')) * 1000)
|
||||
var millisElapsed = (new Date()).getTime() - createdAt.getTime();
|
||||
console.log("createdAt, millis", createdAt, millisElapsed);
|
||||
$duration.text(context.JK.prettyPrintSeconds( parseInt(millisElapsed / 1000)));
|
||||
});
|
||||
}, 333);
|
||||
}
|
||||
}
|
||||
|
||||
initialize();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,377 @@
|
|||
(function(context, $) {
|
||||
|
||||
"use strict";
|
||||
|
||||
context.JK = context.JK || {};
|
||||
|
||||
// the purpose of this code is to simply the interaction for recording widgets
|
||||
context.JK.ListenRecording = function($parentElement, options){
|
||||
|
||||
var WAIT_FOR_BUFFER_TIMEOUT = 5000;
|
||||
|
||||
var logger = context.JK.logger;
|
||||
var rest = context.JK.Rest();
|
||||
var $parent = $parentElement;
|
||||
var $currentTime = null;
|
||||
var $slider = null;
|
||||
var $sliderBar = null;
|
||||
var $audio = null;
|
||||
var audioDomElement = null;
|
||||
var self = this;
|
||||
var waitForBufferingTimeout = null;
|
||||
var destroyed = false;
|
||||
var lastTime = 0;
|
||||
var dragging = false;
|
||||
|
||||
var PlayStateNone = 'none';
|
||||
var PlayStateInitializing = 'initializing'; // user clicked play--nothing has happened yet
|
||||
var PlayStateBuffering = 'buffering'; // user clicked play--the stream is being read, buffer is being built
|
||||
var PlayStatePlaying = 'playing'; // we are playing
|
||||
var PlayStateStalled = 'stalled'; // we were playing, but the stream is stalled
|
||||
var PlayStateEnded = 'ended'; // we were playing, but the stream ended
|
||||
var PlayStateFailedStart = 'failed_start'; // we could not start the stream. no more events are coming
|
||||
var PlayStateFailedPlaying = 'failed_playing'; // failed while playing.
|
||||
var PlayStateNetworkError = 'network_error'; // network error
|
||||
|
||||
var playState = PlayStateNone; // tracks if the stream is actually playing
|
||||
|
||||
var canPlay = false;
|
||||
|
||||
function play(e) {
|
||||
if(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if(destroyed) return;
|
||||
|
||||
if(!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a play"
|
||||
|
||||
if(canPlay) {
|
||||
audioDomElement.currentTime = lastTime
|
||||
}
|
||||
|
||||
audioDomElement.play();
|
||||
|
||||
transition(PlayStateInitializing);
|
||||
|
||||
// keep this after transition, because any transition clears this timer
|
||||
waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT);
|
||||
}
|
||||
|
||||
function pause(e) {
|
||||
if(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if(destroyed) return;
|
||||
|
||||
if(!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a pause"
|
||||
|
||||
transition(PlayStateNone);
|
||||
|
||||
audioDomElement.pause();
|
||||
//recreateAudioElement();
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
if(!destroyed) {
|
||||
$audio.remove();
|
||||
$audio = null;
|
||||
audioDomElement = null;
|
||||
destroyed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function noBuffer() {
|
||||
logger.debug("never received indication of buffering or playing");
|
||||
transition(PlayStateFailedStart);
|
||||
}
|
||||
|
||||
// this is the only way to make audio stop buffering after the user hits pause
|
||||
function recreateAudioElement() {
|
||||
// jeez: http://stackoverflow.com/questions/4071872/html5-video-force-abort-of-buffering/13302599#13302599
|
||||
var originalSource = $audio.html()
|
||||
audioDomElement.pause();
|
||||
audioDomElement.src = '';
|
||||
audioDomElement.load();
|
||||
var $parent = $audio.parent();
|
||||
$audio.remove();
|
||||
$parent.append('<audio preload="none"></audio>');
|
||||
$audio = $('audio', $parent);
|
||||
$audio.append(originalSource);
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
}
|
||||
|
||||
function clearBufferTimeout() {
|
||||
if(waitForBufferingTimeout) {
|
||||
clearTimeout (waitForBufferingTimeout);
|
||||
waitForBufferingTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
function transition(newState) {
|
||||
logger.debug("transitioning from " + playState + " to " + newState);
|
||||
|
||||
playState = newState;
|
||||
|
||||
clearBufferTimeout();
|
||||
|
||||
if( playState == PlayStateNone ||
|
||||
playState == PlayStateEnded ||
|
||||
playState == PlayStateFailedStart ||
|
||||
playState == PlayStateFailedPlaying ||
|
||||
playState == PlayStateNetworkError) {
|
||||
context.JK.ListenBroadcastCurrentlyPlaying = null;
|
||||
}
|
||||
|
||||
triggerStateChange();
|
||||
}
|
||||
|
||||
|
||||
function isNoisyEvent(eventName) {
|
||||
if(playState == PlayStateNone) {
|
||||
console.log("ignoring: " + eventName)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function onPlay() {
|
||||
// this just confirms that the user tried to play
|
||||
}
|
||||
|
||||
function onPlaying() {
|
||||
if(isNoisyEvent('playing')) return;
|
||||
logger.debug("playing", arguments);
|
||||
|
||||
transition(PlayStatePlaying);
|
||||
}
|
||||
|
||||
function onPause() {
|
||||
if(isNoisyEvent('pause')) return;
|
||||
logger.debug("pause", arguments);
|
||||
|
||||
transition(PlayStateStalled);
|
||||
}
|
||||
|
||||
function onError() {
|
||||
if(isNoisyEvent('error')) return;
|
||||
logger.debug("error", arguments);
|
||||
|
||||
if(playState == PlayStatePlaying || playState == PlayStateStalled) {
|
||||
transition(PlayStateFailedPlaying);
|
||||
}
|
||||
else {
|
||||
transition(PlayStateFailedStart);
|
||||
}
|
||||
}
|
||||
|
||||
function onEnded() {
|
||||
if(isNoisyEvent('ended')) return;
|
||||
logger.debug("ended", arguments);
|
||||
|
||||
transition(PlayStateEnded);
|
||||
}
|
||||
|
||||
function onEmptied() {
|
||||
if(isNoisyEvent('emptied')) return;
|
||||
logger.debug("emptied", arguments);
|
||||
}
|
||||
|
||||
function onAbort() {
|
||||
if(isNoisyEvent('abort')) return;
|
||||
logger.debug("abort", arguments);
|
||||
}
|
||||
|
||||
function onStalled() {
|
||||
if(isNoisyEvent('stalled')) return;
|
||||
logger.debug("stalled", arguments);
|
||||
|
||||
// fires in Chrome on page load
|
||||
|
||||
if(playState == PlayStateBuffering || playState == PlayStatePlaying) {
|
||||
transition(PlayStateStalled);
|
||||
}
|
||||
}
|
||||
|
||||
function onSuspend() {
|
||||
if(isNoisyEvent('suspend')) return;
|
||||
logger.debug("onsuspend", arguments);
|
||||
|
||||
// fires in FF on page load
|
||||
|
||||
transition(PlayStateStalled);
|
||||
}
|
||||
|
||||
function onTimeUpdate() {
|
||||
|
||||
if(dragging) {
|
||||
return;
|
||||
}
|
||||
|
||||
var percentComplete = (audioDomElement.currentTime / audioDomElement.duration) * 100;
|
||||
updateSliderPosition(percentComplete);
|
||||
$currentTime.html(context.JK.prettyPrintSeconds(parseInt(audioDomElement.currentTime)));
|
||||
|
||||
// reset icon to play and slider to far left when done
|
||||
if (percentComplete === 100) {
|
||||
updateSliderPosition(0);
|
||||
$currentTime.html("0:00");
|
||||
lastTime = 0
|
||||
}
|
||||
else {
|
||||
lastTime = audioDomElement.currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
function updateSliderPosition(percent) {
|
||||
console.log("updateSliderPosition", percent)
|
||||
$slider.css({'left': percent + '%'});
|
||||
}
|
||||
|
||||
function onProgress() {
|
||||
if(isNoisyEvent('progress')) return;
|
||||
|
||||
if(playState == PlayStateInitializing) {
|
||||
transition(PlayStateBuffering);
|
||||
}
|
||||
}
|
||||
|
||||
function startDrag(e, ui) {
|
||||
dragging = true;
|
||||
}
|
||||
|
||||
function stopDrag(e, ui) {
|
||||
dragging = false;
|
||||
|
||||
var percent = ui.position.left / $sliderBar.width() * 100;
|
||||
updateSliderPosition(percent);
|
||||
|
||||
audioDomElement.currentTime = percent * audioDomElement.duration;
|
||||
}
|
||||
|
||||
function onDrag(e, ui) {
|
||||
updateSliderPosition(ui.position.left / $sliderBar.width() * 100);
|
||||
}
|
||||
|
||||
function triggerStateChange() {
|
||||
|
||||
var isEnd = false;
|
||||
var displayText = null;
|
||||
var refresh = false;
|
||||
|
||||
if(playState == 'none') {
|
||||
//$status.text('SESSION IN PROGRESS');
|
||||
}
|
||||
else if(playState == 'initializing') {
|
||||
displayText = 'PREPARING AUDIO';
|
||||
}
|
||||
else if(playState == 'buffering') {
|
||||
|
||||
}
|
||||
else if(playState == 'playing') {
|
||||
displayText = 'PLAYING';
|
||||
}
|
||||
else if(playState == 'stalled') {
|
||||
displayText = 'RECONNECTING';
|
||||
}
|
||||
else if(playState == 'ended') {
|
||||
displayText = 'DISCONNECTED';
|
||||
isEnd = true;
|
||||
}
|
||||
else if(playState == 'failed_start') {
|
||||
displayText = 'AUDIO DID NOT START';
|
||||
isEnd = true;
|
||||
}
|
||||
else if(playState == 'failed_playing') {
|
||||
displayText = 'STREAM DISCONNECTED';
|
||||
isEnd = true;
|
||||
}
|
||||
else if(playState == 'network_error') {
|
||||
displayText = 'NO NETWORK';
|
||||
isEnd = true;
|
||||
}
|
||||
else {
|
||||
logger.error("unknown state: " + playState)
|
||||
}
|
||||
|
||||
$parent.triggerHandler('statechange.listenRecording',
|
||||
{
|
||||
state: playState,
|
||||
displayText: displayText,
|
||||
isEnd: isEnd
|
||||
})
|
||||
}
|
||||
|
||||
function audioBind() {
|
||||
$audio.bind('play', onPlay);
|
||||
$audio.bind('playing', onPlaying);
|
||||
$audio.bind('error', onError);
|
||||
$audio.bind('emptied', onEmptied);
|
||||
$audio.bind('abort', onAbort);
|
||||
$audio.bind('ended', onEnded);
|
||||
$audio.bind('pause', onPause);
|
||||
$audio.bind('suspend', onSuspend);
|
||||
$audio.bind('stalled', onStalled);
|
||||
$audio.bind('timeupdate', onTimeUpdate);
|
||||
$audio.bind('progress', onProgress);
|
||||
$audio.bind('canplay', function() { canPlay = true;})
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
||||
$slider = $(options.sliderSelector, $parent);
|
||||
$sliderBar = $(options.sliderBarSelector, $parent);
|
||||
$currentTime = $(options.currentTimeSelector, $parent);
|
||||
$audio = $('audio', $parent);
|
||||
|
||||
if($audio.length == 0) {
|
||||
logger.debug("listen_recording: no audio element. deactivating")
|
||||
return;
|
||||
}
|
||||
if($audio.length > 1) {
|
||||
throw "more than one <audio> element found";
|
||||
}
|
||||
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
|
||||
$parent.bind('play.listenRecording', play);
|
||||
$parent.bind('pause.listenRecording', pause);
|
||||
$parent.bind('destroy.listenRecording', destroy);
|
||||
|
||||
$sliderBar.bind('click', function(e) {
|
||||
var offset = e.pageX - $(this).offset().left;
|
||||
var percent = offset / $sliderBar.width() * 100;
|
||||
updateSliderPosition(percent);
|
||||
audioDomElement.currentTime = percent * audioDomElement.duration;
|
||||
return false;
|
||||
});
|
||||
|
||||
$slider.draggable({
|
||||
axis: 'x',
|
||||
containment: $sliderBar,
|
||||
start: startDrag,
|
||||
stop: stopDrag,
|
||||
drag: onDrag
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
initialize();
|
||||
|
||||
this.play = play;
|
||||
this.pause = pause;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
$.fn.listenRecording = function(options) {
|
||||
new context.JK.ListenRecording(this, options);
|
||||
}
|
||||
})(window, jQuery);
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
context.JK = context.JK || {};
|
||||
|
||||
// the purpose of this code is to simply the interaction between user and server
|
||||
// the purpose of this code is to simplify the interaction between user and server
|
||||
// it provides methods to call on user events (primarily play/pause), and will fire
|
||||
// events (such as 'stream_gone'). This element does nothing with UI; only fires events for you to handle
|
||||
|
||||
|
|
@ -328,12 +328,12 @@
|
|||
isEnd = true;
|
||||
}
|
||||
else if(playState == 'failed_playing') {
|
||||
displayText = 'AUDIO FAILED';
|
||||
displayText = 'STREAM DISCONNECTED';
|
||||
isEnd = true;
|
||||
refresh = true;
|
||||
}
|
||||
else if(playState == 'network_error') {
|
||||
displayText = 'STREAM DISCONNECTED';
|
||||
displayText = 'NO NETWORK';
|
||||
isEnd = true;
|
||||
}
|
||||
else if(playState == 'server_error') {
|
||||
|
|
@ -372,7 +372,7 @@
|
|||
$audio.bind('pause', onPause);
|
||||
$audio.bind('suspend', onSuspend);
|
||||
$audio.bind('stalled', onStalled);
|
||||
$audio.bind('timeupdate', onTimeUpdate);
|
||||
//$audio.bind('timeupdate', onTimeUpdate);
|
||||
$audio.bind('progress', onProgress);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@
|
|||
promptLeave = false;
|
||||
context.location = '/client#/home'
|
||||
}
|
||||
else {
|
||||
else if(type != 30 && type != 31){ // these are handled elsewhere
|
||||
context.setTimeout(function() {
|
||||
var alert = alert_type[type];
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
context.JK = context.JK || {};
|
||||
context.JK.TickDuration = function(customSelector) {
|
||||
setInterval(function() {
|
||||
$.each($(customSelector ? customSelector : '.tick-duration'), function(index, item) {
|
||||
$.each($(customSelector ? customSelector : '.inprogress .tick-duration'), function(index, item) {
|
||||
var $duration = $(item);
|
||||
var createdAt = new Date(Number($duration.attr('data-created-at')) * 1000)
|
||||
var millisElapsed = (new Date()).getTime() - createdAt.getTime();
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
context.JK.ShowMusicSession = function(app) {
|
||||
var logger = context.JK.logger;
|
||||
var rest = new JK.Rest();
|
||||
var sessionId = null;
|
||||
|
||||
var sessionId = null;
|
||||
var $controls = null;
|
||||
var $status = null;
|
||||
var playing = false;
|
||||
|
||||
function like() {
|
||||
rest.addSessionLike(sessionId, JK.currentUserId)
|
||||
|
|
@ -33,7 +35,61 @@
|
|||
}
|
||||
}
|
||||
|
||||
function stateChange(e, data) {
|
||||
if(data.displayText)
|
||||
{
|
||||
if(data.displayText == 'SESSION IN PROGRESS') {
|
||||
$status.text('LIVE SESSION IN PROGRESS');
|
||||
}
|
||||
else {
|
||||
$status.text(data.displayText);
|
||||
}
|
||||
}
|
||||
|
||||
if(data.isEnd) stopPlay();
|
||||
|
||||
if(data.isSessionOver) {
|
||||
$controls.removeClass('inprogress').addClass('ended')
|
||||
}
|
||||
}
|
||||
|
||||
function startPlay() {
|
||||
var img = $('.play-icon');
|
||||
img.attr('src', '/assets/content/icon_pausebutton.png');
|
||||
$controls.trigger('play.listenBroadcast');
|
||||
playing = true;
|
||||
}
|
||||
|
||||
function stopPlay() {
|
||||
var img = $('.play-icon');
|
||||
img.attr('src', '/assets/content/icon_playbutton.png');
|
||||
$controls.trigger('pause.listenBroadcast');
|
||||
playing = false;
|
||||
}
|
||||
|
||||
function togglePlay() {
|
||||
if(playing) {
|
||||
$status.text('SESSION IN PROGRESS');
|
||||
stopPlay();
|
||||
}
|
||||
else {
|
||||
startPlay();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function initialize(musicSessionId) {
|
||||
$controls = $('.recording-controls');
|
||||
$status = $('.session-status')
|
||||
|
||||
$('.timeago').timeago();
|
||||
$controls.listenBroadcast();
|
||||
$controls.bind('statechange.listenBroadcast', stateChange);
|
||||
context.JK.prettyPrintElements($('time.duration').show());
|
||||
context.JK.TickDuration(null);
|
||||
$('.play-button').click(togglePlay);
|
||||
|
||||
|
||||
sessionId = musicSessionId;
|
||||
|
||||
if (JK.currentUserId) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//= require jquery
|
||||
//= require jquery.monkeypatch
|
||||
//= require jquery_ujs
|
||||
//= require jquery.ui.draggable
|
||||
//= require jquery.queryparams
|
||||
//= require jquery.hoverIntent
|
||||
//= require jquery.cookie
|
||||
|
|
@ -11,6 +12,7 @@
|
|||
//= require jquery.timeago
|
||||
//= require jquery.dotdotdot
|
||||
//= require jquery.listenbroadcast
|
||||
//= require jquery.listenRecording
|
||||
//= require AAA_Log
|
||||
//= require AAC_underscore
|
||||
//= require globals
|
||||
|
|
@ -21,6 +23,7 @@
|
|||
//= require web/signinDialog
|
||||
//= require web/videoDialog
|
||||
//= require invitationDialog
|
||||
//= require tickDuration
|
||||
//= require hoverMusician
|
||||
//= require feed_item_recording
|
||||
//= require feed_item_session
|
||||
|
|
|
|||
|
|
@ -46,9 +46,10 @@
|
|||
else {
|
||||
new context.JK.FeedItemSession($feedEntry);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
context.JK.TickDuration('.feed-entry.music-session-history-entry .inprogress .tick-duration');
|
||||
|
||||
}
|
||||
|
||||
context.JK.WelcomePage = initialize;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,72 @@
|
|||
height: 36px;
|
||||
}
|
||||
|
||||
|
||||
.session-controls, .recording-controls {
|
||||
|
||||
.tick-duration {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.play-button {
|
||||
outline: 0;
|
||||
}
|
||||
.session-status {
|
||||
font-size:18px;
|
||||
display:inline;
|
||||
}
|
||||
|
||||
.recording-current {
|
||||
top:8px;
|
||||
}
|
||||
|
||||
.session-duration {
|
||||
top:8px;
|
||||
}
|
||||
|
||||
&.ended {
|
||||
|
||||
.play-button {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
&.inprogress {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.feed-entry {
|
||||
.session-controls, .recording-controls {
|
||||
&.ended {
|
||||
background-color: #471f18;
|
||||
|
||||
}
|
||||
|
||||
&.inprogress {
|
||||
background-color: #4C742E;
|
||||
|
||||
.session-status {
|
||||
font-size: 15px;
|
||||
color: #cccc00;
|
||||
margin:auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.recording-controls {
|
||||
.recording-position {
|
||||
width:70%;
|
||||
margin-left:0;
|
||||
}
|
||||
|
||||
.recording-time {
|
||||
display:inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.feed-entry {
|
||||
position:relative;
|
||||
display:block;
|
||||
|
|
@ -58,25 +124,6 @@
|
|||
}
|
||||
*/
|
||||
|
||||
.session-status {
|
||||
float:left;
|
||||
font-size:18px;
|
||||
}
|
||||
|
||||
.inprogress {
|
||||
.session-status {
|
||||
font-size: 15px;
|
||||
color: #cccc00;
|
||||
margin-left:20px;
|
||||
}
|
||||
}
|
||||
|
||||
.recording-current {
|
||||
top:8px;
|
||||
}
|
||||
.session-duration {
|
||||
top:8px;
|
||||
}
|
||||
|
||||
.recording-controls, .session-controls {
|
||||
margin-top:0px;
|
||||
|
|
@ -86,20 +133,6 @@
|
|||
line-height:19px;
|
||||
}
|
||||
|
||||
.session-controls {
|
||||
&.ended {
|
||||
background-color: #471f18;
|
||||
|
||||
.play-button {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
&.inprogress {
|
||||
background-color: #4C742E;
|
||||
}
|
||||
}
|
||||
|
||||
.details {
|
||||
color:#ED3618;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@import "client/common.css.scss";
|
||||
|
||||
.feed-entry .recording-controls, .feed-entry .session-controls, .landing-details .recording-controls {
|
||||
margin-top:0px;
|
||||
margin-bottom:5px;
|
||||
|
|
@ -5,7 +7,19 @@
|
|||
width:98%;
|
||||
position:relative;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.landing-details .recording-controls, .landing-details .recording-controls {
|
||||
|
||||
background-color:#242323;
|
||||
|
||||
@include border_box_sizing;
|
||||
width:100%;
|
||||
|
||||
.session-status {
|
||||
float:left;
|
||||
margin-left:20px;
|
||||
}
|
||||
}
|
||||
|
||||
.recording-position {
|
||||
|
|
@ -52,7 +66,7 @@
|
|||
font-family:Arial, Helvetica, sans-serif;
|
||||
display:inline-block;
|
||||
font-size:18px;
|
||||
position:absolute;
|
||||
float:right;
|
||||
top:3px;
|
||||
right:4px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*= require easydropdown_jk
|
||||
*= require client/screen_common
|
||||
*= require client/content
|
||||
*= require web/audioWidgets
|
||||
*= require client/notify
|
||||
*= require client/ftue
|
||||
*= require client/user_dropdown
|
||||
|
|
|
|||
|
|
@ -14,202 +14,6 @@ body.web {
|
|||
}
|
||||
}
|
||||
|
||||
.session-controls {
|
||||
margin-top: 15px;
|
||||
padding: 3px 5px 3px 10px;
|
||||
width: 93%;
|
||||
min-width: 200px;
|
||||
background-color: #242323;
|
||||
position: relative;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
@include border_box_sizing;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.recording-controls {
|
||||
margin-top: 15px;
|
||||
padding: 3px 5px 3px 10px;
|
||||
width: 93%;
|
||||
min-width: 200px;
|
||||
background-color: #242323;
|
||||
position: relative;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
@include border_box_sizing;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.feed-entry {
|
||||
position:relative;
|
||||
display:block;
|
||||
white-space:nowrap;
|
||||
min-width:700px;
|
||||
border-bottom:solid 1px #666;
|
||||
max-height:74px;
|
||||
overflow:hidden;
|
||||
margin-top:20px;
|
||||
|
||||
&:nth-child(1) {
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
/**
|
||||
&.animate-down {
|
||||
-webkit-transition: max-height height 2s;
|
||||
transition: max-height height 2s;
|
||||
-moz-transition: max-height height 2s;
|
||||
-o-transition: max-height height 2s;
|
||||
-ms-transition: max-height height 2s;
|
||||
}
|
||||
|
||||
&.animate-up {
|
||||
-webkit-transition: max-height height .4s;
|
||||
transition: max-height height .4s;
|
||||
-moz-transition: max-height height .4s;
|
||||
-o-transition: max-height height .4s;
|
||||
-ms-transition: max-height height .4s;
|
||||
}
|
||||
*/
|
||||
|
||||
.session-status {
|
||||
float:left;
|
||||
font-size:18px;
|
||||
}
|
||||
|
||||
.inprogress {
|
||||
.session-status {
|
||||
font-size: 15px;
|
||||
color: #cccc00;
|
||||
margin-left:20px;
|
||||
}
|
||||
}
|
||||
|
||||
.recording-current {
|
||||
top:8px;
|
||||
}
|
||||
.session-duration {
|
||||
top:8px;
|
||||
}
|
||||
|
||||
.recording-controls, .session-controls {
|
||||
margin-top:0px;
|
||||
margin-bottom:5px;
|
||||
padding:8px 5px 8px 10px;
|
||||
width:98%;
|
||||
line-height:19px;
|
||||
}
|
||||
|
||||
.session-controls {
|
||||
&.ended {
|
||||
background-color: #471f18;
|
||||
|
||||
.play-button {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
&.inprogress {
|
||||
background-color: #4C742E;
|
||||
}
|
||||
}
|
||||
|
||||
.details {
|
||||
color:#ED3618;
|
||||
}
|
||||
|
||||
.avatar-small {
|
||||
@include content_box_sizing;
|
||||
margin-top:0px;
|
||||
margin-left:0px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size:16px;
|
||||
color:#999;
|
||||
margin-bottom:3px;
|
||||
}
|
||||
|
||||
.artist {
|
||||
font-size:12px;
|
||||
font-weight:bold;
|
||||
color:#ccc;
|
||||
margin-bottom:10px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-weight:bold;
|
||||
font-size:14px;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size:12px;
|
||||
white-space:normal;
|
||||
line-height:14px;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
height:60px;
|
||||
}
|
||||
|
||||
.feed-details {
|
||||
vertical-align:middle;
|
||||
|
||||
img {
|
||||
vertical-align:middle;
|
||||
}
|
||||
}
|
||||
|
||||
.play-count {
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
.comment-count {
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
.like-count {
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
.musicians {
|
||||
margin-top:10px;
|
||||
font-size:11px;
|
||||
}
|
||||
|
||||
.musicians td {
|
||||
border-right:none;
|
||||
border-top:none;
|
||||
padding:3px;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
.musicians a {
|
||||
color:#fff;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
.avatar-tiny {
|
||||
float:left;
|
||||
padding:1px;
|
||||
width:24px;
|
||||
height:24px;
|
||||
background-color:#ed3618;
|
||||
-webkit-border-radius:12px;
|
||||
-moz-border-radius:12px;
|
||||
border-radius:12px;
|
||||
}
|
||||
|
||||
.avatar-tiny img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
-webkit-border-radius:12px;
|
||||
-moz-border-radius:12px;
|
||||
border-radius:12px;
|
||||
}
|
||||
}
|
||||
|
||||
.buzz {
|
||||
width: 300px;
|
||||
position:relative;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module FeedsHelper
|
|||
image_tag resolve_avatarables(music_session_history.band, music_session_history.user)
|
||||
end
|
||||
|
||||
def session_duration(music_session_history, options)
|
||||
def session_duration(music_session_history, options={})
|
||||
if music_session_history.session_removed_at.nil?
|
||||
duration(Time.now - music_session_history.created_at, options)
|
||||
else
|
||||
|
|
@ -34,7 +34,7 @@ module FeedsHelper
|
|||
image_tag resolve_avatarables(recording.band, recording.owner)
|
||||
end
|
||||
|
||||
def recording_duration(recording, options)
|
||||
def recording_duration(recording, options={})
|
||||
duration(recording.duration, options)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -51,26 +51,17 @@
|
|||
<% end %>
|
||||
<br clear="all" />
|
||||
<div class="w100">
|
||||
<div class="recording-controls">
|
||||
<% if !@music_session.music_session.nil? && !@music_session.music_session.mount.blank? %>
|
||||
<a id="btnPlayPause" class="left mr20">
|
||||
<%= image_tag "content/icon_playbutton.png", {:id => "imgPlayPause", :width => 20, :height => 20, :alt => ""} %>
|
||||
</a>
|
||||
<% end %>
|
||||
<% if @music_session.session_removed_at.blank? %>
|
||||
<div class="session-status">SESSION IN PROGRESS</div>
|
||||
<div class="recording-current"></div>
|
||||
<audio controls preload="none" style="display:none;">
|
||||
<% unless @music_session.music_session.nil? || @music_session.music_session.mount.blank? %>
|
||||
<div class="recording-controls <%= @music_session.is_over? ? 'ended' : 'inprogress' %>" data-music-session="<%=@music_session.id %>">
|
||||
<a class="left play-button" href="#">
|
||||
<%= image_tag 'content/icon_playbutton.png', width:20, height:20, class:'play-icon' %>
|
||||
<% if @music_session.music_session && @music_session.music_session.mount %>
|
||||
<audio preload="none">
|
||||
<source src="<%= @music_session.music_session.mount.url %>" type="<%= @music_session.music_session.mount.resolve_string(:mime_type) %>">
|
||||
<% end %>
|
||||
</audio>
|
||||
<% if @music_session.music_session.nil? || @music_session.music_session.mount.blank? %>
|
||||
<div>NO AUDIO AVAILABLE</div>
|
||||
</audio>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="session-status-ended">LIVE SESSION ENDED</div>
|
||||
<% end %>
|
||||
</a>
|
||||
<div class="session-status"><%= @music_session.is_over? ? 'SESSION ENDED' : 'LIVE SESSION IN PROGRESS' %></div>
|
||||
<%= session_duration(@music_session, class: 'session-duration tick-duration recording-current', 'data-created-at' => @music_session.created_at.to_i) %>
|
||||
</div>
|
||||
|
||||
<div class="left white"><%= @music_session.genres.split('|').first.capitalize %></div>
|
||||
|
|
@ -113,5 +104,6 @@
|
|||
$(function () {
|
||||
var showMusicSession = new JK.ShowMusicSession(JK.app);
|
||||
showMusicSession.initialize("<%= @music_session.id %>");
|
||||
});
|
||||
</script>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
.session-status
|
||||
= feed_item.is_over? ? 'SESSION ENDED' : 'SESSION IN PROGRESS'
|
||||
/ current playback time
|
||||
= session_duration(feed_item, class: 'session-duration recording-current', 'data-created-at' => feed_item.created_at.to_i)
|
||||
= session_duration(feed_item, class: 'session-duration tick-duration recording-current', 'data-created-at' => feed_item.created_at.to_i)
|
||||
/ end recording play controls
|
||||
/ genre and social
|
||||
.left.small
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@
|
|||
.recording-controls
|
||||
/ play button
|
||||
%a.left.play-button{:href => "#"}
|
||||
= image_tag 'content/icon_playbutton.png', width:20, height:20
|
||||
= image_tag 'content/icon_playbutton.png', width:20, height:20, class:'play-icon'
|
||||
- if feed_item.has_mix?
|
||||
%audio{preload: 'none'}
|
||||
%source{src: claimed_recording_download_url(feed_item.candidate_claimed_recording.id, 'mp3'), type:'audio/mpeg'}
|
||||
%source{src: claimed_recording_download_url(feed_item.candidate_claimed_recording.id, 'ogg'), type:'audio/ogg'}
|
||||
/ playback position
|
||||
.recording-position
|
||||
/ start time
|
||||
|
|
@ -30,11 +34,12 @@
|
|||
.recording-slider
|
||||
= image_tag 'content/slider_playcontrols.png', width:5, height:16
|
||||
/ end time
|
||||
.recording-time 4:59
|
||||
.recording-time.recording-duration
|
||||
= recording_duration(feed_item)
|
||||
/ end playback position
|
||||
/ current playback time
|
||||
.recording-current
|
||||
1:23
|
||||
0:00
|
||||
/ end recording play controls
|
||||
/ genre and social
|
||||
.left.small
|
||||
|
|
|
|||
Loading…
Reference in New Issue