diff --git a/README.md b/README.md index 366dceba..68ce59dd 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ Source maps are included in production build for your convenience. Should be applied like that: http://localhost:8080/?test=1 -### Troubleshooting +### Troubleshooting & Suggesting -If you find an issue with this app, let Telegram know using the [Suggestions Platform](https://bugs.telegram.org/c/4002). +If you find an issue with this app or wish something to be added, let Telegram know using the [Suggestions Platform](https://bugs.telegram.org/c/4002). ### Licensing diff --git a/src/components/appSearchSuper..ts b/src/components/appSearchSuper..ts index ad27e06a..eeaea68d 100644 --- a/src/components/appSearchSuper..ts +++ b/src/components/appSearchSuper..ts @@ -70,10 +70,10 @@ export default class AppSearchSuper { public tabs: {[t in SearchSuperType]: HTMLDivElement} = {} as any; public mediaTab: SearchSuperMediaTab; - public tabSelected: HTMLElement; public container: HTMLElement; public nav: HTMLElement; + private navScrollableContainer: HTMLDivElement; private tabsContainer: HTMLElement; private tabsMenu: HTMLElement; private prevTabId = -1; @@ -112,6 +112,8 @@ export default class AppSearchSuper { private membersList: SortedUserList; + private skipScroll: boolean; + // * arguments public mediaTabs: SearchSuperMediaTab[]; public scrollable: Scrollable; @@ -128,7 +130,7 @@ export default class AppSearchSuper { this.container = document.createElement('div'); this.container.classList.add('search-super'); - const navScrollableContainer = document.createElement('div'); + const navScrollableContainer = this.navScrollableContainer = document.createElement('div'); navScrollableContainer.classList.add('search-super-tabs-scrollable', 'menu-horizontal-scrollable', 'sticky'); const navScrollable = new ScrollableX(navScrollableContainer); @@ -185,48 +187,67 @@ export default class AppSearchSuper { this.searchGroupMedia = new SearchGroup('', 'messages', true); this.scrollable.onScrolledBottom = () => { - if(this.tabSelected && this.tabSelected.childElementCount/* && false */) { + if(this.mediaTab.contentTab && this.mediaTab.contentTab.childElementCount/* && false */) { //this.log('onScrolledBottom will load media'); this.load(true); } }; //this.scroll.attachSentinels(undefined, 400); - this.selectTab = horizontalMenu(this.tabsMenu, this.tabsContainer, (id, tabContent) => { - if(this.prevTabId === id) return; - - if(this.prevTabId !== -1) { - this.onTransitionStart(); + this.selectTab = horizontalMenu(this.tabsMenu, this.tabsContainer, (id, tabContent, animate) => { + if(this.prevTabId === id && !this.skipScroll) { + this.scrollable.scrollIntoViewNew(this.container, 'start'); + return; } - this.mediaTab.scroll = {scrollTop: this.scrollable.scrollTop, scrollHeight: this.scrollable.scrollHeight}; - const newMediaTab = this.mediaTabs[id]; - this.tabSelected = tabContent.firstElementChild as HTMLDivElement; - - if(newMediaTab.scroll === undefined) { - const rect = this.container.getBoundingClientRect(); - const rect2 = this.container.parentElement.getBoundingClientRect(); - const diff = rect.y - rect2.y; - - if(this.scrollable.scrollTop > diff) { - newMediaTab.scroll = {scrollTop: diff, scrollHeight: 0}; - } + if(this.onChangeTab) { + this.onChangeTab(newMediaTab); } + + const fromMediaTab = this.mediaTab; + this.mediaTab = newMediaTab; - if(newMediaTab.scroll) { - const diff = this.mediaTab.scroll.scrollTop - newMediaTab.scroll.scrollTop; - //console.log('what you gonna do', this.goingHard, diff); - - if(diff/* && diff < 0 */) { - this.tabSelected.style.transform = `translateY(${diff}px)`; - } + if(this.prevTabId !== -1 && animate) { + this.onTransitionStart(); } - this.mediaTab = newMediaTab; - - if(this.onChangeTab) { - this.onChangeTab(this.mediaTab); + if(this.skipScroll) { + this.skipScroll = false; + } else { + const offsetTop = this.container.offsetTop; + let scrollTop = this.scrollable.scrollTop; + if(scrollTop < offsetTop) { + this.scrollable.scrollIntoViewNew(this.container, 'start'); + scrollTop = offsetTop; + } + + fromMediaTab.scroll = {scrollTop: scrollTop, scrollHeight: this.scrollable.scrollHeight}; + + if(newMediaTab.scroll === undefined) { + const rect = this.container.getBoundingClientRect(); + const rect2 = this.container.parentElement.getBoundingClientRect(); + const diff = rect.y - rect2.y; + + if(scrollTop > diff) { + newMediaTab.scroll = {scrollTop: diff, scrollHeight: 0}; + } + } + + if(newMediaTab.scroll) { + const diff = fromMediaTab.scroll.scrollTop - newMediaTab.scroll.scrollTop; + //console.log('what you gonna do', this.goingHard, diff); + + //this.scrollable.scrollTop = scrollTop; + if(diff/* && diff < 0 */) { + /* if(diff > -(fromMediaTab.contentTab.scrollHeight + this.nav.scrollHeight)) { + fromMediaTab.contentTab.style.transform = `translateY(${diff}px)`; + this.scrollable.scrollTop = scrollTop - diff; + } else { */ + newMediaTab.contentTab.style.transform = `translateY(${diff}px)`; + //} + } + } } /* if(this.prevTabId !== -1 && nav.offsetTop) { @@ -236,7 +257,7 @@ export default class AppSearchSuper { /* this.log('setVirtualContainer', id, this.sharedMediaSelected, this.sharedMediaSelected.childElementCount); this.scroll.setVirtualContainer(this.sharedMediaSelected); */ - if(this.prevTabId !== -1 && !this.tabSelected.childElementCount) { // quick brown fix + if(this.prevTabId !== -1 && !newMediaTab.contentTab.childElementCount) { // quick brown fix //this.contentContainer.classList.remove('loaded'); this.load(true); } @@ -247,7 +268,7 @@ export default class AppSearchSuper { //console.log('what y', this.tabSelected.style.transform); if(this.mediaTab.scroll !== undefined) { - this.tabSelected.style.transform = ''; + this.mediaTab.contentTab.style.transform = ''; this.scrollable.scrollTop = this.mediaTab.scroll.scrollTop; } @@ -1097,6 +1118,7 @@ export default class AppSearchSuper { } let firstMediaTab: SearchSuperMediaTab; + let count = 0; mediaTabs.forEach(mediaTab => { const counter = counters.find(c => c.filter._ === mediaTab.inputFilter); @@ -1107,6 +1129,8 @@ export default class AppSearchSuper { if(counter.count && firstMediaTab === undefined) { firstMediaTab = mediaTab; } + + if(counter.count) ++count; }); const membersTab = this.mediaTabsMap.get('members'); @@ -1120,8 +1144,11 @@ export default class AppSearchSuper { this.container.classList.toggle('hide', !firstMediaTab); this.container.parentElement.classList.toggle('search-empty', !firstMediaTab); if(firstMediaTab) { + this.skipScroll = true; this.selectTab(this.mediaTabs.indexOf(firstMediaTab), false); firstMediaTab.menuTab.classList.add('active'); + + this.navScrollableContainer.classList.toggle('hide', count <= 1); } } diff --git a/src/components/audio.ts b/src/components/audio.ts index 830fe2d7..83d311c0 100644 --- a/src/components/audio.ts +++ b/src/components/audio.ts @@ -217,9 +217,10 @@ function wrapVoiceMessage(audioEl: AudioElement) { e.preventDefault(); if(!audio.paused) { audio.pause(); - scrub(e); - mousedown = true; } + + scrub(e); + mousedown = true; }); progress.addEventListener('mouseup', (e) => { if (mousemove && mousedown) { @@ -437,7 +438,7 @@ export default class AudioElement extends HTMLElement { const getDownloadPromise = () => appDocsManager.downloadDoc(doc); - if(isVoice) { + if(isRealVoice) { if(!preloader) { preloader = new ProgressivePreloader({ cancelable: true diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index 5af4e50a..7b18420f 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -168,6 +168,7 @@ export default class ChatBubbles { const message = this.chat.getMessage(mid); if(+bubble.dataset.timestamp >= (message.date + serverTimeManager.serverTimeOffset - 1)) { + this.bubbleGroups.addBubble(bubble, message, false); return; } @@ -1025,6 +1026,7 @@ export default class ChatBubbles { // if scroll down after search if(history.indexOf(historyStorage.maxId) !== -1) { + this.scrollable.loadedAll.bottom = true; return; } @@ -1414,6 +1416,10 @@ export default class ChatBubbles { const samePeer = this.peerId === peerId; + /* if(samePeer && this.chat.setPeerPromise) { + return {cached: true, promise: this.chat.setPeerPromise}; + } */ + const historyStorage = this.appMessagesManager.getHistoryStorage(peerId, this.chat.threadId); let topMessage = this.chat.type === 'pinned' ? this.appMessagesManager.pinnedMessages[peerId].maxId : historyStorage.maxId ?? 0; const isTarget = lastMsgId !== undefined; @@ -1497,9 +1503,15 @@ export default class ChatBubbles { this.isFirstLoad = true; } + const oldChatInner = this.chatInner; this.cleanup(); this.chatInner = document.createElement('div'); - this.chatInner.classList.add('bubbles-inner'); + if(samePeer) { + this.chatInner.className = oldChatInner.className; + this.chatInner.classList.remove('disable-hover', 'is-scrolling'); + } else { + this.chatInner.classList.add('bubbles-inner'); + } this.lazyLoadQueue.lock(); @@ -1590,6 +1602,8 @@ export default class ChatBubbles { this.scrollable.scrollTop = 99999; } + this.onScroll(); + this.chat.dispatchEvent('setPeer', lastMsgId, !isJump); // warning @@ -1718,7 +1732,7 @@ export default class ChatBubbles { public setBubblePosition(bubble: HTMLElement, message: any, reverse: boolean) { const dateMessage = this.getDateContainerByMessage(message, reverse); - if(this.chat.type === 'scheduled' || this.chat.type === 'pinned') { + if(this.chat.type === 'scheduled' || this.chat.type === 'pinned' || true) { const offset = this.stickyIntersector ? 2 : 1; let children = Array.from(dateMessage.container.children).slice(offset) as HTMLElement[]; let i = 0, foundMidOnSameTimestamp = 0; diff --git a/src/components/chat/chat.ts b/src/components/chat/chat.ts index 8ffe83f0..2c45d164 100644 --- a/src/components/chat/chat.ts +++ b/src/components/chat/chat.ts @@ -206,6 +206,8 @@ export default class Chat extends EventListenerBase<{ if(!samePeer) { rootScope.broadcast('peer_changing', this); this.peerId = peerId; + } else if(this.setPeerPromise) { + return; } //console.time('appImManager setPeer'); diff --git a/src/components/chat/input.ts b/src/components/chat/input.ts index 32c9de3e..03ff0ae0 100644 --- a/src/components/chat/input.ts +++ b/src/components/chat/input.ts @@ -157,9 +157,6 @@ export default class ChatInput { this.chatInput.append(this.inputContainer); this.goDownBtn = Button('bubbles-go-down btn-corner btn-circle z-depth-1 hide', {icon: 'arrow_down'}); - this.goDownUnreadBadge = document.createElement('span'); - this.goDownUnreadBadge.classList.add('badge', 'badge-24', 'badge-primary'); - this.goDownBtn.append(this.goDownUnreadBadge); this.inputContainer.append(this.goDownBtn); attachClickEvent(this.goDownBtn, (e) => { @@ -257,6 +254,10 @@ export default class ChatInput { this.inputMessageContainer.classList.add('input-message-container'); if(this.chat.type === 'chat') { + this.goDownUnreadBadge = document.createElement('span'); + this.goDownUnreadBadge.classList.add('badge', 'badge-24', 'badge-primary'); + this.goDownBtn.append(this.goDownUnreadBadge); + this.btnScheduled = ButtonIcon('scheduled', {noRipple: true}); this.btnScheduled.classList.add('btn-scheduled', 'hide'); @@ -376,7 +377,7 @@ export default class ChatInput { this.inputContainer.append(this.btnCancelRecord, this.btnSendContainer); - emoticonsDropdown.attachButtonListener(this.btnToggleEmoticons); + emoticonsDropdown.attachButtonListener(this.btnToggleEmoticons, this.listenerSetter); emoticonsDropdown.events.onOpen.push(this.onEmoticonsOpen); emoticonsDropdown.events.onClose.push(this.onEmoticonsClose); diff --git a/src/components/emoticonsDropdown/index.ts b/src/components/emoticonsDropdown/index.ts index cf1ee207..0edebf8e 100644 --- a/src/components/emoticonsDropdown/index.ts +++ b/src/components/emoticonsDropdown/index.ts @@ -8,7 +8,7 @@ import { isTouchSupported } from "../../helpers/touchSupport"; import appChatsManager from "../../lib/appManagers/appChatsManager"; import appImManager from "../../lib/appManagers/appImManager"; import rootScope from "../../lib/rootScope"; -import { blurActiveElement, whichChild } from "../../helpers/dom"; +import { attachClickEvent, blurActiveElement, whichChild } from "../../helpers/dom"; import animationIntersector from "../animationIntersector"; import { horizontalMenu } from "../horizontalMenu"; import LazyLoadQueue, { LazyLoadQueueIntersector } from "../lazyLoadQueue"; @@ -24,6 +24,7 @@ import AppGifsTab from "../sidebarRight/tabs/gifs"; import AppStickersTab from "../sidebarRight/tabs/stickers"; import findUpClassName from "../../helpers/dom/findUpClassName"; import findUpTag from "../../helpers/dom/findUpTag"; +import ListenerSetter from "../../helpers/listenerSetter"; export const EMOTICONSSTICKERGROUP = 'emoticons-dropdown'; @@ -32,7 +33,9 @@ export interface EmoticonsTab { onCloseAfterTimeout?: () => void } -const test = false; +const KEEP_OPEN = false; +const TOGGLE_TIMEOUT = 200; +const ANIMATION_DURATION = 200; export class EmoticonsDropdown { public static lazyLoadQueue = new LazyLoadQueue(); @@ -72,36 +75,36 @@ export class EmoticonsDropdown { this.element = document.getElementById('emoji-dropdown') as HTMLDivElement; } - public attachButtonListener(button: HTMLElement) { + public attachButtonListener(button: HTMLElement, listenerSetter: ListenerSetter) { let firstTime = true; if(isTouchSupported) { - button.addEventListener('click', () => { + attachClickEvent(button, () => { if(firstTime) { firstTime = false; this.toggle(true); } else { this.toggle(); } - }); + }, {listenerSetter}); } else { - button.onmouseover = (e) => { + listenerSetter.add(button, 'mouseover', (e) => { //console.log('onmouseover button'); - clearTimeout(this.displayTimeout); - //this.displayTimeout = setTimeout(() => { - if(firstTime) { - button.onmouseout = this.onMouseOut; - - firstTime = false; - } + if(firstTime) { + listenerSetter.add(button, 'mouseout', this.onMouseOut); + firstTime = false; + } + clearTimeout(this.displayTimeout); + this.displayTimeout = window.setTimeout(() => { this.toggle(true); - //}, 0/* 200 */); - }; + }, TOGGLE_TIMEOUT); + }); } } private onMouseOut = (e: MouseEvent) => { - if(test) return; + if(KEEP_OPEN) return; + clearTimeout(this.displayTimeout); if(!this.element.classList.contains('active')) return; const toElement = (e as any).toElement as Element; @@ -109,10 +112,9 @@ export class EmoticonsDropdown { return; } - clearTimeout(this.displayTimeout); this.displayTimeout = window.setTimeout(() => { this.toggle(false); - }, 200); + }, TOGGLE_TIMEOUT); }; private init() { @@ -265,7 +267,7 @@ export class EmoticonsDropdown { this.container.classList.remove('disable-hover'); this.events.onOpenAfter.forEach(cb => cb()); - }, isTouchSupported ? 0 : 200); + }, isTouchSupported ? 0 : ANIMATION_DURATION); // ! can't use together with resizeObserver /* if(isTouchSupported) { @@ -302,7 +304,7 @@ export class EmoticonsDropdown { this.container.classList.remove('disable-hover'); this.events.onCloseAfter.forEach(cb => cb()); - }, isTouchSupported ? 0 : 200); + }, isTouchSupported ? 0 : ANIMATION_DURATION); /* if(isTouchSupported) { const scrollHeight = this.container.scrollHeight; diff --git a/src/components/emoticonsDropdown/tabs/stickers.ts b/src/components/emoticonsDropdown/tabs/stickers.ts index e243aaaa..04746e31 100644 --- a/src/components/emoticonsDropdown/tabs/stickers.ts +++ b/src/components/emoticonsDropdown/tabs/stickers.ts @@ -209,37 +209,44 @@ export default class StickersTab implements EmoticonsTab { //console.log('got stickerSet', stickerSet, li); if(stickerSet.set.thumbs?.length) { - const downloadOptions = appStickersManager.getStickerSetThumbDownloadOptions(stickerSet.set); - const promise = appDownloadManager.download(downloadOptions); - - if(stickerSet.set.pFlags.animated) { - promise - .then(readBlobAsText) - //.then(JSON.parse) - .then(json => { - lottieLoader.loadAnimationWorker({ - container: button, - loop: true, - autoplay: false, - animationData: json, - width: 32, - height: 32, - needUpscale: true - }, EMOTICONSSTICKERGROUP); - }); - } else { - const image = new Image(); - promise.then(blob => { - renderImageFromUrl(image, URL.createObjectURL(blob), () => { - button.append(image); - }); - }); - } + EmoticonsDropdown.lazyLoadQueue.push({ + div: button, + load: () => { + const downloadOptions = appStickersManager.getStickerSetThumbDownloadOptions(stickerSet.set); + const promise = appDownloadManager.download(downloadOptions); + + if(stickerSet.set.pFlags.animated) { + return promise + .then(readBlobAsText) + //.then(JSON.parse) + .then(json => { + lottieLoader.loadAnimationWorker({ + container: button, + loop: true, + autoplay: false, + animationData: json, + width: 32, + height: 32, + needUpscale: true + }, EMOTICONSSTICKERGROUP); + }); + } else { + const image = new Image(); + + return promise.then(blob => { + renderImageFromUrl(image, URL.createObjectURL(blob), () => { + button.append(image); + }); + }); + } + } + }); } else if(stickerSet.documents[0]._ !== 'documentEmpty') { // as thumb will be used first sticker wrapSticker({ doc: stickerSet.documents[0], div: button as any, - group: EMOTICONSSTICKERGROUP + group: EMOTICONSSTICKERGROUP, + lazyLoadQueue: EmoticonsDropdown.lazyLoadQueue }); // kostil } } diff --git a/src/components/horizontalMenu.ts b/src/components/horizontalMenu.ts index 848820e1..20c811cc 100644 --- a/src/components/horizontalMenu.ts +++ b/src/components/horizontalMenu.ts @@ -12,7 +12,7 @@ import { fastRaf } from "../helpers/schedulers"; import { FocusDirection } from "../helpers/fastSmoothScroll"; import findUpAsChild from "../helpers/dom/findUpAsChild"; -export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?: (id: number, tabContent: HTMLDivElement) => void, onTransitionEnd?: () => void, transitionTime = 250, scrollableX?: ScrollableX) { +export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick?: (id: number, tabContent: HTMLDivElement, animate: boolean) => void | boolean, onTransitionEnd?: () => void, transitionTime = 250, scrollableX?: ScrollableX) { const selectTab = TransitionSlider(content, tabs || content.dataset.animation === 'tabs' ? 'tabs' : 'navigation', transitionTime, onTransitionEnd); if(tabs) { @@ -29,7 +29,12 @@ export function horizontalMenu(tabs: HTMLElement, content: HTMLElement, onClick? const selectTarget = (target: HTMLElement, id: number, animate = true) => { const tabContent = content.children[id] as HTMLDivElement; - if(onClick) onClick(id, tabContent); + if(onClick) { + const canChange = onClick(id, tabContent, animate); + if(canChange !== undefined && !canChange) { + return; + } + } if(scrollableX) { scrollableX.scrollIntoViewNew(target.parentElement.children[id] as HTMLElement, 'center', undefined, undefined, animate ? undefined : FocusDirection.Static, transitionTime, 'x'); diff --git a/src/components/inputField.ts b/src/components/inputField.ts index bd5696aa..c344263a 100644 --- a/src/components/inputField.ts +++ b/src/components/inputField.ts @@ -159,6 +159,12 @@ class InputField { } } + if(label || placeholder) { + const border = document.createElement('div'); + border.classList.add('input-field-border'); + this.container.append(border); + } + if(label) { this.label = document.createElement('label'); this.setLabel(); diff --git a/src/components/inputSearch.ts b/src/components/inputSearch.ts index da38037c..e405bb04 100644 --- a/src/components/inputSearch.ts +++ b/src/components/inputSearch.ts @@ -43,7 +43,7 @@ export default class InputSearch { this.input.addEventListener('input', this.onInput); this.clearBtn.addEventListener('click', this.onClearClick); - this.container.append(this.input, searchIcon, this.clearBtn); + this.container.append(searchIcon, this.clearBtn); } onInput = () => { diff --git a/src/components/scrollable.ts b/src/components/scrollable.ts index 921079ba..4b3a3bcf 100644 --- a/src/components/scrollable.ts +++ b/src/components/scrollable.ts @@ -250,8 +250,8 @@ export class ScrollableX extends ScrollableBase { if(!isTouchSupported) { const scrollHorizontally = (e: any) => { - if(!e.deltaX) { - this.container!.scrollLeft += e.deltaY / 4; + if(!e.deltaX && this.container.scrollWidth > this.container.clientWidth) { + this.container.scrollLeft += e.deltaY / 4; cancelEvent(e); } }; diff --git a/src/components/sidebarRight/tabs/sharedMedia.ts b/src/components/sidebarRight/tabs/sharedMedia.ts index f856a1ac..4a317412 100644 --- a/src/components/sidebarRight/tabs/sharedMedia.ts +++ b/src/components/sidebarRight/tabs/sharedMedia.ts @@ -46,10 +46,10 @@ import Scrollable from "../../scrollable"; import { isTouchSupported } from "../../../helpers/touchSupport"; let setText = (text: string, row: Row) => { - fastRaf(() => { + //fastRaf(() => { row.title.innerHTML = text; row.container.style.display = ''; - }); + //}); }; type ListLoaderResult = {count: number, items: any[]}; diff --git a/src/config/app.ts b/src/config/app.ts index f7b6356e..75a1b40a 100644 --- a/src/config/app.ts +++ b/src/config/app.ts @@ -12,8 +12,8 @@ const App = { id: 1025907, hash: '452b0359b988148995f22ff0f4229750', - version: '0.4.1', - langPackVersion: '0.1.3', + version: '0.4.2', + langPackVersion: '0.1.4', langPack: 'macos', langPackCode: 'en', domains: [] as string[], diff --git a/src/lang.ts b/src/lang.ts index b2e77538..c16bf586 100644 --- a/src/lang.ts +++ b/src/lang.ts @@ -91,6 +91,15 @@ const lang = { "Profile": "Profile", "Saved": "Saved", "ReportBug": "Report Bug", + "Notifications.Count": { + "one_value": "%d notification", + "other_value": "%d notifications", + }, + "Notifications.Forwarded": { + "one_value": "Forwarded %d message", + "other_value": "Forwarded %d messages" + }, + "Notifications.New": "New notification", // * android "ActionCreateChannel": "Channel created", diff --git a/src/lib/appManagers/appChatsManager.ts b/src/lib/appManagers/appChatsManager.ts index da2ed556..03d556b6 100644 --- a/src/lib/appManagers/appChatsManager.ts +++ b/src/lib/appManagers/appChatsManager.ts @@ -477,7 +477,7 @@ export class AppChatsManager { apiUpdatesManager.processUpdateMessage(updates); const channelId = updates.chats[0].id; - rootScope.broadcast('history_focus', -channelId); + rootScope.broadcast('history_focus', {peerId: -channelId}); return channelId; }); @@ -503,7 +503,7 @@ export class AppChatsManager { apiUpdatesManager.processUpdateMessage(updates); const chatId = (updates as any as Updates.updates).chats[0].id; - rootScope.broadcast('history_focus', -chatId); + rootScope.broadcast('history_focus', {peerId: -chatId}); return chatId; }); diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts index f33fb691..e4a6ab0c 100644 --- a/src/lib/appManagers/appDialogsManager.ts +++ b/src/lib/appManagers/appDialogsManager.ts @@ -233,6 +233,7 @@ export class AppDialogsManager { }; this.setListClickListener(archivedChatList, null, true); + //this.setListClickListener(archivedChatList, null, true); // * to test peer changing this.chatsPreloader = putPreloader(null, true); diff --git a/src/lib/appManagers/appImManager.ts b/src/lib/appManagers/appImManager.ts index 0203441c..3795ed34 100644 --- a/src/lib/appManagers/appImManager.ts +++ b/src/lib/appManagers/appImManager.ts @@ -169,8 +169,9 @@ export class AppImManager { } }); - rootScope.on('history_focus', (peerId) => { - this.setInnerPeer(peerId); + rootScope.on('history_focus', (e) => { + const {peerId, mid} = e; + this.setInnerPeer(peerId, mid); }); rootScope.on('peer_changing', (chat) => { diff --git a/src/lib/appManagers/appMessagesManager.ts b/src/lib/appManagers/appMessagesManager.ts index b00966ce..40004fd8 100644 --- a/src/lib/appManagers/appMessagesManager.ts +++ b/src/lib/appManagers/appMessagesManager.ts @@ -2953,7 +2953,11 @@ export class AppMessagesManager { } } - public canMessageBeEdited(message: any, kind: 'text' | 'poll') { + private canMessageBeEdited(message: any, kind: 'text' | 'poll') { + if(message.pFlags.is_outgoing) { + return false; + } + const goodMedias = [ 'messageMediaPhoto', 'messageMediaDocument', @@ -2992,7 +2996,7 @@ export class AppMessagesManager { return true; } - if((message.date < tsNow(true) - (2 * 86400) && message.media?._ !== 'messageMediaPoll') || !message.pFlags.out) { + if((message.date < (tsNow(true) - (2 * 86400)) && message.media?._ !== 'messageMediaPoll') || !message.pFlags.out) { return false; } @@ -3005,7 +3009,7 @@ export class AppMessagesManager { || message.fromId === rootScope.myId || appChatsManager.getChat(message.peerId)._ === 'chat' || appChatsManager.hasRights(message.peerId, 'delete_messages') - ); + ) && !message.pFlags.is_outgoing; } public applyConversations(dialogsResult: MessagesPeerDialogs.messagesPeerDialogs) { @@ -4919,60 +4923,31 @@ export class AppMessagesManager { peerTypeNotifySettings: PeerNotifySettings }> = {}) { const peerId = this.getMessagePeer(message); - let peerString: string; const notification: NotifyOptions = {}; - var notificationMessage: string, - notificationPhoto: any; - - const _ = (str: string) => str; + const peerString = appPeersManager.getPeerString(peerId); + let notificationMessage: string; - const localSettings = appNotificationsManager.getLocalSettings(); if(options.peerTypeNotifySettings.show_previews) { if(message._ === 'message' && message.fwd_from && options.fwdCount) { - notificationMessage = 'Forwarded ' + options.fwdCount + ' messages';//fwdMessagesPluralize(options.fwd_count); + notificationMessage = I18n.format('Notifications.Forwarded', true, [options.fwdCount]); } else { notificationMessage = this.wrapMessageForReply(message, undefined, undefined, true); } } else { - notificationMessage = 'New notification'; + notificationMessage = I18n.format('Notifications.New', true); } - if(peerId > 0) { - const fromUser = appUsersManager.getUser(message.fromId); - const fromPhoto = appUsersManager.getUserPhoto(message.fromId); - - notification.title = (fromUser.first_name || '') + - (fromUser.first_name && fromUser.last_name ? ' ' : '') + - (fromUser.last_name || ''); - if(!notification.title) { - notification.title = fromUser.phone || _('conversation_unknown_user_raw'); - } - - notificationPhoto = fromPhoto; - - peerString = appUsersManager.getUserString(peerId); - } else { - notification.title = appChatsManager.getChat(-peerId).title || _('conversation_unknown_chat_raw'); - - if(message.fromId) { - var fromUser = appUsersManager.getUser(message.fromId); - notification.title = (fromUser.first_name || fromUser.last_name || _('conversation_unknown_user_raw')) + + notification.title = appPeersManager.getPeerTitle(peerId, true); + if(peerId < 0 && message.fromId !== message.peerId) { + notification.title = appPeersManager.getPeerTitle(message.fromId, true) + ' @ ' + notification.title; - } - - notificationPhoto = appChatsManager.getChatPhoto(-peerId); - - peerString = appChatsManager.getChatString(-peerId); } notification.title = RichTextProcessor.wrapPlainText(notification.title); notification.onclick = () => { - /* rootScope.broadcast('history_focus', { - peerString: peerString, - messageID: message.flags & 16 ? message.mid : 0 - }); */ + rootScope.broadcast('history_focus', {peerId, mid: message.mid}); }; notification.message = notificationMessage; @@ -4980,16 +4955,17 @@ export class AppMessagesManager { notification.tag = peerString; notification.silent = true;//message.pFlags.silent || false; - /* if(notificationPhoto.location && !notificationPhoto.location.empty) { - apiManager.downloadSmallFile(notificationPhoto.location, notificationPhoto.size).then(function (blob) { - if (message.pFlags.unread) { - notification.image = blob - NotificationsManager.notify(notification) + const peerPhoto = appPeersManager.getPeerPhoto(peerId); + if(peerPhoto) { + appProfileManager.loadAvatar(peerId, peerPhoto, 'photo_small').loadPromise.then(url => { + if(message.pFlags.unread) { + notification.image = url; + appNotificationsManager.notify(notification); } - }) - } else { */ + }); + } else { appNotificationsManager.notify(notification); - //} + } } public getScheduledMessagesStorage(peerId: number) { diff --git a/src/lib/appManagers/appNotificationsManager.ts b/src/lib/appManagers/appNotificationsManager.ts index 06d6a686..7350519a 100644 --- a/src/lib/appManagers/appNotificationsManager.ts +++ b/src/lib/appManagers/appNotificationsManager.ts @@ -17,6 +17,7 @@ import { copy, deepEqual } from "../../helpers/object"; import { convertInputKeyToKey } from "../../helpers/string"; import { isMobile } from "../../helpers/userAgent"; import { InputNotifyPeer, InputPeerNotifySettings, NotifyPeer, PeerNotifySettings, Update } from "../../layer"; +import I18n from "../langPack"; import apiManager from "../mtproto/mtprotoworker"; import rootScope from "../rootScope"; import sessionStorage from "../sessionStorage"; @@ -55,10 +56,9 @@ export class AppNotificationsManager { notifyChats: null as ImSadAboutIt, notifyBroadcasts: null as ImSadAboutIt }; - private exceptions: {[peerId: string]: PeerNotifySettings} = {}; + //private exceptions: {[peerId: string]: PeerNotifySettings} = {}; private notifyContactsSignUp: Promise; private faviconEl: HTMLLinkElement = document.head.querySelector('link[rel="icon"]'); - private langNotificationsPluralize = 'notifications';//_.pluralize('page_title_pluralize_notifications'); private titleBackup = document.title; private titleChanged = false; @@ -221,7 +221,7 @@ export class AppNotificationsManager { resetTitle(); } else { this.titleChanged = true; - document.title = this.notificationsCount + ' ' + this.langNotificationsPluralize; + document.title = I18n.format('Notifications.Count', true, [this.notificationsCount]); //this.setFavicon('assets/img/favicon_unread.ico'); // fetch('assets/img/favicon.ico') @@ -499,8 +499,8 @@ export class AppNotificationsManager { data.image = FileManager.getUrl(data.image, 'image/jpeg') } } - else if (!data.image) */ { - data.image = 'assets/img/logo.svg'; + else */ if(!data.image) { + data.image = 'assets/img/logo_filled_rounded.png'; } // console.log('notify image', data.image) diff --git a/src/lib/appManagers/appProfileManager.ts b/src/lib/appManagers/appProfileManager.ts index 321f7e95..e8ec8adc 100644 --- a/src/lib/appManagers/appProfileManager.ts +++ b/src/lib/appManagers/appProfileManager.ts @@ -37,7 +37,7 @@ export class AppProfileManager { private savedAvatarURLs: { [peerId: number]: { - [size in PeerPhotoSize]?: string | Promise + [size in PeerPhotoSize]?: string | Promise } } = {}; @@ -455,11 +455,11 @@ export class AppProfileManager { } } - public putAvatar(div: HTMLElement, peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize, img = new Image()) { + public loadAvatar(peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize) { const inputPeer = appPeersManager.getInputPeerById(peerId); - let needFadeIn = true; - let getAvatarPromise: Promise; + let cached = false; + let getAvatarPromise: Promise; let saved = this.savedAvatarURLs[peerId]; if(!saved || !saved[size]) { if(!saved) { @@ -489,7 +489,7 @@ export class AppProfileManager { const promise = appDownloadManager.download(downloadOptions); getAvatarPromise = saved[size] = promise.then(blob => { - saved[size] = URL.createObjectURL(blob); + return saved[size] = URL.createObjectURL(blob); /* if(str) { console.log(str, Date.now() / 1000, Date.now() - time); @@ -498,12 +498,18 @@ export class AppProfileManager { } else if(typeof(saved[size]) !== 'string') { getAvatarPromise = saved[size] as Promise; } else { - getAvatarPromise = Promise.resolve(); - needFadeIn = false; + getAvatarPromise = Promise.resolve(saved[size]); + cached = true; } + return {cached, loadPromise: getAvatarPromise}; + } + + public putAvatar(div: HTMLElement, peerId: number, photo: UserProfilePhoto.userProfilePhoto | ChatPhoto.chatPhoto, size: PeerPhotoSize, img = new Image()) { + const {cached, loadPromise} = this.loadAvatar(peerId, photo, size); + let callback: () => void; - if(!needFadeIn) { + if(cached) { // смотри в misc.ts: renderImageFromUrl callback = () => { replaceContent(div, img); @@ -532,16 +538,16 @@ export class AppProfileManager { }; } - const loadPromise = getAvatarPromise.then(() => { + const renderPromise = loadPromise.then((url) => { return new Promise((resolve) => { - renderImageFromUrl(img, saved[size] as string, () => { + renderImageFromUrl(img, url, () => { callback(); resolve(); }/* , false */); }); }); - return {cached: !needFadeIn, loadPromise}; + return {cached, loadPromise: renderPromise}; } // peerId === peerId || title diff --git a/src/lib/mtproto/networker.ts b/src/lib/mtproto/networker.ts index 7539f426..155303c9 100644 --- a/src/lib/mtproto/networker.ts +++ b/src/lib/mtproto/networker.ts @@ -74,6 +74,7 @@ export type MTMessage = InvokeApiOptions & MTMessageOptions & { }; const CONNECTION_TIMEOUT = 5000; +let invokeAfterMsgConstructor: number; export default class MTPNetworker { private authKeyUint8: Uint8Array; @@ -320,15 +321,21 @@ export default class MTPNetworker { } if(options.afterMessageId) { - const invokeAfterMsg = Schema.API.methods.find(m => m.method === 'invokeAfterMsg'); - if(!invokeAfterMsg) throw new Error('no invokeAfterMsg!'); - - if(this.debug) { - this.log('Api call options.afterMessageId!'); + if(invokeAfterMsgConstructor === undefined) { + const m = Schema.API.methods.find(m => m.method === 'invokeAfterMsg'); + invokeAfterMsgConstructor = m ? +m.id >>> 0 : 0; + } + + if(invokeAfterMsgConstructor) { + //if(this.debug) { + //this.log('Api call options.afterMessageId!'); + //} + + serializer.storeInt(invokeAfterMsgConstructor, 'invokeAfterMsg'); + serializer.storeLong(options.afterMessageId, 'msg_id'); + } else { + this.log.error('no invokeAfterMsg!'); } - - serializer.storeInt(+invokeAfterMsg.id >>> 0, 'invokeAfterMsg'); - serializer.storeLong(options.afterMessageId, 'msg_id'); } options.resultType = serializer.storeMethod(method, params); diff --git a/src/lib/mtproto/serverTimeManager.ts b/src/lib/mtproto/serverTimeManager.ts index 2fa918b1..8f7476eb 100644 --- a/src/lib/mtproto/serverTimeManager.ts +++ b/src/lib/mtproto/serverTimeManager.ts @@ -9,6 +9,7 @@ * https://github.com/zhukov/webogram/blob/master/LICENSE */ +import { MOUNT_CLASS_TO } from '../../config/debug'; import { tsNow } from '../../helpers/date'; import sessionStorage from '../sessionStorage'; @@ -37,4 +38,6 @@ export class ServerTimeManager { } } -export default new ServerTimeManager(); +const serverTimeManager = new ServerTimeManager(); +MOUNT_CLASS_TO && (MOUNT_CLASS_TO.serverTimeManager = serverTimeManager); +export default serverTimeManager; diff --git a/src/lib/rootScope.ts b/src/lib/rootScope.ts index 78a35da6..560d5676 100644 --- a/src/lib/rootScope.ts +++ b/src/lib/rootScope.ts @@ -51,7 +51,7 @@ export type BroadcastEvents = { 'history_delete': {peerId: number, msgs: {[mid: number]: true}}, 'history_forbidden': number, 'history_reload': number, - 'history_focus': number, + 'history_focus': {peerId: number, mid?: number}, //'history_request': void, 'message_edit': {storage: MessagesStorage, peerId: number, mid: number}, diff --git a/src/pages/pageAuthCode.ts b/src/pages/pageAuthCode.ts index 5d130550..ccc1e39a 100644 --- a/src/pages/pageAuthCode.ts +++ b/src/pages/pageAuthCode.ts @@ -17,6 +17,7 @@ import TrackingMonkey from '../components/monkeys/tracking'; import CodeInputField from '../components/codeInputField'; import { replaceContent } from '../helpers/dom'; import { i18n, LangPackKey } from '../lib/langPack'; +import { randomLong } from '../helpers/random'; let authCode: AuthSentCode.authSentCode = null; @@ -29,7 +30,7 @@ let onFirstMount = (): Promise => { const codeInputField = new CodeInputField({ label: 'Code', - name: 'code', + name: randomLong(), length: CODELENGTH, onFill: (code) => { submitCode('' + code); diff --git a/src/pages/pageSignIn.ts b/src/pages/pageSignIn.ts index d6f3ad58..417beb23 100644 --- a/src/pages/pageSignIn.ts +++ b/src/pages/pageSignIn.ts @@ -25,6 +25,8 @@ import { LangPackString } from "../layer"; import lottieLoader from "../lib/lottieLoader"; import { ripple } from "../components/ripple"; import findUpTag from "../helpers/dom/findUpTag"; +import findUpClassName from "../helpers/dom/findUpClassName"; +import { randomLong } from "../helpers/random"; type Country = _Country & { li?: HTMLLIElement[] @@ -56,14 +58,14 @@ let onFirstMount = () => { const countryInputField = new InputField({ label: 'Login.CountrySelectorLabel', - name: 'countryCode', + name: randomLong(), plainText: true }); countryInputField.container.classList.add('input-select'); const countryInput = countryInputField.input as HTMLInputElement; - countryInput.autocomplete = 'rrRandomRR'; + countryInput.autocomplete = randomLong(); const selectWrapper = document.createElement('div'); selectWrapper.classList.add('select-wrapper', 'z-depth-3', 'hide'); @@ -77,38 +79,25 @@ let onFirstMount = () => { const scroll = new Scrollable(selectWrapper); - let initedSelect = false; - let initSelect = () => { initSelect = null; countries.forEach((c) => { - initedSelect = true; - - /* let unified = unifiedCountryCodeEmoji(c.code); - let emoji = unified.split('-').reduce((prev, curr) => prev + String.fromCodePoint(parseInt(curr, 16)), ''); */ - //let emoji = countryCodeEmoji(c.code); - let emoji = c.emoji; + const emoji = c.emoji; - let liArr: Array = []; + const liArr: Array = []; c.phoneCode.split(' and ').forEach((phoneCode: string) => { - let li = document.createElement('li'); - var spanEmoji = document.createElement('span'); - /* spanEmoji.innerHTML = countryCodeEmoji(c.code); */ - //spanEmoji.classList.add('emoji-outer', 'emoji-sizer'); - //spanEmoji.innerHTML = ``; - - + const li = document.createElement('li'); + const spanEmoji = document.createElement('span'); - let kek = RichTextProcessor.wrapRichText(emoji); - //console.log(c.name, emoji, kek, spanEmoji.innerHTML); + const kek = RichTextProcessor.wrapRichText(emoji); li.appendChild(spanEmoji); spanEmoji.outerHTML = kek; li.append(c.name); - var span = document.createElement('span'); + const span = document.createElement('span'); span.classList.add('phone-code'); span.innerText = '+' + phoneCode; li.appendChild(span); @@ -120,23 +109,32 @@ let onFirstMount = () => { c.li = liArr; }); - selectList.addEventListener('mousedown', function(e) { + selectList.addEventListener('mousedown', (e) => { + if(e.button !== 0) { // other buttons but left shall not pass + return; + } + let target = e.target as HTMLElement; if(target.tagName !== 'LI') target = findUpTag(target, 'LI'); - let countryName = target.childNodes[1].textContent;//target.innerText.split('\n').shift(); - let phoneCode = target.querySelector('.phone-code').innerText; - - countryInput.value = countryName; - lastCountrySelected = countries.find(c => c.name === countryName); - - telEl.value = lastValue = phoneCode; - setTimeout(() => telEl.focus(), 0); + selectCountryByTarget(target); //console.log('clicked', e, countryName, phoneCode); }); countryInputField.container.appendChild(selectWrapper); }; + + const selectCountryByTarget = (target: HTMLElement) => { + const countryName = target.childNodes[1].textContent;//target.innerText.split('\n').shift(); + const phoneCode = target.querySelector('.phone-code').innerText; + + countryInput.value = countryName; + lastCountrySelected = countries.find(c => c.name === countryName); + + telEl.value = lastValue = phoneCode; + hidePicker(); + setTimeout(() => telEl.focus(), 0); + }; initSelect(); @@ -152,6 +150,7 @@ let onFirstMount = () => { } clearTimeout(hideTimeout); + hideTimeout = undefined; selectWrapper.classList.remove('hide'); void selectWrapper.offsetWidth; // reflow @@ -171,9 +170,9 @@ let onFirstMount = () => { let mouseDownHandlerAttached = false; const onMouseDown = (e: MouseEvent) => { - /* if(findUpClassName(e.target, 'input-select')) { + if(findUpClassName(e.target, 'input-select')) { return; - } */ + } if(e.target === countryInput) { return; } @@ -184,9 +183,11 @@ let onFirstMount = () => { }; const hidePicker = () => { + if(hideTimeout !== undefined) return; selectWrapper.classList.remove('active'); hideTimeout = window.setTimeout(() => { selectWrapper.classList.add('hide'); + hideTimeout = undefined; }, 200); }; /* false && countryInput.addEventListener('blur', function(this: typeof countryInput, e) { @@ -221,6 +222,8 @@ let onFirstMount = () => { countries.forEach((c) => { c.li.forEach(li => li.style.display = ''); }); + } else if(matches.length === 1 && e.key === 'Enter') { + selectCountryByTarget(matches[0].li[0]); } }); diff --git a/src/scss/partials/_audio.scss b/src/scss/partials/_audio.scss index c0d59950..a4b0d19c 100644 --- a/src/scss/partials/_audio.scss +++ b/src/scss/partials/_audio.scss @@ -359,6 +359,10 @@ //overflow: visible!important; opacity: .3; + @include hover() { + opacity: 1; + } + &.active, .audio.is-unread:not(.is-out) & { opacity: 1; } diff --git a/src/scss/partials/_button.scss b/src/scss/partials/_button.scss index 017b6ba2..6db9466a 100644 --- a/src/scss/partials/_button.scss +++ b/src/scss/partials/_button.scss @@ -112,7 +112,7 @@ &.active { visibility: visible; opacity: 1; - transform: scale(1); + transform: scale3d(1, 1, 1); // * scale3d (NOT scale) will fix jumping text } &:not(.active) { @@ -178,7 +178,7 @@ @include hover-background-effect(); &.danger { - @include hover-background-effect(red); + @include hover-background-effect(danger); } &:before { diff --git a/src/scss/partials/_chat.scss b/src/scss/partials/_chat.scss index efb3fedd..a7ec0902 100644 --- a/src/scss/partials/_chat.scss +++ b/src/scss/partials/_chat.scss @@ -1041,12 +1041,6 @@ $chat-helper-size: 39px; } //} } - - .preloader-container { - .preloader-circular { - background-color: rgba(0, 0, 0, .3); - } - } .search-group.search-group-messages { padding: 0.25rem 0 .5rem; @@ -1139,7 +1133,7 @@ $chat-helper-size: 39px; position: absolute; background-color: var(--surface-color); border-radius: 50%; - color: $placeholder-color; + color: var(--secondary-text-color); font-size: 1.5rem; display: flex; align-items: center; @@ -1171,6 +1165,10 @@ $chat-helper-size: 39px; position: absolute; top: -.25rem; right: -.25rem; + + &.badge-primary { + background-color: var(--chatlist-status-color); + } @include respond-to(handhelds) { top: -.75rem; diff --git a/src/scss/partials/_chatBubble.scss b/src/scss/partials/_chatBubble.scss index 4e10da87..241ecdbb 100644 --- a/src/scss/partials/_chatBubble.scss +++ b/src/scss/partials/_chatBubble.scss @@ -1279,8 +1279,8 @@ $bubble-margin: .25rem; visibility: visible; } - .tgico-pinnedchat:before { - font-weight: bold; + .tgico-pinnedchat { + margin-right: .125rem; } } diff --git a/src/scss/partials/_input.scss b/src/scss/partials/_input.scss index a6226278..533ebd7e 100644 --- a/src/scss/partials/_input.scss +++ b/src/scss/partials/_input.scss @@ -11,6 +11,7 @@ .input-field { --height: 54px; + --border-radius: #{$border-radius-medium}; position: relative; @include respond-to(handhelds) { @@ -62,27 +63,39 @@ transition: .2s transform, .2s padding, .1s opacity, font-weight 0s .1s; } } + + &-border { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + border: 2px solid var(--primary-color); + opacity: 0; + border-radius: var(--border-radius); + pointer-events: none; + + @include animation-level(2) { + transition: opacity .2s; + } + } &-input { - --padding: 1.0625rem; + --padding: 1rem; --padding-horizontal: 1rem; --border-width: 1px; - --border-width-top: 2px; border: var(--border-width) solid var(--input-search-border-color); - border-radius: $border-radius-medium; + border-radius: var(--border-radius); background-color: transparent; //padding: 0 1rem; - padding: calc(var(--padding) - var(--border-width-top)) calc(var(--padding-horizontal) - var(--border-width)); + padding: calc(var(--padding) - var(--border-width)); box-sizing: border-box; width: 100%; min-height: var(--height); transition: 0s border-color; position: relative; z-index: 1; - line-height: 1.3125; - //line-height: calc(54px - var(--border-width)); - /* overflow: hidden; - white-space: nowrap; */ + line-height: var(--line-height); @include respond-to(handhelds) { --padding: .9375rem; @@ -116,8 +129,6 @@ } */ &:focus { - --border-width: 2px; - --border-width-top: 3px; border-color: var(--primary-color); //padding: 0 calc(1rem - 1px); } @@ -133,6 +144,10 @@ & ~ label { color: var(--danger-color) !important; } + + & ~ .input-field-border { + border-color: var(--danger-color) !important; + } } &.valid { @@ -141,6 +156,10 @@ & ~ label { color: #26962F !important; } + + & ~ .input-field-border { + border-color: #26962F !important; + } } /* &.error, &.valid { @@ -158,11 +177,15 @@ font-weight: 500; } - // * valid for plain text, empty for contenteditable + &:focus ~ .input-field-border { + opacity: 1; + } + + /* // * valid for plain text, empty for contenteditable &:valid ~ label, &:not(:empty):focus ~ label { transition-delay: 0s, 0s, 0s, 0s; - } + } */ &:focus ~ label, &:valid ~ label, @@ -252,6 +275,7 @@ input:focus, button:focus { margin-left: .4375rem; margin-right: .4375rem; overflow: hidden; + --border-radius: 22px; @include respond-to(handhelds) { margin-left: 1rem; @@ -265,7 +289,6 @@ input:focus, button:focus { min-height: var(--height) !important; max-height: var(--height) !important; //line-height: calc(var(--height) + 2px - var(--border-width) * 2); - border-radius: 22px; border-color: var(--input-search-border-color); line-height: var(--height); @@ -281,7 +304,6 @@ input:focus, button:focus { } &:focus { - --border-width: 2px; background-color: transparent; border-color: var(--primary-color); diff --git a/src/scss/partials/_preloader.scss b/src/scss/partials/_preloader.scss index d93c6078..7622d039 100644 --- a/src/scss/partials/_preloader.scss +++ b/src/scss/partials/_preloader.scss @@ -70,7 +70,7 @@ $transition: .2s ease-in-out; .preloader-circular { animation: none; - background-color: rgba(0, 0, 0, .7); + background-color: rgba(0, 0, 0, .3); border-radius: 50%; width: 100%; height: 100%; diff --git a/src/scss/partials/_rightSidebar.scss b/src/scss/partials/_rightSidebar.scss index ccfc3d28..4de4b100 100644 --- a/src/scss/partials/_rightSidebar.scss +++ b/src/scss/partials/_rightSidebar.scss @@ -173,6 +173,7 @@ justify-content: center; font-size: 1rem; line-height: var(--line-height); + border-radius: 0; } .menu-horizontal-div i { @@ -287,6 +288,10 @@ > div:first-child { transform: translateY(0); + + // * fix saving scroll on tab switching, when FROM tab has height < 100vh, and another is scrolled less than the FROM tab's height + // * adding 1 extra pixel for scroll + min-height: calc(100vh - 111px); } } diff --git a/src/scss/partials/popups/_createPoll.scss b/src/scss/partials/popups/_createPoll.scss index e312eb03..ccd7818a 100644 --- a/src/scss/partials/popups/_createPoll.scss +++ b/src/scss/partials/popups/_createPoll.scss @@ -45,11 +45,16 @@ .btn-icon { position: absolute; - right: .5rem; - top: .5rem; + right: .4375rem; + top: .4375rem; z-index: 1; opacity: 1; transition: opacity .2s ease; + + @include respond-to(handhelds) { + right: .3125rem; + top: .3125rem; + } } /* &:last-child:not(:nth-child(10)) { .btn-icon { @@ -65,7 +70,7 @@ } .poll-create-questions { - padding: 0px 1.25rem 2.03125rem; + padding: 0px 1.25rem 1.5rem; .input-field-input { padding-right: 3.25rem; @@ -90,4 +95,4 @@ top: 54px; right: 20px; } -} \ No newline at end of file +}