diff --git a/package-lock.json b/package-lock.json index cc9b608..2e2091d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "lz-string": "~1.5.0", "masto": "~6.3.1", "mem": "~9.0.2", + "moize": "~6.1.6", "p-retry": "~6.1.0", "p-throttle": "~5.1.0", "preact": "~10.18.1", @@ -4295,6 +4296,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-equals": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-3.0.3.tgz", + "integrity": "sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg==" + }, "node_modules/fast-glob": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", @@ -5321,6 +5327,11 @@ "node": ">= 8" } }, + "node_modules/micro-memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.1.2.tgz", + "integrity": "sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g==" + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -5378,6 +5389,15 @@ "node": "*" } }, + "node_modules/moize": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/moize/-/moize-6.1.6.tgz", + "integrity": "sha512-vSKdIUO61iCmTqhdoIDrqyrtp87nWZUmBPniNjO0fX49wEYmyDO4lvlnFXiGcaH1JLE/s/9HbiK4LSHsbiUY6Q==", + "dependencies": { + "fast-equals": "^3.0.1", + "micro-memoize": "^4.1.2" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -10525,6 +10545,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "fast-equals": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-3.0.3.tgz", + "integrity": "sha512-NCe8qxnZFARSHGztGMZOO/PC1qa5MIFB5Hp66WdzbCRAz8U8US3bx1UTgLS49efBQPcUtO9gf5oVEY8o7y/7Kg==" + }, "fast-glob": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", @@ -11281,6 +11306,11 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, + "micro-memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-4.1.2.tgz", + "integrity": "sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g==" + }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -11320,6 +11350,15 @@ "brace-expansion": "^1.1.7" } }, + "moize": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/moize/-/moize-6.1.6.tgz", + "integrity": "sha512-vSKdIUO61iCmTqhdoIDrqyrtp87nWZUmBPniNjO0fX49wEYmyDO4lvlnFXiGcaH1JLE/s/9HbiK4LSHsbiUY6Q==", + "requires": { + "fast-equals": "^3.0.1", + "micro-memoize": "^4.1.2" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", diff --git a/package.json b/package.json index dd07411..7b78c25 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "lz-string": "~1.5.0", "masto": "~6.3.1", "mem": "~9.0.2", + "moize": "~6.1.6", "p-retry": "~6.1.0", "p-throttle": "~5.1.0", "preact": "~10.18.1", diff --git a/src/components/translation-block.jsx b/src/components/translation-block.jsx index 234cd27..06ce52d 100644 --- a/src/components/translation-block.jsx +++ b/src/components/translation-block.jsx @@ -7,6 +7,7 @@ import { useEffect, useRef, useState } from 'preact/hooks'; import sourceLanguages from '../data/lingva-source-languages'; import getTranslateTargetLanguage from '../utils/get-translate-target-language'; import localeCode2Text from '../utils/localeCode2Text'; +import pmem from '../utils/pmem'; import Icon from './icon'; import Loader from './loader'; @@ -25,7 +26,7 @@ const LINGVA_INSTANCES = [ ]; let currentLingvaInstance = 0; -function lingvaTranslate(text, source, target) { +function _lingvaTranslate(text, source, target) { console.log('TRANSLATE', text, source, target); const fetchCall = () => { let instance = LINGVA_INSTANCES[currentLingvaInstance]; @@ -59,7 +60,14 @@ function lingvaTranslate(text, source, target) { // lang: DEFAULT_LANG, // }); } -const throttledLingvaTranslate = throttle(lingvaTranslate); +const TRANSLATED_MAX_AGE = 1000 * 60 * 60; // 1 hour +const lingvaTranslate = pmem(_lingvaTranslate, { + maxAge: TRANSLATED_MAX_AGE, +}); +const throttledLingvaTranslate = pmem(throttle(lingvaTranslate), { + // I know, this is double-layered memoization + maxAge: TRANSLATED_MAX_AGE, +}); function TranslationBlock({ forceTranslate, diff --git a/src/utils/pmem.js b/src/utils/pmem.js new file mode 100644 index 0000000..8cd0be9 --- /dev/null +++ b/src/utils/pmem.js @@ -0,0 +1,5 @@ +import moize from 'moize'; + +export default function pmem(fn, opts = {}) { + return moize(fn, { isPromise: true, ...opts, maxSize: Infinity }); +}