Browse Source

scroll try #10

master
Eduard Kuzmenko 4 years ago
parent
commit
c86671ce12
  1. BIN
      .DS_Store
  2. 213
      package-lock.json
  3. 4
      package.json
  4. 30
      src/components/misc.ts
  5. 353
      src/components/scrollable.ts
  6. 61
      src/components/wrappers.ts
  7. 1311
      src/lib/appManagers/appImManager.ts
  8. 7
      src/lib/appManagers/appSidebarLeft.ts
  9. 391
      src/lib/appManagers/appSidebarRight.ts
  10. 12
      src/lib/ckin.js
  11. 4
      src/lib/lottieLoader.ts
  12. 22
      src/lib/polyfill.ts
  13. 2
      src/lib/utils.js
  14. 40
      src/scss/partials/_chat.scss
  15. 286
      src/scss/partials/_rightSIdebar.scss
  16. 231
      src/scss/partials/_sidebar.scss
  17. 34
      src/scss/style.scss
  18. 4
      tsconfig.json
  19. 2
      webpack.prod.js

BIN
.DS_Store vendored

Binary file not shown.

213
package-lock.json generated

@ -4926,13 +4926,13 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -7484,7 +7481,7 @@
}
},
"bin-links": {
"version": "1.1.6",
"version": "1.1.7",
"bundled": true,
"dev": true,
"requires": {
@ -7597,7 +7594,7 @@ @@ -7597,7 +7594,7 @@
}
},
"chownr": {
"version": "1.1.3",
"version": "1.1.4",
"bundled": true,
"dev": true
},
@ -8037,7 +8034,7 @@ @@ -8037,7 +8034,7 @@
}
},
"env-paths": {
"version": "1.0.0",
"version": "2.2.0",
"bundled": true,
"dev": true
},
@ -8381,7 +8378,7 @@ @@ -8381,7 +8378,7 @@
}
},
"get-caller-file": {
"version": "1.0.2",
"version": "1.0.3",
"bundled": true,
"dev": true
},
@ -8490,7 +8487,7 @@ @@ -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 @@ @@ -8606,7 +8603,7 @@
}
},
"invert-kv": {
"version": "1.0.0",
"version": "2.0.0",
"bundled": true,
"dev": true
},
@ -8795,11 +8792,11 @@ @@ -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 @@ @@ -8972,7 +8969,7 @@
}
},
"libnpx": {
"version": "10.2.0",
"version": "10.2.2",
"bundled": true,
"dev": true,
"requires": {
@ -9123,17 +9120,34 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -9410,7 +9410,7 @@
}
},
"npm-registry-fetch": {
"version": "4.0.2",
"version": "4.0.3",
"bundled": true,
"dev": true,
"requires": {
@ -9502,13 +9502,41 @@ @@ -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 @@ @@ -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 @@ @@ -9563,7 +9601,7 @@
}
},
"pacote": {
"version": "9.5.11",
"version": "9.5.12",
"bundled": true,
"dev": true,
"requires": {
@ -9877,7 +9915,7 @@ @@ -9877,7 +9915,7 @@
}
},
"readable-stream": {
"version": "3.4.0",
"version": "3.6.0",
"bundled": true,
"dev": true,
"requires": {
@ -10261,11 +10299,18 @@ @@ -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 @@ @@ -10646,7 +10691,7 @@
"dev": true
},
"yargs": {
"version": "11.0.0",
"version": "11.1.1",
"bundled": true,
"dev": true,
"requires": {
@ -10654,7 +10699,7 @@ @@ -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",

4
package.json

@ -42,8 +42,8 @@ @@ -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",

30
src/components/misc.ts

@ -52,11 +52,23 @@ export function ripple(elem: Element) { @@ -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, @@ -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, @@ -139,7 +152,6 @@ export function horizontalMenu(tabs: HTMLUListElement, content: HTMLDivElement,
if(onTransitionEnd) onTransitionEnd();
}, 200);
if(onClick) onClick(id, tabContent);
prevTabContent = tabContent;
});
}

353
src/components/scrollable.ts

@ -32,12 +32,13 @@ export default class Scrollable { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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(() => {

61
src/components/wrappers.ts

@ -259,15 +259,21 @@ export function wrapAudio(doc: MTDocument, withTime = false): HTMLDivElement { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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);

1311
src/lib/appManagers/appImManager.ts

File diff suppressed because it is too large Load Diff

7
src/lib/appManagers/appSidebarLeft.ts

@ -87,9 +87,7 @@ class AppSidebarLeft { @@ -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 { @@ -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 { @@ -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);
}
}

391
src/lib/appManagers/appSidebarRight.ts

@ -1,6 +1,6 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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': {
break;
}
case 'inputMessagesFilterDocument': {
sharedMediaDiv = this.sharedMedia.contentDocuments;
for(let message of messages) {
if(!message.media.document || message.media.document.type == 'voice') {
break;
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 { @@ -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;
}
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;
}
/* 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;
}
if(sharedMediaDiv) {
let parent = sharedMediaDiv.parentElement;
if(parent.lastElementChild.classList.contains('preloader')) {
parent.lastElementChild.remove();
}
});
}
this.onSidebarScroll();
}).then(() => {
@ -430,26 +444,17 @@ class AppSidebarRight { @@ -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 { @@ -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 { @@ -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();
}

12
src/lib/ckin.js

@ -3,18 +3,6 @@ @@ -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);

4
src/lib/lottieLoader.ts

@ -33,9 +33,9 @@ class LottieLoader { @@ -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();
}

22
src/lib/polyfill.ts

@ -53,6 +53,23 @@ Array.prototype.forEachReverse = function<T>(callback: (value: T, index?: number @@ -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 { @@ -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;
}
}

2
src/lib/utils.js

@ -297,7 +297,7 @@ export function getSelectedText() { @@ -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);

40
src/scss/partials/_chat.scss

@ -370,8 +370,8 @@ @@ -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 @@ @@ -387,6 +387,13 @@
}
}
&.sticker {
.bubble__container {
max-width: 200px;
max-height: 200px;
}
}
&.round {
.attachment {
max-width: 200px;
@ -702,11 +709,11 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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

@ -0,0 +1,286 @@ @@ -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;
}
}
}
}

231
src/scss/partials/_sidebar.scss

@ -29,234 +29,3 @@ @@ -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;
}
}
}
}

34
src/scss/style.scss

@ -29,11 +29,15 @@ $bg: #ffffff; @@ -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 { @@ -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 { @@ -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 { @@ -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;

4
tsconfig.json

@ -65,9 +65,9 @@ @@ -65,9 +65,9 @@
"node_modules",
"public",
"coverage",
"./src/lib/StackBlur.js",
/* "./src/lib/StackBlur.js",
"./src/lib/*.js",
"./src/*.js",
"*.js",
"*.js", */
]
}

2
webpack.prod.js

@ -59,7 +59,7 @@ module.exports = merge(common, { @@ -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…
Cancel
Save