Fix polls width

This commit is contained in:
Eduard Kuzmenko 2021-08-26 20:01:59 +03:00
parent 693a586762
commit d0a797f18e
12 changed files with 151 additions and 69 deletions

View File

@ -52,6 +52,7 @@ import { doubleRaf, fastRaf } from "../helpers/schedulers";
import { attachClickEvent } from "../helpers/dom/clickEvent";
import PopupDeleteMessages from "./popups/deleteMessages";
import RangeSelector from "./rangeSelector";
import windowSize from "../helpers/windowSize";
const ZOOM_STEP = 0.5;
const ZOOM_INITIAL_VALUE = 1;
@ -289,7 +290,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
}
//console.log(xDiff, yDiff);
const percents = Math.abs(xDiff) / appPhotosManager.windowW;
const percents = Math.abs(xDiff) / windowSize.windowW;
if(percents > .2 || xDiff > 125) {
//console.log('will swipe', xDiff);
@ -302,7 +303,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
return true;
}
const percentsY = Math.abs(yDiff) / appPhotosManager.windowH;
const percentsY = Math.abs(yDiff) / windowSize.windowH;
if(percentsY > .2 || yDiff > 125) {
this.buttons.close.click();
return true;
@ -630,7 +631,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
let top: number;
if(wasActive) {
left = fromRight === 1 ? appPhotosManager.windowW : -containerRect.width;
left = fromRight === 1 ? windowSize.windowW : -containerRect.width;
top = containerRect.top;
} else {
left = rect.left;
@ -705,8 +706,8 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
if(closing && zoomValue > 1) {
// const width = this.moversContainer.scrollWidth * scaleX;
// const height = this.moversContainer.scrollHeight * scaleY;
const willBeLeft = appPhotosManager.windowW / 2 - rect.width / 2;
const willBeTop = appPhotosManager.windowH / 2 - rect.height / 2;
const willBeLeft = windowSize.windowW / 2 - rect.width / 2;
const willBeTop = windowSize.windowH / 2 - rect.height / 2;
const left = rect.left - willBeLeft/* + (width - rect.width) / 2 */;
const top = rect.top - willBeTop/* + (height - rect.height) / 2 */;
this.moversContainer.style.transform = `matrix(${scaleX}, 0, 0, ${scaleY}, ${left}, ${top})`;
@ -1028,7 +1029,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
}
protected moveTheMover(mover: HTMLElement, toLeft = true) {
const windowW = appPhotosManager.windowW;
const windowW = windowSize.windowW;
this.removeCenterFromMover(mover);
@ -1260,11 +1261,11 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
const mover = this.content.mover;
const maxWidth = appPhotosManager.windowW;
const maxWidth = windowSize.windowW;
//const maxWidth = this.pageEl.scrollWidth;
// TODO: const maxHeight = mediaSizes.isMobile ? appPhotosManager.windowH : appPhotosManager.windowH - 100;
let padding = 0;
const windowH = appPhotosManager.windowH;
const windowH = windowSize.windowH;
if(windowH < 1000000 && !mediaSizes.isMobile) {
padding = 120;
}

View File

@ -40,6 +40,7 @@ import positionElementByIndex from "../helpers/dom/positionElementByIndex";
import cleanSearchText from "../helpers/cleanSearchText";
import { isTouchSupported } from "../helpers/touchSupport";
import handleTabSwipe from "../helpers/dom/handleTabSwipe";
import windowSize from "../helpers/windowSize";
//const testScroll = false;
@ -1177,7 +1178,7 @@ export default class AppSearchSuper {
return;
}
const loadCount = justLoad ? 50 : Math.round((appPhotosManager.windowH / 130 | 0) * 3 * 1.25); // that's good for all types
const loadCount = justLoad ? 50 : Math.round((windowSize.windowH / 130 | 0) * 3 * 1.25); // that's good for all types
const promises: Promise<any>[] = toLoad.map(mediaTab => {
return this.loadType(mediaTab, justLoad, loadCount, middleware)

View File

@ -23,6 +23,7 @@ import { cancelEvent } from "../helpers/dom/cancelEvent";
import replaceContent from "../helpers/dom/replaceContent";
import { filterUnique } from "../helpers/array";
import debounce from "../helpers/schedulers/debounce";
import windowSize from "../helpers/windowSize";
type PeerType = 'contacts' | 'dialogs' | 'channelParticipants';
@ -257,7 +258,7 @@ export default class AppSelectPeers {
}
// в десктопе - сначала без группы, потом архивные, потом контакты без сообщений
const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;
const pageCount = windowSize.windowH / 72 * 1.25 | 0;
const tempId = this.getTempId('dialogs');
const promise = appMessagesManager.getConversations(this.query, this.offsetIndex, pageCount, this.folderId);
@ -359,7 +360,7 @@ export default class AppSelectPeers {
}
if(this.cachedContacts.length) {
const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;
const pageCount = windowSize.windowH / 72 * 1.25 | 0;
const arr = this.cachedContacts.splice(0, pageCount);
this.renderResultsFunc(arr);
}

View File

@ -74,6 +74,7 @@ import { EmoticonsDropdown } from "../emoticonsDropdown";
import debounce from "../../helpers/schedulers/debounce";
import { formatNumber } from "../../helpers/number";
import { SEND_WHEN_ONLINE_TIMESTAMP } from "../../lib/mtproto/constants";
import windowSize from "../../helpers/windowSize";
const USE_MEDIA_TAILS = false;
const IGNORE_ACTIONS: Set<Message.messageService['action']['_']> = new Set([
@ -1106,7 +1107,7 @@ export default class ChatBubbles {
let bad = true;
if(bubble) {
const rect = bubble.getBoundingClientRect();
bad = (this.appPhotosManager.windowH / 2) > rect.top;
bad = (windowSize.windowH / 2) > rect.top;
} else {
const message = this.chat.getMessage(mid);
if(!message.deleted) {
@ -3570,7 +3571,7 @@ export default class ChatBubbles {
const peerId = this.peerId;
//console.time('appImManager call getHistory');
const pageCount = Math.min(30, this.appPhotosManager.windowH / 38/* * 1.25 */ | 0);
const pageCount = Math.min(30, windowSize.windowH / 38/* * 1.25 */ | 0);
//const loadCount = Object.keys(this.bubbles).length > 0 ? 50 : pageCount;
const realLoadCount = Object.keys(this.bubbles).length > 0/* || additionMsgId */ ? Math.max(40, pageCount) : pageCount;//const realLoadCount = 50;
//const realLoadCount = pageCount;//const realLoadCount = 50;

View File

@ -21,9 +21,10 @@ import findUpClassName from "../helpers/dom/findUpClassName";
import { cancelEvent } from "../helpers/dom/cancelEvent";
import { attachClickEvent, detachClickEvent } from "../helpers/dom/clickEvent";
import replaceContent from "../helpers/dom/replaceContent";
import windowSize from "../helpers/windowSize";
let lineTotalLength = 0;
//const tailLength = 9;
const tailLength = 9;
const times = 10;
const fullTime = 340;
const oneTime = fullTime / times;
@ -108,6 +109,15 @@ rootScope.addEventListener('peer_changed', () => {
}
});
mediaSizes.addEventListener('resize', () => {
PollElement.setMaxLength();
PollElement.resizePolls();
});
mediaSizes.addEventListener('changeScreen', () => {
PollElement.setMaxLength();
});
const hideQuizHint = (element: HTMLElement, onHide: () => void, timeout: number) => {
element.classList.remove('active');
@ -155,7 +165,9 @@ const setQuizHint = (solution: string, solution_entities: any[], onHide: () => v
};
export default class PollElement extends HTMLElement {
private svgLines: SVGSVGElement[];
public static MAX_OFFSET = -46.5;
public static MAX_LENGTH = 0;
public svgLines: SVGSVGElement[];
private numberDivs: HTMLDivElement[];
private answerDivs: HTMLDivElement[];
private descDiv: HTMLElement;
@ -164,7 +176,6 @@ export default class PollElement extends HTMLElement {
private viewResults: HTMLElement;
private votersCountDiv: HTMLDivElement;
private maxOffset = -46.5;
// private maxLength: number;
// private maxLengths: number[];
private maxPercents: number[];
@ -193,6 +204,22 @@ export default class PollElement extends HTMLElement {
// элемент создан
}
public static setMaxLength() {
const width = windowSize.windowW <= 360 ? windowSize.windowW - 120 : mediaSizes.active.poll.width;
this.MAX_LENGTH = width + tailLength + this.MAX_OFFSET + -13.7; // 13 - position left
}
public static resizePolls() {
if(!this.MAX_LENGTH) return;
const pollElements = Array.from(document.querySelectorAll('poll-element.is-voted')) as PollElement[];
pollElements.forEach(pollElement => {
pollElement.svgLines.forEach((svg, idx) => {
//void svg.getBoundingClientRect(); // reflow
pollElement.setLineProgress(idx, 1);
});
});
}
public render() {
// браузер вызывает этот метод при добавлении элемента в документ
// (может вызываться много раз, если элемент многократно добавляется/удаляется)
@ -200,6 +227,7 @@ export default class PollElement extends HTMLElement {
if(!lineTotalLength) {
lineTotalLength = (document.getElementById('poll-line') as any as SVGPathElement).getTotalLength();
//console.log('line total length:', lineTotalLength);
PollElement.setMaxLength();
}
const pollId = this.message.media.poll.id;
@ -230,6 +258,8 @@ export default class PollElement extends HTMLElement {
}
}
this.classList.toggle('is-multiple', this.isMultiple);
const multipleSelect = this.isMultiple ? '<span class="poll-answer-selected tgico-check"></span>' : '';
const votes = poll.answers.map((answer, idx) => {
return `
@ -243,7 +273,7 @@ export default class PollElement extends HTMLElement {
</div>
<div class="poll-answer-percents"></div>
<div class="poll-answer-text">${RichTextProcessor.wrapEmojiText(answer.text)}</div>
<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 ${mediaSizes.active.regular.width} 35" 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 485.9 35" xml:space="preserve">
<use href="#poll-line"></use>
</svg>
<span class="poll-answer-selected tgico"></span>
@ -397,6 +427,7 @@ export default class PollElement extends HTMLElement {
}
// const width = this.getBoundingClientRect().width;
// const width = mediaSizes.active.poll.width;
// this.maxLength = width + tailLength + this.maxOffset + -13.7; // 13 - position left
if(poll.chosenIndexes.length || this.isClosed) {
@ -570,16 +601,13 @@ export default class PollElement extends HTMLElement {
}
if(this.isMultiple) {
this.sendVoteBtn.classList.toggle('hide', !!this.chosenIndexes.length);
if(!this.chosenIndexes.length) {
this.votersCountDiv.classList.add('hide');
this.viewResults.classList.add('hide');
} else if(this.isPublic) {
this.viewResults.classList.toggle('hide', !results.total_voters || !this.chosenIndexes.length);
this.votersCountDiv.classList.toggle('hide', !!this.chosenIndexes.length);
} else {
this.votersCountDiv.classList.toggle('hide', !this.chosenIndexes.length);
}
const isVoted = !!this.chosenIndexes.length;
const hideSendVoteBtn = this.isClosed || isVoted;
const hideViewResultsBtn = !this.isPublic || !results.total_voters || (!isVoted && !this.isClosed);
this.sendVoteBtn.classList.toggle('hide', hideSendVoteBtn);
this.viewResults.classList.toggle('hide', hideViewResultsBtn);
this.votersCountDiv.classList.toggle('hide', !hideSendVoteBtn || !hideViewResultsBtn);
}
}
@ -690,9 +718,10 @@ export default class PollElement extends HTMLElement {
svg.style.strokeDasharray = '';
svg.style.strokeDashoffset = '';
} else {
//svg.style.strokeDasharray = (percents * this.maxLengths[index]) + ', 485.9';
svg.style.strokeDasharray = (multiplier * this.maxPercents[index] * 100) + '%, 485.9';
svg.style.strokeDashoffset = '' + multiplier * this.maxOffset;
// svg.style.strokeDasharray = (multiplier * this.maxLengths[index]) + ', 485.9';
svg.style.strokeDasharray = (multiplier * this.maxPercents[index] * PollElement.MAX_LENGTH) + ', 485.9';
// svg.style.strokeDasharray = (multiplier * this.maxPercents[index] * 100) + '%, 485.9';
svg.style.strokeDashoffset = '' + multiplier * PollElement.MAX_OFFSET;
}
}

View File

@ -11,6 +11,7 @@ import appPhotosManager from "../../../lib/appManagers/appPhotosManager";
import InputSearch from "../../inputSearch";
import { isMobile } from "../../../helpers/userAgent";
import { canFocus } from "../../../helpers/dom/canFocus";
import windowSize from "../../../helpers/windowSize";
// TODO: поиск по людям глобальный, если не нашло в контактах никого
@ -75,7 +76,7 @@ export default class AppContactsTab extends SliderSuperTab {
}
let renderPage = () => {
const pageCount = appPhotosManager.windowH / 72 * 1.25 | 0;
const pageCount = windowSize.windowH / 72 * 1.25 | 0;
const arr = contacts.splice(0, pageCount); // надо splice!
arr.forEach((peerId) => {

View File

@ -37,7 +37,8 @@ type MediaTypeSizes = {
esgSticker: MediaSize,
animatedSticker: MediaSize,
staticSticker: MediaSize,
emojiSticker: MediaSize
emojiSticker: MediaSize,
poll: MediaSize
};
export enum ScreenSize {
@ -51,7 +52,8 @@ const MEDIUM_SIZE = 1275;
const LARGE_SIZE = 1680;
class MediaSizes extends EventListenerBase<{
changeScreen: (from: ScreenSize, to: ScreenSize) => void
changeScreen: (from: ScreenSize, to: ScreenSize) => void,
resize: () => void
}> {
private screenSizes: {key: ScreenSize, value: number}[] = [
{key: ScreenSize.mobile, value: MOBILE_SIZE},
@ -67,7 +69,8 @@ class MediaSizes extends EventListenerBase<{
esgSticker: makeMediaSize(68, 68),
animatedSticker: makeMediaSize(180, 180),
staticSticker: makeMediaSize(180, 180),
emojiSticker: makeMediaSize(112, 112)
emojiSticker: makeMediaSize(112, 112),
poll: makeMediaSize(240, 0)
},
desktop: {
regular: makeMediaSize(420, 340),
@ -76,14 +79,15 @@ class MediaSizes extends EventListenerBase<{
esgSticker: makeMediaSize(80, 80),
animatedSticker: makeMediaSize(200, 200),
staticSticker: makeMediaSize(200, 200),
emojiSticker: makeMediaSize(112, 112)
emojiSticker: makeMediaSize(112, 112),
poll: makeMediaSize(330, 0)
}
};
public isMobile = false;
public active: MediaTypeSizes;
public activeScreen: ScreenSize;
public rAF: number;
private rAF: number;
constructor() {
super();
@ -128,6 +132,10 @@ class MediaSizes extends EventListenerBase<{
}
}
if(wasScreen !== undefined) {
this.dispatchEvent('resize');
}
/* if(this.isMobile) {
for(let i in this.active) {
// @ts-ignore

24
src/helpers/windowSize.ts Normal file
View File

@ -0,0 +1,24 @@
/*
* https://github.com/morethanwords/tweb
* Copyright (C) 2019-2021 Eduard Kuzmenko
* https://github.com/morethanwords/tweb/blob/master/LICENSE
*/
export class WindowSize {
public windowW = 0;
public windowH = 0;
constructor() {
// @ts-ignore
const w: any = 'visualViewport' in window ? window.visualViewport : window;
const set = () => {
this.windowW = w.width || w.innerWidth;
this.windowH = w.height || w.innerHeight;
};
w.addEventListener('resize', set);
set();
}
}
const windowSize = new WindowSize();
export default windowSize;

View File

@ -47,6 +47,7 @@ import appPhotosManager from "./appPhotosManager";
import SortedUserList from "../../components/sortedUserList";
import { isTouchSupported } from "../../helpers/touchSupport";
import handleTabSwipe from "../../helpers/dom/handleTabSwipe";
import windowSize from "../../helpers/windowSize";
export type DialogDom = {
avatarEl: AvatarElement,
@ -929,7 +930,7 @@ export class AppDialogsManager {
appUsersManager.getContacts(undefined, undefined, 'online').then(contacts => {
const sortedUserList = new SortedUserList({avatarSize: 42, new: true});
this.loadContacts = () => {
const pageCount = appPhotosManager.windowH / 60 | 0;
const pageCount = windowSize.windowH / 60 | 0;
const arr = contacts.splice(0, pageCount).filter(this.verifyUserIdForContacts);
arr.forEach((peerId) => {

View File

@ -26,6 +26,7 @@ import { MOUNT_CLASS_TO } from "../../config/debug";
import { renderImageFromUrlPromise } from "../../helpers/dom/renderImageFromUrl";
import calcImageInBox from "../../helpers/calcImageInBox";
import { makeMediaSize, MediaSize } from "../../helpers/mediaSizes";
import windowSize from "../../helpers/windowSize";
export type MyPhoto = Photo.photo;
@ -37,23 +38,9 @@ export class AppPhotosManager {
[id: string]: MyPhoto
} = {};
public windowW = 0;
public windowH = 0;
private static jpegHeader = bytesFromHex('ffd8ffe000104a46494600010100000100010000ffdb004300281c1e231e19282321232d2b28303c64413c37373c7b585d4964918099968f808c8aa0b4e6c3a0aadaad8a8cc8ffcbdaeef5ffffff9bc1fffffffaffe6fdfff8ffdb0043012b2d2d3c353c76414176f8a58ca5f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8f8ffc00011080000000003012200021101031101ffc4001f0000010501010101010100000000000000000102030405060708090a0bffc400b5100002010303020403050504040000017d01020300041105122131410613516107227114328191a1082342b1c11552d1f02433627282090a161718191a25262728292a3435363738393a434445464748494a535455565758595a636465666768696a737475767778797a838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae1e2e3e4e5e6e7e8e9eaf1f2f3f4f5f6f7f8f9faffc4001f0100030101010101010101010000000000000102030405060708090a0bffc400b51100020102040403040705040400010277000102031104052131061241510761711322328108144291a1b1c109233352f0156272d10a162434e125f11718191a262728292a35363738393a434445464748494a535455565758595a636465666768696a737475767778797a82838485868788898a92939495969798999aa2a3a4a5a6a7a8a9aab2b3b4b5b6b7b8b9bac2c3c4c5c6c7c8c9cad2d3d4d5d6d7d8d9dae2e3e4e5e6e7e8e9eaf2f3f4f5f6f7f8f9faffda000c03010002110311003f00');
private static jpegTail = bytesFromHex('ffd9');
constructor() {
// @ts-ignore
const w: any = 'visualViewport' in window ? window.visualViewport : window;
const set = () => {
this.windowW = w.width || w.innerWidth;
this.windowH = w.height || w.innerHeight;
};
w.addEventListener('resize', set);
set();
}
public savePhoto(photo: Photo, context?: ReferenceContext) {
if(photo._ === 'photoEmpty') return undefined;
@ -357,8 +344,8 @@ export class AppPhotosManager {
}
if(!photoSize) {
const fullWidth = this.windowW;
const fullHeight = this.windowH;
const fullWidth = windowSize.windowW;
const fullHeight = windowSize.windowH;
photoSize = this.choosePhotoSize(photo, fullWidth, fullHeight);
}

View File

@ -156,7 +156,11 @@ $bubble-margin: .25rem;
}
}
&.channel-post {
.replies-footer + .poll-message .poll-footer-button {
border-radius: 0 !important;
}
/* &.channel-post {
.message.poll-message {
.time {
position: unset;
@ -166,7 +170,7 @@ $bubble-margin: .25rem;
poll-element .poll-footer {
height: auto;
}
}
} */
&-select-checkbox {
z-index: 3;
@ -2207,6 +2211,11 @@ $bubble-margin: .25rem;
.progress-ring__circle {
stroke: var(--message-out-primary-color);
}
.c-ripple__circle {
background-color: var(--message-out-primary-color);
opacity: .08;
}
}
&.is-sending poll-element {

View File

@ -14,6 +14,7 @@ poll-element {
@include respond-to(handhelds) {
width: 240px;
max-width: 100%;
}
&:not(.is-closed):not(.is-voted) .poll-answer {
@ -172,8 +173,8 @@ poll-element {
&-votes-count {
color: var(--secondary-text-color);
font-size: 14px;
padding-top: 1px;
font-size: .875rem;
padding-top: .1875rem;
}
&-line {
@ -194,17 +195,14 @@ poll-element {
&-footer {
text-align: center;
margin-top: 7px;
height: 27px;
margin: -.375rem -.5rem -.375rem -.625rem;
height: 2.875rem;
}
&-footer-button {
cursor: pointer;
position: absolute;
left: 0;
margin-top: -7px;
width: 100%;
height: 41px;
height: 100%;
color: var(--primary-color);
//text-transform: uppercase;
font-weight: 500;
@ -213,10 +211,15 @@ poll-element {
//border-bottom-left-radius: 6px;
//border-bottom-right-radius: 12px;
font-size: 1rem;
line-height: 37px;
overflow: hidden;
}
&-footer, &-footer-button {
display: flex;
align-items: center;
justify-content: center;
}
&-quiz-timer {
width: 32px;
height: 32px;
@ -371,6 +374,22 @@ poll-element {
transition: .1s transform;
}
}
// * correct styles, 26.08.2021
&.is-multiple {
.poll-desc {
margin-bottom: .5rem;
}
// ! conflicts with 100% result
/* .poll-answer {
margin-left: -.375rem;
} */
}
.c-ripple__circle {
background-color: var(--light-primary-color);
}
}
@keyframes pollAnswerRotate {