$ = jQuery context = window logger = context.JK.logger rest = context.JK.Rest(); VideoUploaderActions = @VideoUploaderActions @VideoUploaderStore = Reflux.createStore( { listenables: VideoUploaderActions logger: context.JK.logger preparingUpload: false uploading: false paused: false recordingId: null videoUrl: null bytesSent: 0 bytesTotal: 1 errorReason: null errorDetail: null state: null done: false init: -> # Register with the app store to get @app this.listenTo(context.AppStore, this.onAppInit) @state = {uploading: @uploading, recordingId: @recordingId, videoUrl: @videoUrl, paused: @paused, preparingUpload: @preparingUpload, bytesSent: @bytesSent, bytesTotal: @bytesTotal, errorReason: @errorReason, errorDetail: @errorDetail, done: @done } onAppInit: (app) -> @app = app triggerState: () -> @state = {uploading: @uploading, recordingId: @recordingId, videoUrl: @videoUrl, paused: @paused, preparingUpload: @preparingUpload, bytesSent: @bytesSent, bytesTotal: @bytesTotal, errorReason: @errorReason, errorDetail: @errorDetail, done: @done} @trigger(@state) getState: () -> @state # onPause: () -> # if @uploading # @uploading = false # @paused = true # context.jamClient.pauseVideoUpload() # @triggerState() onPause: `async function() { if (this.uploading) { this.uploading = false; this.paused = true; await context.jamClient.pauseVideoUpload(); this.triggerState(); } }` # onResume: () -> # if @paused && @recordingId? # @uploading = true # @paused = false # context.jamClient.resumeVideoUpload() # @triggerState() # else # if @uploading # @app.layout.notify({title: 'Already uploading', text: "A video is already being uploaded."}) # else # @app.layout.notify({title: 'Nothing to resume', text: "No upload to resume."}) onResume: `async function() { if (this.paused && (this.recordingId != null)) { this.uploading = true; this.paused = false; await context.jamClient.resumeVideoUpload(); this.triggerState(); } else { if (this.uploading) { this.app.layout.notify({title: 'Already uploading', text: "A video is already being uploaded."}); } else { this.app.layout.notify({title: 'Nothing to resume', text: "No upload to resume."}); } } }` # onCancel: () -> # if @uploading # @uploading = false # context.jamClient.cancelVideoUpload() # @triggerState() onCancel: `async function(){ if(this.uploading){ this.uploading=false; await context.jamClient.cancelVideoUpload(); this.triggerState(); } }` # onDelete: (recordingId) -> # context.jamClient.deleteVideo(recordingId); onDelete: `async function(recordingId) { await context.jamClient.deleteVideo(recordingId); }` onNewVideo: (recordingId) -> @onCancel(recordingId) @done = false @paused = false @bytesSent = 0 @bytesTotal = 1 @errorReason = null @errorDetail = null @videoUrl = null @triggerState() onShowUploader: (recordingId) -> if @childWindow? logger.debug("showUploader popup being closed automatically") @childWindow.close() @childWindow = null @childWindow = window.open("/popups/video/upload/" + recordingId, 'Video Uploader', 'scrollbars=yes,toolbar=no,status=no,height=155,width=350') onUploaderClosed: () -> if @childWindow? @childWindow = null # onUploadVideo: (recordingId) -> # if @uploading || @preparingUpload # logger.debug("ignoring upload request") # return # @preparingUpload = true # @onNewVideo() # rest.getRecording({id:recordingId}) # .done((response) => # claim = response.my # privateStatus = 'private' # privateStatus = 'public' if claim.is_public # if claim? # videoInfo = { # "snippet": { # "title": claim.name, # "description": claim.description, # "tags": ["JamKazam"], # "categoryId": 10 # music # }, # "status": { # "privacyStatus": privateStatus, # "embeddable": true, # "license": "youtube" # } # } # rest.getUserAuthorizations() # .done((response) => # # http://localhost:3000/popups/video/upload/d25dbe8e-a066-4ea0-841d-16872c713fc9 # youtube_auth = null # for authorization in response.authorizations # if authorization.provider == 'google_login' # youtube_auth = authorization.token # break # if youtube_auth? # logger.debug("calling uploadVideo(#{recordingId}, #{youtube_auth}, #{videoInfo})") # result = context.jamClient.uploadVideo(recordingId, youtube_auth, JSON.stringify(videoInfo), # "VideoUploaderStore.clientUploadCallback", # "VideoUploaderStore.clientDoneCallback", # "VideoUploaderStore.clientFailCallback") # if result.error # @preparingUpload = false # @triggerState() # @app.layout.notify({title: 'Unable to upload video', text: 'Application error: ' + result.error}) # else # @preparingUpload = false # @videoUrl = null # @uploading = true # @recordingId = recordingId # @triggerState() # else # @preparingUpload = false # @triggerState() # @app.layout.notify({title: 'No Authorization Yet for YouTube', text: 'Youtube authorization still needed'}) # ) # .fail((jqXHR) => # @preparingUpload = false # @triggerState() # @app.layout.notifyServerError(jqXHR, 'Unable to fetch user authorizations') # ) # else # @preparingUpload = false # @triggerState() # @app.layout.notify({title: "You do not have a claim to this recording", text: "If this is in error, contact support@jamkazam.com."}) # ) # .fail((jqXHR) => # @preparingUpload = false # @triggerState() # @app.layout.notifyServerError(jqXHR, 'Unable to fetch recording information') # ) onUploadVideo: `function(recordingId) { if (this.uploading || this.preparingUpload) { logger.debug("ignoring upload request"); return; } this.preparingUpload = true; this.onNewVideo(); return rest.getRecording({id:recordingId}) .done(response => { const claim = response.my; let privateStatus = 'private'; if (claim.is_public) { privateStatus = 'public'; } if (claim != null) { const videoInfo = { "snippet": { "title": claim.name, "description": claim.description, "tags": ["JamKazam"], "categoryId": 10 // music }, "status": { "privacyStatus": privateStatus, "embeddable": true, "license": "youtube" } }; return rest.getUserAuthorizations() .done(async response => { // http://localhost:3000/popups/video/upload/d25dbe8e-a066-4ea0-841d-16872c713fc9 let youtube_auth = null; for (let authorization of Array.from(response.authorizations)) { if (authorization.provider === 'google_login') { youtube_auth = authorization.token; break; } } if (youtube_auth != null) { logger.debug('calling uploadVideo('+recordingId+', '+youtube_auth+', ' +videoInfo); const result = await context.jamClient.uploadVideo(recordingId, youtube_auth, JSON.stringify(videoInfo), "VideoUploaderStore.clientUploadCallback", "VideoUploaderStore.clientDoneCallback", "VideoUploaderStore.clientFailCallback"); if (result.error) { this.preparingUpload = false; this.triggerState(); return this.app.layout.notify({title: 'Unable to upload video', text: 'Application error: ' + result.error}); } else { this.preparingUpload = false; this.videoUrl = null; this.uploading = true; this.recordingId = recordingId; return this.triggerState(); } } else { this.preparingUpload = false; this.triggerState(); return this.app.layout.notify({title: 'No Authorization Yet for YouTube', text: 'Youtube authorization still needed'}); } }) .fail(jqXHR => { this.preparingUpload = false; this.triggerState(); return this.app.layout.notifyServerError(jqXHR, 'Unable to fetch user authorizations'); }); } else { this.preparingUpload = false; this.triggerState(); return this.app.layout.notify({title: "You do not have a claim to this recording", text: "If this is in error, contact support@jamkazam.com."}); } }) .fail(jqXHR => { this.preparingUpload = false; this.triggerState(); return this.app.layout.notifyServerError(jqXHR, 'Unable to fetch recording information'); }); }` clientUploadCallback: (bytesSent, bytesTotal) -> logger.debug("bytesSent: #{bytesSent} bytesTotal: #{bytesTotal}") # backend will report 0 bytes total sometimes as the upload is failing. just ignore it; we'll get an error message soon return if bytesTotal == 0 VideoUploaderStore.bytesSent = Number(bytesSent) VideoUploaderStore.bytesTotal = Number(bytesTotal) VideoUploaderStore.triggerState() clientDoneCallback: (video_id) -> console.log logger.debug("client uploaded video successfully to #{video_id}") VideoUploaderStore.uploading = false VideoUploaderStore.videoUrl = "https://www.youtube.com/watch?v=#{video_id}" rest.addRecordingVideoData(VideoUploaderStore.recordingId, {video_id: video_id}) .fail(() => VideoUploaderStore.app.layout.notify({title: 'Sync Error', text:'Unable to notify server about uploaded video'}) ) VideoUploaderStore.recordingId = null VideoUploaderStore.done = true VideoUploaderStore.triggerState() clientFailCallback: (reason, detail) => logger.warn("client failed to video upload #{reason}, #{detail}") VideoUploaderStore.uploading = false VideoUploaderStore.errorReason = reason VideoUploaderStore.errorDetail = detail # if reason == "create_video_failed" && errorDetail = "401" # then don't trigger state, instead ask server for a fresh token # VideoUploaderStore.triggerState() } ) @VideoUploaderStore