scroll try #10
This commit is contained in:
parent
907925e8df
commit
c86671ce12
213
package-lock.json
generated
213
package-lock.json
generated
@ -4926,13 +4926,13 @@
|
||||
}
|
||||
},
|
||||
"globule": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
|
||||
"integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/globule/-/globule-1.3.1.tgz",
|
||||
"integrity": "sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "~7.1.1",
|
||||
"lodash": "~4.17.10",
|
||||
"lodash": "~4.17.12",
|
||||
"minimatch": "~3.0.2"
|
||||
}
|
||||
},
|
||||
@ -5555,13 +5555,10 @@
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
|
||||
},
|
||||
"is-finite": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
|
||||
"integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
|
||||
"integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
|
||||
"dev": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
@ -6247,9 +6244,9 @@
|
||||
}
|
||||
},
|
||||
"js-base64": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
|
||||
"integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz",
|
||||
"integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ==",
|
||||
"dev": true
|
||||
},
|
||||
"js-sha3": {
|
||||
@ -7088,9 +7085,9 @@
|
||||
}
|
||||
},
|
||||
"node-sass": {
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.0.tgz",
|
||||
"integrity": "sha512-W1XBrvoJ1dy7VsvTAS5q1V45lREbTlZQqFbiHb3R3OTTCma0XBtuG6xZ6Z4506nR4lmHPTqVRwxT6KgtWC97CA==",
|
||||
"version": "4.13.1",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz",
|
||||
"integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-foreach": "^0.1.3",
|
||||
@ -7191,9 +7188,9 @@
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
|
||||
},
|
||||
"npm": {
|
||||
"version": "6.13.4",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-6.13.4.tgz",
|
||||
"integrity": "sha512-vTcUL4SCg3AzwInWTbqg1OIaOXlzKSS8Mb8kc5avwrJpcvevDA5J9BhYSuei+fNs3pwOp4lzA5x2FVDXACvoXA==",
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-6.14.1.tgz",
|
||||
"integrity": "sha512-2hi3UF7g5VL8VKm46Bx5GAW28DPb8BJZbj2uONMBMhY8XkJ56lSmHJNFcjTQr7KHZqWqiBT5BugaQEy+Y/4T2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"JSONStream": "^1.3.5",
|
||||
@ -7202,12 +7199,12 @@
|
||||
"ansistyles": "~0.1.3",
|
||||
"aproba": "^2.0.0",
|
||||
"archy": "~1.0.0",
|
||||
"bin-links": "^1.1.6",
|
||||
"bin-links": "^1.1.7",
|
||||
"bluebird": "^3.5.5",
|
||||
"byte-size": "^5.0.1",
|
||||
"cacache": "^12.0.3",
|
||||
"call-limit": "^1.1.1",
|
||||
"chownr": "^1.1.3",
|
||||
"chownr": "^1.1.4",
|
||||
"ci-info": "^2.0.0",
|
||||
"cli-columns": "^3.1.2",
|
||||
"cli-table3": "^0.5.1",
|
||||
@ -7227,7 +7224,7 @@
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.2.3",
|
||||
"has-unicode": "~2.0.1",
|
||||
"hosted-git-info": "^2.8.5",
|
||||
"hosted-git-info": "^2.8.7",
|
||||
"iferr": "^1.0.2",
|
||||
"imurmurhash": "*",
|
||||
"infer-owner": "^1.0.4",
|
||||
@ -7245,7 +7242,7 @@
|
||||
"libnpmorg": "^1.0.1",
|
||||
"libnpmsearch": "^2.0.2",
|
||||
"libnpmteam": "^1.0.2",
|
||||
"libnpx": "^10.2.0",
|
||||
"libnpx": "^10.2.2",
|
||||
"lock-verify": "^2.1.0",
|
||||
"lockfile": "^1.0.4",
|
||||
"lodash._baseindexof": "*",
|
||||
@ -7264,7 +7261,7 @@
|
||||
"mississippi": "^3.0.0",
|
||||
"mkdirp": "~0.5.1",
|
||||
"move-concurrently": "^1.0.1",
|
||||
"node-gyp": "^5.0.5",
|
||||
"node-gyp": "^5.0.7",
|
||||
"nopt": "~4.0.1",
|
||||
"normalize-package-data": "^2.5.0",
|
||||
"npm-audit-report": "^1.3.2",
|
||||
@ -7272,16 +7269,16 @@
|
||||
"npm-install-checks": "^3.0.2",
|
||||
"npm-lifecycle": "^3.1.4",
|
||||
"npm-package-arg": "^6.1.1",
|
||||
"npm-packlist": "^1.4.7",
|
||||
"npm-packlist": "^1.4.8",
|
||||
"npm-pick-manifest": "^3.0.2",
|
||||
"npm-profile": "^4.0.2",
|
||||
"npm-registry-fetch": "^4.0.2",
|
||||
"npm-registry-fetch": "^4.0.3",
|
||||
"npm-user-validate": "~1.0.0",
|
||||
"npmlog": "~4.1.2",
|
||||
"once": "~1.4.0",
|
||||
"opener": "^1.5.1",
|
||||
"osenv": "^0.1.5",
|
||||
"pacote": "^9.5.11",
|
||||
"pacote": "^9.5.12",
|
||||
"path-is-inside": "~1.0.2",
|
||||
"promise-inflight": "~1.0.1",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
@ -7292,7 +7289,7 @@
|
||||
"read-installed": "~4.0.3",
|
||||
"read-package-json": "^2.1.1",
|
||||
"read-package-tree": "^5.3.1",
|
||||
"readable-stream": "^3.4.0",
|
||||
"readable-stream": "^3.6.0",
|
||||
"readdir-scoped-modules": "^1.1.0",
|
||||
"request": "^2.88.0",
|
||||
"retry": "^0.12.0",
|
||||
@ -7484,7 +7481,7 @@
|
||||
}
|
||||
},
|
||||
"bin-links": {
|
||||
"version": "1.1.6",
|
||||
"version": "1.1.7",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -7597,7 +7594,7 @@
|
||||
}
|
||||
},
|
||||
"chownr": {
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.4",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@ -8037,7 +8034,7 @@
|
||||
}
|
||||
},
|
||||
"env-paths": {
|
||||
"version": "1.0.0",
|
||||
"version": "2.2.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@ -8381,7 +8378,7 @@
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@ -8490,7 +8487,7 @@
|
||||
"dev": true
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.5",
|
||||
"version": "2.8.7",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@ -8606,7 +8603,7 @@
|
||||
}
|
||||
},
|
||||
"invert-kv": {
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
@ -8795,11 +8792,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"lcid": {
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"invert-kv": "^1.0.0"
|
||||
"invert-kv": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"libcipm": {
|
||||
@ -8972,7 +8969,7 @@
|
||||
}
|
||||
},
|
||||
"libnpx": {
|
||||
"version": "10.2.0",
|
||||
"version": "10.2.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -9123,17 +9120,34 @@
|
||||
"ssri": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"map-age-cleaner": {
|
||||
"version": "0.1.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-defer": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"meant": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"mem": {
|
||||
"version": "1.1.0",
|
||||
"version": "4.3.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^1.0.0"
|
||||
"map-age-cleaner": "^0.1.1",
|
||||
"mimic-fn": "^2.0.0",
|
||||
"p-is-promise": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
@ -9149,11 +9163,6 @@
|
||||
"mime-db": "~1.35.0"
|
||||
}
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "1.2.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
@ -9241,6 +9250,11 @@
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"nice-try": {
|
||||
"version": "1.0.5",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"node-fetch-npm": {
|
||||
"version": "2.0.2",
|
||||
"bundled": true,
|
||||
@ -9252,36 +9266,21 @@
|
||||
}
|
||||
},
|
||||
"node-gyp": {
|
||||
"version": "5.0.5",
|
||||
"version": "5.0.7",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"env-paths": "^1.0.0",
|
||||
"glob": "^7.0.3",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"mkdirp": "^0.5.0",
|
||||
"nopt": "2 || 3",
|
||||
"npmlog": "0 || 1 || 2 || 3 || 4",
|
||||
"request": "^2.87.0",
|
||||
"rimraf": "2",
|
||||
"semver": "~5.3.0",
|
||||
"env-paths": "^2.2.0",
|
||||
"glob": "^7.1.4",
|
||||
"graceful-fs": "^4.2.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nopt": "^4.0.1",
|
||||
"npmlog": "^4.1.2",
|
||||
"request": "^2.88.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"semver": "^5.7.1",
|
||||
"tar": "^4.4.12",
|
||||
"which": "1"
|
||||
},
|
||||
"dependencies": {
|
||||
"nopt": {
|
||||
"version": "3.0.6",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"abbrev": "1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.3.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
"which": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
@ -9381,12 +9380,13 @@
|
||||
}
|
||||
},
|
||||
"npm-packlist": {
|
||||
"version": "1.4.7",
|
||||
"version": "1.4.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ignore-walk": "^3.0.1",
|
||||
"npm-bundled": "^1.0.1"
|
||||
"npm-bundled": "^1.0.1",
|
||||
"npm-normalize-package-bin": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"npm-pick-manifest": {
|
||||
@ -9410,7 +9410,7 @@
|
||||
}
|
||||
},
|
||||
"npm-registry-fetch": {
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -9502,13 +9502,41 @@
|
||||
"dev": true
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "2.1.0",
|
||||
"version": "3.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"execa": "^0.7.0",
|
||||
"lcid": "^1.0.0",
|
||||
"mem": "^1.1.0"
|
||||
"execa": "^1.0.0",
|
||||
"lcid": "^2.0.0",
|
||||
"mem": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"nice-try": "^1.0.4",
|
||||
"path-key": "^2.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"execa": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"strip-eof": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"os-tmpdir": {
|
||||
@ -9525,11 +9553,21 @@
|
||||
"os-tmpdir": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"p-defer": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"p-is-promise": {
|
||||
"version": "2.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "1.2.0",
|
||||
"bundled": true,
|
||||
@ -9563,7 +9601,7 @@
|
||||
}
|
||||
},
|
||||
"pacote": {
|
||||
"version": "9.5.11",
|
||||
"version": "9.5.12",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -9877,7 +9915,7 @@
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.4.0",
|
||||
"version": "3.6.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -10261,11 +10299,18 @@
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.2.0",
|
||||
"version": "1.3.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
"safe-buffer": "~5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"stringify-package": {
|
||||
@ -10646,7 +10691,7 @@
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "11.0.0",
|
||||
"version": "11.1.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -10654,7 +10699,7 @@
|
||||
"decamelize": "^1.1.1",
|
||||
"find-up": "^2.1.0",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"os-locale": "^2.0.0",
|
||||
"os-locale": "^3.1.0",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
|
@ -42,8 +42,8 @@
|
||||
"jest": "^24.9.0",
|
||||
"leemon": "^6.2.0",
|
||||
"lottie-web": "^5.6.4",
|
||||
"node-sass": "^4.13.0",
|
||||
"npm": "^6.13.4",
|
||||
"node-sass": "^4.13.1",
|
||||
"npm": "^6.14.1",
|
||||
"offscreen-canvas": "^0.1.1",
|
||||
"on-build-webpack": "^0.1.0",
|
||||
"overlayscrollbars": "^1.10.0",
|
||||
|
@ -52,11 +52,23 @@ export function ripple(elem: Element) {
|
||||
}
|
||||
}
|
||||
|
||||
export function putPreloader(elem: Element) {
|
||||
export function putPreloader(elem: Element, returnDiv = false) {
|
||||
const html = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50">
|
||||
<circle class="preloader-path" cx="50" cy="50" r="20" fill="none" stroke-miterlimit="10"/>
|
||||
</svg>`;
|
||||
|
||||
if(returnDiv) {
|
||||
let div = document.createElement('div');
|
||||
div.classList.add('preloader');
|
||||
div.innerHTML = html;
|
||||
|
||||
if(elem) {
|
||||
elem.appendChild(div);
|
||||
}
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
elem.innerHTML += html;
|
||||
}
|
||||
@ -76,18 +88,19 @@ export function horizontalMenu(tabs: HTMLUListElement, content: HTMLDivElement,
|
||||
|
||||
///////console.log('tabs click:', target);
|
||||
|
||||
if(!target || target.classList.contains('active')) return false;
|
||||
if(!target) return false;
|
||||
|
||||
let id = whichChild(target);
|
||||
let tabContent = content.children[id] as HTMLDivElement;
|
||||
if(onClick) onClick(id, tabContent);
|
||||
if(target.classList.contains('active') || id == prevId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let prev = tabs.querySelector('li.active') as HTMLLIElement;
|
||||
prev && prev.classList.remove('active');
|
||||
|
||||
target.classList.add('active');
|
||||
|
||||
let id = whichChild(target);
|
||||
|
||||
if(id == prevId) return false;
|
||||
|
||||
let tabContent = content.children[id] as HTMLDivElement;
|
||||
tabContent.classList.add('active');
|
||||
|
||||
/////console.log('mambo rap', prevId, id);
|
||||
@ -139,7 +152,6 @@ export function horizontalMenu(tabs: HTMLUListElement, content: HTMLDivElement,
|
||||
if(onTransitionEnd) onTransitionEnd();
|
||||
}, 200);
|
||||
|
||||
if(onClick) onClick(id, tabContent);
|
||||
prevTabContent = tabContent;
|
||||
});
|
||||
}
|
||||
|
@ -32,12 +32,13 @@ export default class Scrollable {
|
||||
|
||||
public type: string;
|
||||
public side: string;
|
||||
public translate: string;
|
||||
public scrollType: string;
|
||||
public scrollSide: string;
|
||||
public clientAxis: string;
|
||||
|
||||
public scrollSize = -1;
|
||||
public size = 0;
|
||||
public scrollSize = -1; // it will be scrollHeight
|
||||
public size = 0; // it will be outerHeight of container (not scrollHeight)
|
||||
public thumbSize = 0;
|
||||
|
||||
public hiddenElements: {
|
||||
@ -57,11 +58,12 @@ export default class Scrollable {
|
||||
public onAddedBottom: () => void = null;
|
||||
public onScrolledTop: () => void = null;
|
||||
public onScrolledBottom: () => void = null;
|
||||
public onScrolledTopFired = false;
|
||||
public onScrolledBottomFired = false;
|
||||
|
||||
public topObserver: IntersectionObserver;
|
||||
public bottomObserver: IntersectionObserver;
|
||||
|
||||
public splitObserver: IntersectionObserver;
|
||||
public splitMeasureTop: Promise<{element: Element, height: number}[]> = null;
|
||||
public splitMeasureBottom: Scrollable['splitMeasureTop'] = null;
|
||||
public splitMeasureAdd: Promise<number> = null;
|
||||
@ -86,37 +88,17 @@ export default class Scrollable {
|
||||
private log: ReturnType<typeof logger>;
|
||||
private debug = false;
|
||||
|
||||
constructor(public el: HTMLDivElement, x = false, y = true, public splitOffset = 300, logPrefix = '') {
|
||||
constructor(public el: HTMLDivElement, x = false, y = true, public splitOffset = 300, logPrefix = '', public appendTo = el, public onScrollOffset = splitOffset) {
|
||||
this.container = document.createElement('div');
|
||||
this.container.classList.add('scrollable');
|
||||
|
||||
this.log = logger('SCROLL' + (logPrefix ? '-' + logPrefix : ''));
|
||||
|
||||
let arr = [];
|
||||
for(let i = 0.001; i < 1; i += 0.001) arr.push(i);
|
||||
this.topObserver = new IntersectionObserver(entries => {
|
||||
let entry = entries[entries.length - 1];
|
||||
|
||||
//console.log('top intersection:', entries, entry.isIntersecting, entry.intersectionRatio > 0);
|
||||
if(entry.isIntersecting) {
|
||||
if(this.onScrolledTop) this.onScrolledTop();
|
||||
}
|
||||
// console.log('top intersection end');
|
||||
}, {root: this.el});
|
||||
|
||||
this.bottomObserver = new IntersectionObserver(entries => {
|
||||
let entry = entries[entries.length - 1];
|
||||
|
||||
//console.log('bottom intersection:', entries, entry, entry.isIntersecting, entry.intersectionRatio > 0);
|
||||
if(entry.isIntersecting) {
|
||||
if(this.onScrolledBottom) this.onScrolledBottom();
|
||||
}
|
||||
}, {root: this.el});
|
||||
|
||||
if(x) {
|
||||
this.container.classList.add('scrollable-x');
|
||||
this.type = 'width';
|
||||
this.side = 'left';
|
||||
this.translate = 'translateX';
|
||||
this.scrollType = 'scrollWidth';
|
||||
this.scrollSide = 'scrollLeft';
|
||||
this.clientAxis = 'clientX';
|
||||
@ -141,6 +123,7 @@ export default class Scrollable {
|
||||
this.container.classList.add('scrollable-y');
|
||||
this.type = 'height';
|
||||
this.side = 'top';
|
||||
this.translate = 'translateY';
|
||||
this.scrollType = 'scrollHeight';
|
||||
this.scrollSide = 'scrollTop';
|
||||
this.clientAxis = 'clientY';
|
||||
@ -181,16 +164,14 @@ export default class Scrollable {
|
||||
window.addEventListener('resize', () => {
|
||||
//this.resize.bind(this);
|
||||
this.onScroll();
|
||||
this.resize();
|
||||
});
|
||||
|
||||
this.paddingTopDiv = document.createElement('div');
|
||||
this.paddingTopDiv.classList.add('scroll-padding');
|
||||
this.paddingBottomDiv = document.createElement('div');
|
||||
this.paddingBottomDiv.classList.add('scroll-padding');
|
||||
|
||||
this.topObserver.observe(this.paddingTopDiv);
|
||||
this.bottomObserver.observe(this.paddingBottomDiv);
|
||||
|
||||
|
||||
this.container.addEventListener('scroll', this.onScroll.bind(this));
|
||||
|
||||
Array.from(el.children).forEach(c => this.container.append(c));
|
||||
@ -280,181 +261,9 @@ export default class Scrollable {
|
||||
});
|
||||
}
|
||||
|
||||
public detachByPrevScroll(child: Element, prevScrollTop: number, needHeight = 0) {
|
||||
if(this.splitMeasureBottom) fastdom.clear(this.splitMeasureBottom);
|
||||
if(this.splitMutateBottom) fastdom.clear(this.splitMutateBottom);
|
||||
|
||||
let attachToTop = this.paddings.up < prevScrollTop;
|
||||
|
||||
this.splitMeasureBottom = fastdom.measure(() => {
|
||||
let sliced: {element: Element, height: number}[] = [];
|
||||
|
||||
do {
|
||||
if(needHeight > 0) {
|
||||
needHeight -= child.scrollHeight;
|
||||
} else {
|
||||
sliced.push({element: child, height: child.scrollHeight});
|
||||
}
|
||||
} while(child = child.nextElementSibling);
|
||||
return sliced;
|
||||
});
|
||||
|
||||
return this.splitMeasureBottom.then(sliced => {
|
||||
if(this.splitMutateBottom) fastdom.clear(this.splitMutateBottom);
|
||||
|
||||
return this.splitMutateBottom = fastdom.mutate(() => {
|
||||
sliced.forEachReverse((child) => {
|
||||
let {element, height} = child;
|
||||
if(!this.splitUp.contains(element)) return;
|
||||
|
||||
this.paddings.down += height;
|
||||
this.hiddenElements.down.unshift(child);
|
||||
this.splitUp.removeChild(element);
|
||||
//element.parentElement.removeChild(element);
|
||||
});
|
||||
|
||||
this.log('sliced down', sliced);
|
||||
this.paddingBottomDiv.style.height = this.paddings.down + 'px';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public splitObserve(entries: IntersectionObserverEntry[]) {
|
||||
let sorted: {
|
||||
intersecting: {
|
||||
top?: IntersectionObserverEntry,
|
||||
bottom?: IntersectionObserverEntry
|
||||
},
|
||||
notIntersecting: {
|
||||
top?: IntersectionObserverEntry,
|
||||
bottom?: IntersectionObserverEntry
|
||||
}
|
||||
} = {
|
||||
intersecting: {},
|
||||
notIntersecting: {}
|
||||
};
|
||||
|
||||
for(let entry of entries) { // there may be duplicates (1st - not intersecting, 2nd - intersecting)
|
||||
//console.log('onscroll entry 1', entry.target, entry.isIntersecting, entry);
|
||||
if(!entry.target.parentElement || !entry.rootBounds) continue;
|
||||
|
||||
if(!entry.isIntersecting) {
|
||||
let isTop = entry.boundingClientRect.top <= 0;
|
||||
let isBottom = entry.rootBounds.height <= entry.boundingClientRect.top;
|
||||
//console.log('onscroll entry notIntersecting', isTop, isBottom, entry.target, entry);
|
||||
|
||||
if(isTop) {
|
||||
sorted.notIntersecting.top = entry;
|
||||
} else if(isBottom && !sorted.notIntersecting.bottom) {
|
||||
sorted.notIntersecting.bottom = entry;
|
||||
}
|
||||
|
||||
//console.log('splitObserver', entry, entry.target, isTop);
|
||||
} else {
|
||||
let isTop = entry.boundingClientRect.top <= entry.rootBounds.top;
|
||||
let isBottom = entry.boundingClientRect.bottom >= entry.rootBounds.bottom;
|
||||
|
||||
if(isTop) {
|
||||
sorted.intersecting.top = entry;
|
||||
} else if(isBottom && !sorted.intersecting.bottom) {
|
||||
sorted.intersecting.bottom = entry;
|
||||
}
|
||||
|
||||
// if(isTop) {
|
||||
// this.onTopIntersection(entry.boundingClientRect.height);
|
||||
// } else if(isBottom) {
|
||||
// this.onTopIntersection(entry.boundingClientRect.height);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
console.log('splitObserve', entries, sorted);
|
||||
|
||||
let needHeight = this.splitOffset;
|
||||
let isOutOfView: boolean;
|
||||
let entry: IntersectionObserverEntry;
|
||||
if(entry = sorted.notIntersecting.top) { // scrolled bottom
|
||||
let child = entry.target;
|
||||
|
||||
let diff = entry.boundingClientRect.bottom + needHeight;
|
||||
if(diff < 0) { // maybe need <=, means out of view
|
||||
if(!(child = child.nextElementSibling)) {
|
||||
this.detachTop(this.splitUp.lastElementChild, 0);
|
||||
} else {
|
||||
if(this.splitMeasureRemoveBad) fastdom.clear(this.splitMeasureRemoveBad);
|
||||
this.splitMeasureRemoveBad = fastdom.measure(() => {
|
||||
do {
|
||||
diff += child.scrollHeight;
|
||||
} while(diff < 0 && (child = child.nextElementSibling));
|
||||
|
||||
return child || this.splitUp.lastElementChild;
|
||||
});
|
||||
|
||||
this.splitMeasureRemoveBad.then(child => {
|
||||
this.detachTop(child, 0);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.detachTop(child, needHeight);
|
||||
}
|
||||
}
|
||||
|
||||
if(entry = sorted.notIntersecting.bottom) { // scrolled top
|
||||
isOutOfView = (entry.boundingClientRect.top - needHeight) >= entry.rootBounds.height;
|
||||
this.detachBottom(entry.target, isOutOfView ? 0 : needHeight);
|
||||
}
|
||||
|
||||
if(entry = sorted.intersecting.top) { // scrolling top
|
||||
let needHeight = this.splitOffset;
|
||||
|
||||
let child = entry.target;
|
||||
if(this.splitMeasureAdd) fastdom.clear(this.splitMeasureAdd);
|
||||
this.splitMeasureAdd = fastdom.measure(() => {
|
||||
while(child = child.previousElementSibling) {
|
||||
needHeight -= child.scrollHeight;
|
||||
}
|
||||
|
||||
return needHeight;
|
||||
});
|
||||
|
||||
this.splitMeasureAdd.then(needHeight => {
|
||||
this.onTopIntersection(needHeight);
|
||||
});
|
||||
}
|
||||
|
||||
if(entry = sorted.intersecting.bottom) { // scrolling bottom
|
||||
let needHeight = this.splitOffset;
|
||||
|
||||
let child = entry.target;
|
||||
if(this.splitMeasureAdd) fastdom.clear(this.splitMeasureAdd);
|
||||
this.splitMeasureAdd = fastdom.measure(() => {
|
||||
while(child = child.nextElementSibling) {
|
||||
needHeight -= child.scrollHeight;
|
||||
}
|
||||
|
||||
return needHeight;
|
||||
});
|
||||
|
||||
this.splitMeasureAdd.then(needHeight => {
|
||||
this.onBottomIntersection(needHeight);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async resize() {
|
||||
public resize() {
|
||||
//console.time('scroll resize');
|
||||
|
||||
await fastdom.measure(() => {
|
||||
// @ts-ignore
|
||||
this.scrollSize = this.container[this.scrollType];
|
||||
|
||||
let rect = this.container.getBoundingClientRect();
|
||||
|
||||
// @ts-ignore
|
||||
this.size = rect[this.type];
|
||||
});
|
||||
|
||||
await fastdom.mutate(() => {
|
||||
fastdom.mutate(() => {
|
||||
if(!this.size || this.size == this.scrollSize) {
|
||||
this.thumbSize = 0;
|
||||
|
||||
@ -480,7 +289,7 @@ export default class Scrollable {
|
||||
//console.log('onresize', thumb.style[type], thumbHeight, height);
|
||||
}
|
||||
|
||||
public async setVirtualContainer(el?: HTMLElement) {
|
||||
public setVirtualContainer(el?: HTMLElement) {
|
||||
this.splitUp = el;
|
||||
|
||||
this.hiddenElements.up.length = this.hiddenElements.down.length = 0;
|
||||
@ -494,12 +303,6 @@ export default class Scrollable {
|
||||
});
|
||||
}
|
||||
|
||||
/* if(this.splitObserver) {
|
||||
this.splitObserver.disconnect();
|
||||
}
|
||||
|
||||
this.splitObserver = new IntersectionObserver((entries) => this.splitObserve(entries), {root: this.el}); */
|
||||
|
||||
this.log('setVirtualContainer:', el, this);
|
||||
|
||||
this.getScrollTopOffset();
|
||||
@ -509,6 +312,9 @@ export default class Scrollable {
|
||||
el.parentElement.insertBefore(this.paddingTopDiv, el);
|
||||
el.parentNode.insertBefore(this.paddingBottomDiv, el.nextSibling);
|
||||
});
|
||||
} else {
|
||||
this.paddingTopDiv.remove();
|
||||
this.paddingBottomDiv.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,33 +335,66 @@ export default class Scrollable {
|
||||
public onScroll() {
|
||||
if(this.onScrollMeasure) fastdom.clear(this.onScrollMeasure);
|
||||
this.onScrollMeasure = fastdom.measure(() => {
|
||||
// @ts-ignore quick brown fix
|
||||
this.size = this.parentElement[this.scrollType];
|
||||
|
||||
// @ts-ignore
|
||||
if(this.container[this.scrollType] != this.scrollSize || this.thumbSize == 0) {
|
||||
let scrollSize = this.container[this.scrollType];
|
||||
if(scrollSize != this.scrollSize || this.thumbSize == 0) {
|
||||
this.resize();
|
||||
}
|
||||
|
||||
this.scrollSize = scrollSize;
|
||||
|
||||
// @ts-ignore
|
||||
let value = this.container[this.scrollSide] / (this.scrollSize - this.size) * 100;
|
||||
let maxValue = 100 - (this.thumbSize / this.size * 100);
|
||||
let scrollPos = this.container[this.scrollSide];
|
||||
|
||||
// let value = scrollPos / (this.scrollSize - this.size) * 100;
|
||||
// let maxValue = 100 - (this.thumbSize / this.size * 100);
|
||||
let value = scrollPos / (this.scrollSize - this.size) * this.size;
|
||||
let maxValue = this.size - this.thumbSize;
|
||||
|
||||
//this.log(scrollPos, this.scrollSize, this.size, value, scrollPos / (this.scrollSize - this.size) * this.size);
|
||||
let ret = {value, maxValue};
|
||||
|
||||
let scrollTop = scrollPos - this.scrollTopOffset;
|
||||
let maxScrollTop = this.scrollSize - this.scrollTopOffset - this.size;
|
||||
|
||||
if(this.onScrolledBottom) {
|
||||
if(!this.hiddenElements.down.length && (maxScrollTop - scrollTop) <= this.onScrollOffset) {
|
||||
if(!this.onScrolledBottomFired) {
|
||||
this.onScrolledBottomFired = true;
|
||||
this.onScrolledBottom();
|
||||
}
|
||||
} else {
|
||||
this.onScrolledBottomFired = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.onScrolledTop) {
|
||||
//this.log('onScrolledTop:', scrollTop, this.onScrollOffset);
|
||||
if(!this.hiddenElements.up.length && scrollTop <= this.onScrollOffset) {
|
||||
if(!this.onScrolledTopFired) {
|
||||
this.onScrolledTopFired = true;
|
||||
this.onScrolledTop();
|
||||
}
|
||||
} else {
|
||||
this.onScrolledTopFired = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!this.splitUp) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
let perf = performance.now();
|
||||
let scrollTop = this.scrollTop - this.scrollTopOffset;
|
||||
let outerHeight = this.parentElement.scrollHeight;
|
||||
|
||||
let maxScrollTop = this.scrollHeight - this.scrollTopOffset - outerHeight;
|
||||
if(scrollTop < 0) scrollTop = 0;
|
||||
else if(scrollTop > maxScrollTop) scrollTop = maxScrollTop;
|
||||
|
||||
let toBottom = scrollTop > this.lastScrollTop;
|
||||
|
||||
let visibleFrom = /* scrollTop < this.paddings.up ? scrollTop : */scrollTop - this.paddings.up;
|
||||
let visibleUntil = visibleFrom + outerHeight;
|
||||
let visibleUntil = visibleFrom + this.size;
|
||||
let sum = 0;
|
||||
|
||||
let firstVisibleElement: Element;
|
||||
@ -619,10 +458,6 @@ export default class Scrollable {
|
||||
this.onBottomIntersection(needHeight);
|
||||
return needHeight;
|
||||
});
|
||||
|
||||
/* this.splitMeasureAdd.then(needHeight => {
|
||||
this.onBottomIntersection(needHeight);
|
||||
}); */
|
||||
} else if(length) { // scrolled manually or safari
|
||||
if(this.debug) {
|
||||
this.log.warn('will detach all of top', length, this.splitUp.childElementCount, maxScrollTop, this.paddings, this.lastScrollTop);
|
||||
@ -652,10 +487,6 @@ export default class Scrollable {
|
||||
this.onTopIntersection(needHeight);
|
||||
return needHeight;
|
||||
});
|
||||
|
||||
/* this.splitMeasureAdd.then(needHeight => {
|
||||
this.onTopIntersection(needHeight);
|
||||
}); */
|
||||
} else if(length) { // scrolled manually or safari
|
||||
if(this.debug) {
|
||||
this.log.warn('will detach all of bottom', length, this.splitUp.childElementCount, maxScrollTop, this.paddings, this.lastScrollTop);
|
||||
@ -681,7 +512,8 @@ export default class Scrollable {
|
||||
this.onScrollMeasure.then(({value, maxValue}) => {
|
||||
fastdom.mutate(() => {
|
||||
// @ts-ignore
|
||||
this.thumb.style[this.side] = (value >= maxValue ? maxValue : value) + '%';
|
||||
//this.thumb.style[this.side] = (value >= maxValue ? maxValue : value) + '%';
|
||||
this.thumb.style.transform = this.translate + '(' + (value >= maxValue ? maxValue : value) + 'px)';
|
||||
});
|
||||
});
|
||||
|
||||
@ -691,7 +523,7 @@ export default class Scrollable {
|
||||
public onManualScrollTop(scrollTop: number, needHeight: number, maxScrollTop: number) {
|
||||
//if(this.splitMutateRemoveBad) fastdom.clear(this.splitMutateRemoveBad);
|
||||
this.splitMutateRemoveBad = fastdom.mutate(() => {
|
||||
let h = maxScrollTop - (scrollTop + outerHeight);
|
||||
let h = maxScrollTop - (scrollTop + this.size);
|
||||
|
||||
while(this.paddings.down < h && this.paddings.up) {
|
||||
let child = this.hiddenElements.up.pop();
|
||||
@ -705,11 +537,8 @@ export default class Scrollable {
|
||||
}
|
||||
|
||||
this.paddingBottomDiv.style.height = this.paddings.down + 'px';
|
||||
this.onTopIntersection((outerHeight * 2) + (needHeight * 2));
|
||||
this.onTopIntersection((this.size * 2) + (needHeight * 2));
|
||||
});
|
||||
|
||||
/* this.splitMutateRemoveBad.then(() => {
|
||||
}); */
|
||||
}
|
||||
|
||||
public onManualScrollBottom(scrollTop: number, needHeight: number) {
|
||||
@ -729,11 +558,8 @@ export default class Scrollable {
|
||||
}
|
||||
|
||||
this.paddingTopDiv.style.height = this.paddings.up + 'px';
|
||||
this.onBottomIntersection(outerHeight + (needHeight * 2));
|
||||
this.onBottomIntersection(this.size + (needHeight * 2));
|
||||
});
|
||||
|
||||
/* this.splitMutateRemoveBad.then(() => {
|
||||
}); */
|
||||
}
|
||||
|
||||
public onTopIntersection(needHeight: number) {
|
||||
@ -813,7 +639,7 @@ export default class Scrollable {
|
||||
});
|
||||
|
||||
if(this.hiddenElements.up.length) {
|
||||
fastdom.mutate(() => {
|
||||
/* fastdom.mutate(() => {
|
||||
this.splitUp.append(...smth);
|
||||
}).then(() => {
|
||||
return fastdom.measure(() => {
|
||||
@ -839,13 +665,26 @@ export default class Scrollable {
|
||||
|
||||
this.onScroll();
|
||||
});
|
||||
}); */
|
||||
this.splitUp.prepend(...smth);
|
||||
smth.forEachReverse(node => {
|
||||
let height = node.scrollHeight;
|
||||
this.log('will append element to up hidden', node, height);
|
||||
this.paddings.up += height;
|
||||
this.hiddenElements.up.unshift({
|
||||
element: node,
|
||||
height: height
|
||||
});
|
||||
node.parentElement.removeChild(node);
|
||||
});
|
||||
this.paddingTopDiv.style.height = this.paddings.up + 'px';
|
||||
this.onScroll();
|
||||
} else {
|
||||
this.splitUp.prepend(...smth);
|
||||
this.onScroll();
|
||||
}
|
||||
} else {
|
||||
this.container.prepend(...smth);
|
||||
this.appendTo.prepend(...smth);
|
||||
this.onScroll();
|
||||
}
|
||||
|
||||
@ -891,7 +730,7 @@ export default class Scrollable {
|
||||
this.onScroll();
|
||||
}
|
||||
} else {
|
||||
this.container.append(...smth);
|
||||
this.appendTo.append(...smth);
|
||||
this.onScroll();
|
||||
}
|
||||
|
||||
@ -914,17 +753,14 @@ export default class Scrollable {
|
||||
}
|
||||
}
|
||||
|
||||
let index = this.hiddenElements.up.findIndex(c => c.element == element);
|
||||
let child: {element: Element, height: number};
|
||||
let child = this.hiddenElements.up.findAndSplice(c => c.element == element);
|
||||
let foundUp = false;
|
||||
if(index !== -1) {
|
||||
child = this.hiddenElements.up.splice(index, 1)[0];
|
||||
if(child) {
|
||||
this.paddings.up -= child.height;
|
||||
foundUp = true;
|
||||
} else {
|
||||
index = this.hiddenElements.down.findIndex(c => c.element == element);
|
||||
if(index !== -1) {
|
||||
child = this.hiddenElements.down.splice(index, 1)[0];
|
||||
child = this.hiddenElements.down.findAndSplice(c => c.element == element);
|
||||
if(child) {
|
||||
this.paddings.down -= child.height;
|
||||
}
|
||||
}
|
||||
@ -943,7 +779,7 @@ export default class Scrollable {
|
||||
}
|
||||
|
||||
public insertBefore(newChild: Element, refChild: Element, height?: number) {
|
||||
this.log('insertBefore', newChild, refChild);
|
||||
//this.log('insertBefore', newChild, refChild);
|
||||
return;
|
||||
|
||||
if(this.splitUp) {
|
||||
@ -1022,6 +858,29 @@ export default class Scrollable {
|
||||
this.onScroll();
|
||||
return ret;
|
||||
}
|
||||
|
||||
public scrollIntoView(element: Element) {
|
||||
if(element.parentElement) {
|
||||
element.scrollIntoView();
|
||||
} else if(this.splitUp) {
|
||||
let index = this.hiddenElements.up.findIndex(e => e.element == element);
|
||||
let y = 0;
|
||||
if(index !== -1) {
|
||||
for(let i = 0; i < index; ++i) {
|
||||
y += this.hiddenElements.up[i].height;
|
||||
}
|
||||
|
||||
this.scrollTop = y;
|
||||
} else if((index = this.hiddenElements.down.findIndex(e => e.element == element)) !== -1) {
|
||||
y += this.paddings.up + this.size;
|
||||
for(let i = 0; i < index; ++i) {
|
||||
y += this.hiddenElements.down[i].height;
|
||||
}
|
||||
|
||||
this.scrollTop = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set scrollTop(y: number) {
|
||||
fastdom.mutate(() => {
|
||||
|
@ -259,15 +259,21 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
|
||||
|
||||
let svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
svg.classList.add('audio-waveform');
|
||||
svg.setAttributeNS(null, 'width', '250');
|
||||
svg.setAttributeNS(null, 'width', '190');
|
||||
svg.setAttributeNS(null, 'height', '23');
|
||||
svg.setAttributeNS(null, 'viewBox', '0 0 250 23');
|
||||
svg.setAttributeNS(null, 'viewBox', '0 0 190 23');
|
||||
|
||||
div.insertBefore(svg, div.lastElementChild);
|
||||
let wave = doc.attributes[0].waveform as Uint8Array;
|
||||
|
||||
let index = 0;
|
||||
let skipped = 0;
|
||||
for(let uint8 of wave) {
|
||||
if (index > 0 && index % 4 == 0) {
|
||||
++index;
|
||||
++skipped;
|
||||
continue;
|
||||
}
|
||||
let percents = uint8 / 255;
|
||||
|
||||
let height = 23 * percents;
|
||||
@ -276,12 +282,14 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
|
||||
}
|
||||
|
||||
svg.insertAdjacentHTML('beforeend', `
|
||||
<rect x="${index * 4}" y="${23 - height}" width="2" height="${height}" rx="1" ry="1"></rect>
|
||||
<rect x="${(index - skipped) * 4}" y="${23 - height}" width="2" height="${height}" rx="1" ry="1"></rect>
|
||||
`);
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
let progress = div.querySelector('.audio-waveform') as HTMLDivElement;
|
||||
|
||||
let onClick = () => {
|
||||
if(!promise) {
|
||||
if(downloadDiv.classList.contains('downloading')) {
|
||||
@ -310,6 +318,7 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
|
||||
let toggle = div.querySelector('.audio-toggle') as HTMLDivElement;
|
||||
|
||||
let interval = 0;
|
||||
let lastIndex = 0;
|
||||
|
||||
toggle.addEventListener('click', () => {
|
||||
if(audio.paused) {
|
||||
@ -327,7 +336,6 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
|
||||
|
||||
(Array.from(svg.children) as HTMLElement[]).forEach(node => node.classList.remove('active'));
|
||||
|
||||
let lastIndex = 0;
|
||||
interval = setInterval(() => {
|
||||
if(lastIndex > svg.childElementCount || isNaN(audio.duration)) {
|
||||
clearInterval(interval);
|
||||
@ -337,10 +345,11 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
|
||||
// @ts-ignore
|
||||
timeDiv.innerText = String(audio.currentTime | 0).toHHMMSS(true);
|
||||
|
||||
lastIndex = Math.round(audio.currentTime / audio.duration * 62);
|
||||
lastIndex = Math.round(audio.currentTime / audio.duration * 47);
|
||||
|
||||
//svg.children[lastIndex].setAttributeNS(null, 'fill', '#000');
|
||||
svg.children[lastIndex].classList.add('active');
|
||||
//svg.children[lastIndex].classList.add('active'); #Иногда пропускает полоски..
|
||||
(Array.from(svg.children) as HTMLElement[]).slice(0,lastIndex+1).forEach(node => node.classList.add('active'));
|
||||
//++lastIndex;
|
||||
//console.log('lastIndex:', lastIndex, audio.currentTime);
|
||||
//}, duration * 1000 / svg.childElementCount | 0/* 63 * duration / 10 */);
|
||||
@ -358,11 +367,51 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement {
|
||||
toggle.classList.add('tgico-largeplay');
|
||||
toggle.classList.remove('tgico-largepause');
|
||||
clearInterval(interval);
|
||||
(Array.from(svg.children) as HTMLElement[]).forEach(node => node.classList.remove('active'));
|
||||
|
||||
// @ts-ignore
|
||||
timeDiv.innerText = String(audio.currentTime | 0).toHHMMSS(true);
|
||||
});
|
||||
|
||||
let mousedown = false, mousemove = false;
|
||||
progress.addEventListener('mouseleave', (e) => {
|
||||
if(mousedown) {
|
||||
audio.play();
|
||||
mousedown = false;
|
||||
}
|
||||
mousemove = false;
|
||||
})
|
||||
progress.addEventListener('mousemove', (e) => {
|
||||
mousemove = true;
|
||||
if(mousedown) scrub(e, audio, progress);
|
||||
});
|
||||
progress.addEventListener('mousedown', (e) => {
|
||||
e.preventDefault();
|
||||
if(!audio.paused) {
|
||||
audio.pause();
|
||||
scrub(e, audio, progress);
|
||||
mousedown = true;
|
||||
}
|
||||
});
|
||||
progress.addEventListener('mouseup', (e) => {
|
||||
if (mousemove && mousedown) {
|
||||
audio.play();
|
||||
mousedown = false;
|
||||
}
|
||||
});
|
||||
progress.addEventListener('click', (e) => {
|
||||
if(!audio.paused) scrub(e, audio, progress);
|
||||
});
|
||||
|
||||
function scrub(e: MouseEvent, audio: HTMLAudioElement, progress: HTMLDivElement) {
|
||||
let scrubTime = e.offsetX / 190 /* width */ * audio.duration;
|
||||
(Array.from(svg.children) as HTMLElement[]).forEach(node => node.classList.remove('active'));
|
||||
lastIndex = Math.round(scrubTime / audio.duration * 47);
|
||||
|
||||
(Array.from(svg.children) as HTMLElement[]).slice(0,lastIndex+1).forEach(node => node.classList.add('active'));
|
||||
audio.currentTime = scrubTime;
|
||||
}
|
||||
|
||||
audio.append(source);
|
||||
audio.style.display = 'none';
|
||||
div.append(audio);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -87,9 +87,7 @@ class AppSidebarLeft {
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.chatsPreloader = document.createElement('div');
|
||||
this.chatsPreloader.classList.add('preloader');
|
||||
putPreloader(this.chatsPreloader);
|
||||
this.chatsPreloader = putPreloader(null, true);
|
||||
//this.chatsContainer.append(this.chatsPreloader);
|
||||
|
||||
//this.chatsLoadCount = Math.round(document.body.scrollHeight / 70 * 1.5);
|
||||
@ -98,7 +96,6 @@ class AppSidebarLeft {
|
||||
this.scroll.setVirtualContainer(appDialogsManager.chatList);
|
||||
this.scroll.onScrolledBottom = this.onChatsScroll.bind(this);
|
||||
appDialogsManager.chatsHidden = this.scroll.hiddenElements;
|
||||
//this.scroll.container.addEventListener('scroll', this.onChatsScroll.bind(this));
|
||||
|
||||
this.scrollArchived = new Scrollable(this.chatsArchivedContainer as HTMLDivElement, false, true, 300, 'CLA');
|
||||
this.scrollArchived.setVirtualContainer(appDialogsManager.chatListArchived);
|
||||
@ -134,7 +131,7 @@ class AppSidebarLeft {
|
||||
for(let i = 0; i < 1000; ++i) {
|
||||
let li = document.createElement('li');
|
||||
li.dataset.id = '' + i;
|
||||
li.innerHTML = `<div class="rp"><div class="user-avatar" style="background-color: rgb(166, 149, 231); font-size: 0px;"><img src="blob:https://localhost:9000/ce99a2a3-f34b-4ca1-a09e-f716f89930d8"></div><div class="user-caption"><p><span class="user-title">${i}</span><span><span class="message-status"></span><span class="message-time">18:33</span></span></p><p><span class="user-last-message"><b>Ильяс: </b>Гагагагга</span><span></span></p></div></div>`;
|
||||
li.innerHTML = `<div class="rp"><div class="user-avatar" style="background-color: rgb(166, 149, 231); font-size: 0px;"><img src="#"></div><div class="user-caption"><p><span class="user-title">${i}</span><span><span class="message-status"></span><span class="message-time">18:33</span></span></p><p><span class="user-last-message"><b>-_-_-_-: </b>qweasd</span><span></span></p></div></div>`;
|
||||
this.scroll.append(li);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { horizontalMenu, formatPhoneNumber } from "../../components/misc";
|
||||
import { horizontalMenu, formatPhoneNumber, putPreloader } from "../../components/misc";
|
||||
import Scrollable from '../../components/scrollable';
|
||||
import { isElementInViewport, $rootScope } from "../utils";
|
||||
import { $rootScope } from "../utils";
|
||||
import appMessagesManager from "./appMessagesManager";
|
||||
import appPhotosManager from "./appPhotosManager";
|
||||
import appPeersManager from "./appPeersManager";
|
||||
@ -38,13 +38,13 @@ class AppSidebarRight {
|
||||
contentLinks: this.profileContentEl.querySelector('#content-links') as HTMLDivElement,
|
||||
contentAudio: this.profileContentEl.querySelector('#content-audio') as HTMLDivElement,
|
||||
};
|
||||
|
||||
|
||||
public lastSharedMediaDiv: HTMLDivElement = null;
|
||||
|
||||
|
||||
private loadSidebarMediaPromises: {
|
||||
[type: string]: Promise<void>
|
||||
} = {};
|
||||
|
||||
|
||||
public sharedMediaTypes = [
|
||||
'inputMessagesFilterContacts',
|
||||
'inputMessagesFilterPhotoVideo',
|
||||
@ -54,7 +54,7 @@ class AppSidebarRight {
|
||||
];
|
||||
public sharedMediaType: string = '';
|
||||
private sharedMediaSelected: HTMLDivElement = null;
|
||||
|
||||
|
||||
private lazyLoadQueueSidebar = new LazyLoadQueue(5);
|
||||
/* public minMediaID: {
|
||||
[type: string]: number
|
||||
@ -62,17 +62,17 @@ class AppSidebarRight {
|
||||
public cleared: {
|
||||
[type: string]: boolean
|
||||
} = {};
|
||||
|
||||
|
||||
public historiesStorage: {
|
||||
[peerID: number]: {
|
||||
[type: string]: number[]
|
||||
}
|
||||
} = {};
|
||||
|
||||
|
||||
private log = logger('SR');
|
||||
|
||||
|
||||
private peerID = 0;
|
||||
|
||||
|
||||
public sidebarScroll: Scrollable = null;
|
||||
private savedVirtualStates: {
|
||||
[id: number]: {
|
||||
@ -80,25 +80,37 @@ class AppSidebarRight {
|
||||
paddings: any
|
||||
}
|
||||
} = {};
|
||||
|
||||
|
||||
private profileTabs: HTMLUListElement;
|
||||
private prevTabID = -1;
|
||||
|
||||
|
||||
private mediaDivsByIDs: {
|
||||
[mid: number]: HTMLDivElement
|
||||
} = {};
|
||||
|
||||
|
||||
constructor() {
|
||||
let container = this.profileContentEl.querySelector('.profile-tabs-content') as HTMLDivElement;
|
||||
this.profileTabs = this.profileContentEl.querySelector('.profile-tabs') as HTMLUListElement;
|
||||
|
||||
|
||||
this.sidebarScroll = new Scrollable(this.sidebarEl, false, true, 500, 'SR');
|
||||
this.sidebarScroll.container.addEventListener('scroll', this.onSidebarScroll.bind(this));
|
||||
|
||||
this.sidebarScroll.onScrolledBottom = () => {
|
||||
if(this.sharedMediaSelected && !this.sidebarScroll.hiddenElements.down.length
|
||||
&& this.sharedMediaSelected.childElementCount/* && false */) {
|
||||
this.loadSidebarMedia(true);
|
||||
}
|
||||
};
|
||||
|
||||
horizontalMenu(this.profileTabs, container, (id, tabContent) => {
|
||||
if(this.prevTabID == id) return;
|
||||
|
||||
this.sharedMediaType = this.sharedMediaTypes[id];
|
||||
this.sharedMediaSelected = tabContent.firstElementChild as HTMLDivElement;
|
||||
|
||||
if(this.prevTabID != -1 && !this.sharedMediaSelected.childElementCount) { // quick brown fix
|
||||
this.loadSidebarMedia(true);
|
||||
}
|
||||
|
||||
if(this.prevTabID != -1) {
|
||||
this.savedVirtualStates[this.prevTabID] = {
|
||||
hiddenElements: {
|
||||
@ -111,254 +123,248 @@ class AppSidebarRight {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
this.prevTabID = id;
|
||||
|
||||
//this.log('setVirtualContainer', id, this.sharedMediaSelected);
|
||||
|
||||
this.log('setVirtualContainer', id, this.sharedMediaSelected);
|
||||
this.sidebarScroll.setVirtualContainer(this.sharedMediaSelected);
|
||||
|
||||
|
||||
if(this.savedVirtualStates[id]) {
|
||||
this.log(this.savedVirtualStates[id]);
|
||||
this.sidebarScroll.hiddenElements = this.savedVirtualStates[id].hiddenElements;
|
||||
this.sidebarScroll.paddings = this.savedVirtualStates[id].paddings;
|
||||
}
|
||||
}, this.onSidebarScroll.bind(this));
|
||||
|
||||
//(this.profileTabs.children[1] as HTMLLIElement).click(); // set media
|
||||
|
||||
|
||||
let sidebarCloseBtn = this.sidebarEl.querySelector('.sidebar-close-button') as HTMLButtonElement;
|
||||
sidebarCloseBtn.addEventListener('click', () => {
|
||||
this.toggleSidebar(false);
|
||||
});
|
||||
|
||||
|
||||
this.sharedMedia.contentMedia.addEventListener('click', (e) => {
|
||||
let target = e.target as HTMLDivElement;
|
||||
|
||||
|
||||
let messageID = +target.getAttribute('message-id');
|
||||
if(!messageID) {
|
||||
this.log.warn('no messageID by click on target:', target);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let message = appMessagesManager.getMessage(messageID);
|
||||
|
||||
|
||||
let ids = Object.keys(this.mediaDivsByIDs).map(k => +k).sort();
|
||||
let idx = ids.findIndex(i => i == messageID);
|
||||
|
||||
|
||||
let prev = ids[idx + 1] || null;
|
||||
let next = ids[idx - 1] || null;
|
||||
|
||||
|
||||
appMediaViewer.openMedia(message, target, this.mediaDivsByIDs[prev] || null, this.mediaDivsByIDs[next] || null);
|
||||
});
|
||||
|
||||
|
||||
this.profileElements.notificationsCheckbox.addEventListener('change', () => {
|
||||
let checked = this.profileElements.notificationsCheckbox.checked;
|
||||
//let checked = this.profileElements.notificationsCheckbox.checked;
|
||||
appImManager.mutePeer();
|
||||
});
|
||||
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
setTimeout(() => {
|
||||
this.sidebarScroll.onScroll();
|
||||
this.onSidebarScroll();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
|
||||
if(testScroll) {
|
||||
let div = document.createElement('div');
|
||||
for(let i = 0; i < 500; ++i) {
|
||||
//div.insertAdjacentHTML('beforeend', `<div message-id="0" style="background-image: url(assets/img/camomile.jpg);"></div>`);
|
||||
div.insertAdjacentHTML('beforeend', `<div data-id="${i / 3 | 0}">${i / 3 | 0}</div>`);
|
||||
|
||||
|
||||
if((i + 1) % 3 == 0) {
|
||||
this.sharedMedia.contentMedia.append(div);
|
||||
div = document.createElement('div');
|
||||
}
|
||||
|
||||
|
||||
div.dataset.id = '' + (i / 3 | 0);
|
||||
}
|
||||
this.sharedMedia.contentMedia.append(div);
|
||||
(this.profileTabs.children[1] as HTMLLIElement).click(); // set media
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public onSidebarScroll() {
|
||||
this.lazyLoadQueueSidebar.check();
|
||||
|
||||
if(this.sharedMediaSelected && !this.sidebarScroll.hiddenElements.down.length/* && false */) {
|
||||
let media = Array.from(this.sharedMediaSelected.childNodes).slice(-15);
|
||||
for(let div of media) {
|
||||
if(isElementInViewport(div)) {
|
||||
//this.log('Will load more media');
|
||||
this.loadSidebarMedia(true);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public toggleSidebar(enable?: boolean) {
|
||||
/////this.log('sidebarEl', this.sidebarEl, enable, isElementInViewport(this.sidebarEl));
|
||||
|
||||
/* if(enable !== undefined) {
|
||||
this.sidebarEl.style.display = enable ? 'block' : 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
this.sidebarEl.style.display = isElementInViewport(this.sidebarEl) ? 'none' : 'block'; */
|
||||
|
||||
if(enable !== undefined) {
|
||||
this.sidebarEl.style.width = enable ? '25%' : '0%';
|
||||
if(enable) this.sidebarEl.classList.add('active');
|
||||
else this.sidebarEl.classList.remove('active');
|
||||
return;
|
||||
}
|
||||
|
||||
this.sidebarEl.style.width = isElementInViewport(this.sidebarEl) ? '0%' : '25%';
|
||||
|
||||
if(this.sidebarEl.classList.contains('active')) {
|
||||
this.sidebarEl.classList.remove('active');
|
||||
} else {
|
||||
this.sidebarEl.classList.add('active');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public loadSidebarMedia(single = false) {
|
||||
if(testScroll) {
|
||||
if(testScroll /* || 1 == 1 */) {
|
||||
return;
|
||||
}
|
||||
|
||||
//this.log('loadSidebarMedia', single, this.peerID);
|
||||
|
||||
let peerID = this.peerID;
|
||||
|
||||
let typesToLoad = single ? [this.sharedMediaType] : this.sharedMediaTypes;
|
||||
|
||||
|
||||
if(!this.historiesStorage[peerID]) this.historiesStorage[peerID] = {};
|
||||
let historyStorage = this.historiesStorage[peerID];
|
||||
|
||||
|
||||
let promises = typesToLoad.map(type => {
|
||||
if(this.loadSidebarMediaPromises[type]) return this.loadSidebarMediaPromises[type];
|
||||
|
||||
|
||||
if(!historyStorage[type]) historyStorage[type] = [];
|
||||
let history = historyStorage[type];
|
||||
|
||||
|
||||
// заливать новую картинку сюда только после полной отправки!
|
||||
//let maxID = this.minMediaID[type] || 0;
|
||||
let maxID = history[history.length - 1] || 0;
|
||||
|
||||
|
||||
let ids = !maxID && appMessagesManager.historiesStorage[peerID]
|
||||
? appMessagesManager.historiesStorage[peerID].history.slice() : [];
|
||||
|
||||
? appMessagesManager.historiesStorage[peerID].history.slice() : [];
|
||||
|
||||
maxID = !maxID && ids.length ? ids[ids.length - 1] : maxID;
|
||||
//this.log('search house of glass pre', type, ids, maxID);
|
||||
|
||||
return this.loadSidebarMediaPromises[type] = appMessagesManager.getSearch(peerID, '', {_: type}, maxID, 50)
|
||||
|
||||
return this.loadSidebarMediaPromises[type] = appMessagesManager.getSearch(peerID, '', {_: type}, maxID, history.length ? 50 : 15)
|
||||
.then(value => {
|
||||
ids = ids.concat(value.history);
|
||||
history.push(...ids);
|
||||
|
||||
|
||||
//this.log('search house of glass', type, value, ids, this.cleared);
|
||||
|
||||
|
||||
if($rootScope.selectedPeerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(this.cleared[type]) {
|
||||
ids = history;
|
||||
delete this.cleared[type];
|
||||
}
|
||||
|
||||
ids.forEach(mid => {
|
||||
//this.minMediaID[type] = mid;
|
||||
|
||||
let sharedMediaDiv: HTMLDivElement;
|
||||
let messages: any[] = [];
|
||||
for(let mid of ids) {
|
||||
let message = appMessagesManager.getMessage(mid);
|
||||
if(!message.media) return;
|
||||
|
||||
/*'inputMessagesFilterContacts',
|
||||
'inputMessagesFilterPhotoVideo',
|
||||
'inputMessagesFilterDocument',
|
||||
'inputMessagesFilterUrl',
|
||||
'inputMessagesFilterVoice'*/
|
||||
switch(type) {
|
||||
case 'inputMessagesFilterPhotoVideo': {
|
||||
/* if(!(message.media.photo || message.media.document || message.media.webpage.document)) {
|
||||
this.log.error('no media!', message);
|
||||
break;
|
||||
} */
|
||||
if(message.media) messages.push(message);
|
||||
}
|
||||
|
||||
/*'inputMessagesFilterContacts',
|
||||
'inputMessagesFilterPhotoVideo',
|
||||
'inputMessagesFilterDocument',
|
||||
'inputMessagesFilterUrl',
|
||||
'inputMessagesFilterVoice'*/
|
||||
switch(type) {
|
||||
case 'inputMessagesFilterPhotoVideo': {
|
||||
sharedMediaDiv = this.sharedMedia.contentMedia;
|
||||
|
||||
for(let message of messages) {
|
||||
let media = message.media.photo || message.media.document || (message.media.webpage && message.media.webpage.document);
|
||||
|
||||
if(!media) {
|
||||
//this.log('no media!', message);
|
||||
break;
|
||||
continue;;
|
||||
}
|
||||
|
||||
|
||||
if(media._ == 'document' && media.type != 'video'/* && media.type != 'gif' */) {
|
||||
//this.log('broken video', media);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
let div = document.createElement('div');
|
||||
//console.log(message, photo);
|
||||
|
||||
|
||||
let sizes = media.sizes || media.thumbs;
|
||||
if(sizes && sizes[0].bytes) {
|
||||
appPhotosManager.setAttachmentPreview(sizes[0].bytes, div, false, true);
|
||||
} /* else {
|
||||
this.log('no stripped size', message, media);
|
||||
} */
|
||||
|
||||
|
||||
//this.log('inputMessagesFilterPhotoVideo', message, media);
|
||||
|
||||
|
||||
let load = () => appPhotosManager.preloadPhoto(media, appPhotosManager.choosePhotoSize(media, 380, 0))
|
||||
.then((blob) => {
|
||||
if($rootScope.selectedPeerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
div.style.backgroundImage = 'url(' + URL.createObjectURL(blob) + ')';
|
||||
});
|
||||
|
||||
div.setAttribute('message-id', '' + mid);
|
||||
|
||||
|
||||
div.setAttribute('message-id', '' + message.mid);
|
||||
|
||||
this.lazyLoadQueueSidebar.push({div, load});
|
||||
|
||||
|
||||
this.lastSharedMediaDiv.append(div);
|
||||
if(this.lastSharedMediaDiv.childElementCount == 3) {
|
||||
this.sharedMedia.contentMedia.append(this.lastSharedMediaDiv);
|
||||
this.sidebarScroll.append(this.lastSharedMediaDiv);
|
||||
this.lastSharedMediaDiv = document.createElement('div');
|
||||
}
|
||||
|
||||
this.mediaDivsByIDs[mid] = div;
|
||||
|
||||
//this.sharedMedia.contentMedia.append(div);
|
||||
|
||||
break;
|
||||
|
||||
this.mediaDivsByIDs[message.mid] = div;
|
||||
|
||||
//sharedMediaDiv.append(div);
|
||||
}
|
||||
|
||||
case 'inputMessagesFilterDocument': {
|
||||
if(!message.media.document || message.media.document.type == 'voice') {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'inputMessagesFilterDocument': {
|
||||
sharedMediaDiv = this.sharedMedia.contentDocuments;
|
||||
|
||||
for(let message of messages) {
|
||||
if(!message.media.document || message.media.document.type == 'voice') {
|
||||
continue;
|
||||
}
|
||||
|
||||
let doc = message.media.document;
|
||||
if(doc.attributes) {
|
||||
if(doc.attributes.find((a: any) => a._ == "documentAttributeSticker")) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//this.log('come back down to my knees', message);
|
||||
|
||||
|
||||
let div = wrapDocument(message.media.document, true);
|
||||
this.sharedMedia.contentDocuments.append(div);
|
||||
break;
|
||||
this.sidebarScroll.append(div);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'inputMessagesFilterUrl': {
|
||||
sharedMediaDiv = this.sharedMedia.contentLinks;
|
||||
|
||||
case 'inputMessagesFilterUrl': {
|
||||
for(let message of messages) {
|
||||
if(!message.media.webpage || message.media.webpage._ == 'webPageEmpty') {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
let webpage = message.media.webpage;
|
||||
let div = document.createElement('div');
|
||||
|
||||
let previewDiv = document.createElement('div');
|
||||
previewDiv.classList.add('preview');
|
||||
|
||||
|
||||
//this.log('wrapping webpage', webpage);
|
||||
|
||||
|
||||
if(webpage.photo) {
|
||||
let load = () => appPhotosManager.preloadPhoto(webpage.photo.id, appPhotosManager.choosePhotoSize(webpage.photo, 380, 0))
|
||||
.then((blob) => {
|
||||
@ -366,61 +372,69 @@ class AppSidebarRight {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
previewDiv.style.backgroundImage = 'url(' + URL.createObjectURL(blob) + ')';
|
||||
});
|
||||
|
||||
|
||||
this.lazyLoadQueueSidebar.push({div: previewDiv, load});
|
||||
} else {
|
||||
previewDiv.innerText = (webpage.title || webpage.description || webpage.url || webpage.display_url).slice(0, 1);
|
||||
previewDiv.classList.add('empty');
|
||||
}
|
||||
|
||||
|
||||
let title = webpage.rTitle || '';
|
||||
let subtitle = webpage.rDescription || '';
|
||||
let url = RichTextProcessor.wrapRichText(webpage.url || '');
|
||||
|
||||
|
||||
if(!title) {
|
||||
//title = new URL(webpage.url).hostname;
|
||||
title = webpage.display_url.split('/', 1)[0];
|
||||
}
|
||||
|
||||
|
||||
div.append(previewDiv);
|
||||
div.insertAdjacentHTML('beforeend', `
|
||||
<div class="title">${title}</div>
|
||||
<div class="subtitle">${subtitle}</div>
|
||||
<div class="url">${url}</div>
|
||||
<div class="title">${title}</div>
|
||||
<div class="subtitle">${subtitle}</div>
|
||||
<div class="url">${url}</div>
|
||||
`);
|
||||
|
||||
|
||||
if(div.innerText.trim().length) {
|
||||
this.sharedMedia.contentLinks.append(div);
|
||||
this.sidebarScroll.append(div);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* case 'inputMessagesFilterVoice': {
|
||||
//this.log('wrapping audio', message.media);
|
||||
if(!message.media || !message.media.document || message.media.document.type != 'voice') {
|
||||
break;
|
||||
}
|
||||
|
||||
/* case 'inputMessagesFilterVoice': {
|
||||
//this.log('wrapping audio', message.media);
|
||||
if(!message.media || !message.media.document || message.media.document.type != 'voice') {
|
||||
break;
|
||||
}
|
||||
|
||||
let doc = message.media.document;
|
||||
|
||||
this.log('wrapping audio', doc);
|
||||
|
||||
let audioDiv = wrapAudio(doc);
|
||||
|
||||
this.sharedMedia.contentAudio.append(audioDiv);
|
||||
|
||||
break;
|
||||
} */
|
||||
|
||||
default:
|
||||
//console.warn('death is my friend', message);
|
||||
break;
|
||||
let doc = message.media.document;
|
||||
|
||||
this.log('wrapping audio', doc);
|
||||
|
||||
let audioDiv = wrapAudio(doc);
|
||||
|
||||
this.sharedMedia.contentAudio.append(audioDiv);
|
||||
|
||||
break;
|
||||
} */
|
||||
|
||||
default:
|
||||
//console.warn('death is my friend', message);
|
||||
break;
|
||||
}
|
||||
|
||||
if(sharedMediaDiv) {
|
||||
let parent = sharedMediaDiv.parentElement;
|
||||
if(parent.lastElementChild.classList.contains('preloader')) {
|
||||
parent.lastElementChild.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.onSidebarScroll();
|
||||
}).then(() => {
|
||||
@ -430,26 +444,17 @@ class AppSidebarRight {
|
||||
this.loadSidebarMediaPromises[type] = null;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
return promises;
|
||||
}
|
||||
|
||||
|
||||
public fillProfileElements() {
|
||||
let peerID = this.peerID = $rootScope.selectedPeerID;
|
||||
this.loadSidebarMediaPromises = {};
|
||||
this.lastSharedMediaDiv = document.createElement('div');
|
||||
|
||||
|
||||
//this.log('fillProfileElements');
|
||||
|
||||
this.savedVirtualStates = {};
|
||||
this.prevTabID = -1;
|
||||
this.sidebarScroll.setVirtualContainer(null);
|
||||
(this.profileTabs.children[1] as HTMLLIElement).click(); // set media
|
||||
|
||||
if(this.sharedMediaSelected) {
|
||||
//this.sidebarScroll.setVirtualContainer(this.sharedMediaSelected);
|
||||
}
|
||||
|
||||
|
||||
this.profileContentEl.parentElement.scrollTop = 0;
|
||||
this.profileElements.bio.style.display = 'none';
|
||||
this.profileElements.phone.style.display = 'none';
|
||||
@ -457,40 +462,48 @@ class AppSidebarRight {
|
||||
this.profileElements.notificationsRow.style.display = '';
|
||||
this.profileElements.notificationsCheckbox.checked = true;
|
||||
this.profileElements.notificationsStatus.innerText = 'Enabled';
|
||||
|
||||
|
||||
this.mediaDivsByIDs = {};
|
||||
|
||||
|
||||
this.lazyLoadQueueSidebar.clear();
|
||||
|
||||
|
||||
Object.keys(this.sharedMedia).forEach(key => {
|
||||
this.sharedMedia[key].innerHTML = '';
|
||||
|
||||
let parent = this.sharedMedia[key].parentElement;
|
||||
if(!parent.querySelector('.preloader')) {
|
||||
putPreloader(parent, true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.sharedMediaTypes.forEach(type => {
|
||||
//this.minMediaID[type] = 0;
|
||||
this.cleared[type] = true;
|
||||
});
|
||||
|
||||
|
||||
this.savedVirtualStates = {};
|
||||
this.prevTabID = -1;
|
||||
this.sidebarScroll.setVirtualContainer(null);
|
||||
(this.profileTabs.children[1] as HTMLLIElement).click(); // set media
|
||||
|
||||
let setText = (text: string, el: HTMLDivElement) => {
|
||||
el.style.display = '';
|
||||
if(el.childElementCount > 1) {
|
||||
el.firstElementChild.remove();
|
||||
}
|
||||
|
||||
|
||||
let p = document.createElement('p');
|
||||
p.innerHTML = text;
|
||||
el.prepend(p);
|
||||
};
|
||||
|
||||
|
||||
// username
|
||||
if(peerID != appImManager.myID) {
|
||||
let username = appPeersManager.getPeerUsername(peerID);
|
||||
if(username) {
|
||||
setText(appPeersManager.getPeerUsername(peerID), this.profileElements.username);
|
||||
}
|
||||
}
|
||||
|
||||
if(peerID != appImManager.myID) {
|
||||
|
||||
let dialog: any = appMessagesManager.getDialogByPeerID(peerID);
|
||||
if(dialog.length) {
|
||||
dialog = dialog[0];
|
||||
@ -498,57 +511,57 @@ class AppSidebarRight {
|
||||
if(dialog.notify_settings && dialog.notify_settings.mute_until) {
|
||||
muted = new Date(dialog.notify_settings.mute_until * 1000) > new Date();
|
||||
}
|
||||
|
||||
|
||||
appImManager.setMutedState(muted);
|
||||
}
|
||||
} else {
|
||||
this.profileElements.notificationsRow.style.display = 'none';
|
||||
}
|
||||
|
||||
|
||||
if(peerID > 0) {
|
||||
let user = appUsersManager.getUser(peerID);
|
||||
if(user.phone && peerID != appImManager.myID) {
|
||||
setText('+' + formatPhoneNumber(user.phone).formatted, this.profileElements.phone);
|
||||
}
|
||||
|
||||
|
||||
appProfileManager.getProfile(peerID, true).then(userFull => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(userFull.rAbout && peerID != appImManager.myID) {
|
||||
setText(userFull.rAbout, this.profileElements.bio);
|
||||
}
|
||||
|
||||
|
||||
//this.log('userFull', userFull);
|
||||
|
||||
|
||||
if(userFull.pinned_msg_id) { // request pinned message
|
||||
appImManager.pinnedMsgID = userFull.pinned_msg_id;
|
||||
appMessagesManager.wrapSingleMessage(userFull.pinned_msg_id);
|
||||
}
|
||||
|
||||
|
||||
this.sidebarScroll.getScrollTopOffset();
|
||||
});
|
||||
} else {
|
||||
let chat = appPeersManager.getPeer(peerID);
|
||||
|
||||
|
||||
appProfileManager.getChatFull(chat.id).then((chatFull: any) => {
|
||||
if(this.peerID != peerID) {
|
||||
this.log.warn('peer changed');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//this.log('chatInfo res 2:', chatFull);
|
||||
|
||||
|
||||
if(chatFull.about) {
|
||||
setText(RichTextProcessor.wrapRichText(chatFull.about), this.profileElements.bio);
|
||||
}
|
||||
|
||||
|
||||
this.sidebarScroll.getScrollTopOffset();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.sidebarScroll.getScrollTopOffset();
|
||||
//this.loadSidebarMedia();
|
||||
}
|
||||
|
@ -3,18 +3,6 @@
|
||||
NodeList.prototype.forEach = Array.prototype.forEach;
|
||||
})();
|
||||
|
||||
String.prototype.toHHMMSS = function(leadZero) {
|
||||
let sec_num = parseInt(this, 10);
|
||||
let hours = Math.floor(sec_num / 3600);
|
||||
let minutes = Math.floor((sec_num - (hours * 3600)) / 60);
|
||||
let seconds = sec_num - (hours * 3600) - (minutes * 60);
|
||||
|
||||
if(hours < 10) hours = "0" + hours;
|
||||
if(minutes < 10) minutes = leadZero ? "0" + minutes : minutes;
|
||||
if(seconds < 10) seconds = "0" + seconds;
|
||||
return minutes + ':' + seconds;
|
||||
}
|
||||
|
||||
function stylePlayer(player, video) {
|
||||
let skin = attachSkin(video.dataset.ckin);
|
||||
player.classList.add(skin);
|
||||
|
@ -33,9 +33,9 @@ class LottieLoader {
|
||||
for(let i = length - 1; i >= 0; --i) {
|
||||
let {animation, container, paused, autoplay, canvas} = animations[i];
|
||||
|
||||
if(canvas && isElementInViewport(container)) {
|
||||
if(canvas) {
|
||||
let c = container.firstElementChild as HTMLCanvasElement;
|
||||
if(!c.height && !c.width) {
|
||||
if(!c.height && !c.width && isElementInViewport(container)) {
|
||||
//console.log('lottie need resize');
|
||||
animation.resize();
|
||||
}
|
||||
|
@ -53,6 +53,23 @@ Array.prototype.forEachReverse = function<T>(callback: (value: T, index?: number
|
||||
}
|
||||
};
|
||||
|
||||
Array.prototype.findAndSplice = function<T>(verify: (value: T, index?: number, array?: Array<T>) => boolean) {
|
||||
let index = this.findIndex(verify);
|
||||
return index !== -1 ? this.splice(index, 1)[0] : undefined;
|
||||
};
|
||||
|
||||
String.prototype.toHHMMSS = function(leadZero = false) {
|
||||
let sec_num = parseInt(this + '', 10);
|
||||
let hours: any = Math.floor(sec_num / 3600);
|
||||
let minutes: any = Math.floor((sec_num - (hours * 3600)) / 60);
|
||||
let seconds: any = sec_num - (hours * 3600) - (minutes * 60);
|
||||
|
||||
if(hours < 10) hours = "0" + hours;
|
||||
if(minutes < 10) minutes = leadZero ? "0" + minutes : minutes;
|
||||
if(seconds < 10) seconds = "0" + seconds;
|
||||
return minutes + ':' + seconds;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Uint8Array {
|
||||
hex: string;
|
||||
@ -62,5 +79,10 @@ declare global {
|
||||
|
||||
interface Array<T> {
|
||||
forEachReverse(callback: (value: T, index?: number, array?: Array<T>) => void): void;
|
||||
findAndSplice(verify: (value: T, index?: number, array?: Array<T>) => boolean): T;
|
||||
}
|
||||
|
||||
interface String {
|
||||
toHHMMSS(leadZero?: boolean): string;
|
||||
}
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ export function getSelectedText() {
|
||||
|
||||
export const $rootScope = {
|
||||
$broadcast: (name/* : string */, detail/*? : any */) => {
|
||||
////console.log(dT(), 'Broadcasting ' + name + ' event, with args:', detail);
|
||||
//console.log(dT(), 'Broadcasting ' + name + ' event, with args:', detail);
|
||||
//console.trace();
|
||||
let myCustomEvent = new CustomEvent(name, {detail});
|
||||
document.dispatchEvent(myCustomEvent);
|
||||
|
@ -370,8 +370,8 @@
|
||||
cursor: pointer;
|
||||
background: none!important;
|
||||
box-shadow: none;
|
||||
max-width: 300px;
|
||||
max-height: 300px;
|
||||
/* max-width: 300px;
|
||||
max-height: 300px; */
|
||||
}
|
||||
|
||||
img {
|
||||
@ -387,6 +387,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.sticker {
|
||||
.bubble__container {
|
||||
max-width: 200px;
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
&.round {
|
||||
.attachment {
|
||||
max-width: 200px;
|
||||
@ -702,11 +709,11 @@
|
||||
/* padding-bottom: 4px; */
|
||||
color: $darkblue;
|
||||
font-size: .9rem;
|
||||
width: max-content;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
//width: max-content;
|
||||
//white-space: nowrap;
|
||||
}
|
||||
|
||||
&:not(.webpage) {
|
||||
@ -732,16 +739,25 @@
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
&:not(.sticker):not(.emoji-big):not(.round):last-child .bubble__container:after {
|
||||
&:not(.sticker):not(.emoji-big):not(.round).is-group-last .bubble__container:after {
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
bottom: 0;
|
||||
width: 11px;
|
||||
height: 20px;
|
||||
background-repeat: no-repeat repeat;
|
||||
content: '';
|
||||
background-size: 11px 20px;
|
||||
background-position-y: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.bubble-audio.is-in .time {
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
.bubble-audio.is-out .time {
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
/* .bubble + .bubble {
|
||||
margin-top: 5px;
|
||||
@ -761,11 +777,11 @@
|
||||
border-radius: 6px 12px 12px 6px;
|
||||
}
|
||||
|
||||
&:first-child .bubble__container {
|
||||
&.is-group-first .bubble__container {
|
||||
border-radius: 12px 12px 12px 6px;
|
||||
}
|
||||
|
||||
&:last-child .bubble__container {
|
||||
&.is-group-last .bubble__container {
|
||||
border-radius: 6px 12px 12px 0px;
|
||||
//border-radius: 12px 12px 12px 0px;
|
||||
|
||||
@ -775,7 +791,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child:last-child .bubble__container {
|
||||
&.is-group-first.is-group-last .bubble__container {
|
||||
border-radius: 12px 12px 12px 0px;
|
||||
}
|
||||
|
||||
@ -835,11 +851,11 @@
|
||||
border-radius: 12px 6px 6px 12px;
|
||||
}
|
||||
|
||||
&:first-child .bubble__container {
|
||||
&.is-group-first .bubble__container {
|
||||
border-radius: 12px 12px 6px 12px;
|
||||
}
|
||||
|
||||
&:last-child .bubble__container {
|
||||
&.is-group-last .bubble__container {
|
||||
border-radius: 12px 6px 0px 12px;
|
||||
|
||||
&:after {
|
||||
@ -848,7 +864,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child:last-child .bubble__container {
|
||||
&.is-group-first.is-group-last .bubble__container {
|
||||
border-radius: 12px 12px 0px 12px;
|
||||
}
|
||||
|
||||
|
286
src/scss/partials/_rightSIdebar.scss
Normal file
286
src/scss/partials/_rightSIdebar.scss
Normal file
@ -0,0 +1,286 @@
|
||||
.profile-container {
|
||||
width: 0%;
|
||||
/* grid-column: 3; */
|
||||
position: relative;
|
||||
transition: .2s ease-in-out;
|
||||
|
||||
> .scrollable {
|
||||
min-width: 25vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@media (min-width: $large-screen) {
|
||||
> .scrollable {
|
||||
min-width: calc(#{$large-screen} / 4 - 1px);
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.active) {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-content {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.profile-name {
|
||||
text-align: center;
|
||||
font-size: 23px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 3px;
|
||||
|
||||
span.emoji {
|
||||
vertical-align: inherit;
|
||||
min-width: min-content;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-subtitle {
|
||||
text-align: center;
|
||||
color: $darkgrey;
|
||||
font-size: 14px;
|
||||
|
||||
&.online {
|
||||
color: $darkblue;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
padding-left: 80px;
|
||||
padding-top: 2px;
|
||||
padding-right: 12px;
|
||||
font-size: 15px;
|
||||
position: relative;
|
||||
margin-top: 1.75rem;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
/* top: 0; */
|
||||
font-size: 24px;
|
||||
color: $darkgrey;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #000;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&-bio {
|
||||
.emoji {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.profile-row-label {
|
||||
color: $placeholder-color;
|
||||
font-size: 14px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin: 0 auto 20px;
|
||||
font-size: 4rem!important;
|
||||
}
|
||||
|
||||
[type="checkbox"] + span {
|
||||
padding-left: 54px;
|
||||
margin-left: -54px;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.profile-tabs {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.profile-tabs-content {
|
||||
height: 100%;
|
||||
/* width: 500%;
|
||||
margin-left: -100%;
|
||||
*/
|
||||
/* > div {
|
||||
height: 0;
|
||||
|
||||
&.active {
|
||||
height: auto;
|
||||
}
|
||||
} */
|
||||
|
||||
> div {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* > div > div:not(.scroll-padding) {
|
||||
height: 100%;
|
||||
} */
|
||||
|
||||
.preloader {
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
|
||||
> svg {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
#content-media {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 4px;
|
||||
|
||||
> div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-auto-rows: max-content;
|
||||
grid-gap: 3.5px;
|
||||
place-items: start;
|
||||
padding-top: 3.5px;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
display: flex;
|
||||
background-color: #cecece;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#content-docs {
|
||||
padding: 7px 20px;
|
||||
|
||||
.document {
|
||||
padding-left: 4rem;
|
||||
padding-right: 1rem;
|
||||
//height: 54px;
|
||||
height: calc(50px + 1.5rem);
|
||||
|
||||
&-ico, &-download {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
/* & + .document {
|
||||
margin-top: 1.5rem;
|
||||
} */
|
||||
}
|
||||
|
||||
.document-name {
|
||||
font-weight: normal;
|
||||
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
#content-links {
|
||||
padding: 0 30px 15px 15px;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 20px;
|
||||
margin-left: 5px;
|
||||
padding-bottom: 2px;
|
||||
//padding-bottom: 10px;
|
||||
position: relative;
|
||||
padding-left: 60px;
|
||||
overflow: hidden;
|
||||
//min-height: 48px;
|
||||
min-height: 58px;
|
||||
|
||||
.preview {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
&.empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2rem;
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
background-color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
.url {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
#content-audio {
|
||||
padding: 0 15px 15px 15px;
|
||||
|
||||
> div {
|
||||
margin-top: 15px;
|
||||
padding-bottom: 10px;
|
||||
min-height: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -29,234 +29,3 @@
|
||||
margin-left: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-content {
|
||||
.profile-name {
|
||||
text-align: center;
|
||||
font-size: 23px;
|
||||
font-weight: 500;
|
||||
margin: 3px 0;
|
||||
|
||||
span.emoji {
|
||||
vertical-align: inherit;
|
||||
min-width: min-content;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-subtitle {
|
||||
text-align: center;
|
||||
color: $darkgrey;
|
||||
font-size: 14px;
|
||||
margin: 0 0 18px;
|
||||
|
||||
&.online {
|
||||
color: $darkblue;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
padding-left: 80px;
|
||||
padding-top: 2px;
|
||||
padding-right: 12px;
|
||||
font-size: 15px;
|
||||
position: relative;
|
||||
margin: 1.75rem 0;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
/* top: 0; */
|
||||
font-size: 24px;
|
||||
color: $darkgrey;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #000;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.profile-row-label {
|
||||
color: $placeholder-color;
|
||||
font-size: 14px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-row-bio {
|
||||
.emoji {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin: 0 auto 20px;
|
||||
font-size: 4rem!important;
|
||||
}
|
||||
|
||||
[type="checkbox"] + span {
|
||||
padding-left: 54px;
|
||||
margin-left: -54px;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.profile-tabs {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.profile-tabs-content {
|
||||
/* width: 500%;
|
||||
margin-left: -100%;
|
||||
*/
|
||||
/* > div {
|
||||
height: 0;
|
||||
|
||||
&.active {
|
||||
height: auto;
|
||||
}
|
||||
} */
|
||||
|
||||
#content-media {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 4px;
|
||||
|
||||
> div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-auto-rows: max-content;
|
||||
grid-gap: 3.5px;
|
||||
place-items: start;
|
||||
padding-top: 3.5px;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
display: flex;
|
||||
background-color: #cecece;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 1px;
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#content-docs {
|
||||
padding: 7px 20px;
|
||||
|
||||
.document {
|
||||
padding-left: 4rem;
|
||||
padding-right: 1rem;
|
||||
//height: 54px;
|
||||
height: calc(50px + 1.5rem);
|
||||
|
||||
&-ico, &-download {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
/* & + .document {
|
||||
margin-top: 1.5rem;
|
||||
} */
|
||||
}
|
||||
|
||||
.document-name {
|
||||
font-weight: normal;
|
||||
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
#content-links {
|
||||
padding: 0 30px 15px 15px;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 20px;
|
||||
margin-left: 5px;
|
||||
padding-bottom: 2px;
|
||||
//padding-bottom: 10px;
|
||||
position: relative;
|
||||
padding-left: 60px;
|
||||
overflow: hidden;
|
||||
//min-height: 48px;
|
||||
min-height: 58px;
|
||||
|
||||
.preview {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
|
||||
&.empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2rem;
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
background-color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
.url {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
#content-audio {
|
||||
padding: 0 15px 15px 15px;
|
||||
|
||||
> div {
|
||||
margin-top: 15px;
|
||||
padding-bottom: 10px;
|
||||
min-height: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,15 @@ $bg: #ffffff;
|
||||
$text-size: 16px;
|
||||
$time-size: 12px;
|
||||
|
||||
//$large-screen: 1680px;
|
||||
$large-screen: 16800px;
|
||||
|
||||
@import "partials/ico";
|
||||
@import "partials/chatlist";
|
||||
@import "partials/chat";
|
||||
@import "partials/sidebar";
|
||||
@import "partials/leftSidebar";
|
||||
@import "partials/rightSidebar";
|
||||
@import "partials/mediaViewer";
|
||||
@import "partials/ckin";
|
||||
@import "partials/emojiDropdown";
|
||||
@ -59,7 +63,18 @@ button, input, optgroup, select, textarea, html {
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
//min-width: 100%;
|
||||
margin: 0 auto;
|
||||
max-width: $large-screen;
|
||||
|
||||
@media (min-width: $large-screen) {
|
||||
border-top-width: 0;
|
||||
border-bottom-width: 0;
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #DADCE0;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
@ -481,13 +496,13 @@ input {
|
||||
position: relative;
|
||||
padding-left: 67px;
|
||||
min-height: 58px;
|
||||
max-width: 286px;
|
||||
max-width: 244px;
|
||||
overflow: visible!important;
|
||||
|
||||
&-toggle, &-download {
|
||||
border-radius: 50%;
|
||||
background-color: $blue;
|
||||
font-size: 2.2rem;
|
||||
font-size: 2.3rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@ -1563,19 +1578,6 @@ div.scrollable::-webkit-scrollbar-thumb {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.profile-container {
|
||||
//display: none;
|
||||
width: 0%;
|
||||
/* grid-column: 3; */
|
||||
position: relative;
|
||||
|
||||
transition: .2s ease-in-out;
|
||||
|
||||
> .scrollable {
|
||||
min-width: 25vw;
|
||||
}
|
||||
}
|
||||
|
||||
.preloader {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
|
@ -65,9 +65,9 @@
|
||||
"node_modules",
|
||||
"public",
|
||||
"coverage",
|
||||
"./src/lib/StackBlur.js",
|
||||
/* "./src/lib/StackBlur.js",
|
||||
"./src/lib/*.js",
|
||||
"./src/*.js",
|
||||
"*.js",
|
||||
"*.js", */
|
||||
]
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ module.exports = merge(common, {
|
||||
files.forEach(file => {
|
||||
//console.log('to unlink 1:', file);
|
||||
|
||||
if(file.includes('mitm.') || file.includes('sw.js')) return;
|
||||
if(file.includes('mitm.') || file.includes('sw.js') || file.includes('.xml') || file.includes('.webmanifest')) return;
|
||||
|
||||
let p = path.resolve(buildDir + file);
|
||||
if(!newlyCreatedAssets[file] && ['.gz', '.js'].find(ext => file.endsWith(ext)) !== undefined) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user