diff --git a/images/icon/download.svg b/images/icon/download.svg new file mode 100644 index 0000000..c65a448 --- /dev/null +++ b/images/icon/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/scripts/glitcher.js b/scripts/glitcher.js index e9c467d..abe92dd 100644 --- a/scripts/glitcher.js +++ b/scripts/glitcher.js @@ -25,6 +25,7 @@ require( [ 'views/workspaceview', 'views/welcomeview', 'views/settingsview', + 'views/downloadview', 'models/controlsmodel', 'models/imagemodel', 'models/glitchmodel', @@ -54,6 +55,7 @@ require( [ WorkspaceView, WelcomeView, SettingsView, + DownloadView, ControlsModel, ImageModel, GlitchModel, @@ -87,9 +89,10 @@ require( [ var saveView = SaveView( navView.el ); var webcamView = WebCamView( navView.el ); var shareView = ShareView( navView.el ); - var aboutView = AboutView( navView.el ); var settingsView = SettingsView( navView.el ); + var aboutView = AboutView( navView.el ); var fullscreenView = FullscreenView( workspaceView.el ); + var downloadView = DownloadView( workspaceView.el ); var dragAndDropView = DragAndDropView( canvasView.el ); var welcomeView = WelcomeView(); @@ -318,13 +321,12 @@ require( [ var downloadLinkTimeoutId = NaN; function updateDownloadLink () { - if ( saveView.getActive() ) { - clearTimeout( downloadLinkTimeoutId ); + clearTimeout( downloadLinkTimeoutId ); - downloadLinkTimeoutId = setTimeout( function () { - glitchModel.getImageGenerationFn( saveView.updateDownloadLink, 'original' )( imageModel.getLastFileName() ) - }, 200 ); - } + downloadLinkTimeoutId = setTimeout( function () { + glitchModel.getImageGenerationFn( saveView.updateDownloadLink, 'original' )( imageModel.getLastFileName() ); + glitchModel.getImageGenerationFn( downloadView.updateDownloadLink, 'original' )( imageModel.getLastFileName() ); + }, 200 ); } function hideAppLoader () { diff --git a/scripts/views/downloadview.js b/scripts/views/downloadview.js new file mode 100644 index 0000000..3b9a985 --- /dev/null +++ b/scripts/views/downloadview.js @@ -0,0 +1,49 @@ +/*global define*/ +define( + [ 'util/browser', 'util/el', 'util/time' ], + function ( browser, elHelper, timeHelper ) { + // the fullscreen button + // includes a lot of code to account for the different browser implementations + function DownloadView ( parentEl ) { + if ( ! ( this instanceof DownloadView ) ) { + return new DownloadView( parentEl ); + } + + var self = this; + var isInFullScreen = false; + var downloadLinkEl = elHelper.createLink( + 'file.download', + 'file.downloadtitle', + null, null, + 'download-button', + parentEl + ); + + downloadLinkEl.target = '_blank';; + + // the href attribute of the download link is updated every time + // we change a parameter + function updateDownloadLink ( newUrl, fileName ) { + fileName = fileName || 'glitched'; + + var newNameParts = fileName.split( '/' ); + var newName = newNameParts.length > 1 ? newNameParts.pop() : newNameParts[0]; + newName = newName.split( '.' ).shift(); + + date = new Date(); + fileId = timeHelper.dateTimeToLocalStr( date ); + var newFileName = ( newName + '-glitched-' + fileId + '.png' ) + newFileName = newFileName.replace( /(\s|\/|:)/gmi, '-' ); + + // setting the download attribute makes the browser + // download the link target instead of opening it + downloadLinkEl.setAttribute( 'download', newFileName ); + downloadLinkEl.href = newUrl; + } + + self.updateDownloadLink = updateDownloadLink; + } + + return DownloadView; + } +); \ No newline at end of file diff --git a/scripts/views/navview.js b/scripts/views/navview.js index f15b115..5093a98 100644 --- a/scripts/views/navview.js +++ b/scripts/views/navview.js @@ -162,10 +162,20 @@ define( var dx = touchPos.x - touchStartPos.x; if ( translateX > -navWidth && translateX < 0 && Math.abs( dx ) > 0 ) { - if ( translateX < -navWidth / 2 ) { - deactivate(); + if ( dx > 0 ) { + // swiped in + if ( translateX < -navWidth * 0.75 ) { + deactivate(); + } else { + activate(); + } } else { - activate(); + // swiped out + if ( translateX < -navWidth * 0.25 ) { + deactivate(); + } else { + activate(); + } } } } diff --git a/scripts/views/shareview.js b/scripts/views/shareview.js index 5a01825..2e0aaee 100644 --- a/scripts/views/shareview.js +++ b/scripts/views/shareview.js @@ -69,12 +69,12 @@ define( .add( isOnlineCssClass, uploadButtonEl ) .add( isOnlineCssClass, 'loader', statusEl ) .add( isOnlineCssClass, imgLinkLabel, imgLinkEl ) - .add( isOnlineCssClass, imgurLinkEl ) - .add( isOnlineCssClass, redditShareLinkEl ) .add( isOnlineCssClass, twitterShareLinkEl ) .add( isOnlineCssClass, facebookShareLinkEl ) - .add( isOnlineCssClass, pinterestShareLinkEl ) - .add( isOnlineCssClass, vkontakteShareLinkEl ); + .add( isOnlineCssClass, imgurLinkEl ) + .add( isOnlineCssClass, redditShareLinkEl ) + .add( isOnlineCssClass, vkontakteShareLinkEl ) + .add( isOnlineCssClass, pinterestShareLinkEl ); if ( browser.test( 'localforage' ) ) { sharedListEl = elHelper.createEl( 'ul', 'shared-list dialog-list' ); @@ -326,7 +326,7 @@ define( } if ( service === 'twitter' ) { - params.text = loc( 'share.link.description.withname' ) + ' ' + imgUrl + ' ' + config.share.appURL; + params.text = loc( 'share.link.description.withname' ) + ' ' + imgurLink + ' ' + config.share.appURL; } return config.share.sharer[service] + '?' + strHelper.objToQueryStr( params ); diff --git a/scripts/views/webcamview.js b/scripts/views/webcamview.js index 46f9e53..136fe47 100644 --- a/scripts/views/webcamview.js +++ b/scripts/views/webcamview.js @@ -90,8 +90,10 @@ define( function userMediaFailed () { if ( stream ) { stopStream(); - publishers.error.dispatch( 'webcam.error.access' ); } + + closeVideo(); + publishers.error.dispatch( 'webcam.error.access' ); } function closeVideo () { diff --git a/serviceworker.js b/serviceworker.js index 7af4548..de44ac1 100644 --- a/serviceworker.js +++ b/serviceworker.js @@ -25,6 +25,7 @@ function updateStaticCache () { 'images/icon/open-in-app.svg', 'images/icon/share-variant.svg', 'images/icon/settings.svg', + 'images/icon/download.svg', 'lang/en-us.json' ] ); // These items must be cached for the Service Worker to complete installation diff --git a/styles/global/reset.css b/styles/global/reset.css index f8f2bf1..8ea6ea7 100644 --- a/styles/global/reset.css +++ b/styles/global/reset.css @@ -2,4 +2,8 @@ content: ''; display: table; clear: both; +} + +a, button { + -webkit-tap-highlight-color: rgba( 0, 0, 0, 0 ); } \ No newline at end of file diff --git a/styles/modules/dialog.css b/styles/modules/dialog.css index 2783d76..ad8fa08 100644 --- a/styles/modules/dialog.css +++ b/styles/modules/dialog.css @@ -289,6 +289,16 @@ overflow: auto; } +.has-touch .share-dialog .dialog-item .button { + width: 100%; + text-align: center; +} + +.has-touch .share-dialog .entry-button-wrapper .button { + width: auto; + text-align: left; +} + /*pulse keyframe animation is inlined in html*/ .dialog .loader { diff --git a/styles/modules/workspace-nav.css b/styles/modules/workspace-nav.css index 185b86f..d5f348b 100644 --- a/styles/modules/workspace-nav.css +++ b/styles/modules/workspace-nav.css @@ -82,7 +82,8 @@ input.scale-slider { float: left; } -.fullscreen-button { +.fullscreen-button, +.download-button { display: block; position: absolute; top: 10px; @@ -102,6 +103,11 @@ input.scale-slider { opacity: 1; } +.download-button { + top: 60px; + background-image: url(../../images/icon/download.svg); +} + html:not(.has-touch) .fullscreen-button { opacity: 0.7; }