From 28c105cb0cc9593930f069584662380a7674c249 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sat, 23 May 2020 19:34:00 -0700 Subject: Add auto resize to text areas --- .../com/pitchedapps/frost/injectors/JsAssets.kt | 2 +- .../pitchedapps/frost/web/FrostWebViewClients.kt | 1 + app/src/web/ts/auto_resize_textarea.ts | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 app/src/web/ts/auto_resize_textarea.ts diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt index 03ab6e96..91f8aa71 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt @@ -35,7 +35,7 @@ import kotlinx.coroutines.withContext */ enum class JsAssets : InjectorContract { MENU, CLICK_A, CONTEXT_A, MEDIA, HEADER_BADGES, TEXTAREA_LISTENER, NOTIF_MSG, - DOCUMENT_WATCHER, HORIZONTAL_SCROLLING + DOCUMENT_WATCHER, HORIZONTAL_SCROLLING, AUTO_RESIZE_TEXTAREA ; @VisibleForTesting diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt index 4d635547..657bf93e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -128,6 +128,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { ), JsAssets.DOCUMENT_WATCHER, JsAssets.HORIZONTAL_SCROLLING, + JsAssets.AUTO_RESIZE_TEXTAREA, JsAssets.CLICK_A, CssHider.ADS.maybe(!prefs.showFacebookAds), JsAssets.CONTEXT_A, diff --git a/app/src/web/ts/auto_resize_textarea.ts b/app/src/web/ts/auto_resize_textarea.ts new file mode 100644 index 00000000..f690d4c0 --- /dev/null +++ b/app/src/web/ts/auto_resize_textarea.ts @@ -0,0 +1,22 @@ +// Credits to https://codepen.io/tomhodgins/pen/KgazaE +(function () { + const textareas = >document.querySelectorAll('textarea.frostAutoExpand'); + + const _frostAutoExpand = (el: HTMLElement) => { + el.style.height = 'inherit' + el.style.height = `${el.scrollHeight}px` + }; + function _frostExpandAll() { + textareas.forEach(_frostAutoExpand); + } + textareas.forEach(el => { + const __frostAutoExpand = () => { + _frostAutoExpand(el) + }; + el.addEventListener('paste', __frostAutoExpand) + el.addEventListener('input', __frostAutoExpand) + el.addEventListener('keyup', __frostAutoExpand) + }); + window.addEventListener('load', _frostExpandAll) + window.addEventListener('resize', _frostExpandAll) +}).call(undefined); -- cgit v1.2.3 From 0a0108e69d0e720634b1f0fdfb946fce7e714fe7 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sat, 23 May 2020 20:49:26 -0700 Subject: Allow text area to fill with default min height --- .../com/pitchedapps/frost/injectors/JsAssets.kt | 10 +-- .../pitchedapps/frost/web/FrostWebViewClients.kt | 1 + app/src/web/package-lock.json | 72 ++++++++++------------ app/src/web/package.json | 4 +- app/src/web/ts/auto_resize_textarea.ts | 15 ++++- 5 files changed, 53 insertions(+), 49 deletions(-) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt index 91f8aa71..b7c4bfb0 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt @@ -22,20 +22,20 @@ import androidx.annotation.VisibleForTesting import ca.allanwang.kau.kotlin.lazyContext import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import java.io.BufferedReader import java.io.FileNotFoundException import java.util.Locale -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext /** * Created by Allan Wang on 2017-05-31. * Mapping of the available assets * The enum name must match the css file name */ -enum class JsAssets : InjectorContract { +enum class JsAssets(private val singleLoad: Boolean = true) : InjectorContract { MENU, CLICK_A, CONTEXT_A, MEDIA, HEADER_BADGES, TEXTAREA_LISTENER, NOTIF_MSG, - DOCUMENT_WATCHER, HORIZONTAL_SCROLLING, AUTO_RESIZE_TEXTAREA + DOCUMENT_WATCHER, HORIZONTAL_SCROLLING, AUTO_RESIZE_TEXTAREA(singleLoad = false) ; @VisibleForTesting @@ -43,7 +43,7 @@ enum class JsAssets : InjectorContract { private val injector = lazyContext { try { val content = it.assets.open("js/$file").bufferedReader().use(BufferedReader::readText) - JsBuilder().js(content).single(name).build() + JsBuilder().js(content).run { if (singleLoad) single(name) else this }.build() } catch (e: FileNotFoundException) { L.e(e) { "JsAssets file not found" } JsInjector(JsActions.EMPTY.function) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt index 657bf93e..973efc4b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt @@ -80,6 +80,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() { super.doUpdateVisitedHistory(view, url, isReload) urlSupportsRefresh = urlSupportsRefresh(url) web.parent.swipeEnabled = urlSupportsRefresh + view.jsInject(JsAssets.AUTO_RESIZE_TEXTAREA, prefs = prefs) v { "History $url; refresh $urlSupportsRefresh" } } diff --git a/app/src/web/package-lock.json b/app/src/web/package-lock.json index d27e49ef..9cad6fce 100644 --- a/app/src/web/package-lock.json +++ b/app/src/web/package-lock.json @@ -3,19 +3,14 @@ "lockfileVersion": 1, "dependencies": { "anymatch": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.0.2.tgz", - "integrity": "sha512-rUe9SxpRQlVg4EM8It7JMNWWYHAirTPpbTuvaSKybb5IejNgWB3PGBBX9rrPKDx2pM/p3Wh+7+ASaWRyyAbxmQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -44,19 +39,18 @@ } }, "chokidar": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.1.tgz", - "integrity": "sha512-2ww34sJWehnbpV0Q4k4V5Hh7juo7po6z7LUWkcIQnSGN1lHOL8GGtLtfwabKvLFQw/hbSUQ0u6V7OgGYgBzlkQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", "requires": { - "anymatch": "^3.0.1", - "async-each": "^1.0.3", - "braces": "^3.0.2", - "fsevents": "^2.0.6", - "glob-parent": "^5.0.0", - "is-binary-path": "^2.1.0", - "is-glob": "^4.0.1", - "normalize-path": "^3.0.0", - "readdirp": "^3.0.2" + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" } }, "compile": { @@ -78,15 +72,15 @@ } }, "fsevents": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", - "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "optional": true }, "glob-parent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", - "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "requires": { "is-glob": "^4.0.1" } @@ -131,16 +125,16 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "picomatch": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", - "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "readdirp": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.0.2.tgz", - "integrity": "sha512-LbyJYv48eywrhOlScq16H/VkCiGKGPC2TpOdZCJ7QXnYEjn3NN/Oblh8QEU3vqfSRBB7OGvh5x45NKiVeNujIQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "requires": { - "picomatch": "^2.0.4" + "picomatch": "^2.2.1" } }, "run": { @@ -152,9 +146,9 @@ } }, "sass": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.22.2.tgz", - "integrity": "sha512-enuQuy/CbfrZLA2vOy9tB7CK7pP5bZllnMbr5nPGWCFelwt0EMUVGC11gsv9rybkWc8pp/NKVY/c5+AKyjbnXg==", + "version": "1.26.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.5.tgz", + "integrity": "sha512-FG2swzaZUiX53YzZSjSakzvGtlds0lcbF+URuU9mxOv7WBh7NhXEVDa4kPKN4hN6fC2TkOTOKqiqp6d53N9X5Q==", "requires": { "chokidar": ">=2.0.0 <4.0.0" } @@ -168,9 +162,9 @@ } }, "typescript": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.2.tgz", - "integrity": "sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA==" + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.3.tgz", + "integrity": "sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==" } } } diff --git a/app/src/web/package.json b/app/src/web/package.json index 3a9b6acc..c3c71b46 100644 --- a/app/src/web/package.json +++ b/app/src/web/package.json @@ -10,7 +10,7 @@ "dependencies": { "compile": "0.0.2", "run": "^1.4.0", - "sass": "^1.19.0", - "typescript": "^3.3.1" + "sass": "^1.26.5", + "typescript": "^3.9.3" } } diff --git a/app/src/web/ts/auto_resize_textarea.ts b/app/src/web/ts/auto_resize_textarea.ts index f690d4c0..e170d14e 100644 --- a/app/src/web/ts/auto_resize_textarea.ts +++ b/app/src/web/ts/auto_resize_textarea.ts @@ -1,15 +1,24 @@ // Credits to https://codepen.io/tomhodgins/pen/KgazaE (function () { - const textareas = >document.querySelectorAll('textarea.frostAutoExpand'); + const textareas = >document.querySelectorAll('textarea:not(.frostAutoExpand)'); + + const dataAttribute = 'data-frost-minHeight'; const _frostAutoExpand = (el: HTMLElement) => { - el.style.height = 'inherit' - el.style.height = `${el.scrollHeight}px` + if (!el.hasAttribute(dataAttribute)) { + el.setAttribute(dataAttribute, el.offsetHeight.toString()); + } + // If no height is defined, have min bound to current height; + // otherwise we will allow for height decreases in case user deletes text + const minHeight = parseInt(el.getAttribute(dataAttribute) ?? '0'); + el.style.height = 'inherit'; + el.style.height = `${Math.max(el.scrollHeight, minHeight)}px`; }; function _frostExpandAll() { textareas.forEach(_frostAutoExpand); } textareas.forEach(el => { + el.classList.add('frostAutoExpand') const __frostAutoExpand = () => { _frostAutoExpand(el) }; -- cgit v1.2.3