diff --git a/addons/README.md b/addons/README.md index 9ee2e34..51e1c73 100644 --- a/addons/README.md +++ b/addons/README.md @@ -115,7 +115,7 @@ The base class from which addons are inherited. If you use the function interfac | `changingActiveImage` | Notification before changing the current image. | | | *Argument*: currentImageIndex, fadeTime (ms) | | `changedActiveImage` | Notification that the current image has been changed. | - | | *Argument*: currentImageIndex (ms) | + | | *Argument*: currentImageIndex | diff --git a/css/style.css b/css/style.css index 7941b7c..9ddec6d 100644 --- a/css/style.css +++ b/css/style.css @@ -145,6 +145,12 @@ h1 { color: white; } +.touch-bar:hover, +.touchBarElement:hover { + cursor: pointer; +} + + .disabled-icon { color: #333; } diff --git a/js/defaultConfig.js b/js/defaultConfig.js index b805b6c..540ebd4 100644 --- a/js/defaultConfig.js +++ b/js/defaultConfig.js @@ -182,6 +182,19 @@ var defaultConfig = { ] }, + gestures: { + // enable gesture support + enabled: true, + // swipe image out duration + swipeAnimationDuration: 400, + // fade in duration for the loading image + swipeFadeInImgDuration: 800, + // percent per event for pinch/zoom gestures + zoomPercentPerEvent: 1.5, + // maximum factor for zoom/shrink operations + maxScaleFactor: 5 + }, + // options for the addonHandler class addonInterface: { // configure which types should be logged diff --git a/js/renderer.js b/js/renderer.js index 94f4874..1d8e220 100644 --- a/js/renderer.js +++ b/js/renderer.js @@ -9,6 +9,7 @@ const velocity = require("velocity-animate"); const logger = remote.getGlobal("rendererLogger"); const config = remote.getGlobal("config"); const {TouchBar, TouchBarElement} = require("./js/touchBar.js") +const initGestures = require('./js/touchGestures.js'); // Inform that Renderer started logger.info("Renderer started ..."); @@ -52,6 +53,17 @@ if (config.playSoundOnRecieve !== false) { if (config.touchBar) { touchBar = new TouchBar(touchBarElements, config.touchBar) + // initialize swipe/pinch gestures + if (config.gestures.enabled) { + initGestures(config, { + pauseCallback: () => { + if (!isPaused) { + pause(); + } + }, + loadImage: loadImage + }); + } } else { // handle touch events for navigation and voice reply $("body").on('touchstart', function() { @@ -727,10 +739,12 @@ function loadImage(isNext, fadeTime, goToLatest = false) { cleanUp(); } else { $assetDiv.velocity("fadeIn", { - duration: fadeTime + duration: fadeTime, + queue: false }); $currentAsset.velocity("fadeOut", { duration: fadeTime, + queue: false, complete: function() { $(this).remove(); cleanUp(); diff --git a/js/touchBar.js b/js/touchBar.js index 92354d6..aa70a79 100644 --- a/js/touchBar.js +++ b/js/touchBar.js @@ -31,7 +31,7 @@ class TouchBar { el.classList = name + " touchBarElement"; el.style.lineHeight = self.height; el.style.fontSize = ($('#touch-bar-container').height()*0.8) + 'px'; - $(el).on('touchend', function(event) { + $(el).on('click', function(event) { // don't bubble up events to prevent disappearing sweetalert messages event.preventDefault(); clearTimeout(self.autoHideTimerId); @@ -47,7 +47,7 @@ class TouchBar { touchBarContainer.appendChild(touchBarBlur); touchBarContainer.appendChild(touchBar); - $("#touch-container").on('touchend', function(event) { + $("#touch-container").on('click', function(event) { self.toggle() }); } diff --git a/js/touchGestures.js b/js/touchGestures.js new file mode 100644 index 0000000..b2f868f --- /dev/null +++ b/js/touchGestures.js @@ -0,0 +1,61 @@ +const Hammer = require('hammerjs'); + +/** + * Initialize touch gesture handling + * @param {object} config TeleFrame configuration object + * @param {object} options object providing callbacks for loadImage and pause + * { + * loadImage: function loadImage(next, fadeTime) {...}, + * pause: function pause() {...} + * } + * @return {undefined} + */ +const initGestures = (config, options) => { + // initialize swipe/pinch gestures + new Hammer.Manager(document.getElementById('touch-container'), { + recognizers: [ + [Hammer.Swipe, { direction: Hammer.DIRECTION_HORIZONTAL }], + [Hammer.Pinch] + ] + }) + // Subscribe to the desired events + .on('swipe pinch', function(event) { + switch(event.type) { + case 'swipe': + if (typeof options.loadImage !== 'function') { + $('.imgcontainer').animate({ left: (event.offsetDirection === Hammer.DIRECTION_LEFT ? '-=' : '+=') + '100%'}, 50, + () => $(event.offsetDirection === Hammer.DIRECTION_LEFT ? '.nextImage' : '.previousImage').trigger('click') + ); + } else { + $('.imgcontainer').animate({ left: (event.offsetDirection === Hammer.DIRECTION_LEFT ? '-=' : '+=') + '110%'}, config.gestures.swipeAnimationDuration); + options.loadImage(event.offsetDirection === Hammer.DIRECTION_LEFT, config.gestures.swipeFadeInImgDuration); + } + break; + case 'pinch': + if (event.scale) { + const MAX_SCALE_FACTOR = config.gestures.maxScaleFactor; + const ZOOM_PERCENT = config.gestures.zoomPercentPerEvent; + const $assetContainer = $container.find('.imgcontainer'); + if (typeof options.pauseCallback === 'function') { + options.pauseCallback(); + } + if ($assetContainer.length > 0) { + let attrib = 'height'; + // get the current zomm (starts with '100%') + let currentZoom = $assetContainer[0].style.width; + if (currentZoom) { + attrib = 'width'; + } else { + currentZoom = $assetContainer[0].style.height; + } + currentZoom = parseInt(currentZoom.replace('%', '')) || 100; + $assetContainer.css(`max-${attrib}`, ''); + $assetContainer[attrib](Math.min((100 * MAX_SCALE_FACTOR), Math.max((100 / MAX_SCALE_FACTOR), currentZoom + (event.scale > 1.0 ? ZOOM_PERCENT : -ZOOM_PERCENT))) + '%'); + } + } + break; + } + }); +} + +module.exports = initGestures; diff --git a/main.js b/main.js index 8cb8956..97bc051 100644 --- a/main.js +++ b/main.js @@ -28,6 +28,8 @@ if(config.switchLedsOff){ } app.commandLine.appendSwitch("autoplay-policy", "no-user-gesture-required"); +// avoid deprecation warning from electron 8 +app.allowRendererProcessReuse = true; // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let win; diff --git a/package-lock.json b/package-lock.json index 5b756b7..6a69e23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,9 +21,9 @@ } }, "@fortawesome/fontawesome-free": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.12.0.tgz", - "integrity": "sha512-vKDJUuE2GAdBERaQWmmtsciAMzjwNrROXA5KTGSZvayAsmuTGjam5z6QNqNPCwDfVljLWuov1nEC3mEQf/n6fQ==" + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.12.1.tgz", + "integrity": "sha512-ZtjIIFplxncqxvogq148C3hBLQE+W3iJ8E4UvJ09zIJUgzwLcROsWwFDErVSXY2Plzao5J9KUYNHKHMEUYDMKw==" }, "@sindresorhus/is": { "version": "0.14.0", @@ -366,9 +366,9 @@ } }, "electron": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/electron/-/electron-7.2.4.tgz", - "integrity": "sha512-Z+R692uTzXgP8AHrabE+kkrMlQJ6pnAYoINenwj9QSqaD2YbO8IuXU9DMCcUY0+VpA91ee09wFZJNUKYPMnCKg==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-8.1.1.tgz", + "integrity": "sha512-t+5zzFo7VOgckJc9YpImHJkpqeWxwpmEjywWbAa4IT5MULS7h1XU52H9gMswK/y8xc5lBNwxLhJSty/15+gi1A==", "requires": { "@electron/get": "^1.0.1", "@types/node": "^12.0.12", @@ -588,6 +588,11 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, + "hammerjs": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", + "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -1165,14 +1170,14 @@ } }, "sweetalert2": { - "version": "9.5.4", - "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-9.5.4.tgz", - "integrity": "sha512-9FSmW9mCbRTHyx6Nbtgeb5348pJYNGaBafn3reKe/Zx/gOBgxsRVHj3GQ4VusU/tuqDobKAIHUdUvNdsU3MXPQ==" + "version": "9.10.1", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-9.10.1.tgz", + "integrity": "sha512-8wQIqk1bRub5SwE4mQIgzHdgGoh0NVwmC5peSmhDtKwZpwPO0Be8ucPtCTuO/VROPwvrlkyWFKwSPaPJejft7Q==" }, "telegraf": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.35.0.tgz", - "integrity": "sha512-C60rps0vEnKcg8ZwS3czwFRVUsq10tn+babK+ujdQeflX267yqB8sw4vVV7c7qCApccqI7sbCrBOPRVb2+4MoQ==", + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.36.0.tgz", + "integrity": "sha512-9o6AJKRiTm5vMWYI6WpTfBHzu4FMpWBNKxvnMxRds/cbMY9RnsVVjdi8i4bFFlfd+xbi73EbrnI3dybayryICA==", "requires": { "@types/node": "^13.1.0", "debug": "^4.0.1", @@ -1184,17 +1189,9 @@ }, "dependencies": { "@types/node": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.1.2.tgz", - "integrity": "sha512-B8emQA1qeKerqd1dmIsQYnXi+mmAzTB7flExjmy5X1aVAKFNNNDubkavwR13kR6JnpeLp3aLoJhwn9trWPAyFQ==" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.0.tgz", + "integrity": "sha512-0ARSQootUG1RljH2HncpsY2TJBfGQIKOOi7kxzUY6z54ePu/ZD+wJA8zI2Q6v8rol2qpG/rvqsReco8zNMPvhQ==" } } }, diff --git a/package.json b/package.json index 3528455..53aa71b 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,11 @@ }, "homepage": "https://github.com/LukeSkywalker92/teleframe#readme", "dependencies": { - "@fortawesome/fontawesome-free": "^5.12.0", + "@fortawesome/fontawesome-free": "^5.12.1", "chroma-js": "^2.1.0", "dotenv": "^8.2.0", - "electron": "^7.2.4", + "electron": "^8.1.0", + "hammerjs": "^2.0.8", "image-downloader": "^3.5.0", "jquery": "^3.5.0", "moment": "^2.24.0", @@ -30,8 +31,8 @@ "node-schedule": "^1.3.2", "randomcolor": "^0.5.4", "sweetalert": "^2.1.2", - "sweetalert2": "^9.5.4", - "telegraf": "^3.35.0", + "sweetalert2": "^9.10.1", + "telegraf": "^3.36.0", "velocity-animate": "^1.5.2", "winston": "^3.2.1" }