Poll vote & update & scroll chat fix & QR page & chat list updates
This commit is contained in:
parent
a884a9cea8
commit
a6d9d69909
@ -1,5 +1,6 @@
|
|||||||
import appPollsManager, { PollResults } from "../lib/appManagers/appPollsManager";
|
import appPollsManager, { PollResults, Poll } from "../lib/appManagers/appPollsManager";
|
||||||
import { RichTextProcessor } from "../lib/richtextprocessor";
|
import { RichTextProcessor } from "../lib/richtextprocessor";
|
||||||
|
import { findUpClassName, $rootScope } from "../lib/utils";
|
||||||
|
|
||||||
let lineTotalLength = 0;
|
let lineTotalLength = 0;
|
||||||
const tailLength = 9;
|
const tailLength = 9;
|
||||||
@ -7,13 +8,81 @@ const times = 10;
|
|||||||
const fullTime = 340;
|
const fullTime = 340;
|
||||||
const oneTime = fullTime / times;
|
const oneTime = fullTime / times;
|
||||||
|
|
||||||
|
let roundPercents = (percents: number[]) => {
|
||||||
|
//console.log('roundPercents before percents:', percents);
|
||||||
|
|
||||||
|
let sum = percents.reduce((acc, p) => acc + Math.round(p), 0);
|
||||||
|
if(sum > 100) {
|
||||||
|
let diff = sum - 100;
|
||||||
|
let length = percents.length;
|
||||||
|
for(let i = 0; i < diff; ++i) {
|
||||||
|
let minIndex = -1, minRemainder = 1;
|
||||||
|
for(let k = 0; k < length; ++k) {
|
||||||
|
let remainder = percents[k] % 1;
|
||||||
|
if(remainder >= 0.5 && remainder < minRemainder) {
|
||||||
|
minRemainder = remainder;
|
||||||
|
minIndex = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minIndex == -1) {
|
||||||
|
throw new Error('lol chto');
|
||||||
|
}
|
||||||
|
|
||||||
|
percents[minIndex] -= minRemainder;
|
||||||
|
}
|
||||||
|
} else if(sum < 100) {
|
||||||
|
let diff = 100 - sum;
|
||||||
|
let length = percents.length;
|
||||||
|
for(let i = 0; i < diff; ++i) {
|
||||||
|
let minIndex = -1, maxRemainder = 0;
|
||||||
|
for(let k = 0; k < length; ++k) {
|
||||||
|
let remainder = percents[k] % 1;
|
||||||
|
if(remainder < 0.5 && remainder > maxRemainder) {
|
||||||
|
maxRemainder = remainder;
|
||||||
|
minIndex = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minIndex == -1) {
|
||||||
|
throw new Error('lol chto');
|
||||||
|
}
|
||||||
|
|
||||||
|
percents[minIndex] += 1 - maxRemainder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log('roundPercents after percents:', percents);
|
||||||
|
};
|
||||||
|
|
||||||
|
const connectedPolls: {id: string, element: PollElement}[] = [];
|
||||||
|
$rootScope.$on('poll_update', (e: CustomEvent) => {
|
||||||
|
let {poll, results} = e.detail as {poll: Poll, results: PollResults};
|
||||||
|
|
||||||
|
for(let connected of connectedPolls) {
|
||||||
|
if(connected.id == poll.id) {
|
||||||
|
let pollElement = connected.element;
|
||||||
|
pollElement.performResults(results, poll.chosenIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default class PollElement extends HTMLElement {
|
export default class PollElement extends HTMLElement {
|
||||||
private svgLines: SVGSVGElement[];
|
private svgLines: SVGSVGElement[];
|
||||||
private numberDivs: HTMLDivElement[];
|
private numberDivs: HTMLDivElement[];
|
||||||
private maxOffset = -44.8;
|
private selectedSpan: HTMLSpanElement;
|
||||||
|
private answerDivs: HTMLDivElement[];
|
||||||
|
private votersCountDiv: HTMLDivElement;
|
||||||
|
|
||||||
|
private maxOffset = -46.5;
|
||||||
private maxLength: number;
|
private maxLength: number;
|
||||||
private maxLengths: number[];
|
private maxLengths: number[];
|
||||||
|
|
||||||
|
private isQuiz = false;
|
||||||
|
private isRetracted = false;
|
||||||
|
private chosenIndex = -1;
|
||||||
|
private percents: number[];
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
// элемент создан
|
// элемент создан
|
||||||
@ -31,6 +100,8 @@ export default class PollElement extends HTMLElement {
|
|||||||
let pollID = this.getAttribute('poll-id');
|
let pollID = this.getAttribute('poll-id');
|
||||||
let {poll, results} = appPollsManager.getPoll(pollID);
|
let {poll, results} = appPollsManager.getPoll(pollID);
|
||||||
|
|
||||||
|
connectedPolls.push({id: pollID, element: this});
|
||||||
|
|
||||||
console.log('pollElement poll:', poll, results);
|
console.log('pollElement poll:', poll, results);
|
||||||
|
|
||||||
let desc = '';
|
let desc = '';
|
||||||
@ -38,13 +109,18 @@ export default class PollElement extends HTMLElement {
|
|||||||
if(poll.pFlags.closed) {
|
if(poll.pFlags.closed) {
|
||||||
desc = 'Final results';
|
desc = 'Final results';
|
||||||
} else {
|
} else {
|
||||||
desc = poll.pFlags.public_voters ? 'Public Poll' : 'Anonymous Poll';
|
if(poll.pFlags.quiz) {
|
||||||
|
this.isQuiz = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let type = this.isQuiz ? 'Quiz' : 'Poll';
|
||||||
|
desc = (poll.pFlags.public_voters ? 'Public' : 'Anonymous') + ' ' + type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let votes = poll.answers.map(answer => {
|
let votes = poll.answers.map((answer, idx) => {
|
||||||
return `
|
return `
|
||||||
<div class="poll-answer">
|
<div class="poll-answer" data-index="${idx}">
|
||||||
<div class="circle-hover">
|
<div class="circle-hover">
|
||||||
<div class="animation-ring"></div>
|
<div class="animation-ring"></div>
|
||||||
<svg class="progress-ring">
|
<svg class="progress-ring">
|
||||||
@ -52,7 +128,7 @@ export default class PollElement extends HTMLElement {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="poll-answer-percents"></div>
|
<div class="poll-answer-percents"></div>
|
||||||
<svg version="1.1" class="poll-line" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 480 28" xml:space="preserve">
|
<svg version="1.1" class="poll-line" style="display: none;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 480 35" xml:space="preserve">
|
||||||
<use href="#poll-line"></use>
|
<use href="#poll-line"></use>
|
||||||
</svg>
|
</svg>
|
||||||
<div class="poll-answer-text">${RichTextProcessor.wrapEmojiText(answer.text)}</div>
|
<div class="poll-answer-text">${RichTextProcessor.wrapEmojiText(answer.text)}</div>
|
||||||
@ -64,17 +140,30 @@ export default class PollElement extends HTMLElement {
|
|||||||
<div class="poll-title">${poll.rQuestion}</div>
|
<div class="poll-title">${poll.rQuestion}</div>
|
||||||
<div class="poll-desc">${desc}</div>
|
<div class="poll-desc">${desc}</div>
|
||||||
${votes}
|
${votes}
|
||||||
<div class="poll-votes-count">${results.total_voters ? results.total_voters + ' voters' : 'No votes'}</div>
|
<div class="poll-votes-count"></div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
this.answerDivs = Array.from(this.querySelectorAll('.poll-answer')) as HTMLDivElement[];
|
||||||
|
this.votersCountDiv = this.querySelector('.poll-votes-count') as HTMLDivElement;
|
||||||
|
this.svgLines = Array.from(this.querySelectorAll('.poll-line')) as SVGSVGElement[];
|
||||||
|
this.numberDivs = Array.from(this.querySelectorAll('.poll-answer-percents')) as HTMLDivElement[];
|
||||||
|
|
||||||
let width = this.getBoundingClientRect().width;
|
let width = this.getBoundingClientRect().width;
|
||||||
this.maxLength = width + tailLength + this.maxOffset + -9; // 13 - position left
|
this.maxLength = width + tailLength + this.maxOffset + -13.7; // 13 - position left
|
||||||
this.performResults(results);
|
|
||||||
|
if(poll.chosenIndex !== -1) {
|
||||||
|
this.performResults(results, poll.chosenIndex);
|
||||||
|
} else {
|
||||||
|
this.setVotersCount(results);
|
||||||
|
this.addEventListener('click', this.clickHandler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
// браузер вызывает этот метод при удалении элемента из документа
|
// браузер вызывает этот метод при удалении элемента из документа
|
||||||
// (может вызываться много раз, если элемент многократно добавляется/удаляется)
|
// (может вызываться много раз, если элемент многократно добавляется/удаляется)
|
||||||
|
|
||||||
|
connectedPolls.findAndSplice(c => c.element == this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get observedAttributes(): string[] {
|
static get observedAttributes(): string[] {
|
||||||
@ -90,108 +179,136 @@ export default class PollElement extends HTMLElement {
|
|||||||
// (происходит в document.adoptNode, используется очень редко)
|
// (происходит в document.adoptNode, используется очень редко)
|
||||||
}
|
}
|
||||||
|
|
||||||
performResults(results: PollResults) {
|
clickHandler(e: MouseEvent) {
|
||||||
const percents = results.results.map(v => v.voters / results.total_voters * 100);
|
let target = findUpClassName(e.target, 'poll-answer') as HTMLElement;
|
||||||
this.setResults(percents);
|
if(!target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let answerIndex = +target.dataset.index;
|
||||||
|
this.sendVote(answerIndex);
|
||||||
|
|
||||||
|
/* target.classList.add('is-voting');
|
||||||
|
setTimeout(() => { // simulate
|
||||||
|
this.setResults([100, 0], answerIndex);
|
||||||
|
target.classList.remove('is-voting');
|
||||||
|
}, 1000); */
|
||||||
}
|
}
|
||||||
|
|
||||||
setResults(percents: number[]) {
|
sendVote(index: number) {
|
||||||
if(!this.svgLines) {
|
let target = this.answerDivs[index];
|
||||||
this.svgLines = Array.from(this.querySelectorAll('.poll-line')) as SVGSVGElement[];
|
target.classList.add('is-voting');
|
||||||
this.numberDivs = Array.from(this.querySelectorAll('.poll-answer-percents')) as HTMLDivElement[];
|
let mid = +this.getAttribute('message-id');
|
||||||
|
|
||||||
|
this.classList.add('disable-hover');
|
||||||
|
appPollsManager.sendVote(mid, [index]).then(() => {
|
||||||
|
target.classList.remove('is-voting');
|
||||||
|
this.classList.remove('disable-hover');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
performResults(results: PollResults, chosenIndex: number) {
|
||||||
|
if(this.chosenIndex != chosenIndex) { // if we voted
|
||||||
|
this.isRetracted = this.chosenIndex != -1 && chosenIndex == -1;
|
||||||
|
this.chosenIndex = chosenIndex;
|
||||||
|
|
||||||
|
if(this.isRetracted) {
|
||||||
|
this.addEventListener('click', this.clickHandler);
|
||||||
|
} else {
|
||||||
|
this.removeEventListener('click', this.clickHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// is need update
|
||||||
|
if(this.chosenIndex != -1 || this.isRetracted) {
|
||||||
|
const percents = results.results.map(v => v.voters / results.total_voters * 100);
|
||||||
|
this.setResults(this.isRetracted ? this.percents : percents, chosenIndex);
|
||||||
|
this.percents = percents;
|
||||||
|
this.isRetracted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setVotersCount(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
setResults(percents: number[], chosenIndex: number) {
|
||||||
|
this.svgLines.forEach(svg => svg.style.display = '');
|
||||||
|
|
||||||
|
if(chosenIndex !== -1) {
|
||||||
|
let answerDiv = this.answerDivs[chosenIndex];
|
||||||
|
if(!this.selectedSpan) {
|
||||||
|
this.selectedSpan = document.createElement('span');
|
||||||
|
this.selectedSpan.classList.add('poll-answer-selected', 'tgico-check');
|
||||||
|
}
|
||||||
|
answerDiv.append(this.selectedSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
let maxValue = Math.max(...percents);
|
let maxValue = Math.max(...percents);
|
||||||
|
|
||||||
this.maxLengths = percents.map(p => p / maxValue * this.maxLength);
|
this.maxLengths = percents.map(p => p / maxValue * this.maxLength);
|
||||||
|
|
||||||
/* this.svgLines.forEach((svg, idx) => {
|
// line
|
||||||
this.setLineProgress(idx, 1);
|
if(this.isRetracted) {
|
||||||
}); */
|
this.svgLines.forEach((svg, idx) => {
|
||||||
|
this.setLineProgress(idx, -1);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.svgLines.forEach((svg, idx) => {
|
||||||
|
void svg.getBoundingClientRect(); // reflow
|
||||||
|
this.setLineProgress(idx, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/* percents = percents.map(p => {
|
percents = percents.slice();
|
||||||
return Math.round(p);
|
roundPercents(percents);
|
||||||
}); */
|
// numbers
|
||||||
|
if(this.isRetracted) {
|
||||||
console.log('setResults before percents:', percents);
|
for(let i = (times - 1), k = 0; i >= 0; --i, ++k) {
|
||||||
|
setTimeout(() => {
|
||||||
let sum = percents.reduce((acc, p) => acc + Math.round(p), 0);
|
percents.forEach((percents, idx) => {
|
||||||
if(sum > 100) {
|
let value = Math.round(percents / times * i);
|
||||||
let diff = sum - 100;
|
this.numberDivs[idx].innerText = value + '%';
|
||||||
let length = percents.length;
|
});
|
||||||
for(let i = 0; i < diff; ++i) {
|
}, oneTime * k);
|
||||||
let minIndex = -1, minRemainder = 1;
|
|
||||||
for(let k = 0; k < length; ++k) {
|
|
||||||
let remainder = percents[k] % 1;
|
|
||||||
if(remainder >= 0.5 && remainder < minRemainder) {
|
|
||||||
minRemainder = remainder;
|
|
||||||
minIndex = k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(minIndex == -1) {
|
|
||||||
throw new Error('lol chto');
|
|
||||||
}
|
|
||||||
|
|
||||||
percents[minIndex] -= minRemainder;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let diff = 100 - sum;
|
for(let i = 0; i < times; ++i) {
|
||||||
let length = percents.length;
|
setTimeout(() => {
|
||||||
for(let i = 0; i < diff; ++i) {
|
percents.forEach((percents, idx) => {
|
||||||
let minIndex = -1, maxRemainder = 0;
|
let value = Math.round(percents / times * (i + 1));
|
||||||
for(let k = 0; k < length; ++k) {
|
this.numberDivs[idx].innerText = value + '%';
|
||||||
let remainder = percents[k] % 1;
|
});
|
||||||
if(remainder < 0.5 && remainder > maxRemainder) {
|
}, oneTime * i);
|
||||||
maxRemainder = remainder;
|
|
||||||
minIndex = k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(minIndex == -1) {
|
|
||||||
throw new Error('lol chto');
|
|
||||||
}
|
|
||||||
|
|
||||||
percents[minIndex] += 1 - maxRemainder;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('setResults after percents:', percents, sum);
|
if(this.isRetracted) {
|
||||||
|
this.classList.add('is-retracting');
|
||||||
let start = Date.now();
|
this.classList.remove('is-voted');
|
||||||
let r = () => {
|
|
||||||
let diff = Date.now() - start;
|
|
||||||
let progress = diff / fullTime;
|
|
||||||
if(progress > 1) progress = 1;
|
|
||||||
|
|
||||||
this.svgLines.forEach((svg, idx) => {
|
|
||||||
this.setLineProgress(idx, progress);
|
|
||||||
});
|
|
||||||
|
|
||||||
if(progress < 1) {
|
|
||||||
window.requestAnimationFrame(r);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
window.requestAnimationFrame(r);
|
|
||||||
|
|
||||||
for(let i = 0; i < times; ++i) {
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
percents.forEach((percents, idx) => {
|
this.classList.remove('is-retracting');
|
||||||
let value = Math.round(percents / times * (i + 1));
|
this.svgLines.forEach(svg => svg.style.display = 'none');
|
||||||
let div = this.numberDivs[idx];
|
}, fullTime);
|
||||||
//div.style.opacity = ((i + 1) * 0.10).toFixed(1); // опасити в 10 шагов от 0.1 до 1
|
} else {
|
||||||
div.innerText = value + '%';
|
this.classList.add('is-voted');
|
||||||
});
|
|
||||||
}, oneTime * i);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.classList.add('is-voted');
|
setVotersCount(results: PollResults) {
|
||||||
|
let votersCount = results.total_voters || 0;
|
||||||
|
let votersOrAnswers = this.isQuiz ? (votersCount > 1 || !votersCount ? 'answers' : 'answer') : (votersCount > 1 || !votersCount ? 'votes' : 'vote');
|
||||||
|
|
||||||
|
this.votersCountDiv.innerText = `${results.total_voters ? results.total_voters + ' ' + votersOrAnswers : 'No ' + votersOrAnswers}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLineProgress(index: number, percents: number) {
|
setLineProgress(index: number, percents: number) {
|
||||||
let svg = this.svgLines[index];
|
let svg = this.svgLines[index];
|
||||||
svg.style.strokeDasharray = (percents * this.maxLengths[index]) + ', 485.9';
|
|
||||||
svg.style.strokeDashoffset = '' + percents * this.maxOffset;
|
if(percents == -1) {
|
||||||
|
svg.style.strokeDasharray = '';
|
||||||
|
svg.style.strokeDashoffset = '';
|
||||||
|
} else {
|
||||||
|
svg.style.strokeDasharray = (percents * this.maxLengths[index]) + ', 485.9';
|
||||||
|
svg.style.strokeDashoffset = '' + percents * this.maxOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// у элемента могут быть ещё другие методы и свойства
|
// у элемента могут быть ещё другие методы и свойства
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { logger, deferredPromise, CancellablePromise } from "../lib/polyfill";
|
import { logger, deferredPromise, CancellablePromise } from "../lib/polyfill";
|
||||||
|
import smoothscroll from '../lib/smoothscroll';
|
||||||
|
(window as any).__forceSmoothScrollPolyfill__ = true;
|
||||||
|
smoothscroll.polyfill();
|
||||||
/*
|
/*
|
||||||
var el = $0;
|
var el = $0;
|
||||||
var height = 0;
|
var height = 0;
|
||||||
@ -66,6 +68,8 @@ export default class Scrollable {
|
|||||||
private lastBottomID = 0;
|
private lastBottomID = 0;
|
||||||
private lastScrollDirection = 0; // true = bottom
|
private lastScrollDirection = 0; // true = bottom
|
||||||
|
|
||||||
|
private scrollLocked = 0;
|
||||||
|
|
||||||
private setVisible(element: HTMLElement) {
|
private setVisible(element: HTMLElement) {
|
||||||
if(this.visible.has(element)) return;
|
if(this.visible.has(element)) return;
|
||||||
|
|
||||||
@ -152,61 +156,6 @@ export default class Scrollable {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// внизу - самый производительный вариант
|
|
||||||
if(false) this.observer = new IntersectionObserver(entries => {
|
|
||||||
entries/* .filter(entry => entry.isIntersecting) */.forEach((entry, idx, arr) => {
|
|
||||||
let target = entry.target as HTMLElement;
|
|
||||||
|
|
||||||
if(entry.isIntersecting) {
|
|
||||||
let isTop = entry.boundingClientRect.top <= 0;
|
|
||||||
let isBottom = entry.rootBounds.height <= (entry.boundingClientRect.top + entry.boundingClientRect.height);
|
|
||||||
|
|
||||||
/* let id = +target.dataset.virtual;
|
|
||||||
let isOutOfRange = id < (this.lastTopID - 15) || id > (this.lastBottomID + 15);
|
|
||||||
if(isOutOfRange) {
|
|
||||||
this.debug && this.log('out of range, scroll jumped!');
|
|
||||||
if(idx == 0) this.lastTopID = id;
|
|
||||||
else if(idx == (arr.length - 1)) this.lastBottomID = id;
|
|
||||||
} */
|
|
||||||
|
|
||||||
this.setVisible(target);
|
|
||||||
if(isTop) {
|
|
||||||
/* this.lastTopID = id;
|
|
||||||
this.debug && this.log('set lastTopID to:', this.lastTopID); */
|
|
||||||
|
|
||||||
for(let i = 0; i < 15; ++i) {
|
|
||||||
target = target.previousElementSibling as HTMLElement;
|
|
||||||
if(!target) break;
|
|
||||||
this.setVisible(target);
|
|
||||||
}
|
|
||||||
} else if(isBottom) {
|
|
||||||
/* this.lastBottomID = id;
|
|
||||||
this.debug && this.log('set lastBottomID to:', this.lastBottomID); */
|
|
||||||
|
|
||||||
for(let i = 0; i < 15; ++i) {
|
|
||||||
target = target.nextElementSibling as HTMLElement;
|
|
||||||
if(!target) break;
|
|
||||||
this.setVisible(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.setHidden(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//this.debug && this.log('intersection entry:', entry, isTop, isBottom, this.lastTopID, this.lastBottomID);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* let minVisibleID = this.lastTopID - 15;
|
|
||||||
let maxVisibleID = this.lastBottomID + 15;
|
|
||||||
for(let target of this.visible) {
|
|
||||||
let id = +target.dataset.virtual;
|
|
||||||
if(id < minVisibleID || id > maxVisibleID) {
|
|
||||||
this.setHidden(target);
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
});
|
|
||||||
|
|
||||||
if(!appendTo) {
|
if(!appendTo) {
|
||||||
this.appendTo = this.container;
|
this.appendTo = this.container;
|
||||||
}
|
}
|
||||||
@ -326,7 +275,7 @@ export default class Scrollable {
|
|||||||
let scrollTop = scrollPos - this.scrollTopOffset;
|
let scrollTop = scrollPos - this.scrollTopOffset;
|
||||||
let maxScrollTop = this.scrollSize - this.scrollTopOffset - this.size;
|
let maxScrollTop = this.scrollSize - this.scrollTopOffset - this.size;
|
||||||
|
|
||||||
if(this.onScrolledBottom) {
|
if(this.onScrolledBottom && !this.scrollLocked) {
|
||||||
if((maxScrollTop - scrollTop) <= this.onScrollOffset) {
|
if((maxScrollTop - scrollTop) <= this.onScrollOffset) {
|
||||||
//if(!this.onScrolledBottomFired) {
|
//if(!this.onScrolledBottomFired) {
|
||||||
this.onScrolledBottomFired = true;
|
this.onScrolledBottomFired = true;
|
||||||
@ -337,7 +286,7 @@ export default class Scrollable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.onScrolledTop) {
|
if(this.onScrolledTop && !this.scrollLocked) {
|
||||||
//this.log('onScrolledTop:', scrollTop, this.onScrollOffset);
|
//this.log('onScrolledTop:', scrollTop, this.onScrollOffset);
|
||||||
if(scrollTop <= this.onScrollOffset) {
|
if(scrollTop <= this.onScrollOffset) {
|
||||||
this.onScrolledTopFired = true;
|
this.onScrolledTopFired = true;
|
||||||
@ -357,6 +306,23 @@ export default class Scrollable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public reorder() {
|
||||||
|
(Array.from(this.splitUp.children) as HTMLElement[]).forEach((el, idx) => {
|
||||||
|
el.dataset.virtual = '' + idx;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateElement(element: HTMLElement) {
|
||||||
|
element.style.minHeight = '';
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
let height = element.scrollHeight;
|
||||||
|
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
element.style.minHeight = height + 'px';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public prepareElement(element: HTMLElement, append = true) {
|
public prepareElement(element: HTMLElement, append = true) {
|
||||||
element.dataset.virtual = '' + (append ? this.virtualTempIDBottom++ : this.virtualTempIDTop--);
|
element.dataset.virtual = '' + (append ? this.virtualTempIDBottom++ : this.virtualTempIDTop--);
|
||||||
|
|
||||||
@ -401,9 +367,29 @@ export default class Scrollable {
|
|||||||
return !!element.parentElement;
|
return !!element.parentElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public scrollIntoView(element: Element) {
|
public scrollIntoView(element: HTMLElement) {
|
||||||
if(element.parentElement) {
|
if(element.parentElement) {
|
||||||
element.scrollIntoView();
|
let scrollTop = this.scrollTop;
|
||||||
|
let offsetTop = element.offsetTop;
|
||||||
|
let clientHeight = this.container.clientHeight;
|
||||||
|
|
||||||
|
let height = element.scrollHeight;
|
||||||
|
|
||||||
|
let diff = (clientHeight - height) / 2;
|
||||||
|
|
||||||
|
/* if(scrollTop < offsetTop) {
|
||||||
|
offsetTop += diff;
|
||||||
|
} else { */
|
||||||
|
offsetTop -= diff;
|
||||||
|
//}
|
||||||
|
|
||||||
|
if(this.scrollLocked) clearTimeout(this.scrollLocked);
|
||||||
|
this.scrollLocked = setTimeout(() => {
|
||||||
|
this.scrollLocked = 0;
|
||||||
|
this.onScroll();
|
||||||
|
}, 468);
|
||||||
|
this.container.scrollTo({behavior: 'smooth', top: offsetTop});
|
||||||
|
//element.scrollIntoView({behavior: 'smooth', block: 'center'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -875,22 +875,7 @@ export function wrapReply(title: string, subtitle: string, message?: any) {
|
|||||||
|
|
||||||
let media = message && message.media;
|
let media = message && message.media;
|
||||||
if(media) {
|
if(media) {
|
||||||
if(message.grouped_id) {
|
replySubtitle.innerHTML = message.rReply;
|
||||||
replySubtitle.innerHTML = 'Album';
|
|
||||||
} else if(media._ == 'messageMediaContact') {
|
|
||||||
replySubtitle.innerHTML = 'Contact';
|
|
||||||
} else if(media._ == 'messageMediaPoll') {
|
|
||||||
replySubtitle.innerHTML = media.poll.rReply;
|
|
||||||
} else if(media.photo) {
|
|
||||||
replySubtitle.innerHTML = 'Photo';
|
|
||||||
} else if(media.document && media.document.type) {
|
|
||||||
let type = media.document.type as string;
|
|
||||||
replySubtitle.innerHTML = type.charAt(0).toUpperCase() + type.slice(1); // capitalizeFirstLetter
|
|
||||||
} else if(media.webpage) {
|
|
||||||
replySubtitle.innerHTML = RichTextProcessor.wrapPlainText(media.webpage.url);
|
|
||||||
} else {
|
|
||||||
replySubtitle.innerHTML = media._;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(media.photo || (media.document && ['video'].indexOf(media.document.type) !== -1)) {
|
if(media.photo || (media.document && ['video'].indexOf(media.document.type) !== -1)) {
|
||||||
let replyMedia = document.createElement('div');
|
let replyMedia = document.createElement('div');
|
||||||
@ -1054,8 +1039,9 @@ export function wrapAlbum({groupID, attachmentDiv, middleware, uploading, lazyLo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function wrapPoll(poll: Poll, results: PollResults) {
|
export function wrapPoll(pollID: string, mid: number) {
|
||||||
let elem = new PollElement();
|
let elem = new PollElement();
|
||||||
elem.setAttribute('poll-id', poll.id);
|
elem.setAttribute('poll-id', pollID);
|
||||||
|
elem.setAttribute('message-id', '' + mid);
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
@ -143,28 +143,41 @@ export class AppDialogsManager {
|
|||||||
let dialog: any = e.detail;
|
let dialog: any = e.detail;
|
||||||
|
|
||||||
this.setLastMessage(dialog);
|
this.setLastMessage(dialog);
|
||||||
|
this.setUnreadMessages(dialog);
|
||||||
this.setDialogPosition(dialog);
|
this.setDialogPosition(dialog);
|
||||||
|
|
||||||
|
this.setPinnedDelimiter();
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootScope.$on('dialogs_multiupdate', (e: CustomEvent) => {
|
$rootScope.$on('dialogs_multiupdate', (e: CustomEvent) => {
|
||||||
let dialogs = e.detail;
|
let dialogs = e.detail;
|
||||||
|
|
||||||
let performed = 0;
|
|
||||||
for(let id in dialogs) {
|
for(let id in dialogs) {
|
||||||
let dialog = dialogs[id];
|
let dialog = dialogs[id];
|
||||||
|
|
||||||
/////console.log('updating dialog:', dialog);
|
/////console.log('updating dialog:', dialog);
|
||||||
|
|
||||||
++performed;
|
|
||||||
|
|
||||||
if(!(dialog.peerID in this.doms)) {
|
if(!(dialog.peerID in this.doms)) {
|
||||||
this.addDialog(dialog);
|
this.addDialog(dialog);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setLastMessage(dialog);
|
this.setLastMessage(dialog);
|
||||||
|
this.setUnreadMessages(dialog);
|
||||||
this.setDialogPosition(dialog);
|
this.setDialogPosition(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setPinnedDelimiter();
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('dialog_drop', (e: CustomEvent) => {
|
||||||
|
let {peerID, dialog} = e.detail;
|
||||||
|
|
||||||
|
let dom = this.getDialogDom(peerID);
|
||||||
|
if(dom) {
|
||||||
|
dom.listEl.remove();
|
||||||
|
delete this.doms[peerID];
|
||||||
|
(dialog.folder_id == 1 ? this.scrollArchived : this.scroll).reorder();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootScope.$on('dialog_unread', (e: CustomEvent) => {
|
$rootScope.$on('dialog_unread', (e: CustomEvent) => {
|
||||||
@ -184,6 +197,7 @@ export class AppDialogsManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.loadDialogs().then(result => {
|
this.loadDialogs().then(result => {
|
||||||
|
this.setPinnedDelimiter();
|
||||||
//appSidebarLeft.onChatsScroll();
|
//appSidebarLeft.onChatsScroll();
|
||||||
this.loadDialogs(true);
|
this.loadDialogs(true);
|
||||||
});
|
});
|
||||||
@ -331,10 +345,11 @@ export class AppDialogsManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public setDialogPosition(dialog: any) {
|
public setDialogPosition(dialog: Dialog) {
|
||||||
let pos = appMessagesManager.getDialogByPeerID(dialog.peerID)[1];
|
let pos = appMessagesManager.getDialogByPeerID(dialog.peerID)[1];
|
||||||
let dom = this.getDialogDom(dialog.peerID);
|
let dom = this.getDialogDom(dialog.peerID);
|
||||||
let prevPos = whichChild(dom.listEl);
|
let prevPos = whichChild(dom.listEl);
|
||||||
|
|
||||||
if(prevPos == pos) {
|
if(prevPos == pos) {
|
||||||
return;
|
return;
|
||||||
} else if(prevPos < pos) { // was higher
|
} else if(prevPos < pos) { // was higher
|
||||||
@ -348,102 +363,44 @@ export class AppDialogsManager {
|
|||||||
chatList.append(dom.listEl);
|
chatList.append(dom.listEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix order
|
(dialog.folder_id == 1 ? this.scrollArchived : this.scroll).reorder();
|
||||||
(Array.from(chatList.children) as HTMLElement[]).forEach((el, idx) => {
|
|
||||||
el.dataset.virtual = '' + idx;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.log('setDialogPosition:', dialog, dom, pos);
|
this.log('setDialogPosition:', dialog, dom, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* public sortDom(archived = false) {
|
public setPinnedDelimiter() {
|
||||||
//if(archived) return;
|
let index = -1;
|
||||||
|
let dialogs = appMessagesManager.dialogsStorage.dialogs[0];
|
||||||
let dialogs = appMessagesManager.dialogsStorage.dialogs.slice();
|
for(let dialog of dialogs) {
|
||||||
|
if(dialog.pFlags?.pinned) {
|
||||||
let inUpper: Scrollable['hiddenElements']['up'] = [];
|
index++;
|
||||||
let inBottom: Scrollable['hiddenElements']['down'] = [];
|
|
||||||
let inVisible: Scrollable['visibleElements'] = [];
|
|
||||||
let pinnedDialogs = [];
|
|
||||||
|
|
||||||
let sorted = dialogs;
|
|
||||||
|
|
||||||
if(!archived) {
|
|
||||||
for(let i = 0; i < dialogs.length; ++i) {
|
|
||||||
let dialog = dialogs[i];
|
|
||||||
if(!dialog.pFlags.pinned) break;
|
|
||||||
pinnedDialogs.push(dialog);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(pinnedDialogs.length) {
|
let currentIndex = (this.pinnedDelimiter.parentElement && whichChild(this.pinnedDelimiter.parentElement)) ?? -1;
|
||||||
let dom = this.getDialogDom(pinnedDialogs[pinnedDialogs.length - 1].peerID);
|
|
||||||
if(dom) {
|
|
||||||
dom.listEl.append(this.pinnedDelimiter);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(this.pinnedDelimiter.parentElement) {
|
|
||||||
this.pinnedDelimiter.parentElement.removeChild(this.pinnedDelimiter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sorted = sorted.filter((d: any) => !d.pFlags.pinned && d.folder_id != 1);
|
if(index == currentIndex) return;
|
||||||
|
|
||||||
|
let children = this.chatList.children;
|
||||||
|
|
||||||
|
let modifying: HTMLElement[] = [];
|
||||||
|
if(currentIndex != -1 && children.length > currentIndex) {
|
||||||
|
let li = children[currentIndex] as HTMLElement;
|
||||||
|
modifying.push(li);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index != -1 && children.length > index) {
|
||||||
|
let li = children[index] as HTMLElement;
|
||||||
|
modifying.push(li);
|
||||||
|
li.append(this.pinnedDelimiter);
|
||||||
} else {
|
} else {
|
||||||
sorted = sorted.filter((d: any) => d.folder_id == 1);
|
this.pinnedDelimiter.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
sorted = sorted.sort((a: any, b: any) => {
|
modifying.forEach(elem => {
|
||||||
let timeA = appMessagesManager.getMessage(a.top_message).date;
|
this.scroll.updateElement(elem);
|
||||||
let timeB = appMessagesManager.getMessage(b.top_message).date;
|
|
||||||
|
|
||||||
return timeB - timeA;
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
if(!archived) {
|
|
||||||
sorted = pinnedDialogs.concat(sorted);
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log('sortDom', sorted, this.chatsHidden, this.chatsHidden.up, this.chatsHidden.down);
|
|
||||||
|
|
||||||
let chatList = archived ? this.chatListArchived : this.chatList;
|
|
||||||
let chatsHidden = archived ? this.chatsArchivedHidden : this.chatsHidden;
|
|
||||||
let chatsVisible = archived ? this.chatsArchivedVisible : this.chatsVisible;
|
|
||||||
|
|
||||||
let hiddenLength: number = chatsHidden.up.length;
|
|
||||||
let inViewportLength = chatList.childElementCount;
|
|
||||||
let concated = chatsHidden.up.concat(chatsVisible, chatsHidden.down);
|
|
||||||
|
|
||||||
//console.log('sortDom clearing innerHTML', archived, hiddenLength, inViewportLength);
|
|
||||||
|
|
||||||
chatList.innerHTML = '';
|
|
||||||
|
|
||||||
let inViewportIndex = 0;
|
|
||||||
sorted.forEach((d: any, idx) => {
|
|
||||||
let dom = this.getDialogDom(d.peerID);
|
|
||||||
if(!dom) return;
|
|
||||||
|
|
||||||
let child = concated.find((obj: any) => obj.element == dom.listEl);
|
|
||||||
if(!child) {
|
|
||||||
return this.log.error('no child by listEl:', dom.listEl, archived, concated);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(inUpper.length < hiddenLength) {
|
|
||||||
inUpper.push(child);
|
|
||||||
} else if(inViewportIndex <= inViewportLength - 1) {
|
|
||||||
chatList.append(dom.listEl);
|
|
||||||
inVisible.push(child);
|
|
||||||
++inViewportIndex;
|
|
||||||
} else {
|
|
||||||
inBottom.push(child);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//console.log('sortDom', sorted.length, inUpper.length, chatList.childElementCount, inBottom.length);
|
|
||||||
|
|
||||||
chatsHidden.up = inUpper;
|
|
||||||
chatsVisible.length = 0;
|
|
||||||
chatsVisible.push(...inVisible);
|
|
||||||
chatsHidden.down = inBottom;
|
|
||||||
} */
|
|
||||||
|
|
||||||
public setLastMessage(dialog: any, lastMessage?: any, dom?: DialogDom, highlightWord?: string) {
|
public setLastMessage(dialog: any, lastMessage?: any, dom?: DialogDom, highlightWord?: string) {
|
||||||
if(!lastMessage) {
|
if(!lastMessage) {
|
||||||
@ -465,94 +422,7 @@ export class AppDialogsManager {
|
|||||||
//console.log('setting last message:', lastMessage);
|
//console.log('setting last message:', lastMessage);
|
||||||
|
|
||||||
/* if(!dom.lastMessageSpan.classList.contains('user-typing')) */ {
|
/* if(!dom.lastMessageSpan.classList.contains('user-typing')) */ {
|
||||||
let lastMessageText = '';
|
/* let messageText = lastMessage.message;
|
||||||
|
|
||||||
if(lastMessage.media) {
|
|
||||||
switch(lastMessage.media._) {
|
|
||||||
case 'messageMediaPhoto':
|
|
||||||
lastMessageText += '<i>' + (lastMessage.grouped_id ? 'Album' : 'Photo') + (lastMessage.message ? ', ' : '') + '</i>';
|
|
||||||
break;
|
|
||||||
case 'messageMediaGeo':
|
|
||||||
lastMessageText += '<i>Geolocation</i>';
|
|
||||||
break;
|
|
||||||
case 'messageMediaPoll':
|
|
||||||
lastMessageText += '<i>' + lastMessage.media.poll.rReply + '</i>';
|
|
||||||
break;
|
|
||||||
case 'messageMediaContact':
|
|
||||||
lastMessageText += '<i>Contact</i>';
|
|
||||||
break;
|
|
||||||
case 'messageMediaDocument':
|
|
||||||
let document = lastMessage.media.document;
|
|
||||||
|
|
||||||
let found = false;
|
|
||||||
for(let attribute of document.attributes) {
|
|
||||||
if(found) break;
|
|
||||||
|
|
||||||
switch(attribute._) {
|
|
||||||
case 'documentAttributeSticker':
|
|
||||||
lastMessageText += RichTextProcessor.wrapRichText(attribute.alt) + '<i>Sticker</i>';
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
case 'documentAttributeFilename':
|
|
||||||
lastMessageText += '<i>' + attribute.file_name + '</i>';
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
/* default:
|
|
||||||
console.warn('Got unknown document type!', lastMessage);
|
|
||||||
break; */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(document.type == 'video') {
|
|
||||||
lastMessageText = '<i>Video' + (lastMessage.message ? ', ' : '') + '</i>';
|
|
||||||
found = true;
|
|
||||||
} else if(document.type == 'voice') {
|
|
||||||
lastMessageText = '<i>Voice message</i>';
|
|
||||||
found = true;
|
|
||||||
} else if(document.type == 'gif') {
|
|
||||||
lastMessageText = '<i>GIF' + (lastMessage.message ? ', ' : '') + '</i>';
|
|
||||||
found = true;
|
|
||||||
} else if(document.type == 'round') {
|
|
||||||
lastMessageText = '<i>Video message' + (lastMessage.message ? ', ' : '') + '</i>';
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(found) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
///////console.warn('Got unknown lastMessage.media type!', lastMessage);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lastMessage.action) {
|
|
||||||
let action = lastMessage.action;
|
|
||||||
|
|
||||||
console.log('lastMessage action:', action);
|
|
||||||
|
|
||||||
let suffix = '';
|
|
||||||
let _ = action._;
|
|
||||||
if(_ == "messageActionPhoneCall") {
|
|
||||||
_ += '.' + action.type;
|
|
||||||
|
|
||||||
let duration = action.duration;
|
|
||||||
if(duration) {
|
|
||||||
let d = [];
|
|
||||||
|
|
||||||
d.push(duration % 60 + ' s');
|
|
||||||
if(duration >= 60) d.push((duration / 60 | 0) + ' min');
|
|
||||||
//if(duration >= 3600) d.push((duration / 3600 | 0) + ' h');
|
|
||||||
suffix = ' (' + d.reverse().join(' ') + ')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
lastMessageText = '<i>' + langPack[_] + suffix + '</i>';
|
|
||||||
}
|
|
||||||
|
|
||||||
let messageText = lastMessage.message;
|
|
||||||
let messageWrapped = '';
|
let messageWrapped = '';
|
||||||
if(messageText) {
|
if(messageText) {
|
||||||
let entities = RichTextProcessor.parseEntities(messageText.replace(/\n/g, ' '), {noLinebreakers: true});
|
let entities = RichTextProcessor.parseEntities(messageText.replace(/\n/g, ' '), {noLinebreakers: true});
|
||||||
@ -577,9 +447,10 @@ export class AppDialogsManager {
|
|||||||
entities: entities,
|
entities: entities,
|
||||||
noTextFormat: true
|
noTextFormat: true
|
||||||
});
|
});
|
||||||
}
|
} */
|
||||||
|
|
||||||
dom.lastMessageSpan.innerHTML = lastMessageText + messageWrapped;
|
//dom.lastMessageSpan.innerHTML = lastMessageText + messageWrapped;
|
||||||
|
dom.lastMessageSpan.innerHTML = lastMessage.rReply;
|
||||||
|
|
||||||
/* if(lastMessage.from_id == auth.id) { // You: */
|
/* if(lastMessage.from_id == auth.id) { // You: */
|
||||||
if(peer._ != 'peerUser' && peerID != -lastMessage.from_id) {
|
if(peer._ != 'peerUser' && peerID != -lastMessage.from_id) {
|
||||||
@ -629,10 +500,9 @@ export class AppDialogsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setUnreadMessages(dialog: any) {
|
public setUnreadMessages(dialog: Dialog) {
|
||||||
let dom = this.getDialogDom(dialog.peerID);
|
let dom = this.getDialogDom(dialog.peerID);
|
||||||
|
|
||||||
dom.statusSpan.innerHTML = '';
|
|
||||||
let lastMessage = appMessagesManager.getMessage(dialog.top_message);
|
let lastMessage = appMessagesManager.getMessage(dialog.top_message);
|
||||||
if(lastMessage._ != 'messageEmpty' &&
|
if(lastMessage._ != 'messageEmpty' &&
|
||||||
lastMessage.from_id == $rootScope.myID && lastMessage.peerID != $rootScope.myID &&
|
lastMessage.from_id == $rootScope.myID && lastMessage.peerID != $rootScope.myID &&
|
||||||
@ -651,10 +521,11 @@ export class AppDialogsManager {
|
|||||||
}
|
}
|
||||||
} else dom.statusSpan.classList.remove('tgico-check', 'tgico-checks');
|
} else dom.statusSpan.classList.remove('tgico-check', 'tgico-checks');
|
||||||
|
|
||||||
dom.unreadMessagesSpan.innerHTML = '';
|
dom.unreadMessagesSpan.innerText = '';
|
||||||
|
dom.unreadMessagesSpan.classList.remove('tgico-pinnedchat');
|
||||||
if(dialog.unread_count) {
|
if(dialog.unread_count) {
|
||||||
dom.unreadMessagesSpan.innerHTML = dialog.unread_count;
|
dom.unreadMessagesSpan.innerText = '' + dialog.unread_count;
|
||||||
dom.unreadMessagesSpan.classList.remove('tgico-pinnedchat');
|
//dom.unreadMessagesSpan.classList.remove('tgico-pinnedchat');
|
||||||
dom.unreadMessagesSpan.classList.add(new Date(dialog.notify_settings.mute_until * 1000) > new Date() ?
|
dom.unreadMessagesSpan.classList.add(new Date(dialog.notify_settings.mute_until * 1000) > new Date() ?
|
||||||
'unread-muted' : 'unread');
|
'unread-muted' : 'unread');
|
||||||
} else if(dialog.pFlags.pinned) {
|
} else if(dialog.pFlags.pinned) {
|
||||||
@ -826,12 +697,6 @@ export class AppDialogsManager {
|
|||||||
this.doms[dialog.peerID] = dom;
|
this.doms[dialog.peerID] = dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dialog.pFlags.pinned) {
|
|
||||||
li.classList.add('dialog-pinned');
|
|
||||||
//this.chatList.insertBefore(this.pinnedDelimiter, li.nextSibling);
|
|
||||||
dom.listEl.append(this.pinnedDelimiter);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setLastMessage(dialog);
|
this.setLastMessage(dialog);
|
||||||
} else {
|
} else {
|
||||||
container.append(li);
|
container.append(li);
|
||||||
|
@ -274,7 +274,7 @@ export class AppImManager {
|
|||||||
/////this.log('setting pinned message', message);
|
/////this.log('setting pinned message', message);
|
||||||
this.pinnedMessageContainer.dataset.mid = '' + mid;
|
this.pinnedMessageContainer.dataset.mid = '' + mid;
|
||||||
this.pinnedMessageContainer.style.display = '';
|
this.pinnedMessageContainer.style.display = '';
|
||||||
this.pinnedMessageContent.innerHTML = RichTextProcessor.wrapEmojiText(message.message);
|
this.pinnedMessageContent.innerHTML = message.rReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.needUpdate.forEachReverse((obj, idx) => {
|
this.needUpdate.forEachReverse((obj, idx) => {
|
||||||
@ -329,11 +329,17 @@ export class AppImManager {
|
|||||||
let target = e.target as HTMLElement;
|
let target = e.target as HTMLElement;
|
||||||
let bubble: HTMLDivElement = null;
|
let bubble: HTMLDivElement = null;
|
||||||
try {
|
try {
|
||||||
bubble = findUpClassName(e.target, 'bubble');
|
bubble = findUpClassName(target, 'bubble');
|
||||||
} catch(err) {}
|
} catch(err) {}
|
||||||
|
|
||||||
if(!bubble) return;
|
if(!bubble) return;
|
||||||
|
|
||||||
|
let contactDiv = findUpClassName(target, 'contact');
|
||||||
|
if(contactDiv) {
|
||||||
|
this.setPeer(+contactDiv.dataset.peerID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//this.log('chatInner click:', target);
|
//this.log('chatInner click:', target);
|
||||||
if(target.tagName == 'SPAN') {
|
if(target.tagName == 'SPAN') {
|
||||||
(target.parentElement.querySelector('video') as HTMLElement).click(); // hot-fix for time and play button
|
(target.parentElement.querySelector('video') as HTMLElement).click(); // hot-fix for time and play button
|
||||||
@ -859,7 +865,7 @@ export class AppImManager {
|
|||||||
appMessagesManager.wrapSingleMessage(chatInfo.pinned_msg_id);
|
appMessagesManager.wrapSingleMessage(chatInfo.pinned_msg_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let participants_count = chatInfo.participants_count || chatInfo.participants.participants.length;
|
let participants_count = chatInfo.participants_count || (chatInfo.participants && chatInfo.participants.participants.length);
|
||||||
let subtitle = numberWithCommas(participants_count) + ' ' + (isChannel ? 'subscribers' : 'members');
|
let subtitle = numberWithCommas(participants_count) + ' ' + (isChannel ? 'subscribers' : 'members');
|
||||||
|
|
||||||
if(onlines > 1) {
|
if(onlines > 1) {
|
||||||
@ -1091,9 +1097,9 @@ export class AppImManager {
|
|||||||
return true;
|
return true;
|
||||||
})/* .catch(err => {
|
})/* .catch(err => {
|
||||||
this.log.error(err);
|
this.log.error(err);
|
||||||
}) *//* ,
|
}) */,
|
||||||
|
|
||||||
appSidebarRight.fillProfileElements() *//* ,
|
appSidebarRight.fillProfileElements()/* ,
|
||||||
appSidebarRight.loadSidebarMedia(true) */
|
appSidebarRight.loadSidebarMedia(true) */
|
||||||
]).catch(err => {
|
]).catch(err => {
|
||||||
this.log.error('setPeer promises error:', err);
|
this.log.error('setPeer promises error:', err);
|
||||||
@ -1716,6 +1722,8 @@ export class AppImManager {
|
|||||||
|
|
||||||
let contactDiv = document.createElement('div');
|
let contactDiv = document.createElement('div');
|
||||||
contactDiv.classList.add('contact');
|
contactDiv.classList.add('contact');
|
||||||
|
contactDiv.dataset.peerID = '' + message.media.user_id;
|
||||||
|
|
||||||
messageDiv.classList.add('contact-message');
|
messageDiv.classList.add('contact-message');
|
||||||
processingWebPage = true;
|
processingWebPage = true;
|
||||||
|
|
||||||
@ -1724,12 +1732,16 @@ export class AppImManager {
|
|||||||
if(message.media.last_name) texts.push(RichTextProcessor.wrapEmojiText(message.media.last_name));
|
if(message.media.last_name) texts.push(RichTextProcessor.wrapEmojiText(message.media.last_name));
|
||||||
|
|
||||||
contactDiv.innerHTML = `
|
contactDiv.innerHTML = `
|
||||||
<div class="contact-avatar user-avatar"><img src="blob:https://192.168.0.105:9000/803514b4-4a46-4125-984f-ca8f86405ef2"></div>
|
|
||||||
<div class="contact-details">
|
<div class="contact-details">
|
||||||
<div class="contact-name">${texts.join(' ')}</div>
|
<div class="contact-name">${texts.join(' ')}</div>
|
||||||
<div class="contact-number">${message.media.phone_number ? '+' + formatPhoneNumber(message.media.phone_number).formatted : 'Unknown phone number'}</div>
|
<div class="contact-number">${message.media.phone_number ? '+' + formatPhoneNumber(message.media.phone_number).formatted : 'Unknown phone number'}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
|
let avatarDiv = document.createElement('div');
|
||||||
|
avatarDiv.classList.add('contact-avatar', 'user-avatar');
|
||||||
|
contactDiv.prepend(avatarDiv);
|
||||||
|
appProfileManager.putPhoto(avatarDiv, message.media.user_id);
|
||||||
|
|
||||||
bubble.classList.remove('is-message-empty');
|
bubble.classList.remove('is-message-empty');
|
||||||
messageDiv.append(contactDiv);
|
messageDiv.append(contactDiv);
|
||||||
|
|
||||||
@ -1739,7 +1751,7 @@ export class AppImManager {
|
|||||||
case 'messageMediaPoll': {
|
case 'messageMediaPoll': {
|
||||||
bubble.classList.remove('is-message-empty');
|
bubble.classList.remove('is-message-empty');
|
||||||
|
|
||||||
let pollElement = wrapPoll(message.media.poll, message.media.results);
|
let pollElement = wrapPoll(message.media.poll.id, message.mid);
|
||||||
messageDiv.prepend(pollElement);
|
messageDiv.prepend(pollElement);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1927,11 +1939,14 @@ export class AppImManager {
|
|||||||
bubbles.push(bubble);
|
bubbles.push(bubble);
|
||||||
}); */
|
}); */
|
||||||
|
|
||||||
//let leftHeightToScroll = this.scrollable.innerHeight;
|
let scrollTop = this.scrollable.scrollTop;
|
||||||
|
let leftHeightToScroll = scrollTop > 0 ? 0 : (Object.keys(this.bubbles).length > 0 ? 1 : this.scrollable.container.clientHeight);
|
||||||
|
let setScrollRAF = 0;
|
||||||
|
let previousScrollHeightMinusTop = this.scrollable.scrollHeight - scrollTop;
|
||||||
|
|
||||||
//console.timeEnd('appImManager: pre render start');
|
//console.timeEnd('appImManager: pre render start');
|
||||||
|
|
||||||
//this.log('start performHistoryResult, scrollTop:', this.scrollable.scrollTop, this.scrollable.scrollHeight, this.scrollable.innerHeight);
|
this.log('start performHistoryResult, scrollTop:', scrollTop, leftHeightToScroll);
|
||||||
|
|
||||||
let method = (reverse ? history.shift : history.pop).bind(history);
|
let method = (reverse ? history.shift : history.pop).bind(history);
|
||||||
|
|
||||||
@ -1981,21 +1996,27 @@ export class AppImManager {
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
if(!renderedFirstScreen) {
|
if(!renderedFirstScreen) {
|
||||||
if(!this.scrollable.scrollTop) {
|
/* if(!this.scrollable.scrollTop) {
|
||||||
let height = bubble.scrollHeight;
|
let height = bubble.scrollHeight;
|
||||||
//let height = Math.ceil(bubble.getBoundingClientRect().height);
|
//let height = Math.ceil(bubble.getBoundingClientRect().height);
|
||||||
this.scrollable.scrollTop += height;
|
this.scrollable.scrollTop += height;
|
||||||
//innerHeight -= height;
|
//innerHeight -= height;
|
||||||
}
|
} */
|
||||||
/* if(leftHeightToScroll >= 0) {
|
/* if(leftHeightToScroll > 0) {
|
||||||
let height = bubble.scrollHeight;
|
let height = bubble.scrollHeight;
|
||||||
leftHeightToScroll -= height;
|
leftHeightToScroll -= height;
|
||||||
this.scrollable.scrollTop += height;
|
|
||||||
} */ else {
|
if(setScrollRAF) window.cancelAnimationFrame(setScrollRAF);
|
||||||
|
setScrollRAF = window.requestAnimationFrame(() => {
|
||||||
|
//this.scrollable.scrollTop += height;
|
||||||
|
this.scrollable.scrollTop = this.scrollable.scrollHeight - previousScrollHeightMinusTop;
|
||||||
|
});
|
||||||
|
//this.scrollable.scrollTop += height;
|
||||||
|
} else { */
|
||||||
renderedFirstScreen = true;
|
renderedFirstScreen = true;
|
||||||
resolve();
|
resolve();
|
||||||
resolved = true;
|
resolved = true;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
////////this.scrollable.append(bubble);
|
////////this.scrollable.append(bubble);
|
||||||
@ -2026,6 +2047,14 @@ export class AppImManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
firstLoad ? window.requestAnimationFrame(r) : r();
|
firstLoad ? window.requestAnimationFrame(r) : r();
|
||||||
|
|
||||||
|
if(reverse) {
|
||||||
|
//if(setScrollRAF) window.cancelAnimationFrame(setScrollRAF);
|
||||||
|
//setScrollRAF = window.requestAnimationFrame(() => {
|
||||||
|
//this.scrollable.scrollTop += height;
|
||||||
|
this.scrollable.scrollTop = this.scrollable.scrollHeight - previousScrollHeightMinusTop;
|
||||||
|
//});
|
||||||
|
}
|
||||||
//r();
|
//r();
|
||||||
/* method((msgID) => {
|
/* method((msgID) => {
|
||||||
let message = appMessagesManager.getMessage(msgID);
|
let message = appMessagesManager.getMessage(msgID);
|
||||||
@ -2054,7 +2083,7 @@ export class AppImManager {
|
|||||||
|
|
||||||
let pageCount = this.bubblesContainer.clientHeight / 38/* * 1.25 */ | 0;
|
let pageCount = this.bubblesContainer.clientHeight / 38/* * 1.25 */ | 0;
|
||||||
//let loadCount = Object.keys(this.bubbles).length > 0 ? 50 : pageCount;
|
//let loadCount = Object.keys(this.bubbles).length > 0 ? 50 : pageCount;
|
||||||
let realLoadCount = Object.keys(this.bubbles).length > 0 ? 40 : pageCount;//let realLoadCount = 50;
|
let realLoadCount = Object.keys(this.bubbles).length > 0 ? Math.max(40, pageCount) : pageCount;//let realLoadCount = 50;
|
||||||
let loadCount = realLoadCount;
|
let loadCount = realLoadCount;
|
||||||
|
|
||||||
if(testScroll) {
|
if(testScroll) {
|
||||||
@ -2122,10 +2151,9 @@ export class AppImManager {
|
|||||||
ids = Object.keys(this.bubbles).map(i => +i).sort((a, b) => a - b);
|
ids = Object.keys(this.bubbles).map(i => +i).sort((a, b) => a - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log('getHistory: slice loadedTimes:', reverse, pageCount, this.loadedTopTimes, this.loadedBottomTimes, ids && ids.length);
|
|
||||||
|
|
||||||
//let removeCount = loadCount / 2;
|
//let removeCount = loadCount / 2;
|
||||||
let safeCount = Math.min(realLoadCount * 2, 35); // cause i've been runningrunningrunning all day
|
let safeCount = realLoadCount * 2; // cause i've been runningrunningrunning all day
|
||||||
|
this.log('getHistory: slice loadedTimes:', reverse, pageCount, this.loadedTopTimes, this.loadedBottomTimes, ids && ids.length, safeCount);
|
||||||
if(ids && ids.length > safeCount) {
|
if(ids && ids.length > safeCount) {
|
||||||
if(reverse) {
|
if(reverse) {
|
||||||
//ids = ids.slice(-removeCount);
|
//ids = ids.slice(-removeCount);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { SearchIndexManager, $rootScope, copy, tsNow, safeReplaceObject, dT, _, listMergeSorted, deepEqual } from "../utils";
|
import { SearchIndexManager, $rootScope, copy, tsNow, safeReplaceObject, dT, _, listMergeSorted, deepEqual, langPack } from "../utils";
|
||||||
import appMessagesIDsManager from "./appMessagesIDsManager";
|
import appMessagesIDsManager from "./appMessagesIDsManager";
|
||||||
import appChatsManager from "./appChatsManager";
|
import appChatsManager from "./appChatsManager";
|
||||||
import appUsersManager from "./appUsersManager";
|
import appUsersManager from "./appUsersManager";
|
||||||
@ -106,15 +106,13 @@ export class AppMessagesManager {
|
|||||||
public pinnedIndex = 0;
|
public pinnedIndex = 0;
|
||||||
public dialogsNum = 0;
|
public dialogsNum = 0;
|
||||||
|
|
||||||
public migratedFromTo: any = {};
|
public migratedFromTo: {[peerID: number]: number} = {};
|
||||||
public migratedToFrom: any = {};
|
public migratedToFrom: {[peerID: number]: number} = {};
|
||||||
|
|
||||||
public newMessagesHandlePromise = 0;
|
public newMessagesHandlePromise = 0;
|
||||||
public newMessagesToHandle: any = {};
|
public newMessagesToHandle: any = {};
|
||||||
public newDialogsHandlePromise = 0;
|
public newDialogsHandlePromise = 0;
|
||||||
public newDialogsToHandle: any = {};
|
public newDialogsToHandle: {[peerID: string]: {reload: true} | Dialog} = {};
|
||||||
//public notificationsHandlePromise = 0;
|
|
||||||
//public notificationsToHandle: any = {};
|
|
||||||
public newUpdatesAfterReloadToHandle: any = {};
|
public newUpdatesAfterReloadToHandle: any = {};
|
||||||
|
|
||||||
public fwdMessagesPluralize = _('conversation_forwarded_X_messages');
|
public fwdMessagesPluralize = _('conversation_forwarded_X_messages');
|
||||||
@ -125,7 +123,7 @@ export class AppMessagesManager {
|
|||||||
if(maxID && !appMessagesIDsManager.getMessageIDInfo(maxID)[1]) {
|
if(maxID && !appMessagesIDsManager.getMessageIDInfo(maxID)[1]) {
|
||||||
this.maxSeenID = maxID;
|
this.maxSeenID = maxID;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
|
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
|
||||||
let update: any = e.detail;
|
let update: any = e.detail;
|
||||||
@ -183,7 +181,7 @@ export class AppMessagesManager {
|
|||||||
index: dialog.index
|
index: dialog.index
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getInputEntities(entities: any) {
|
public getInputEntities(entities: any) {
|
||||||
@ -248,7 +246,7 @@ export class AppMessagesManager {
|
|||||||
entities: this.getInputEntities(entities),
|
entities: this.getInputEntities(entities),
|
||||||
no_webpage: noWebPage,
|
no_webpage: noWebPage,
|
||||||
}).then((updates) => {
|
}).then((updates) => {
|
||||||
apiUpdatesManager.processUpdateMessage(updates)
|
apiUpdatesManager.processUpdateMessage(updates);
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
if(error && error.type == 'MESSAGE_NOT_MODIFIED') {
|
if(error && error.type == 'MESSAGE_NOT_MODIFIED') {
|
||||||
error.handled = true;
|
error.handled = true;
|
||||||
@ -1129,20 +1127,6 @@ export class AppMessagesManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getConversation(peerID: number) {
|
|
||||||
var foundDialog = this.getDialogByPeerID(peerID);
|
|
||||||
if(foundDialog.length) {
|
|
||||||
return foundDialog[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
peerID: peerID,
|
|
||||||
top_message: 0,
|
|
||||||
index: this.generateDialogIndex(this.generateDialogPinnedDate()),
|
|
||||||
pFlags: {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public getConversations(offsetIndex?: number, limit = 20, folderID = 0) {
|
public getConversations(offsetIndex?: number, limit = 20, folderID = 0) {
|
||||||
let curDialogStorage = this.dialogsStorage.dialogs[folderID] ?? (this.dialogsStorage.dialogs[folderID] = []);
|
let curDialogStorage = this.dialogsStorage.dialogs[folderID] ?? (this.dialogsStorage.dialogs[folderID] = []);
|
||||||
|
|
||||||
@ -1327,13 +1311,47 @@ export class AppMessagesManager {
|
|||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
var date = Date.now() / 1000 | 0;
|
||||||
|
var m = date * 0x10000;
|
||||||
|
|
||||||
|
var k = (date + 1) * 0x10000;
|
||||||
|
k - m;
|
||||||
|
65536
|
||||||
|
*/
|
||||||
public generateDialogIndex(date?: any) {
|
public generateDialogIndex(date?: any) {
|
||||||
if(date === undefined) {
|
if(date === undefined) {
|
||||||
date = tsNow(true) + serverTimeManager.serverTimeOffset;
|
date = tsNow(true) + serverTimeManager.serverTimeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (date * 0x10000) + ((++this.dialogsNum) & 0xFFFF);
|
return (date * 0x10000) + ((++this.dialogsNum) & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public generateIndexForDialog(dialog: Dialog) {
|
||||||
|
let channelID = AppPeersManager.isChannel(dialog.peerID) ? -dialog.peerID : 0;
|
||||||
|
let mid = appMessagesIDsManager.getFullMessageID(dialog.top_message, channelID);
|
||||||
|
let message = this.getMessage(mid);
|
||||||
|
|
||||||
|
let topDate = message.date;
|
||||||
|
if(channelID) {
|
||||||
|
let channel = appChatsManager.getChat(channelID);
|
||||||
|
if(!topDate || channel.date && channel.date > topDate) {
|
||||||
|
topDate = channel.date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let savedDraft: any = {};// DraftsManager.saveDraft(peerID, dialog.draft); // warning
|
||||||
|
if(savedDraft && savedDraft.date > topDate) {
|
||||||
|
topDate = savedDraft.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dialog.pFlags.pinned) {
|
||||||
|
topDate = this.generateDialogPinnedDate(dialog);
|
||||||
|
//console.log('topDate', peerID, topDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.index = this.generateDialogIndex(topDate);
|
||||||
|
}
|
||||||
|
|
||||||
public pushDialogToStorage(dialog: Dialog, offsetDate?: number) {
|
public pushDialogToStorage(dialog: Dialog, offsetDate?: number) {
|
||||||
let dialogs = this.dialogsStorage.dialogs[dialog.folder_id] ?? (this.dialogsStorage.dialogs[dialog.folder_id] = []);
|
let dialogs = this.dialogsStorage.dialogs[dialog.folder_id] ?? (this.dialogsStorage.dialogs[dialog.folder_id] = []);
|
||||||
let pos = this.getDialogByPeerID(dialog.peerID)[1];
|
let pos = this.getDialogByPeerID(dialog.peerID)[1];
|
||||||
@ -1504,7 +1522,7 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'messageMediaPoll':
|
case 'messageMediaPoll':
|
||||||
appPollsManager.savePoll(apiMessage.media.poll, apiMessage.media.results);
|
apiMessage.media.poll = appPollsManager.savePoll(apiMessage.media.poll, apiMessage.media.results);
|
||||||
break;
|
break;
|
||||||
case 'messageMediaDocument':
|
case 'messageMediaDocument':
|
||||||
if(apiMessage.media.ttl_seconds) {
|
if(apiMessage.media.ttl_seconds) {
|
||||||
@ -1512,6 +1530,8 @@ export class AppMessagesManager {
|
|||||||
} else {
|
} else {
|
||||||
apiMessage.media.document = appDocsManager.saveDoc(apiMessage.media.document, mediaContext); // 11.04.2020 warning
|
apiMessage.media.document = appDocsManager.saveDoc(apiMessage.media.document, mediaContext); // 11.04.2020 warning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'messageMediaWebPage':
|
case 'messageMediaWebPage':
|
||||||
/* if(apiMessage.media.webpage.document) {
|
/* if(apiMessage.media.webpage.document) {
|
||||||
@ -1615,6 +1635,8 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apiMessage.rReply = this.getRichReplyText(apiMessage);
|
||||||
|
|
||||||
if(apiMessage.message && apiMessage.message.length) {
|
if(apiMessage.message && apiMessage.message.length) {
|
||||||
var myEntities = RichTextProcessor.parseEntities(apiMessage.message);
|
var myEntities = RichTextProcessor.parseEntities(apiMessage.message);
|
||||||
var apiEntities = apiMessage.entities || [];
|
var apiEntities = apiMessage.entities || [];
|
||||||
@ -1626,7 +1648,110 @@ export class AppMessagesManager {
|
|||||||
if(!options.isEdited) {
|
if(!options.isEdited) {
|
||||||
this.messagesStorage[mid] = apiMessage;
|
this.messagesStorage[mid] = apiMessage;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRichReplyText(message: any) {
|
||||||
|
let messageText = '';
|
||||||
|
|
||||||
|
if(message.media) {
|
||||||
|
switch(message.media._) {
|
||||||
|
case 'messageMediaPhoto':
|
||||||
|
messageText += '<i>' + (message.grouped_id ? 'Album' : 'Photo') + (message.message ? ', ' : '') + '</i>';
|
||||||
|
break;
|
||||||
|
case 'messageMediaGeo':
|
||||||
|
messageText += '<i>Geolocation</i>';
|
||||||
|
break;
|
||||||
|
case 'messageMediaPoll':
|
||||||
|
messageText += '<i>' + message.media.poll.rReply + '</i>';
|
||||||
|
break;
|
||||||
|
case 'messageMediaContact':
|
||||||
|
messageText += '<i>Contact</i>';
|
||||||
|
break;
|
||||||
|
case 'messageMediaDocument':
|
||||||
|
let document = message.media.document;
|
||||||
|
|
||||||
|
let found = false;
|
||||||
|
for(let attribute of document.attributes) {
|
||||||
|
if(found) break;
|
||||||
|
|
||||||
|
switch(attribute._) {
|
||||||
|
case 'documentAttributeSticker':
|
||||||
|
messageText += RichTextProcessor.wrapRichText(attribute.alt) + '<i>Sticker</i>';
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
case 'documentAttributeFilename':
|
||||||
|
messageText += '<i>' + attribute.file_name + '</i>';
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
/* default:
|
||||||
|
console.warn('Got unknown document type!', message);
|
||||||
|
break; */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(document.type == 'video') {
|
||||||
|
messageText = '<i>Video' + (message.message ? ', ' : '') + '</i>';
|
||||||
|
found = true;
|
||||||
|
} else if(document.type == 'voice') {
|
||||||
|
messageText = '<i>Voice message</i>';
|
||||||
|
found = true;
|
||||||
|
} else if(document.type == 'gif') {
|
||||||
|
messageText = '<i>GIF' + (message.message ? ', ' : '') + '</i>';
|
||||||
|
found = true;
|
||||||
|
} else if(document.type == 'round') {
|
||||||
|
messageText = '<i>Video message' + (message.message ? ', ' : '') + '</i>';
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(found) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
///////console.warn('Got unknown message.media type!', message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(message.action) {
|
||||||
|
let action = message.action;
|
||||||
|
|
||||||
|
console.log('message action:', action);
|
||||||
|
|
||||||
|
let suffix = '';
|
||||||
|
let _ = action._;
|
||||||
|
if(_ == "messageActionPhoneCall") {
|
||||||
|
_ += '.' + action.type;
|
||||||
|
|
||||||
|
let duration = action.duration;
|
||||||
|
if(duration) {
|
||||||
|
let d = [];
|
||||||
|
|
||||||
|
d.push(duration % 60 + ' s');
|
||||||
|
if(duration >= 60) d.push((duration / 60 | 0) + ' min');
|
||||||
|
//if(duration >= 3600) d.push((duration / 3600 | 0) + ' h');
|
||||||
|
suffix = ' (' + d.reverse().join(' ') + ')';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
messageText = '<i>' + langPack[_] + suffix + '</i>';
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = message.message;
|
||||||
|
let messageWrapped = '';
|
||||||
|
if(text) {
|
||||||
|
let entities = RichTextProcessor.parseEntities(text.replace(/\n/g, ' '), {noLinebreakers: true});
|
||||||
|
|
||||||
|
messageWrapped = RichTextProcessor.wrapRichText(text, {
|
||||||
|
noLinebreakers: true,
|
||||||
|
entities: entities,
|
||||||
|
noTextFormat: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageText + messageWrapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
public migrateChecks(migrateFrom: number, migrateTo: number) {
|
public migrateChecks(migrateFrom: number, migrateTo: number) {
|
||||||
@ -1644,7 +1769,7 @@ export class AppMessagesManager {
|
|||||||
var foundDialog = this.getDialogByPeerID(migrateFrom);
|
var foundDialog = this.getDialogByPeerID(migrateFrom);
|
||||||
if(foundDialog.length) {
|
if(foundDialog.length) {
|
||||||
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||||
$rootScope.$broadcast('dialog_drop', {peerID: migrateFrom});
|
$rootScope.$broadcast('dialog_drop', {peerID: migrateFrom, dialog: foundDialog[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootScope.$broadcast('dialog_migrate', {migrateFrom: migrateFrom, migrateTo: migrateTo});
|
$rootScope.$broadcast('dialog_migrate', {migrateFrom: migrateFrom, migrateTo: migrateTo});
|
||||||
@ -1703,7 +1828,7 @@ export class AppMessagesManager {
|
|||||||
|
|
||||||
//console.log('applyConversation', dialogsResult);
|
//console.log('applyConversation', dialogsResult);
|
||||||
|
|
||||||
var updatedDialogs: any = {};
|
var updatedDialogs: {[peerID: number]: Dialog} = {};
|
||||||
var hasUpdated = false;
|
var hasUpdated = false;
|
||||||
dialogsResult.dialogs.forEach((dialog: any) => {
|
dialogsResult.dialogs.forEach((dialog: any) => {
|
||||||
var peerID = AppPeersManager.getPeerID(dialog.peer);
|
var peerID = AppPeersManager.getPeerID(dialog.peer);
|
||||||
@ -1738,7 +1863,7 @@ export class AppMessagesManager {
|
|||||||
var foundDialog = this.getDialogByPeerID(peerID);
|
var foundDialog = this.getDialogByPeerID(peerID);
|
||||||
if(foundDialog.length) {
|
if(foundDialog.length) {
|
||||||
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||||
$rootScope.$broadcast('dialog_drop', {peerID: peerID});
|
$rootScope.$broadcast('dialog_drop', {peerID: peerID, dialog: foundDialog[0]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1806,24 +1931,7 @@ export class AppMessagesManager {
|
|||||||
dialog.read_inbox_max_id = appMessagesIDsManager.getFullMessageID(dialog.read_inbox_max_id, channelID);
|
dialog.read_inbox_max_id = appMessagesIDsManager.getFullMessageID(dialog.read_inbox_max_id, channelID);
|
||||||
dialog.read_outbox_max_id = appMessagesIDsManager.getFullMessageID(dialog.read_outbox_max_id, channelID);
|
dialog.read_outbox_max_id = appMessagesIDsManager.getFullMessageID(dialog.read_outbox_max_id, channelID);
|
||||||
|
|
||||||
var topDate = message.date;
|
this.generateIndexForDialog(dialog);
|
||||||
if(channelID) {
|
|
||||||
var channel = appChatsManager.getChat(channelID);
|
|
||||||
if(!topDate || channel.date && channel.date > topDate) {
|
|
||||||
topDate = channel.date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var savedDraft: any = {};// DraftsManager.saveDraft(peerID, dialog.draft); // warning
|
|
||||||
if(savedDraft && savedDraft.date > topDate) {
|
|
||||||
topDate = savedDraft.date;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dialog.pFlags.pinned) {
|
|
||||||
topDate = this.generateDialogPinnedDate(dialog);
|
|
||||||
//console.log('topDate', peerID, topDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog.index = this.generateDialogIndex(topDate);
|
|
||||||
dialog.peerID = peerID;
|
dialog.peerID = peerID;
|
||||||
if(!dialog.folder_id) dialog.folder_id = 0;
|
if(!dialog.folder_id) dialog.folder_id = 0;
|
||||||
|
|
||||||
@ -2146,7 +2254,7 @@ export class AppMessagesManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public generateDialogPinnedDate(dialog?: any) {
|
public generateDialogPinnedDate(dialog?: Dialog) {
|
||||||
let pinnedIndex: number;
|
let pinnedIndex: number;
|
||||||
|
|
||||||
if(dialog) {
|
if(dialog) {
|
||||||
@ -2174,10 +2282,10 @@ export class AppMessagesManager {
|
|||||||
clearTimeout(this.newDialogsHandlePromise);
|
clearTimeout(this.newDialogsHandlePromise);
|
||||||
this.newDialogsHandlePromise = 0;
|
this.newDialogsHandlePromise = 0;
|
||||||
|
|
||||||
var newMaxSeenID = 0
|
let newMaxSeenID = 0;
|
||||||
Object.keys(this.newDialogsToHandle).forEach((peerID) => {
|
Object.keys(this.newDialogsToHandle).forEach((peerID) => {
|
||||||
let dialog = this.newDialogsToHandle[peerID];
|
let dialog = this.newDialogsToHandle[peerID];
|
||||||
if(dialog.reload) {
|
if('reload' in dialog) {
|
||||||
this.reloadConversation(+peerID);
|
this.reloadConversation(+peerID);
|
||||||
delete this.newDialogsToHandle[peerID];
|
delete this.newDialogsToHandle[peerID];
|
||||||
} else {
|
} else {
|
||||||
@ -2186,7 +2294,9 @@ export class AppMessagesManager {
|
|||||||
newMaxSeenID = Math.max(newMaxSeenID, dialog.top_message || 0);
|
newMaxSeenID = Math.max(newMaxSeenID, dialog.top_message || 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
console.log('after order:', this.dialogsStorage.dialogs[0].map(d => d.peerID));
|
||||||
|
|
||||||
if(newMaxSeenID != 0) {
|
if(newMaxSeenID != 0) {
|
||||||
this.incrementMaxSeenID(newMaxSeenID);
|
this.incrementMaxSeenID(newMaxSeenID);
|
||||||
@ -2339,7 +2449,7 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public handleUpdate(update: any) {
|
public handleUpdate(update: any) {
|
||||||
//console.log('AMM: handleUpdate:', update._);
|
console.log('AMM: handleUpdate:', update._);
|
||||||
switch(update._) {
|
switch(update._) {
|
||||||
case 'updateMessageID': {
|
case 'updateMessageID': {
|
||||||
var randomID = update.random_id;
|
var randomID = update.random_id;
|
||||||
@ -2469,26 +2579,37 @@ export class AppMessagesManager {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* case 'updateDialogPinned': {
|
case 'updateDialogPinned': {
|
||||||
var peerID = AppPeersManager.getPeerID(update.peer);
|
console.log('updateDialogPinned', update);
|
||||||
var foundDialog = this.getDialogByPeerID(peerID);
|
let peerID = AppPeersManager.getPeerID(update.peer.peer);
|
||||||
|
let foundDialog = this.getDialogByPeerID(peerID);
|
||||||
|
|
||||||
if(!foundDialog.length || !update.pFlags.pinned) {
|
if(!this.newDialogsHandlePromise) {
|
||||||
this.newDialogsToHandle[peerID] = {reload: true};
|
this.newDialogsHandlePromise = window.setTimeout(this.handleNewDialogs.bind(this), 0);
|
||||||
if(!this.newDialogsHandlePromise) {
|
}
|
||||||
this.newDialogsHandlePromise = window.setTimeout(this.handleNewDialogs.bind(this), 0);
|
|
||||||
}
|
if(!foundDialog.length) {
|
||||||
break;
|
this.newDialogsToHandle[peerID] = {reload: true};
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
let dialog = foundDialog[0];
|
||||||
|
this.newDialogsToHandle[peerID] = dialog;
|
||||||
|
|
||||||
|
if(!update.pFlags.pinned) {
|
||||||
|
delete dialog.pFlags.pinned;
|
||||||
|
} else { // means set
|
||||||
|
dialog.pFlags.pinned = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.generateIndexForDialog(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dialog = foundDialog[0];
|
|
||||||
dialog.index = this.generateDialogIndex(this.generateDialogPinnedDate(dialog));
|
|
||||||
dialog.pFlags.pinned = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'updatePinnedDialogs': {
|
case 'updatePinnedDialogs': {
|
||||||
var newPinned: any = {};
|
console.log('updatePinnedDialogs', update);
|
||||||
|
let newPinned: {[peerID: number]: true} = {};
|
||||||
if(!update.order) {
|
if(!update.order) {
|
||||||
apiManager.invokeApi('messages.getPinnedDialogs', {}).then((dialogsResult: any) => {
|
apiManager.invokeApi('messages.getPinnedDialogs', {}).then((dialogsResult: any) => {
|
||||||
dialogsResult.dialogs.reverse();
|
dialogsResult.dialogs.reverse();
|
||||||
@ -2498,8 +2619,8 @@ export class AppMessagesManager {
|
|||||||
newPinned[dialog.peerID] = true;
|
newPinned[dialog.peerID] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.dialogsStorage.dialogs.forEach((dialog: any) => {
|
this.dialogsStorage.dialogs[0].forEach((dialog: any) => {
|
||||||
var peerID = dialog.peerID;
|
let peerID = dialog.peerID;
|
||||||
if(dialog.pFlags.pinned && !newPinned[peerID]) {
|
if(dialog.pFlags.pinned && !newPinned[peerID]) {
|
||||||
this.newDialogsToHandle[peerID] = {reload: true};
|
this.newDialogsToHandle[peerID] = {reload: true};
|
||||||
if(!this.newDialogsHandlePromise) {
|
if(!this.newDialogsHandlePromise) {
|
||||||
@ -2511,42 +2632,45 @@ export class AppMessagesManager {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
update.order.reverse();
|
console.log('before order:', this.dialogsStorage.dialogs[0].map(d => d.peerID));
|
||||||
|
|
||||||
|
this.pinnedIndex = 0;
|
||||||
|
let willHandle = false;
|
||||||
|
update.order.reverse(); // index must be higher
|
||||||
update.order.forEach((peer: any) => {
|
update.order.forEach((peer: any) => {
|
||||||
var peerID = AppPeersManager.getPeerID(peer);
|
let peerID = AppPeersManager.getPeerID(peer.peer);
|
||||||
newPinned[peerID] = true;
|
newPinned[peerID] = true;
|
||||||
|
|
||||||
var foundDialog = this.getDialogByPeerID(peerID);
|
let foundDialog = this.getDialogByPeerID(peerID);
|
||||||
|
|
||||||
if(!foundDialog.length) {
|
if(!foundDialog.length) {
|
||||||
this.newDialogsToHandle[peerID] = {reload: true}
|
this.newDialogsToHandle[peerID] = {reload: true};
|
||||||
if(!this.newDialogsHandlePromise) {
|
willHandle = true;
|
||||||
this.newDialogsHandlePromise = window.setTimeout(this.handleNewDialogs.bind(this), 0);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dialog = foundDialog[0]
|
let dialog = foundDialog[0];
|
||||||
dialog.index = this.generateDialogIndex(this.generateDialogPinnedDate(dialog));
|
delete dialog.pinnedIndex;
|
||||||
dialog.pFlags.pinned = true;
|
dialog.pFlags.pinned = true;
|
||||||
|
this.generateIndexForDialog(dialog);
|
||||||
|
|
||||||
this.newDialogsToHandle[peerID] = dialog
|
this.newDialogsToHandle[peerID] = dialog;
|
||||||
if(!this.newDialogsHandlePromise) {
|
willHandle = true;
|
||||||
this.newDialogsHandlePromise = window.setTimeout(this.handleNewDialogs.bind(this), 0);
|
});
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.dialogsStorage.dialogs.forEach((dialog: any) => {
|
this.dialogsStorage.dialogs[0].forEach(dialog => {
|
||||||
var peerID = dialog.peerID;
|
let peerID = dialog.peerID;
|
||||||
if(dialog.pFlags.pinned && !newPinned[peerID]) {
|
if(dialog.pFlags.pinned && !newPinned[peerID]) {
|
||||||
this.newDialogsToHandle[peerID] = {reload: true}
|
this.newDialogsToHandle[peerID] = {reload: true};
|
||||||
if(!this.newDialogsHandlePromise) {
|
willHandle = true;
|
||||||
this.newDialogsHandlePromise = window.setTimeout(this.handleNewDialogs.bind(this), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
if(willHandle && !this.newDialogsHandlePromise) {
|
||||||
|
this.newDialogsHandlePromise = window.setTimeout(this.handleNewDialogs.bind(this), 0);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} */
|
}
|
||||||
|
|
||||||
case 'updateEditMessage':
|
case 'updateEditMessage':
|
||||||
case 'updateEditChannelMessage': {
|
case 'updateEditChannelMessage': {
|
||||||
@ -2819,7 +2943,7 @@ export class AppMessagesManager {
|
|||||||
} else {
|
} else {
|
||||||
if(foundDialog[0]) {
|
if(foundDialog[0]) {
|
||||||
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
this.dialogsStorage.dialogs[foundDialog[0].folder_id].splice(foundDialog[1], 1);
|
||||||
$rootScope.$broadcast('dialog_drop', {peerID: peerID});
|
$rootScope.$broadcast('dialog_drop', {peerID: peerID, dialog: foundDialog[0]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2964,25 +3088,16 @@ export class AppMessagesManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getHistory(peerID: number, maxID = 0, limit = 0, backLimit?: number, prerendered?: number) {
|
public getHistory(peerID: number, maxID = 0, limit: number, backLimit?: number) {
|
||||||
if(this.migratedFromTo[peerID]) {
|
if(this.migratedFromTo[peerID]) {
|
||||||
peerID = this.migratedFromTo[peerID];
|
peerID = this.migratedFromTo[peerID];
|
||||||
}
|
}
|
||||||
var historyStorage = this.historiesStorage[peerID];
|
var historyStorage = this.historiesStorage[peerID] ?? (this.historiesStorage[peerID] = {count: null, history: [], pending: []});
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
var offsetNotFound = false;
|
var offsetNotFound = false;
|
||||||
var unreadOffset = 0;
|
var unreadOffset = 0;
|
||||||
var unreadSkip = false;
|
var unreadSkip = false;
|
||||||
|
|
||||||
prerendered = prerendered ? Math.min(50, prerendered) : 0;
|
|
||||||
|
|
||||||
if(historyStorage === undefined) {
|
|
||||||
historyStorage = this.historiesStorage[peerID] = {count: null, history: [], pending: []};
|
|
||||||
}
|
|
||||||
|
|
||||||
if(maxID < 0) {
|
|
||||||
maxID = 0;
|
|
||||||
}
|
|
||||||
var isMigrated = false;
|
var isMigrated = false;
|
||||||
var reqPeerID = peerID;
|
var reqPeerID = peerID;
|
||||||
if(this.migratedToFrom[peerID]) {
|
if(this.migratedToFrom[peerID]) {
|
||||||
@ -2992,30 +3107,6 @@ export class AppMessagesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!limit && !maxID) {
|
|
||||||
var foundDialog = this.getDialogByPeerID(peerID)[0];
|
|
||||||
if(foundDialog && foundDialog.unread_count > 1) {
|
|
||||||
var unreadCount = foundDialog.unread_count;
|
|
||||||
if(unreadSkip = (unreadCount > 50)) {
|
|
||||||
if(foundDialog.read_inbox_max_id) {
|
|
||||||
maxID = foundDialog.read_inbox_max_id;
|
|
||||||
backLimit = 16;
|
|
||||||
unreadOffset = 16;
|
|
||||||
limit = 4;
|
|
||||||
} else {
|
|
||||||
limit = 20;
|
|
||||||
unreadOffset = 16;
|
|
||||||
offset = unreadCount - unreadOffset;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
limit = Math.max(10, prerendered, unreadCount + 2);
|
|
||||||
unreadOffset = unreadCount;
|
|
||||||
}
|
|
||||||
}/* else if('Mobile' in Config) {
|
|
||||||
limit = 20;
|
|
||||||
} */
|
|
||||||
}
|
|
||||||
|
|
||||||
if(maxID > 0) {
|
if(maxID > 0) {
|
||||||
offsetNotFound = true;
|
offsetNotFound = true;
|
||||||
for(offset = 0; offset < historyStorage.history.length; offset++) {
|
for(offset = 0; offset < historyStorage.history.length; offset++) {
|
||||||
@ -3035,7 +3126,7 @@ export class AppMessagesManager {
|
|||||||
offset = Math.max(0, offset - backLimit);
|
offset = Math.max(0, offset - backLimit);
|
||||||
limit += backLimit;
|
limit += backLimit;
|
||||||
} else {
|
} else {
|
||||||
limit = limit || (offset ? 20 : (prerendered || 5));
|
limit = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
var history = historyStorage.history.slice(offset, offset + limit);
|
var history = historyStorage.history.slice(offset, offset + limit);
|
||||||
@ -3051,9 +3142,6 @@ export class AppMessagesManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!backLimit && !limit) {
|
|
||||||
limit = prerendered || 20;
|
|
||||||
}
|
|
||||||
if(offsetNotFound) {
|
if(offsetNotFound) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
import { RichTextProcessor } from "../richtextprocessor";
|
import { RichTextProcessor } from "../richtextprocessor";
|
||||||
|
import appMessagesManager from './appMessagesManager';
|
||||||
|
import appPeersManager from './appPeersManager';
|
||||||
|
import apiManager from "../mtproto/mtprotoworker";
|
||||||
|
import apiUpdatesManager from "./apiUpdatesManager";
|
||||||
|
import { $rootScope } from "../utils";
|
||||||
|
|
||||||
export type PollAnswer = {
|
export type PollAnswer = {
|
||||||
_: 'pollAnswer',
|
_: 'pollAnswer',
|
||||||
@ -58,24 +63,60 @@ export type Poll = {
|
|||||||
}>,
|
}>,
|
||||||
rQuestion?: string,
|
rQuestion?: string,
|
||||||
rReply?: string,
|
rReply?: string,
|
||||||
|
chosenIndex?: number
|
||||||
};
|
};
|
||||||
|
|
||||||
class AppPollsManager {
|
class AppPollsManager {
|
||||||
private polls: {[id: string]: Poll} = {};
|
private polls: {[id: string]: Poll} = {};
|
||||||
private results: {[id: string]: PollResults} = {};
|
private results: {[id: string]: PollResults} = {};
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
$rootScope.$on('apiUpdate', (e: CustomEvent) => {
|
||||||
|
let update = e.detail;
|
||||||
|
|
||||||
|
this.handleUpdate(update);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public handleUpdate(update: any) {
|
||||||
|
switch(update._) {
|
||||||
|
case 'updateMessagePoll': { // when someone voted, we too
|
||||||
|
console.log('updateMessagePoll:', update);
|
||||||
|
|
||||||
|
let poll: Poll = this.polls[update.poll_id] || update.poll;
|
||||||
|
if(!poll) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
poll = this.savePoll(poll, update.results);
|
||||||
|
$rootScope.$broadcast('poll_update', {poll, results: update.results});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public savePoll(poll: Poll, results: PollResults) {
|
public savePoll(poll: Poll, results: PollResults) {
|
||||||
let id = poll.id;
|
let id = poll.id;
|
||||||
if(this.polls[id]) {
|
if(this.polls[id]) {
|
||||||
this.results[id] = results;
|
poll = this.polls[id];
|
||||||
return;
|
this.saveResults(poll, results);
|
||||||
|
return poll;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.polls[id] = poll;
|
this.polls[id] = poll;
|
||||||
this.results[id] = results;
|
|
||||||
|
|
||||||
poll.rQuestion = RichTextProcessor.wrapEmojiText(poll.question);
|
poll.rQuestion = RichTextProcessor.wrapEmojiText(poll.question);
|
||||||
poll.rReply = RichTextProcessor.wrapEmojiText('📊') + ' ' + (poll.rQuestion || 'poll');
|
poll.rReply = RichTextProcessor.wrapEmojiText('📊') + ' ' + (poll.rQuestion || 'poll');
|
||||||
|
this.saveResults(poll, results);
|
||||||
|
return poll;
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveResults(poll: Poll, results: PollResults) {
|
||||||
|
this.results[poll.id] = results;
|
||||||
|
poll.chosenIndex = (results && results.results && results.results.findIndex(answer => answer.pFlags?.chosen)) ?? -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPoll(pollID: string): {poll: Poll, results: PollResults} {
|
public getPoll(pollID: string): {poll: Poll, results: PollResults} {
|
||||||
@ -84,6 +125,27 @@ class AppPollsManager {
|
|||||||
results: this.results[pollID]
|
results: this.results[pollID]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sendVote(mid: number, optionIDs: number[]) {
|
||||||
|
let message = appMessagesManager.getMessage(mid);
|
||||||
|
let poll: Poll = message.media.poll;
|
||||||
|
|
||||||
|
let options: Uint8Array[] = optionIDs.map(index => {
|
||||||
|
return poll.answers[index].option;
|
||||||
|
});
|
||||||
|
|
||||||
|
let inputPeer = appPeersManager.getInputPeerByID(message.peerID);
|
||||||
|
let messageID = message.id;
|
||||||
|
|
||||||
|
return apiManager.invokeApi('messages.sendVote', {
|
||||||
|
peer: inputPeer,
|
||||||
|
msg_id: messageID,
|
||||||
|
options
|
||||||
|
}).then(updates => {
|
||||||
|
console.log('appPollsManager sendVote updates:', updates);
|
||||||
|
apiUpdatesManager.processUpdateMessage(updates);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new AppPollsManager();
|
export default new AppPollsManager();
|
2
src/lib/smoothscroll.js
Normal file
2
src/lib/smoothscroll.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// credits to https://github.com/iamdustan/smoothscroll
|
||||||
|
!function(){"use strict";function o(){var o=window,t=document;if(!("scrollBehavior"in t.documentElement.style&&!0!==o.__forceSmoothScrollPolyfill__)){var l,e=o.HTMLElement||o.Element,r=468,i={scroll:o.scroll||o.scrollTo,scrollBy:o.scrollBy,elementScroll:e.prototype.scroll||n,scrollIntoView:e.prototype.scrollIntoView},s=o.performance&&o.performance.now?o.performance.now.bind(o.performance):Date.now,c=(l=o.navigator.userAgent,new RegExp(["MSIE ","Trident/","Edge/"].join("|")).test(l)?1:0);o.scroll=o.scrollTo=function(){void 0!==arguments[0]&&(!0!==f(arguments[0])?h.call(o,t.body,void 0!==arguments[0].left?~~arguments[0].left:o.scrollX||o.pageXOffset,void 0!==arguments[0].top?~~arguments[0].top:o.scrollY||o.pageYOffset):i.scroll.call(o,void 0!==arguments[0].left?arguments[0].left:"object"!=typeof arguments[0]?arguments[0]:o.scrollX||o.pageXOffset,void 0!==arguments[0].top?arguments[0].top:void 0!==arguments[1]?arguments[1]:o.scrollY||o.pageYOffset))},o.scrollBy=function(){void 0!==arguments[0]&&(f(arguments[0])?i.scrollBy.call(o,void 0!==arguments[0].left?arguments[0].left:"object"!=typeof arguments[0]?arguments[0]:0,void 0!==arguments[0].top?arguments[0].top:void 0!==arguments[1]?arguments[1]:0):h.call(o,t.body,~~arguments[0].left+(o.scrollX||o.pageXOffset),~~arguments[0].top+(o.scrollY||o.pageYOffset)))},e.prototype.scroll=e.prototype.scrollTo=function(){if(void 0!==arguments[0])if(!0!==f(arguments[0])){var o=arguments[0].left,t=arguments[0].top;h.call(this,this,void 0===o?this.scrollLeft:~~o,void 0===t?this.scrollTop:~~t)}else{if("number"==typeof arguments[0]&&void 0===arguments[1])throw new SyntaxError("Value could not be converted");i.elementScroll.call(this,void 0!==arguments[0].left?~~arguments[0].left:"object"!=typeof arguments[0]?~~arguments[0]:this.scrollLeft,void 0!==arguments[0].top?~~arguments[0].top:void 0!==arguments[1]?~~arguments[1]:this.scrollTop)}},e.prototype.scrollBy=function(){void 0!==arguments[0]&&(!0!==f(arguments[0])?this.scroll({left:~~arguments[0].left+this.scrollLeft,top:~~arguments[0].top+this.scrollTop,behavior:arguments[0].behavior}):i.elementScroll.call(this,void 0!==arguments[0].left?~~arguments[0].left+this.scrollLeft:~~arguments[0]+this.scrollLeft,void 0!==arguments[0].top?~~arguments[0].top+this.scrollTop:~~arguments[1]+this.scrollTop))},e.prototype.scrollIntoView=function(){if(!0!==f(arguments[0])){var l=function(o){for(;o!==t.body&&!1===(e=p(l=o,"Y")&&a(l,"Y"),r=p(l,"X")&&a(l,"X"),e||r);)o=o.parentNode||o.host;var l,e,r;return o}(this),e=l.getBoundingClientRect(),r=this.getBoundingClientRect();l!==t.body?(h.call(this,l,l.scrollLeft+r.left-e.left,l.scrollTop+r.top-e.top),"fixed"!==o.getComputedStyle(l).position&&o.scrollBy({left:e.left,top:e.top,behavior:"smooth"})):o.scrollBy({left:r.left,top:r.top,behavior:"smooth"})}else i.scrollIntoView.call(this,void 0===arguments[0]||arguments[0])}}function n(o,t){this.scrollLeft=o,this.scrollTop=t}function f(o){if(null===o||"object"!=typeof o||void 0===o.behavior||"auto"===o.behavior||"instant"===o.behavior)return!0;if("object"==typeof o&&"smooth"===o.behavior)return!1;throw new TypeError("behavior member of ScrollOptions "+o.behavior+" is not a valid value for enumeration ScrollBehavior.")}function p(o,t){return"Y"===t?o.clientHeight+c<o.scrollHeight:"X"===t?o.clientWidth+c<o.scrollWidth:void 0}function a(t,l){var e=o.getComputedStyle(t,null)["overflow"+l];return"auto"===e||"scroll"===e}function d(t){var l,e,i,c,n=(s()-t.startTime)/r;c=n=n>1?1:n,l=.5*(1-Math.cos(Math.PI*c)),e=t.startX+(t.x-t.startX)*l,i=t.startY+(t.y-t.startY)*l,t.method.call(t.scrollable,e,i),e===t.x&&i===t.y||o.requestAnimationFrame(d.bind(o,t))}function h(l,e,r){var c,f,p,a,h=s();l===t.body?(c=o,f=o.scrollX||o.pageXOffset,p=o.scrollY||o.pageYOffset,a=i.scroll):(c=l,f=l.scrollLeft,p=l.scrollTop,a=n),d({scrollable:c,method:a,startTime:h,startX:f,startY:p,x:e,y:r})}}"object"==typeof exports&&"undefined"!=typeof module?module.exports={polyfill:o}:o()}();
|
@ -288,7 +288,7 @@ export function getSelectedText() {
|
|||||||
|
|
||||||
export const $rootScope = {
|
export const $rootScope = {
|
||||||
$broadcast: (name/* : string */, detail/*? : any */) => {
|
$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();
|
//console.trace();
|
||||||
let myCustomEvent = new CustomEvent(name, {detail});
|
let myCustomEvent = new CustomEvent(name, {detail});
|
||||||
document.dispatchEvent(myCustomEvent);
|
document.dispatchEvent(myCustomEvent);
|
||||||
|
@ -5,6 +5,7 @@ import Config from '../lib/config';
|
|||||||
|
|
||||||
import { findUpTag } from "../lib/utils";
|
import { findUpTag } from "../lib/utils";
|
||||||
import pageAuthCode from "./pageAuthCode";
|
import pageAuthCode from "./pageAuthCode";
|
||||||
|
import pageSignQR from './pageSignQR';
|
||||||
//import apiManager from "../lib/mtproto/apiManager";
|
//import apiManager from "../lib/mtproto/apiManager";
|
||||||
import apiManager from "../lib/mtproto/mtprotoworker";
|
import apiManager from "../lib/mtproto/mtprotoworker";
|
||||||
import Page from "./page";
|
import Page from "./page";
|
||||||
@ -54,6 +55,10 @@ let onFirstMount = () => {
|
|||||||
|
|
||||||
let initedSelect = false;
|
let initedSelect = false;
|
||||||
|
|
||||||
|
page.pageEl.querySelector('.a-qr').addEventListener('click', () => {
|
||||||
|
pageSignQR.mount();
|
||||||
|
});
|
||||||
|
|
||||||
selectCountryCode.addEventListener('focus', function(this: typeof selectCountryCode, e) {
|
selectCountryCode.addEventListener('focus', function(this: typeof selectCountryCode, e) {
|
||||||
/* this.removeAttribute('readonly'); */
|
/* this.removeAttribute('readonly'); */
|
||||||
if(!initedSelect) {
|
if(!initedSelect) {
|
||||||
@ -114,7 +119,7 @@ let onFirstMount = () => {
|
|||||||
parent.appendChild(wrapper);
|
parent.appendChild(wrapper);
|
||||||
}/* , {once: true} */);
|
}/* , {once: true} */);
|
||||||
selectCountryCode.addEventListener('blur', function(this: typeof selectCountryCode, e) {
|
selectCountryCode.addEventListener('blur', function(this: typeof selectCountryCode, e) {
|
||||||
//parent.removeChild(wrapper);
|
parent.removeChild(wrapper);
|
||||||
e.cancelBubble = true;
|
e.cancelBubble = true;
|
||||||
}, {capture: true});
|
}, {capture: true});
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import apiManager from '../lib/mtproto/mtprotoworker';
|
|||||||
import Page from './page';
|
import Page from './page';
|
||||||
import pageIm from './pageIm';
|
import pageIm from './pageIm';
|
||||||
import pagePassword from './pagePassword';
|
import pagePassword from './pagePassword';
|
||||||
|
import pageSignIn from './pageSignIn';
|
||||||
import { App } from '../lib/mtproto/mtproto_config';
|
import { App } from '../lib/mtproto/mtproto_config';
|
||||||
import { bytesToBase64, bytesCmp } from '../lib/bin_utils';
|
import { bytesToBase64, bytesCmp } from '../lib/bin_utils';
|
||||||
import serverTimeManager from '../lib/mtproto/serverTimeManager';
|
import serverTimeManager from '../lib/mtproto/serverTimeManager';
|
||||||
@ -53,6 +54,10 @@ let onFirstMount = async() => {
|
|||||||
const pageElement = page.pageEl;
|
const pageElement = page.pageEl;
|
||||||
const imageDiv = pageElement.querySelector('.auth-image') as HTMLDivElement;
|
const imageDiv = pageElement.querySelector('.auth-image') as HTMLDivElement;
|
||||||
|
|
||||||
|
page.pageEl.querySelector('.a-qr').addEventListener('click', () => {
|
||||||
|
pageSignIn.mount();
|
||||||
|
});
|
||||||
|
|
||||||
const results = await Promise.all([
|
const results = await Promise.all([
|
||||||
import('qr-code-styling' as any)
|
import('qr-code-styling' as any)
|
||||||
]);
|
]);
|
||||||
|
@ -362,6 +362,11 @@ $time-background: rgba(0, 0, 0, 0.35);
|
|||||||
background-position: center center;
|
background-position: center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-style: normal;
|
||||||
|
color: $color-blue;
|
||||||
|
}
|
||||||
|
|
||||||
img.emoji {
|
img.emoji {
|
||||||
height: 16px;
|
height: 16px;
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
@ -6,6 +6,18 @@
|
|||||||
max-width: $chat-max-width;
|
max-width: $chat-max-width;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
|
&.is-selected {
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #7ca09f;
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.is-date {
|
&.is-date {
|
||||||
position: -webkit-sticky;
|
position: -webkit-sticky;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
@ -106,7 +118,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.is-group-last) .user-avatar {
|
&:not(.is-group-last) .bubble__container > .user-avatar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +200,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.emoji-1x {
|
&.emoji-1x .attachment {
|
||||||
font-size: 96px;
|
font-size: 96px;
|
||||||
|
|
||||||
img.emoji {
|
img.emoji {
|
||||||
@ -199,7 +211,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.emoji-2x {
|
&.emoji-2x .attachment {
|
||||||
font-size: 64px;
|
font-size: 64px;
|
||||||
|
|
||||||
img.emoji {
|
img.emoji {
|
||||||
@ -210,7 +222,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.emoji-3x {
|
&.emoji-3x .attachment {
|
||||||
font-size: 52px;
|
font-size: 52px;
|
||||||
|
|
||||||
img.emoji {
|
img.emoji {
|
||||||
@ -590,6 +602,10 @@
|
|||||||
content: "\e929";
|
content: "\e929";
|
||||||
margin-right: -2px;
|
margin-right: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.message.contact-message {
|
.message.contact-message {
|
||||||
@ -599,6 +615,7 @@
|
|||||||
.contact {
|
.contact {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&-avatar {
|
&-avatar {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@ -639,6 +656,8 @@
|
|||||||
&-name {
|
&-name {
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -844,15 +863,15 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img.emoji {
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bubble-audio.is-in .time {
|
.bubble-audio .time {
|
||||||
width: inherit;
|
width: unset !important;
|
||||||
}
|
|
||||||
|
|
||||||
.bubble-audio.is-out .time {
|
|
||||||
width: inherit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bubble.is-in {
|
.bubble.is-in {
|
||||||
@ -959,6 +978,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* .poll {
|
||||||
|
&-answer-selected {
|
||||||
|
&:before {
|
||||||
|
margin-left: -1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
.bubble.is-out {
|
.bubble.is-out {
|
||||||
@ -1122,6 +1149,10 @@
|
|||||||
stroke: #4fae4e;
|
stroke: #4fae4e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-answer-selected {
|
||||||
|
background-color: #4fae4e;
|
||||||
|
}
|
||||||
|
|
||||||
&-answer:hover {
|
&-answer:hover {
|
||||||
.animation-ring {
|
.animation-ring {
|
||||||
background-color: rgba(79, 174, 78, 0.08);
|
background-color: rgba(79, 174, 78, 0.08);
|
||||||
@ -1163,7 +1194,7 @@ poll-element {
|
|||||||
|
|
||||||
&-text {
|
&-text {
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
margin-left: 7px;
|
margin-left: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-percents {
|
&-percents {
|
||||||
@ -1174,7 +1205,26 @@ poll-element {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
transition: .34s opacity;
|
transition: .34s opacity;
|
||||||
margin-left: -1px;
|
margin-left: -3px;
|
||||||
|
text-align: right;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-selected {
|
||||||
|
position: absolute;
|
||||||
|
top: 33px;
|
||||||
|
left: 26px;
|
||||||
|
color: #fff;
|
||||||
|
background: #50a2e9;
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 15px;
|
||||||
|
opacity: 0;
|
||||||
|
animation: fadeIn .1s ease forwards;
|
||||||
|
animation-direction: reverse;
|
||||||
|
animation-delay: .24s;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -1182,7 +1232,9 @@ poll-element {
|
|||||||
visibility: visible;
|
visibility: visible;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-voting {
|
||||||
.progress-ring__circle {
|
.progress-ring__circle {
|
||||||
stroke-dashoffset: -19.792;
|
stroke-dashoffset: -19.792;
|
||||||
animation: pollAnswerRotate 0.65s linear infinite;
|
animation: pollAnswerRotate 0.65s linear infinite;
|
||||||
@ -1197,13 +1249,16 @@ poll-element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-line {
|
&-line {
|
||||||
height: 28px;
|
height: 35px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 11.5px;
|
left: 17.5px;
|
||||||
top: 14px;
|
top: 11px;
|
||||||
|
transition: stroke-dashoffset .34s linear, stroke-dasharray .34s linear;
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
stroke-dasharray: 0, 485.9;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
stroke-width: 3.5px;
|
stroke-width: 4px;
|
||||||
stroke-linecap: round;
|
stroke-linecap: round;
|
||||||
stroke: #50a2e9;
|
stroke: #50a2e9;
|
||||||
fill: none;
|
fill: none;
|
||||||
@ -1223,7 +1278,7 @@ poll-element {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
width: 34px;
|
width: 34px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
margin-left: -1px;
|
margin-left: 5px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -1256,6 +1311,7 @@ poll-element {
|
|||||||
stroke-dashoffset: 0;
|
stroke-dashoffset: 0;
|
||||||
stroke-opacity: 1;
|
stroke-opacity: 1;
|
||||||
stroke-width: 2;
|
stroke-width: 2;
|
||||||
|
stroke: #8d969c;
|
||||||
fill: transparent;
|
fill: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1268,6 +1324,20 @@ poll-element {
|
|||||||
.poll-answer-percents {
|
.poll-answer-percents {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.poll-answer-selected {
|
||||||
|
animation-direction: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-retracting {
|
||||||
|
.circle-hover {
|
||||||
|
transition-delay: .24s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animation-ring {
|
||||||
|
transition-delay: .22s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,10 +102,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* li.dialog-pinned + .pinned-delimiter {
|
|
||||||
display: flex;
|
|
||||||
} */
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -634,6 +634,20 @@ input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-sign, .page-signQR {
|
||||||
|
.qr {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.qr-description {
|
||||||
|
color: #707579;
|
||||||
|
line-height: 1.85;
|
||||||
|
text-align: left;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* .page-signQR {
|
/* .page-signQR {
|
||||||
.auth-image {
|
.auth-image {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user