From 238d5a9b4df868579ab7c7edc4782d92bfd1e8d4 Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Sun, 9 Aug 2020 15:33:54 +0800 Subject: [PATCH 01/13] Update injected.js Incorporate https://github.com/MLaritz/Vanilla-Notify/blob/master/dist/vanilla-notify.js. --- Vimari Extension/js/injected.js | 234 ++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) diff --git a/Vimari Extension/js/injected.js b/Vimari Extension/js/injected.js index 406a3d6..614c580 100644 --- a/Vimari Extension/js/injected.js +++ b/Vimari Extension/js/injected.js @@ -28,6 +28,240 @@ var topWindow = (window.top === window), hudDuration = 5000, extensionCommunicator = SafariExtensionCommunicator(messageHandler); +// vNotify: https://github.com/MLaritz/Vanilla-Notify +var vNotify = (function() { + + var positionOption = { + topLeft: 'topLeft', + topRight: 'topRight', + bottomLeft: 'bottomLeft', + bottomRight: 'bottomRight', + center: 'center' + }; + + var options = { + fadeInDuration: 1000, + fadeOutDuration: 1000, + fadeInterval: 50, + visibleDuration: 5000, + postHoverVisibleDuration: 500, + position: positionOption.bottomRight, + sticky: false, + showClose: true + }; + + var info = function(params) { + params.notifyClass = 'vnotify-info'; + return addNotify(params); + }; + + var success = function(params) { + params.notifyClass = 'vnotify-success'; + return addNotify(params); + }; + + var error = function(params) { + params.notifyClass = 'vnotify-error'; + return addNotify(params); + }; + + var warning = function(params) { + params.notifyClass = 'vnotify-warning'; + return addNotify(params); + }; + + var notify = function(params) { + params.notifyClass = 'vnotify-notify'; + return addNotify(params); + }; + + var custom = function(params) { + return addNotify(params); + }; + + var addNotify = function(params) { + if (!params.title && !params.text) { + return null; + } + + var frag = document.createDocumentFragment(); + + var item = document.createElement('div'); + item.classList.add('vnotify-item'); + item.classList.add(params.notifyClass); + item.style.opacity = 0; + + item.options = getOptions(params); + + if (params.title) { + item.appendChild(addTitle(params.title)); + } + if (params.text) { + item.appendChild(addText(params.text)); + } + if (item.options.showClose) { + item.appendChild(addClose(item)); + } + + item.visibleDuration = item.options.visibleDuration; //option + + var hideNotify = function() { + item.fadeInterval = fade('out', item.options.fadeOutDuration, item); + }; + + var resetInterval = function() { + clearTimeout(item.interval); + clearTimeout(item.fadeInterval); + item.style.opacity = null; + item.visibleDuration = item.options.postHoverVisibleDuration; + }; + + var hideTimeout = function () { + item.interval = setTimeout(hideNotify, item.visibleDuration); + }; + + frag.appendChild(item); + var container = getNotifyContainer(item.options.position); + container.appendChild(frag); + + item.addEventListener("mouseover", resetInterval); + + fade('in', item.options.fadeInDuration, item); + + if (!item.options.sticky){ + item.addEventListener("mouseout", hideTimeout); + hideTimeout(); + } + + return item; + }; + + var addText = function(text) { + var item = document.createElement('div'); + item.classList.add('vnotify-text'); + item.innerHTML = text; + return item; + }; + + var addTitle = function(title) { + var item = document.createElement('div'); + item.classList.add('vnotify-title'); + item.innerHTML = title; + return item; + }; + + var addClose = function(parent) { + var item = document.createElement('span'); + item.classList.add('vn-close'); + item.addEventListener('click', function(){remove(parent);}); + return item; + }; + + var getNotifyContainer = function(position) { + var positionClass = getPositionClass(position); + var container = document.querySelector('.' + positionClass); + return container ? container : createNotifyContainer(positionClass); + }; + + var createNotifyContainer = function(positionClass) { + var frag = document.createDocumentFragment(); + container = document.createElement('div'); + container.classList.add('vnotify-container'); + container.classList.add(positionClass); + container.setAttribute('role', 'alert'); + + frag.appendChild(container); + document.body.appendChild(frag); + + return container; + }; + + var getPositionClass = function(option) { + switch (option) { + case positionOption.topLeft: + return 'vn-top-left'; + case positionOption.bottomRight: + return 'vn-bottom-right'; + case positionOption.bottomLeft: + return 'vn-bottom-left'; + case positionOption.center: + return 'vn-center'; + default: + return 'vn-top-right'; + } + }; + + var getOptions = function(opts) { + return { + fadeInDuration: opts.fadeInDuration || options.fadeInDuration, + fadeOutDuration: opts.fadeOutDuration || options.fadeOutDuration, + fadeInterval: opts.fadeInterval || options.fadeInterval, + visibleDuration: opts.visibleDuration || options.visibleDuration, + postHoverVisibleDuration: opts.postHoverVisibleDuration || options.postHoverVisibleDuration, + position: opts.position || options.position, + sticky: opts.sticky != null ? opts.sticky : options.sticky, + showClose: opts.showClose != null ? opts.showClose : options.showClose + }; + }; + + var remove = function(item) { + item.style.display = 'none'; + item.outerHTML = ''; + item = null; + }; + + //New fade - based on http://toddmotto.com/raw-javascript-jquery-style-fadein-fadeout-functions-hugo-giraudel/ + var fade = function(type, ms, el) { + var isIn = type === 'in', + opacity = isIn ? 0 : el.style.opacity || 1, + goal = isIn ? 0.8 : 0, + gap = options.fadeInterval / ms; + + if(isIn) { + el.style.display = 'block'; + el.style.opacity = opacity; + } + + function func() { + opacity = isIn ? opacity + gap : opacity - gap; + el.style.opacity = opacity; + + if(opacity <= 0) { + remove(el); + checkRemoveContainer(); + } + if((!isIn && opacity <= goal) || (isIn && opacity >= goal)) { + window.clearInterval(fading); + } + } + + var fading = window.setInterval(func, options.fadeInterval); + return fading; + }; + + var checkRemoveContainer = function() { + var item = document.querySelector('.vnotify-item'); + if (!item) { + var container = document.querySelectorAll('.vnotify-container'); + for (var i=0; i< container.length; i++) { + container[i].outerHTML = ''; + container[i] = null; + } + } + }; + + return { + info: info, + success: success, + error: error, + warning: warning, + notify: notify, + custom: custom, + options: options, + positionOption: positionOption + }; +})(); + var actionMap = { 'hintToggle' : function() { HUD.showForDuration('Open link in current tab', hudDuration); From caebc9f3194bb71c362f23ae44e65a9acbdd5506 Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Sun, 9 Aug 2020 15:35:03 +0800 Subject: [PATCH 02/13] Update injected.css Incorporate https://github.com/MLaritz/Vanilla-Notify/blob/master/dist/vanilla-notify.css --- Vimari Extension/css/injected.css | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/Vimari Extension/css/injected.css b/Vimari Extension/css/injected.css index 3d20791..89e5622 100644 --- a/Vimari Extension/css/injected.css +++ b/Vimari Extension/css/injected.css @@ -112,3 +112,85 @@ div.internalVimiumHintMarker > .matchingCharacter { -webkit-user-select:none; } +/* vNotify: https://github.com/MLaritz/Vanilla-Notify */ +.vnotify-container { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important; + font-size: 12px !important; + position: fixed !important; } + .vnotify-container.vn-top-right { + right: 10px !important; + top: 10px !important; } + .vnotify-container.vn-top-left { + top: 10px !important; + left: 10px !important; } + .vnotify-container.vn-bottom-right { + bottom: 10px !important; + right: 10px !important; } + .vnotify-container.vn-bottom-left { + bottom: 10px !important; + left: 10px !important; } + .vnotify-container.vn-center { + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%) !important; } + .vnotify-container .vn-close { + position: absolute !important; + top: 5px !important; + right: 10px !important; + width: 15px !important; + height: 15px !important; + padding: 2px !important; + cursor: pointer !important; } + .vnotify-container .vn-close: before, .vnotify-container .vn-close: after { + content: '' !important; + position: absolute !important; + width: 100% !important; + top: 50% !important; + height: 2px !important; + background: #fff !important; } + .vnotify-container .vn-close: before { + -webkit-transform: rotate(45deg) !important; + -moz-transform: rotate(45deg) !important; + transform: rotate(45deg) !important; } + .vnotify-container .vn-close: after { + -webkit-transform: rotate(-45deg) !important; + -moz-transform: rotate(-45deg) !important; + transform: rotate(-45deg) !important; } + +.vnotify-item { + width: 8em !important; + padding: 7.5px !important; + position: relative !important; + -webkit-border-radius: 5px !important; + -moz-border-radius: 5px !important; + -ms-border-radius: 5px !important; + border-radius: 5px !important; + margin-bottom: 7.5px !important; + opacity: 0.5 !important; + -ms-filter: "progid: DXImageTransform.Microsoft.Alpha(Opacity=75)" !important; + filter: alpha(opacity=50) !important; } + .vnotify-item: hover { + opacity: 1 !important; } + +.vnotify-title { + font-weight: bold !important; } + +.vnotify-info { + background: #3498db !important; + color: #fff !important; } + +.vnotify-success { + background: #2ecc71 !important; + color: #fff !important; } + +.vnotify-error { + background: #e74c3c !important; + color: #fff !important; } + +.vnotify-warning { + background: #f39c12 !important; + color: #fff !important; } + +.vnotify-notify { + background: #333 !important; + color: #fff !important; } From 9a86ffb4c1a14656a7536af8db189605a536aa01 Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Sun, 9 Aug 2020 15:55:01 +0800 Subject: [PATCH 03/13] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 4090806..56607bc 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Vimari - Keyboard Shortcuts extension for Safari -[![Actions Status](https://github.com/danielcompton/vimari/workflows/Node%20CI/badge.svg)](https://github.com/danielcompton/vimari/actions) - [![Download on the Mac App Store](assets/Download_on_the_Mac_App_Store_Badge_US.svg)](https://apps.apple.com/us/app/vimari/id1480933944?ls=1&mt=12) Vimari is a Safari extension that provides keyboard based navigation. From 35f27fa2d625e7b10430985ae2957b63fc432c16 Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Wed, 12 Aug 2020 08:58:19 +0800 Subject: [PATCH 04/13] Streamline .vnotify --- Vimari Extension/css/injected.css | 62 +++++++++++++++++-------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/Vimari Extension/css/injected.css b/Vimari Extension/css/injected.css index 89e5622..ed00537 100644 --- a/Vimari Extension/css/injected.css +++ b/Vimari Extension/css/injected.css @@ -1,3 +1,4 @@ +/* vimium */ .vimiumReset { background: none; border: none; @@ -7,7 +8,7 @@ cursor: auto; display: inline; float: none; - font-family : "Helvetica Neue", "Helvetica", "Arial", sans-serif; + font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif; font-size: inherit; font-style: normal; font-variant: normal; @@ -81,7 +82,7 @@ div.internalVimiumHintMarker > .matchingCharacter { border: 1px solid #b3b3b3; border-bottom: none; border-radius: 4px 4px 0 0; - font-family: Lucida Grande, Arial, Sans; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important; /* One less than vimium's hint markers, so link hints can be shown e.g. for the panel's close button. */ z-index: 99999998; text-shadow: 0px 1px 2px #FFF; @@ -89,43 +90,46 @@ div.internalVimiumHintMarker > .matchingCharacter { opacity: 0; } -.vimiumHUD a, .vimiumHUD a:hover { +.vimiumHUD a, .vimiumHUD a: hover { background: transparent; color: blue; text-decoration: underline; } .vimiumHUD a.close-button { - float:right; - font-family:courier new; - font-weight:bold; - color:#9C9A9A; - text-decoration:none; - padding-left:10px; - margin-top:-1px; - font-size:14px; + float: right; + font-family: courier new; + font-weight: bold; + color: #9C9A9A; + text-decoration: none; + padding-left: 10px; + margin-top: -1px; + font-size: 14px; } -.vimiumHUD a.close-button:hover { - color:#333333; - cursor:default; - -webkit-user-select:none; +.vimiumHUD a.close-button: hover { + color: #333333; + cursor: default; + -webkit-user-select: none; } -/* vNotify: https://github.com/MLaritz/Vanilla-Notify */ +/* vNotify */ .vnotify-container { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important; font-size: 12px !important; position: fixed !important; } +/* .vnotify-container.vn-top-right { right: 10px !important; top: 10px !important; } .vnotify-container.vn-top-left { top: 10px !important; left: 10px !important; } +*/ .vnotify-container.vn-bottom-right { bottom: 10px !important; right: 10px !important; } +/* .vnotify-container.vn-bottom-left { bottom: 10px !important; left: 10px !important; } @@ -133,6 +137,7 @@ div.internalVimiumHintMarker > .matchingCharacter { top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; } + */ .vnotify-container .vn-close { position: absolute !important; top: 5px !important; @@ -150,11 +155,11 @@ div.internalVimiumHintMarker > .matchingCharacter { background: #fff !important; } .vnotify-container .vn-close: before { -webkit-transform: rotate(45deg) !important; - -moz-transform: rotate(45deg) !important; +/* -moz-transform: rotate(45deg) !important;*/ transform: rotate(45deg) !important; } .vnotify-container .vn-close: after { -webkit-transform: rotate(-45deg) !important; - -moz-transform: rotate(-45deg) !important; +/* -moz-transform: rotate(-45deg) !important;*/ transform: rotate(-45deg) !important; } .vnotify-item { @@ -162,12 +167,12 @@ div.internalVimiumHintMarker > .matchingCharacter { padding: 7.5px !important; position: relative !important; -webkit-border-radius: 5px !important; - -moz-border-radius: 5px !important; - -ms-border-radius: 5px !important; +/* -moz-border-radius: 5px !important;*/ +/* -ms-border-radius: 5px !important;*/ border-radius: 5px !important; margin-bottom: 7.5px !important; opacity: 0.5 !important; - -ms-filter: "progid: DXImageTransform.Microsoft.Alpha(Opacity=75)" !important; +/* -ms-filter: "progid: DXImageTransform.Microsoft.Alpha(Opacity=75)" !important;*/ filter: alpha(opacity=50) !important; } .vnotify-item: hover { opacity: 1 !important; } @@ -175,10 +180,11 @@ div.internalVimiumHintMarker > .matchingCharacter { .vnotify-title { font-weight: bold !important; } -.vnotify-info { - background: #3498db !important; - color: #fff !important; } +.vnotify-notify { +background: #333 !important; +color: #fff !important; } +/* .vnotify-success { background: #2ecc71 !important; color: #fff !important; } @@ -191,6 +197,8 @@ div.internalVimiumHintMarker > .matchingCharacter { background: #f39c12 !important; color: #fff !important; } -.vnotify-notify { - background: #333 !important; - color: #fff !important; } + .vnotify-info { + background: #3498db !important; + color: #fff !important; } + +*/ From ff41cc4c62d9c8770520ab4602a19a6928b41133 Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Wed, 12 Aug 2020 09:00:38 +0800 Subject: [PATCH 05/13] Move vNotify to ./Vimari Extension/js/lib/ --- Vimari Extension/js/injected.js | 241 +------------------------------- 1 file changed, 7 insertions(+), 234 deletions(-) diff --git a/Vimari Extension/js/injected.js b/Vimari Extension/js/injected.js index 614c580..4ea3385 100644 --- a/Vimari Extension/js/injected.js +++ b/Vimari Extension/js/injected.js @@ -28,240 +28,6 @@ var topWindow = (window.top === window), hudDuration = 5000, extensionCommunicator = SafariExtensionCommunicator(messageHandler); -// vNotify: https://github.com/MLaritz/Vanilla-Notify -var vNotify = (function() { - - var positionOption = { - topLeft: 'topLeft', - topRight: 'topRight', - bottomLeft: 'bottomLeft', - bottomRight: 'bottomRight', - center: 'center' - }; - - var options = { - fadeInDuration: 1000, - fadeOutDuration: 1000, - fadeInterval: 50, - visibleDuration: 5000, - postHoverVisibleDuration: 500, - position: positionOption.bottomRight, - sticky: false, - showClose: true - }; - - var info = function(params) { - params.notifyClass = 'vnotify-info'; - return addNotify(params); - }; - - var success = function(params) { - params.notifyClass = 'vnotify-success'; - return addNotify(params); - }; - - var error = function(params) { - params.notifyClass = 'vnotify-error'; - return addNotify(params); - }; - - var warning = function(params) { - params.notifyClass = 'vnotify-warning'; - return addNotify(params); - }; - - var notify = function(params) { - params.notifyClass = 'vnotify-notify'; - return addNotify(params); - }; - - var custom = function(params) { - return addNotify(params); - }; - - var addNotify = function(params) { - if (!params.title && !params.text) { - return null; - } - - var frag = document.createDocumentFragment(); - - var item = document.createElement('div'); - item.classList.add('vnotify-item'); - item.classList.add(params.notifyClass); - item.style.opacity = 0; - - item.options = getOptions(params); - - if (params.title) { - item.appendChild(addTitle(params.title)); - } - if (params.text) { - item.appendChild(addText(params.text)); - } - if (item.options.showClose) { - item.appendChild(addClose(item)); - } - - item.visibleDuration = item.options.visibleDuration; //option - - var hideNotify = function() { - item.fadeInterval = fade('out', item.options.fadeOutDuration, item); - }; - - var resetInterval = function() { - clearTimeout(item.interval); - clearTimeout(item.fadeInterval); - item.style.opacity = null; - item.visibleDuration = item.options.postHoverVisibleDuration; - }; - - var hideTimeout = function () { - item.interval = setTimeout(hideNotify, item.visibleDuration); - }; - - frag.appendChild(item); - var container = getNotifyContainer(item.options.position); - container.appendChild(frag); - - item.addEventListener("mouseover", resetInterval); - - fade('in', item.options.fadeInDuration, item); - - if (!item.options.sticky){ - item.addEventListener("mouseout", hideTimeout); - hideTimeout(); - } - - return item; - }; - - var addText = function(text) { - var item = document.createElement('div'); - item.classList.add('vnotify-text'); - item.innerHTML = text; - return item; - }; - - var addTitle = function(title) { - var item = document.createElement('div'); - item.classList.add('vnotify-title'); - item.innerHTML = title; - return item; - }; - - var addClose = function(parent) { - var item = document.createElement('span'); - item.classList.add('vn-close'); - item.addEventListener('click', function(){remove(parent);}); - return item; - }; - - var getNotifyContainer = function(position) { - var positionClass = getPositionClass(position); - var container = document.querySelector('.' + positionClass); - return container ? container : createNotifyContainer(positionClass); - }; - - var createNotifyContainer = function(positionClass) { - var frag = document.createDocumentFragment(); - container = document.createElement('div'); - container.classList.add('vnotify-container'); - container.classList.add(positionClass); - container.setAttribute('role', 'alert'); - - frag.appendChild(container); - document.body.appendChild(frag); - - return container; - }; - - var getPositionClass = function(option) { - switch (option) { - case positionOption.topLeft: - return 'vn-top-left'; - case positionOption.bottomRight: - return 'vn-bottom-right'; - case positionOption.bottomLeft: - return 'vn-bottom-left'; - case positionOption.center: - return 'vn-center'; - default: - return 'vn-top-right'; - } - }; - - var getOptions = function(opts) { - return { - fadeInDuration: opts.fadeInDuration || options.fadeInDuration, - fadeOutDuration: opts.fadeOutDuration || options.fadeOutDuration, - fadeInterval: opts.fadeInterval || options.fadeInterval, - visibleDuration: opts.visibleDuration || options.visibleDuration, - postHoverVisibleDuration: opts.postHoverVisibleDuration || options.postHoverVisibleDuration, - position: opts.position || options.position, - sticky: opts.sticky != null ? opts.sticky : options.sticky, - showClose: opts.showClose != null ? opts.showClose : options.showClose - }; - }; - - var remove = function(item) { - item.style.display = 'none'; - item.outerHTML = ''; - item = null; - }; - - //New fade - based on http://toddmotto.com/raw-javascript-jquery-style-fadein-fadeout-functions-hugo-giraudel/ - var fade = function(type, ms, el) { - var isIn = type === 'in', - opacity = isIn ? 0 : el.style.opacity || 1, - goal = isIn ? 0.8 : 0, - gap = options.fadeInterval / ms; - - if(isIn) { - el.style.display = 'block'; - el.style.opacity = opacity; - } - - function func() { - opacity = isIn ? opacity + gap : opacity - gap; - el.style.opacity = opacity; - - if(opacity <= 0) { - remove(el); - checkRemoveContainer(); - } - if((!isIn && opacity <= goal) || (isIn && opacity >= goal)) { - window.clearInterval(fading); - } - } - - var fading = window.setInterval(func, options.fadeInterval); - return fading; - }; - - var checkRemoveContainer = function() { - var item = document.querySelector('.vnotify-item'); - if (!item) { - var container = document.querySelectorAll('.vnotify-container'); - for (var i=0; i< container.length; i++) { - container[i].outerHTML = ''; - container[i] = null; - } - } - }; - - return { - info: info, - success: success, - error: error, - warning: warning, - notify: notify, - custom: custom, - options: options, - positionOption: positionOption - }; -})(); - var actionMap = { 'hintToggle' : function() { HUD.showForDuration('Open link in current tab', hudDuration); @@ -368,6 +134,12 @@ function enterNormalMode() { // Re-enable if in insert mode insertMode = false; Mousetrap.bind('i', enterInsertMode); + var container = document.querySelectorAll('.vnotify-container'); + for (var i=0; i< container.length; i++) { + container[i].outerHTML = ''; + container[i] = null; + } + vNotify.notify({text: 'Normal Mode', title:'Vimari', visibleDuration: 500, showClose: false}); } // Calling it 'insert mode', but it's really just a user-triggered @@ -375,6 +147,7 @@ function enterNormalMode() { function enterInsertMode() { insertMode = true; Mousetrap.unbind('i'); + vNotify.notify({text: 'Insert Mode', title:'Vimari', visibleDuration: 500, showClose: false, sticky: true}); } function executeAction(actionName) { From cda0350019590abb2ba421f2a6b3e93251dbdf0d Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Wed, 12 Aug 2020 09:01:25 +0800 Subject: [PATCH 06/13] Add vnotify.js to ./Vimari Extension/js/lib/ --- Vimari Extension/js/lib/vnotify.js | 239 +++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 Vimari Extension/js/lib/vnotify.js diff --git a/Vimari Extension/js/lib/vnotify.js b/Vimari Extension/js/lib/vnotify.js new file mode 100644 index 0000000..1dbb34b --- /dev/null +++ b/Vimari Extension/js/lib/vnotify.js @@ -0,0 +1,239 @@ +var vNotify = (function() { + + var positionOption = { + topLeft: 'topLeft', + topRight: 'topRight', + bottomLeft: 'bottomLeft', + bottomRight: 'bottomRight', + center: 'center' + }; + + var options = { + fadeInDuration: 1000, + fadeOutDuration: 1000, + fadeInterval: 50, + visibleDuration: 5000, + postHoverVisibleDuration: 500, + position: positionOption.bottomRight, + sticky: false, + showClose: true + }; + +// var info = function(params) { +// params.notifyClass = 'vnotify-info'; +// return addNotify(params); +// }; +// var success = function(params) { +// params.notifyClass = 'vnotify-success'; +// return addNotify(params); +// }; +// +// var error = function(params) { +// params.notifyClass = 'vnotify-error'; +// return addNotify(params); +// }; +// +// var warning = function(params) { +// params.notifyClass = 'vnotify-warning'; +// return addNotify(params); +// }; + + var notify = function(params) { + params.notifyClass = 'vnotify-notify'; + return addNotify(params); + }; + +// var custom = function(params) { +// return addNotify(params); +// }; + + var addNotify = function(params) { + if (!params.title && !params.text) { + return null; + } + + var frag = document.createDocumentFragment(); + + var item = document.createElement('div'); + item.classList.add('vnotify-item'); + item.classList.add(params.notifyClass); + item.style.opacity = 0; + + item.options = getOptions(params); + + if (params.title) { + item.appendChild(addTitle(params.title)); + } + if (params.text) { + item.appendChild(addText(params.text)); + } + if (item.options.showClose) { + item.appendChild(addClose(item)); + } + + item.visibleDuration = item.options.visibleDuration; //option + + var hideNotify = function() { + item.fadeInterval = fade('out', item.options.fadeOutDuration, item); + }; + + var resetInterval = function() { + clearTimeout(item.interval); + clearTimeout(item.fadeInterval); + item.style.opacity = null; + item.visibleDuration = item.options.postHoverVisibleDuration; + }; + + var hideTimeout = function () { + item.interval = setTimeout(hideNotify, item.visibleDuration); + }; + + frag.appendChild(item); + var container = getNotifyContainer(item.options.position); + container.appendChild(frag); + + item.addEventListener("mouseover", resetInterval); + + fade('in', item.options.fadeInDuration, item); + + if (!item.options.sticky){ + item.addEventListener("mouseout", hideTimeout); + hideTimeout(); + } + + return item; + }; + + var addText = function(text) { + var item = document.createElement('div'); + item.classList.add('vnotify-text'); + item.innerHTML = text; + return item; + }; + + var addTitle = function(title) { + var item = document.createElement('div'); + item.classList.add('vnotify-title'); + item.innerHTML = title; + return item; + }; + + var addClose = function(parent) { + var item = document.createElement('span'); + item.classList.add('vn-close'); + item.addEventListener('click', function(){remove(parent);}); + return item; + }; + + var getNotifyContainer = function(position) { + var positionClass = getPositionClass(position); + var container = document.querySelector('.' + positionClass); + return container ? container : createNotifyContainer(positionClass); + }; + + var createNotifyContainer = function(positionClass) { + var frag = document.createDocumentFragment(); + container = document.createElement('div'); + container.classList.add('vnotify-container'); + container.classList.add(positionClass); + container.setAttribute('role', 'alert'); + + frag.appendChild(container); + document.body.appendChild(frag); + + return container; + }; + + var getPositionClass = function(option) { + switch (option) { + case positionOption.topLeft: + return 'vn-top-left'; + case positionOption.bottomRight: + return 'vn-bottom-right'; + case positionOption.bottomLeft: + return 'vn-bottom-left'; + case positionOption.center: + return 'vn-center'; + default: + return 'vn-top-right'; + } + }; + + var getOptions = function(opts) { + return { + fadeInDuration: opts.fadeInDuration || options.fadeInDuration, + fadeOutDuration: opts.fadeOutDuration || options.fadeOutDuration, + fadeInterval: opts.fadeInterval || options.fadeInterval, + visibleDuration: opts.visibleDuration || options.visibleDuration, + postHoverVisibleDuration: opts.postHoverVisibleDuration || options.postHoverVisibleDuration, + position: opts.position || options.position, + sticky: opts.sticky != null ? opts.sticky : options.sticky, + showClose: opts.showClose != null ? opts.showClose : options.showClose + }; + }; + + var remove = function(item) { + item.style.display = 'none'; + item.outerHTML = ''; + item = null; + }; + + //New fade - based on http://toddmotto.com/raw-javascript-jquery-style-fadein-fadeout-functions-hugo-giraudel/ + var fade = function(type, ms, el) { + var isIn = type === 'in', + opacity = isIn ? 0 : el.style.opacity || 1, + goal = isIn ? 0.8 : 0, + gap = options.fadeInterval / ms; + + if(isIn) { + el.style.display = 'block'; + el.style.opacity = opacity; + } + + function func() { + opacity = isIn ? opacity + gap : opacity - gap; + el.style.opacity = opacity; + + if(opacity <= 0) { + remove(el); + checkRemoveContainer(); + } + if((!isIn && opacity <= goal) || (isIn && opacity >= goal)) { + window.clearInterval(fading); + } + } + + var fading = window.setInterval(func, options.fadeInterval); + return fading; + }; + + var checkRemoveContainer = function() { + var item = document.querySelector('.vnotify-item'); + if (!item) { + var container = document.querySelectorAll('.vnotify-container'); + for (var i=0; i< container.length; i++) { + container[i].outerHTML = ''; + container[i] = null; + } + } + }; + + return { +// info: info, +// success: success, +// error: error, +// warning: warning, +// custom: custom, + notify: notify, + options: options, + positionOption: positionOption + }; +})(); + +// expose vNotify to the global object +window.vNotify = vNotify; + +// expose as a common js module +if (typeof module !== 'undefined' && module.exports) { + module.exports = vNotify; +}; From fd372d44cce2003775942f597f8575777a639289 Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Wed, 12 Aug 2020 09:03:18 +0800 Subject: [PATCH 07/13] Add vnotify.js --- Vimari Extension/Info.plist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Vimari Extension/Info.plist b/Vimari Extension/Info.plist index 8a2de28..926cf6e 100644 --- a/Vimari Extension/Info.plist +++ b/Vimari Extension/Info.plist @@ -30,6 +30,10 @@ $(PRODUCT_MODULE_NAME).SafariExtensionHandler SFSafariContentScript + + Script + vnotify.js + Script SafariExtensionCommunicator.js From 849a6e8c3e453dd030dc39646958939841aa39ef Mon Sep 17 00:00:00 2001 From: agboh Date: Wed, 12 Aug 2020 11:07:13 +0800 Subject: [PATCH 08/13] Optimize vnotify, add insertModeUrls - Move vnotify scripts into ./Vimari Extension/js/lib/. - Add option to enter Insert Mode automatically for insertModeUrls in config settings. Useful for cases such as youtube.com/watch --- .gitignore | 1 + Vimari Extension/js/injected.js | 20 ++++++++++++-------- Vimari Extension/js/lib/mousetrap.js | 4 +++- Vimari Extension/js/lib/vimium-scripts.js | 2 +- Vimari Extension/js/lib/vnotify.js | 4 ++++ Vimari Extension/json/defaultSettings.json | 1 + Vimari.xcodeproj/project.pbxproj | 12 ++++++++---- 7 files changed, 30 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 855c269..f3a30ae 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ timeline.xctimeline playground.xcworkspace .vscode/ +.DS_Store diff --git a/Vimari Extension/js/injected.js b/Vimari Extension/js/injected.js index 4ea3385..cc83ecd 100644 --- a/Vimari Extension/js/injected.js +++ b/Vimari Extension/js/injected.js @@ -107,7 +107,8 @@ Mousetrap.prototype.stopCallback = function(e, element, combo) { function bindKeyCodesToActions(settings) { var excludedUrl = false if (typeof settings != "undefined") { - excludedUrl = isExcludedUrl(settings.excludedUrls, document.URL) + excludedUrl = isDesignatedUrl(settings.excludedUrls, document.URL); + insertModeUrl = isDesignatedUrl(settings.insertModeUrls, document.URL); } // Only add if topWindow... not iframe Mousetrap.reset(); @@ -122,6 +123,9 @@ function bindKeyCodesToActions(settings) { } } } + if (insertModeUrl) { + enterInsertMode(); + } } function enterNormalMode() { @@ -256,15 +260,15 @@ function activateExtension(settings) { bindKeyCodesToActions(settings); } -function isExcludedUrl(storedExcludedUrls, currentUrl) { - if (!storedExcludedUrls.length) { +function isDesignatedUrl(storedDesignatedUrls, currentUrl) { + if (!storedDesignatedUrls.length) { return false; } - var excludedUrls, regexp, url, formattedUrl, _i, _len; - excludedUrls = storedExcludedUrls.split(","); - for (_i = 0, _len = excludedUrls.length; _i < _len; _i++) { - url = excludedUrls[_i]; + var designatedUrls, regexp, url, formattedUrl, _i, _len; + designatedUrls = storedDesignatedUrls.split(","); + for (_i = 0, _len = designatedUrls.length; _i < _len; _i++) { + url = designatedUrls[_i]; formattedUrl = stripProtocolAndWww(url); formattedUrl = formattedUrl.toLowerCase().trim(); regexp = new RegExp('((.*)?(' + formattedUrl + ')+(.*))'); @@ -303,5 +307,5 @@ if(!inIframe()){ } // Export to make it testable -window.isExcludedUrl = isExcludedUrl; +window.isDesignatedUrl = isDesignatedUrl; window.stripProtocolAndWww = stripProtocolAndWww; diff --git a/Vimari Extension/js/lib/mousetrap.js b/Vimari Extension/js/lib/mousetrap.js index 941372a..35c741d 100644 --- a/Vimari Extension/js/lib/mousetrap.js +++ b/Vimari Extension/js/lib/mousetrap.js @@ -1,7 +1,8 @@ // Custom behaviour for Vimari implemented at line 185. Be aware of this // when upgrading mousetrap. -/*global define:false */ +/* global define:false */ + /** * Copyright 2012-2017 Craig Campbell * @@ -23,6 +24,7 @@ * @version 1.6.5 * @url craig.is/killing/mice */ + (function(window, document, undefined) { // Check if mousetrap is used inside browser, if not, return diff --git a/Vimari Extension/js/lib/vimium-scripts.js b/Vimari Extension/js/lib/vimium-scripts.js index 698725d..109ebcb 100644 --- a/Vimari Extension/js/lib/vimium-scripts.js +++ b/Vimari Extension/js/lib/vimium-scripts.js @@ -2,11 +2,11 @@ * Code in this file is taken directly from vimium */ - /* * A heads-up-display (HUD) for showing Vimium page operations. * Note: you cannot interact with the HUD until document.body is available. */ + HUD = { _tweenId: -1, _displayElement: null, diff --git a/Vimari Extension/js/lib/vnotify.js b/Vimari Extension/js/lib/vnotify.js index 1dbb34b..f2d1bf9 100644 --- a/Vimari Extension/js/lib/vnotify.js +++ b/Vimari Extension/js/lib/vnotify.js @@ -1,3 +1,7 @@ +/* +* Code in this file is taken directly from [Vanilla-Notify](https://github.com/MLaritz/Vanilla-Notify) +*/ + var vNotify = (function() { var positionOption = { diff --git a/Vimari Extension/json/defaultSettings.json b/Vimari Extension/json/defaultSettings.json index 06fb864..4832e6c 100644 --- a/Vimari Extension/json/defaultSettings.json +++ b/Vimari Extension/json/defaultSettings.json @@ -1,5 +1,6 @@ { "excludedUrls": "", + "insertModeUrls": "", "linkHintCharacters": "asdfjklqwerzxc", "detectByCursorStyle": false, "scrollSize": 50, diff --git a/Vimari.xcodeproj/project.pbxproj b/Vimari.xcodeproj/project.pbxproj index 56635a7..0c9259d 100644 --- a/Vimari.xcodeproj/project.pbxproj +++ b/Vimari.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 4C9DFE0C24E37A60002B9455 /* vnotify.js in Resources */ = {isa = PBXBuildFile; fileRef = 4C9DFE0B24E37A60002B9455 /* vnotify.js */; }; 65E444F324CC3A1B008EA1DC /* SafariExtensionCommunicator.js in Resources */ = {isa = PBXBuildFile; fileRef = 65E444F224CC3A1B008EA1DC /* SafariExtensionCommunicator.js */; }; B1E3C17023A65ED400A56807 /* ConfigurationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E3C16F23A65ED400A56807 /* ConfigurationModel.swift */; }; B1FD3B9923A588DE00677A52 /* defaultSettings.json in Resources */ = {isa = PBXBuildFile; fileRef = B1FD3B9823A588DE00677A52 /* defaultSettings.json */; }; @@ -57,6 +58,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 4C9DFE0B24E37A60002B9455 /* vnotify.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = vnotify.js; sourceTree = ""; }; 65E444F224CC3A1B008EA1DC /* SafariExtensionCommunicator.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = SafariExtensionCommunicator.js; sourceTree = ""; }; B1E3C16F23A65ED400A56807 /* ConfigurationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationModel.swift; sourceTree = ""; }; B1FD3B9823A588DE00677A52 /* defaultSettings.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = defaultSettings.json; sourceTree = ""; }; @@ -190,6 +192,7 @@ children = ( E380F27E233183EE00640547 /* mousetrap.js */, E380F27F233183EE00640547 /* vimium-scripts.js */, + 4C9DFE0B24E37A60002B9455 /* vnotify.js */, ); path = lib; sourceTree = ""; @@ -295,6 +298,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4C9DFE0C24E37A60002B9455 /* vnotify.js in Resources */, E380F26C2331806500640547 /* ToolbarItemIcon.pdf in Resources */, B1FD3B9923A588DE00677A52 /* defaultSettings.json in Resources */, 65E444F324CC3A1B008EA1DC /* SafariExtensionCommunicator.js in Resources */, @@ -481,7 +485,7 @@ CODE_SIGN_ENTITLEMENTS = "Vimari Extension/Vimari_Extension.entitlements"; CODE_SIGN_IDENTITY = "Mac Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y48UDGWSSQ; + DEVELOPMENT_TEAM = 98QL363Q8S; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "Vimari Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( @@ -504,7 +508,7 @@ CODE_SIGN_ENTITLEMENTS = "Vimari Extension/Vimari_Extension.entitlements"; CODE_SIGN_IDENTITY = "Mac Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = Y48UDGWSSQ; + DEVELOPMENT_TEAM = 98QL363Q8S; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "Vimari Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( @@ -529,7 +533,7 @@ CODE_SIGN_IDENTITY = "Mac Developer"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = Y48UDGWSSQ; + DEVELOPMENT_TEAM = 98QL363Q8S; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Vimari/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -552,7 +556,7 @@ CODE_SIGN_IDENTITY = "Mac Developer"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = Y48UDGWSSQ; + DEVELOPMENT_TEAM = 98QL363Q8S; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Vimari/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( From 8be1705a9fd330d1784ec68e01dcc0ee04bbfa25 Mon Sep 17 00:00:00 2001 From: agboh Date: Wed, 12 Aug 2020 23:50:45 +0800 Subject: [PATCH 09/13] Separate vnotify.css, revert insertModeUrls --- Vimari Extension/Info.plist | 4 + Vimari Extension/css/injected.css | 90 ------------- Vimari Extension/css/vnotify.css | 89 +++++++++++++ Vimari Extension/js/injected.js | 196 ++++++++++++++--------------- Vimari Extension/js/lib/vnotify.js | 2 +- Vimari.xcodeproj/project.pbxproj | 4 + 6 files changed, 194 insertions(+), 191 deletions(-) create mode 100644 Vimari Extension/css/vnotify.css diff --git a/Vimari Extension/Info.plist b/Vimari Extension/Info.plist index 926cf6e..954f0b8 100644 --- a/Vimari Extension/Info.plist +++ b/Vimari Extension/Info.plist @@ -61,6 +61,10 @@ SFSafariStyleSheet + + Style Sheet + vnotify.css + Style Sheet injected.css diff --git a/Vimari Extension/css/injected.css b/Vimari Extension/css/injected.css index ed00537..001d275 100644 --- a/Vimari Extension/css/injected.css +++ b/Vimari Extension/css/injected.css @@ -112,93 +112,3 @@ div.internalVimiumHintMarker > .matchingCharacter { cursor: default; -webkit-user-select: none; } - -/* vNotify */ -.vnotify-container { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important; - font-size: 12px !important; - position: fixed !important; } -/* - .vnotify-container.vn-top-right { - right: 10px !important; - top: 10px !important; } - .vnotify-container.vn-top-left { - top: 10px !important; - left: 10px !important; } -*/ - .vnotify-container.vn-bottom-right { - bottom: 10px !important; - right: 10px !important; } -/* - .vnotify-container.vn-bottom-left { - bottom: 10px !important; - left: 10px !important; } - .vnotify-container.vn-center { - top: 50% !important; - left: 50% !important; - transform: translate(-50%, -50%) !important; } - */ - .vnotify-container .vn-close { - position: absolute !important; - top: 5px !important; - right: 10px !important; - width: 15px !important; - height: 15px !important; - padding: 2px !important; - cursor: pointer !important; } - .vnotify-container .vn-close: before, .vnotify-container .vn-close: after { - content: '' !important; - position: absolute !important; - width: 100% !important; - top: 50% !important; - height: 2px !important; - background: #fff !important; } - .vnotify-container .vn-close: before { - -webkit-transform: rotate(45deg) !important; -/* -moz-transform: rotate(45deg) !important;*/ - transform: rotate(45deg) !important; } - .vnotify-container .vn-close: after { - -webkit-transform: rotate(-45deg) !important; -/* -moz-transform: rotate(-45deg) !important;*/ - transform: rotate(-45deg) !important; } - -.vnotify-item { - width: 8em !important; - padding: 7.5px !important; - position: relative !important; - -webkit-border-radius: 5px !important; -/* -moz-border-radius: 5px !important;*/ -/* -ms-border-radius: 5px !important;*/ - border-radius: 5px !important; - margin-bottom: 7.5px !important; - opacity: 0.5 !important; -/* -ms-filter: "progid: DXImageTransform.Microsoft.Alpha(Opacity=75)" !important;*/ - filter: alpha(opacity=50) !important; } - .vnotify-item: hover { - opacity: 1 !important; } - -.vnotify-title { - font-weight: bold !important; } - -.vnotify-notify { -background: #333 !important; -color: #fff !important; } - -/* -.vnotify-success { - background: #2ecc71 !important; - color: #fff !important; } - -.vnotify-error { - background: #e74c3c !important; - color: #fff !important; } - -.vnotify-warning { - background: #f39c12 !important; - color: #fff !important; } - - .vnotify-info { - background: #3498db !important; - color: #fff !important; } - -*/ diff --git a/Vimari Extension/css/vnotify.css b/Vimari Extension/css/vnotify.css new file mode 100644 index 0000000..5f5af00 --- /dev/null +++ b/Vimari Extension/css/vnotify.css @@ -0,0 +1,89 @@ +/* vNotify */ +.vnotify-container { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important; + font-size: 12px !important; + position: fixed !important; } +/* + .vnotify-container.vn-top-right { + right: 10px !important; + top: 10px !important; } + .vnotify-container.vn-top-left { + top: 10px !important; + left: 10px !important; } +*/ + .vnotify-container.vn-bottom-right { + bottom: 10px !important; + right: 10px !important; } +/* + .vnotify-container.vn-bottom-left { + bottom: 10px !important; + left: 10px !important; } + .vnotify-container.vn-center { + top: 50% !important; + left: 50% !important; + transform: translate(-50%, -50%) !important; } + */ + .vnotify-container .vn-close { + position: absolute !important; + top: 5px !important; + right: 10px !important; + width: 15px !important; + height: 15px !important; + padding: 2px !important; + cursor: pointer !important; } + .vnotify-container .vn-close: before, .vnotify-container .vn-close: after { + content: '' !important; + position: absolute !important; + width: 100% !important; + top: 50% !important; + height: 2px !important; + background: #fff !important; } + .vnotify-container .vn-close: before { + -webkit-transform: rotate(45deg) !important; +/* -moz-transform: rotate(45deg) !important;*/ + transform: rotate(45deg) !important; } + .vnotify-container .vn-close: after { + -webkit-transform: rotate(-45deg) !important; +/* -moz-transform: rotate(-45deg) !important;*/ + transform: rotate(-45deg) !important; } + +.vnotify-item { + width: 8em !important; + padding: 7.5px !important; + position: relative !important; + -webkit-border-radius: 5px !important; +/* -moz-border-radius: 5px !important;*/ +/* -ms-border-radius: 5px !important;*/ + border-radius: 5px !important; + margin-bottom: 7.5px !important; + opacity: 0.5 !important; +/* -ms-filter: "progid: DXImageTransform.Microsoft.Alpha(Opacity=75)" !important;*/ + filter: alpha(opacity=50) !important; } + .vnotify-item: hover { + opacity: 1 !important; } + +.vnotify-title { + font-weight: bold !important; } + +.vnotify-notify { +background: #333 !important; +color: #fff !important; } + +/* +.vnotify-success { + background: #2ecc71 !important; + color: #fff !important; } + +.vnotify-error { + background: #e74c3c !important; + color: #fff !important; } + +.vnotify-warning { + background: #f39c12 !important; + color: #fff !important; } + + .vnotify-info { + background: #3498db !important; + color: #fff !important; } + +*/ diff --git a/Vimari Extension/js/injected.js b/Vimari Extension/js/injected.js index cc83ecd..4107481 100644 --- a/Vimari Extension/js/injected.js +++ b/Vimari Extension/js/injected.js @@ -19,82 +19,82 @@ */ var topWindow = (window.top === window), - settings = {}, - currentZoomLevel = 100, - linkHintCss = {}, - extensionActive = true, - insertMode = false, - shiftKeyToggle = false, - hudDuration = 5000, + settings = {}, + currentZoomLevel = 100, + linkHintCss = {}, + extensionActive = true, + insertMode = false, + shiftKeyToggle = false, + hudDuration = 5000, extensionCommunicator = SafariExtensionCommunicator(messageHandler); var actionMap = { - 'hintToggle' : function() { - HUD.showForDuration('Open link in current tab', hudDuration); - activateLinkHintsMode(false, false); }, + 'hintToggle' : function() { + HUD.showForDuration('Open link in current tab', hudDuration); + activateLinkHintsMode(false, false); }, - 'newTabHintToggle' : function() { - HUD.showForDuration('Open link in new tab', hudDuration); - activateLinkHintsMode(true, false); }, + 'newTabHintToggle' : function() { + HUD.showForDuration('Open link in new tab', hudDuration); + activateLinkHintsMode(true, false); }, - 'tabForward': + 'tabForward': function() { extensionCommunicator.requestTabForward(); }, - 'tabBack': + 'tabBack': function() { extensionCommunicator.requestTabBackward() }, - 'scrollDown': - function() { window.scrollBy(0, settings.scrollSize); }, + 'scrollDown': + function() { window.scrollBy(0, settings.scrollSize); }, - 'scrollUp': - function() { window.scrollBy(0, -settings.scrollSize); }, + 'scrollUp': + function() { window.scrollBy(0, -settings.scrollSize); }, - 'scrollLeft': - function() { window.scrollBy(-settings.scrollSize, 0); }, + 'scrollLeft': + function() { window.scrollBy(-settings.scrollSize, 0); }, - 'scrollRight': - function() { window.scrollBy(settings.scrollSize, 0); }, + 'scrollRight': + function() { window.scrollBy(settings.scrollSize, 0); }, - 'goBack': - function() { window.history.back(); }, + 'goBack': + function() { window.history.back(); }, - 'goForward': - function() { window.history.forward(); }, + 'goForward': + function() { window.history.forward(); }, - 'reload': - function() { window.location.reload(); }, + 'reload': + function() { window.location.reload(); }, - 'openTab': - function() { extensionCommunicator.requestNewTab(); }, + 'openTab': + function() { extensionCommunicator.requestNewTab(); }, - 'closeTab': - function() { extensionCommunicator.requestCloseTab(); }, + 'closeTab': + function() { extensionCommunicator.requestCloseTab(); }, - 'scrollDownHalfPage': - function() { window.scrollBy(0, window.innerHeight / 2); }, + 'scrollDownHalfPage': + function() { window.scrollBy(0, window.innerHeight / 2); }, - 'scrollUpHalfPage': - function() { window.scrollBy(0, window.innerHeight / -2); }, + 'scrollUpHalfPage': + function() { window.scrollBy(0, window.innerHeight / -2); }, - 'goToPageBottom': - function() { window.scrollBy(0, document.body.scrollHeight); }, + 'goToPageBottom': + function() { window.scrollBy(0, document.body.scrollHeight); }, - 'goToPageTop': - function() { window.scrollBy(0, -document.body.scrollHeight); } + 'goToPageTop': + function() { window.scrollBy(0, -document.body.scrollHeight); } }; // Meant to be overridden, but still has to be copy/pasted from the original... Mousetrap.prototype.stopCallback = function(e, element, combo) { - // Escape key is special, no need to stop. Vimari-specific. - if (combo === 'esc' || combo === 'ctrl+[') { return false; } + // Escape key is special, no need to stop. Vimari-specific. + if (combo === 'esc' || combo === 'ctrl+[') { return false; } // Preserve the behavior of allowing ex. ctrl-j in an input if (settings.modifier) { return false; } - // if the element has the class "mousetrap" then no need to stop - if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) { - return false; - } + // if the element has the class "mousetrap" then no need to stop + if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) { + return false; + } var tagName = element.tagName; var contentIsEditable = (element.contentEditable && element.contentEditable === 'true'); @@ -107,37 +107,33 @@ Mousetrap.prototype.stopCallback = function(e, element, combo) { function bindKeyCodesToActions(settings) { var excludedUrl = false if (typeof settings != "undefined") { - excludedUrl = isDesignatedUrl(settings.excludedUrls, document.URL); - insertModeUrl = isDesignatedUrl(settings.insertModeUrls, document.URL); + excludedUrl = isExcludedUrl(settings.excludedUrls, document.URL) } - // Only add if topWindow... not iframe + // Only add if topWindow... not iframe Mousetrap.reset(); - if (topWindow && !excludedUrl) { - Mousetrap.bind('esc', enterNormalMode); - Mousetrap.bind('ctrl+[', enterNormalMode); - Mousetrap.bind('i', enterInsertMode); - for (var actionName in actionMap) { - if (actionMap.hasOwnProperty(actionName)) { - var keyCode = getKeyCode(actionName); - Mousetrap.bind(keyCode, executeAction(actionName), 'keydown'); - } - } - } - if (insertModeUrl) { - enterInsertMode(); + if (topWindow && !excludedUrl) { + Mousetrap.bind('esc', enterNormalMode); + Mousetrap.bind('ctrl+[', enterNormalMode); + Mousetrap.bind('i', enterInsertMode); + for (var actionName in actionMap) { + if (actionMap.hasOwnProperty(actionName)) { + var keyCode = getKeyCode(actionName); + Mousetrap.bind(keyCode, executeAction(actionName), 'keydown'); } + } + } } function enterNormalMode() { - // Clear input focus - document.activeElement.blur(); + // Clear input focus + document.activeElement.blur(); - // Clear link hints (if any) - deactivateLinkHintsMode(); + // Clear link hints (if any) + deactivateLinkHintsMode(); - // Re-enable if in insert mode - insertMode = false; - Mousetrap.bind('i', enterInsertMode); + // Re-enable if in insert mode + insertMode = false; + Mousetrap.bind('i', enterInsertMode); var container = document.querySelectorAll('.vnotify-container'); for (var i=0; i< container.length; i++) { container[i].outerHTML = ''; @@ -149,27 +145,27 @@ function enterNormalMode() { // Calling it 'insert mode', but it's really just a user-triggered // off switch for the actions. function enterInsertMode() { - insertMode = true; - Mousetrap.unbind('i'); + insertMode = true; + Mousetrap.unbind('i'); vNotify.notify({text: 'Insert Mode', title:'Vimari', visibleDuration: 500, showClose: false, sticky: true}); } function executeAction(actionName) { - return function() { - // don't do anything if we're not supposed to - if (linkHintsModeActivated || !extensionActive || insertMode) - return; + return function() { + // don't do anything if we're not supposed to + if (linkHintsModeActivated || !extensionActive || insertMode) + return; - //Call the action function - actionMap[actionName](); + //Call the action function + actionMap[actionName](); - // Tell mousetrap to stop propagation - return false; - } + // Tell mousetrap to stop propagation + return false; + } } function unbindKeyCodes() { - Mousetrap.reset(); + Mousetrap.reset(); document.removeEventListener("keydown", stopSitePropagation); } @@ -193,14 +189,14 @@ function isActiveElementEditable() { // Adds an optional modifier to the configured key code for the action function getKeyCode(actionName) { - var keyCode = ''; + var keyCode = ''; if (typeof settings != 'undefined') { if(settings.modifier) { keyCode += settings.modifier + '+'; } return keyCode + settings["bindings"][actionName]; } - return keyCode; + return keyCode; } @@ -210,7 +206,7 @@ function getKeyCode(actionName) { * css is pre loaded into the page. */ function addCssToPage(css) { - return; + return; } @@ -222,10 +218,10 @@ function addCssToPage(css) { * can be controlled via the keyboard, particularly SELECT combo boxes. */ function isEditable(target) { - if (target.getAttribute("contentEditable") === "true") - return true; - var focusableInputs = ["input", "textarea", "select", "button"]; - return focusableInputs.indexOf(target.tagName.toLowerCase()) >= 0; + if (target.getAttribute("contentEditable") === "true") + return true; + var focusableInputs = ["input", "textarea", "select", "button"]; + return focusableInputs.indexOf(target.tagName.toLowerCase()) >= 0; } @@ -250,8 +246,8 @@ function messageHandler(event){ * Callback to pass settings to injected script */ function setSettings(msg) { - settings = msg; - activateExtension(settings); + settings = msg; + activateExtension(settings); } function activateExtension(settings) { @@ -260,15 +256,15 @@ function activateExtension(settings) { bindKeyCodesToActions(settings); } -function isDesignatedUrl(storedDesignatedUrls, currentUrl) { - if (!storedDesignatedUrls.length) { - return false; - } +function isExcludedUrl(storedExcludedUrls, currentUrl) { + if (!storedExcludedUrls.length) { + return false; + } - var designatedUrls, regexp, url, formattedUrl, _i, _len; - designatedUrls = storedDesignatedUrls.split(","); - for (_i = 0, _len = designatedUrls.length; _i < _len; _i++) { - url = designatedUrls[_i]; + var excludedUrls, regexp, url, formattedUrl, _i, _len; + excludedUrls = storedExcludedUrls.split(","); + for (_i = 0, _len = excludedUrls.length; _i < _len; _i++) { + url = excludedUrls[_i]; formattedUrl = stripProtocolAndWww(url); formattedUrl = formattedUrl.toLowerCase().trim(); regexp = new RegExp('((.*)?(' + formattedUrl + ')+(.*))'); @@ -307,5 +303,5 @@ if(!inIframe()){ } // Export to make it testable -window.isDesignatedUrl = isDesignatedUrl; +window.isExcludedUrl = isExcludedUrl; window.stripProtocolAndWww = stripProtocolAndWww; diff --git a/Vimari Extension/js/lib/vnotify.js b/Vimari Extension/js/lib/vnotify.js index f2d1bf9..598968d 100644 --- a/Vimari Extension/js/lib/vnotify.js +++ b/Vimari Extension/js/lib/vnotify.js @@ -182,7 +182,7 @@ var vNotify = (function() { item = null; }; - //New fade - based on http://toddmotto.com/raw-javascript-jquery-style-fadein-fadeout-functions-hugo-giraudel/ + // New fade - based on http://toddmotto.com/raw-javascript-jquery-style-fadein-fadeout-functions-hugo-giraudel/ var fade = function(type, ms, el) { var isIn = type === 'in', opacity = isIn ? 0 : el.style.opacity || 1, diff --git a/Vimari.xcodeproj/project.pbxproj b/Vimari.xcodeproj/project.pbxproj index 0c9259d..abffbb7 100644 --- a/Vimari.xcodeproj/project.pbxproj +++ b/Vimari.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 4C15F22C24E4441C009DC451 /* vnotify.css in Resources */ = {isa = PBXBuildFile; fileRef = 4C15F22B24E4441C009DC451 /* vnotify.css */; }; 4C9DFE0C24E37A60002B9455 /* vnotify.js in Resources */ = {isa = PBXBuildFile; fileRef = 4C9DFE0B24E37A60002B9455 /* vnotify.js */; }; 65E444F324CC3A1B008EA1DC /* SafariExtensionCommunicator.js in Resources */ = {isa = PBXBuildFile; fileRef = 65E444F224CC3A1B008EA1DC /* SafariExtensionCommunicator.js */; }; B1E3C17023A65ED400A56807 /* ConfigurationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E3C16F23A65ED400A56807 /* ConfigurationModel.swift */; }; @@ -58,6 +59,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 4C15F22B24E4441C009DC451 /* vnotify.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = vnotify.css; sourceTree = ""; }; 4C9DFE0B24E37A60002B9455 /* vnotify.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = vnotify.js; sourceTree = ""; }; 65E444F224CC3A1B008EA1DC /* SafariExtensionCommunicator.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = SafariExtensionCommunicator.js; sourceTree = ""; }; B1E3C16F23A65ED400A56807 /* ConfigurationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationModel.swift; sourceTree = ""; }; @@ -201,6 +203,7 @@ isa = PBXGroup; children = ( E380F282233183EE00640547 /* injected.css */, + 4C15F22B24E4441C009DC451 /* vnotify.css */, ); path = css; sourceTree = ""; @@ -305,6 +308,7 @@ E380F28B233183EF00640547 /* injected.css in Resources */, E380F285233183EF00640547 /* injected.js in Resources */, E380F287233183EF00640547 /* keyboard-utils.js in Resources */, + 4C15F22C24E4441C009DC451 /* vnotify.css in Resources */, E380F289233183EF00640547 /* vimium-scripts.js in Resources */, E380F2672331806500640547 /* SafariExtensionViewController.xib in Resources */, E380F286233183EF00640547 /* mocks.js in Resources */, From 4e9c78a41c67aaefdbef8585b3547970098c6513 Mon Sep 17 00:00:00 2001 From: agboh Date: Thu, 13 Aug 2020 00:00:57 +0800 Subject: [PATCH 10/13] Update injected.js according to master --- Vimari Extension/js/injected.js | 55 ++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/Vimari Extension/js/injected.js b/Vimari Extension/js/injected.js index 4107481..f5b2cec 100644 --- a/Vimari Extension/js/injected.js +++ b/Vimari Extension/js/injected.js @@ -80,7 +80,60 @@ var actionMap = { function() { window.scrollBy(0, document.body.scrollHeight); }, 'goToPageTop': - function() { window.scrollBy(0, -document.body.scrollHeight); } + function() { window.scrollBy(0, -document.body.scrollHeight); }, + + 'goToFirstInput': + function() { goToFirstInput(); }, +}; + +// Inspiration and general algorithm taken from sVim. +function goToFirstInput() { + var inputs = document.querySelectorAll('input,textarea'); + + var bestInput = null; + var bestInViewInput = null; + + inputs.forEach(function(input) { + // Skip if hidden or disabled + if ((input.offsetParent === null) || + input.disabled || + (input.getAttribute('type') === 'hidden') || + (getComputedStyle(input).visibility === 'hidden') || + (input.getAttribute('display') === 'none')) { + return; + } + + // Skip things that are not actual inputs + if ((input.localName !== 'textarea') && + (input.localName !== 'input') && + (input.getAttribute('contenteditable') !== 'true')) { + return; + } + + // Skip non-text inputs + if (/button|radio|file|image|checkbox|submit/i.test(input.getAttribute('type'))) { + return; + } + + var inputRect = input.getClientRects()[0]; + var isInView = (inputRect.top >= -inputRect.height) && + (inputRect.top <= window.innerHeight) && + (inputRect.left >= -inputRect.width) && + (inputRect.left <= window.innerWidth); + + if (bestInput === null) { + bestInput = input; + } + + if (isInView && (bestInViewInput === null)) { + bestInViewInput = input; + } + }); + + var inputToFocus = bestInViewInput || bestInput; + if (inputToFocus !== null) { + inputToFocus.focus(); + } }; // Meant to be overridden, but still has to be copy/pasted from the original... From 1a26a3f9e43d6905f3ff6554ac7fd5c41733f2ba Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Thu, 13 Aug 2020 00:42:19 +0800 Subject: [PATCH 11/13] Replace hintToggle HUD with vNotify --- Vimari Extension/js/injected.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Vimari Extension/js/injected.js b/Vimari Extension/js/injected.js index f5b2cec..bfe7ca6 100644 --- a/Vimari Extension/js/injected.js +++ b/Vimari Extension/js/injected.js @@ -25,16 +25,18 @@ var topWindow = (window.top === window), extensionActive = true, insertMode = false, shiftKeyToggle = false, - hudDuration = 5000, +// hudDuration = 5000, extensionCommunicator = SafariExtensionCommunicator(messageHandler); var actionMap = { 'hintToggle' : function() { - HUD.showForDuration('Open link in current tab', hudDuration); + vNotify.notify({text: 'Current Tab', title:'Vimari', visibleDuration: 2000, showClose: false}); +// HUD.showForDuration('Open link in current tab', hudDuration); activateLinkHintsMode(false, false); }, 'newTabHintToggle' : function() { - HUD.showForDuration('Open link in new tab', hudDuration); + vNotify.notify({text: 'New Tab', title:'Vimari', visibleDuration: 2000, showClose: false}); +// HUD.showForDuration('Open link in new tab', hudDuration); activateLinkHintsMode(true, false); }, 'tabForward': From 0116f35954ff35471248b1157c4db019d33cf06a Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Thu, 13 Aug 2020 00:46:43 +0800 Subject: [PATCH 12/13] Enforce line-height for vNotify --- Vimari Extension/css/vnotify.css | 1 + 1 file changed, 1 insertion(+) diff --git a/Vimari Extension/css/vnotify.css b/Vimari Extension/css/vnotify.css index 5f5af00..aa6c29d 100644 --- a/Vimari Extension/css/vnotify.css +++ b/Vimari Extension/css/vnotify.css @@ -2,6 +2,7 @@ .vnotify-container { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important; font-size: 12px !important; + line-height: 1.5 !important; position: fixed !important; } /* .vnotify-container.vn-top-right { From fe17b369822d1632fbb124253b734ee3d5e0a448 Mon Sep 17 00:00:00 2001 From: agbohub <14964685+agbohub@users.noreply.github.com> Date: Sun, 23 Aug 2020 10:19:31 +0800 Subject: [PATCH 13/13] Update Info.plist Update Info.plist to conform with v2.1.0-beta2. --- Vimari Extension/Info.plist | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Vimari Extension/Info.plist b/Vimari Extension/Info.plist index 6e512e2..6abd427 100644 --- a/Vimari Extension/Info.plist +++ b/Vimari Extension/Info.plist @@ -33,6 +33,9 @@ Script vnotify.js + + + Script svim-scripts.js