From b75758808ef4a2ab9c54ea401c667b60845e95e3 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 21 Oct 2020 12:50:24 -0400 Subject: [PATCH] Ensure the bottom of dashboard panes is visible Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1304 On small displays, not being able to scroll down could become a usability issue. --- src/css/3p-filters.css | 3 +++ src/css/about.css | 3 +++ src/css/codemirror.css | 3 +++ src/css/settings.css | 3 +++ src/js/1p-filters.js | 39 ++++++++++++++++++------------------ src/js/dyna-rules.js | 2 +- src/js/whitelist.js | 45 ++++++++++++++++++++++-------------------- 7 files changed, 57 insertions(+), 41 deletions(-) diff --git a/src/css/3p-filters.css b/src/css/3p-filters.css index 7100267db..f8d369b45 100644 --- a/src/css/3p-filters.css +++ b/src/css/3p-filters.css @@ -2,6 +2,9 @@ 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } +body { + margin-bottom: 6rem; + } #actions { background-color: var(--default-surface); padding: var(--default-gap-small) 0 var(--default-gap-xsmall) 0; diff --git a/src/css/about.css b/src/css/about.css index f6f143f17..b32bcc811 100644 --- a/src/css/about.css +++ b/src/css/about.css @@ -1,3 +1,6 @@ +body { + margin-bottom: 6rem; + } .entries { margin: 0.5em 0; margin-inline-start: 2em; diff --git a/src/css/codemirror.css b/src/css/codemirror.css index 8a9b9453f..6d27ca984 100644 --- a/src/css/codemirror.css +++ b/src/css/codemirror.css @@ -12,6 +12,9 @@ height: 100%; width: 100%; } +.CodeMirror-lines { + padding-bottom: 6rem; + } .CodeMirror-gutters { background-color: var(--cm-gutter-surface); border-color: var(--cm-gutter-border); diff --git a/src/css/settings.css b/src/css/settings.css index dcd860373..0a030b563 100644 --- a/src/css/settings.css +++ b/src/css/settings.css @@ -1,3 +1,6 @@ +body { + margin-bottom: 6rem; + } .synopsis { font-size: 90%; } diff --git a/src/js/1p-filters.js b/src/js/1p-filters.js index b99faf1c7..c30122958 100644 --- a/src/js/1p-filters.js +++ b/src/js/1p-filters.js @@ -63,6 +63,17 @@ let cachedUserFilters = ''; /******************************************************************************/ +const getEditorText = function() { + const text = cmEditor.getValue().replace(/\s+$/, ''); + return text === '' ? text : text + '\n'; +}; + +const setEditorText = function(text) { + cmEditor.setValue(text.replace(/\s+$/, '') + '\n\n'); +}; + +/******************************************************************************/ + // This is to give a visual hint that the content of user blacklist has changed. const userFiltersChanged = function(changed) { @@ -83,10 +94,7 @@ const renderUserFilters = async function() { let content = details.content.trim(); cachedUserFilters = content; - if ( content.length !== 0 ) { - content += '\n'; - } - cmEditor.setValue(content); + setEditorText(content); userFiltersChanged(false); }; @@ -117,13 +125,10 @@ const handleImportFilePicker = function() { const fileReaderOnLoadHandler = function() { let content = abpImporter(this.result); - content = uBlockDashboard.mergeNewLines( - cmEditor.getValue().trim(), - content - ); + content = uBlockDashboard.mergeNewLines(getEditorText(), content); cmEditor.operation(( ) => { const cmPos = cmEditor.getCursor(); - cmEditor.setValue(`${content}\n`); + setEditorText(content); cmEditor.setCursor(cmPos); cmEditor.focus(); }); @@ -150,7 +155,7 @@ const startImportFilePicker = function() { /******************************************************************************/ const exportUserFiltersToFile = function() { - const val = cmEditor.getValue().trim(); + const val = getEditorText(); if ( val === '' ) { return; } const filename = vAPI.i18n('1pExportFilename') .replace('{{datetime}}', uBlockDashboard.dateNowToSensibleString()) @@ -166,7 +171,7 @@ const exportUserFiltersToFile = function() { const applyChanges = async function() { const details = await vAPI.messaging.send('dashboard', { what: 'writeUserFilters', - content: cmEditor.getValue(), + content: getEditorText(), }); if ( details instanceof Object === false || details.error ) { return; } @@ -178,23 +183,19 @@ const applyChanges = async function() { }; const revertChanges = function() { - let content = cachedUserFilters; - if ( content.length !== 0 ) { - content += '\n'; - } - cmEditor.setValue(content); + setEditorText(cachedUserFilters); }; /******************************************************************************/ const getCloudData = function() { - return cmEditor.getValue(); + return getEditorText(); }; const setCloudData = function(data, append) { if ( typeof data !== 'string' ) { return; } if ( append ) { - data = uBlockDashboard.mergeNewLines(cmEditor.getValue(), data); + data = uBlockDashboard.mergeNewLines(getEditorText(), data); } cmEditor.setValue(data); }; @@ -205,7 +206,7 @@ self.cloud.onPull = setCloudData; /******************************************************************************/ self.hasUnsavedData = function() { - return cmEditor.getValue().trim() !== cachedUserFilters; + return getEditorText().trim() !== cachedUserFilters; }; /******************************************************************************/ diff --git a/src/js/dyna-rules.js b/src/js/dyna-rules.js index 7d1df9624..581d48fc6 100644 --- a/src/js/dyna-rules.js +++ b/src/js/dyna-rules.js @@ -39,7 +39,7 @@ const mergeView = new CodeMirror.MergeView( lineWrapping: false, origLeft: '', revertButtons: true, - value: '' + value: '', } ); mergeView.editor().setOption('styleActiveLine', true); diff --git a/src/js/whitelist.js b/src/js/whitelist.js index 546308df2..0ff38cd10 100644 --- a/src/js/whitelist.js +++ b/src/js/whitelist.js @@ -92,7 +92,7 @@ const cmEditor = new CodeMirror( autofocus: true, lineNumbers: true, lineWrapping: true, - styleActiveLine: true + styleActiveLine: true, } ); @@ -100,10 +100,21 @@ uBlockDashboard.patchCodeMirrorEditor(cmEditor); /******************************************************************************/ +const getEditorText = function() { + let text = cmEditor.getValue().replace(/\s+$/, ''); + return text === '' ? text : text + '\n'; +}; + +const setEditorText = function(text) { + cmEditor.setValue(text.replace(/\s+$/, '') + '\n'); +}; + +/******************************************************************************/ + const whitelistChanged = function() { const whitelistElem = uDom.nodeFromId('whitelist'); const bad = whitelistElem.querySelector('.cm-error') !== null; - const changedWhitelist = cmEditor.getValue().trim(); + const changedWhitelist = getEditorText().trim(); const changed = changedWhitelist !== cachedWhitelist; uDom.nodeFromId('whitelistApply').disabled = !changed || bad; uDom.nodeFromId('whitelistRevert').disabled = !changed; @@ -144,12 +155,9 @@ const renderWhitelist = async function() { } return ad.localeCompare(bd); }); - let whitelistStr = details.whitelist.join('\n').trim(); + const whitelistStr = details.whitelist.join('\n').trim(); cachedWhitelist = whitelistStr; - if ( whitelistStr !== '' ) { - whitelistStr += '\n'; - } - cmEditor.setValue(whitelistStr); + setEditorText(whitelistStr); if ( first ) { cmEditor.clearHistory(); } @@ -164,11 +172,8 @@ const handleImportFilePicker = function() { const fr = new FileReader(); fr.onload = ev => { if ( ev.type !== 'load' ) { return; } - cmEditor.setValue( - [ - cmEditor.getValue().trim(), - fr.result.trim() - ].join('\n').trim() + setEditorText( + [ getEditorText().trim(), fr.result.trim() ].join('\n').trim() ); }; fr.readAsText(file); @@ -188,7 +193,7 @@ const startImportFilePicker = function() { /******************************************************************************/ const exportWhitelistToFile = function() { - const val = cmEditor.getValue().trim(); + const val = getEditorText(); if ( val === '' ) { return; } const filename = vAPI.i18n('whitelistExportFilename') @@ -203,7 +208,7 @@ const exportWhitelistToFile = function() { /******************************************************************************/ const applyChanges = async function() { - cachedWhitelist = cmEditor.getValue().trim(); + cachedWhitelist = getEditorText().trim(); await messaging.send('dashboard', { what: 'setWhitelist', whitelist: cachedWhitelist, @@ -212,23 +217,21 @@ const applyChanges = async function() { }; const revertChanges = function() { - let content = cachedWhitelist; - if ( content !== '' ) { content += '\n'; } - cmEditor.setValue(content); + setEditorText(cachedWhitelist); }; /******************************************************************************/ const getCloudData = function() { - return cmEditor.getValue(); + return getEditorText(); }; const setCloudData = function(data, append) { if ( typeof data !== 'string' ) { return; } if ( append ) { - data = uBlockDashboard.mergeNewLines(cmEditor.getValue().trim(), data); + data = uBlockDashboard.mergeNewLines(getEditorText().trim(), data); } - cmEditor.setValue(data.trim() + '\n'); + setEditorText(data.trim()); }; self.cloud.onPush = getCloudData; @@ -237,7 +240,7 @@ self.cloud.onPull = setCloudData; /******************************************************************************/ self.hasUnsavedData = function() { - return cmEditor.getValue().trim() !== cachedWhitelist; + return getEditorText().trim() !== cachedWhitelist; }; /******************************************************************************/