From d0a797f18e423bbc648fd95786b4490a94f89e20 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Thu, 26 Aug 2021 20:01:59 +0300 Subject: [PATCH] Fix polls width --- src/components/appMediaViewer.ts | 17 ++--- src/components/appSearchSuper..ts | 3 +- src/components/appSelectPeers.ts | 5 +- src/components/chat/bubbles.ts | 5 +- src/components/poll.ts | 73 ++++++++++++++------- src/components/sidebarLeft/tabs/contacts.ts | 3 +- src/helpers/mediaSizes.ts | 18 +++-- src/helpers/windowSize.ts | 24 +++++++ src/lib/appManagers/appDialogsManager.ts | 3 +- src/lib/appManagers/appPhotosManager.ts | 19 +----- src/scss/partials/_chatBubble.scss | 13 +++- src/scss/partials/_poll.scss | 37 ++++++++--- 12 files changed, 151 insertions(+), 69 deletions(-) create mode 100644 src/helpers/windowSize.ts diff --git a/src/components/appMediaViewer.ts b/src/components/appMediaViewer.ts index 701f7cf0..e00e5e3f 100644 --- a/src/components/appMediaViewer.ts +++ b/src/components/appMediaViewer.ts @@ -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 .2 || xDiff > 125) { //console.log('will swipe', xDiff); @@ -302,7 +303,7 @@ class AppMediaViewerBase .2 || yDiff > 125) { this.buttons.close.click(); return true; @@ -630,7 +631,7 @@ class AppMediaViewerBase 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[] = toLoad.map(mediaTab => { return this.loadType(mediaTab, justLoad, loadCount, middleware) diff --git a/src/components/appSelectPeers.ts b/src/components/appSelectPeers.ts index 6dfed1b6..9830f011 100644 --- a/src/components/appSelectPeers.ts +++ b/src/components/appSelectPeers.ts @@ -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); } diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 423a0e87..ff3828df 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -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 = 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; diff --git a/src/components/poll.ts b/src/components/poll.ts index 9341f348..231dfdb3 100644 --- a/src/components/poll.ts +++ b/src/components/poll.ts @@ -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,9 +176,8 @@ export default class PollElement extends HTMLElement { private viewResults: HTMLElement; private votersCountDiv: HTMLDivElement; - private maxOffset = -46.5; - //private maxLength: number; - //private maxLengths: number[]; + // private maxLength: number; + // private maxLengths: number[]; private maxPercents: number[]; public isClosed = false; @@ -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 ? '' : ''; const votes = poll.answers.map((answer, idx) => { return ` @@ -243,7 +273,7 @@ export default class PollElement extends HTMLElement {
${RichTextProcessor.wrapEmojiText(answer.text)}
- @@ -396,8 +426,9 @@ export default class PollElement extends HTMLElement { footerDiv.append(this.sendVoteBtn); } - //const width = this.getBoundingClientRect().width; - //this.maxLength = width + tailLength + this.maxOffset + -13.7; // 13 - position left + // 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) { this.performResults(results, poll.chosenIndexes, false); @@ -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); } } @@ -591,7 +619,7 @@ export default class PollElement extends HTMLElement { }); const maxValue = Math.max(...percents); - //this.maxLengths = percents.map(p => p / maxValue * this.maxLength); + // this.maxLengths = percents.map(p => p / maxValue * this.maxLength); this.maxPercents = percents.map(p => p / maxValue); // line @@ -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; } } diff --git a/src/components/sidebarLeft/tabs/contacts.ts b/src/components/sidebarLeft/tabs/contacts.ts index 49ecc6e0..14e49928 100644 --- a/src/components/sidebarLeft/tabs/contacts.ts +++ b/src/components/sidebarLeft/tabs/contacts.ts @@ -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) => { diff --git a/src/helpers/mediaSizes.ts b/src/helpers/mediaSizes.ts index c3fe6bcb..427131f5 100644 --- a/src/helpers/mediaSizes.ts +++ b/src/helpers/mediaSizes.ts @@ -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 diff --git a/src/helpers/windowSize.ts b/src/helpers/windowSize.ts new file mode 100644 index 00000000..e5448605 --- /dev/null +++ b/src/helpers/windowSize.ts @@ -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; diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts index b7d9126f..5c3a337f 100644 --- a/src/lib/appManagers/appDialogsManager.ts +++ b/src/lib/appManagers/appDialogsManager.ts @@ -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) => { diff --git a/src/lib/appManagers/appPhotosManager.ts b/src/lib/appManagers/appPhotosManager.ts index ce06ef74..b04b097e 100644 --- a/src/lib/appManagers/appPhotosManager.ts +++ b/src/lib/appManagers/appPhotosManager.ts @@ -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); } diff --git a/src/scss/partials/_chatBubble.scss b/src/scss/partials/_chatBubble.scss index e1d4ab9f..3c45acbf 100644 --- a/src/scss/partials/_chatBubble.scss +++ b/src/scss/partials/_chatBubble.scss @@ -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 { diff --git a/src/scss/partials/_poll.scss b/src/scss/partials/_poll.scss index b030e3a8..8458d3be 100644 --- a/src/scss/partials/_poll.scss +++ b/src/scss/partials/_poll.scss @@ -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 {