From aae32daf168c54467de45292891b21f22d290012 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Fri, 23 Apr 2021 16:44:19 +0400 Subject: [PATCH] FF64 fixes: Fix grid (slider) layout Fix button dropdowns Fix ripple Disabled parallax --- src/components/button.ts | 14 ++++++-- src/components/buttonIcon.ts | 2 +- src/components/buttonMenuToggle.ts | 3 +- src/components/ripple.ts | 22 ++++++------ .../sidebarRight/tabs/sharedMedia.ts | 36 ++++++++++++------- src/helpers/userAgent.ts | 1 + src/pages/pageSignQR.ts | 5 +++ src/scss/partials/_button.scss | 10 +++--- src/scss/partials/_leftSidebar.scss | 3 +- src/scss/partials/_profile.scss | 4 +++ src/scss/partials/_rightSidebar.scss | 2 +- src/scss/partials/_ripple.scss | 1 + src/scss/partials/_slider.scss | 10 +++--- 13 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/components/button.ts b/src/components/button.ts index f0d7940d..2fb996a4 100644 --- a/src/components/button.ts +++ b/src/components/button.ts @@ -7,8 +7,16 @@ import { i18n, LangPackKey } from "../lib/langPack"; import { ripple } from "./ripple"; -const Button = (className: string, options: Partial<{noRipple: true, onlyMobile: true, icon: string, rippleSquare: true, text: LangPackKey, disabled: boolean}> = {}) => { - const button = document.createElement('button'); +const Button = (className: string, options: Partial<{ + noRipple: true, + onlyMobile: true, + icon: string, + rippleSquare: true, + text: LangPackKey, + disabled: boolean, + asDiv: boolean +}> = {}) => { + const button: HTMLButtonElement = document.createElement(options.asDiv ? 'div' : 'button') as any; button.className = className + (options.icon ? ' tgico-' + options.icon : ''); if(!options.noRipple) { @@ -24,7 +32,7 @@ const Button = (className: string, options: Partial<{noRipple: true, onlyMobile: } if(options.disabled) { - button.disabled = true; + button.setAttribute('disabled', 'true'); } if(options.text) { diff --git a/src/components/buttonIcon.ts b/src/components/buttonIcon.ts index 6afd43fb..9cab3156 100644 --- a/src/components/buttonIcon.ts +++ b/src/components/buttonIcon.ts @@ -6,7 +6,7 @@ import Button from "./button"; -const ButtonIcon = (className: string, options: Partial<{noRipple: true, onlyMobile: true}> = {}) => { +const ButtonIcon = (className: string, options: Partial<{noRipple: true, onlyMobile: true, asDiv: boolean}> = {}) => { const button = Button('btn-icon', {icon: className, ...options}); return button; }; diff --git a/src/components/buttonMenuToggle.ts b/src/components/buttonMenuToggle.ts index 37066357..6911c415 100644 --- a/src/components/buttonMenuToggle.ts +++ b/src/components/buttonMenuToggle.ts @@ -10,7 +10,8 @@ import ButtonIcon from "./buttonIcon"; import ButtonMenu, { ButtonMenuItemOptions } from "./buttonMenu"; import { closeBtnMenu, openBtnMenu } from "./misc"; -const ButtonMenuToggle = (options: Partial<{noRipple: true, onlyMobile: true, listenerSetter: ListenerSetter}> = {}, direction: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right', buttons: ButtonMenuItemOptions[], onOpen?: (e: Event) => void) => { +const ButtonMenuToggle = (options: Partial<{noRipple: true, onlyMobile: true, listenerSetter: ListenerSetter, asDiv: boolean}> = {}, direction: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right', buttons: ButtonMenuItemOptions[], onOpen?: (e: Event) => void) => { + options.asDiv = true; const button = ButtonIcon('more btn-menu-toggle', options); const btnMenu = ButtonMenu(buttons, options.listenerSetter); diff --git a/src/components/ripple.ts b/src/components/ripple.ts index ed2450a7..7f3bec53 100644 --- a/src/components/ripple.ts +++ b/src/components/ripple.ts @@ -129,6 +129,11 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise e.target !== elem && ( + ['BUTTON', 'A'].includes((e.target as HTMLElement).tagName) + || findUpClassName(e.target as HTMLElement, 'c-ripple') !== r + ); + // TODO: rename this variable let touchStartFired = false; if(isTouchSupported) { @@ -142,10 +147,7 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise 1 - || touchStartFired - || (['BUTTON', 'A'].includes((e.target as HTMLElement).tagName) && e.target !== elem) - || findUpClassName(e.target as HTMLElement, 'c-ripple') !== r) { + if(e.touches.length > 1 || touchStartFired || isRippleUnneeded(e)) { return; } @@ -174,17 +176,17 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise { //fastRaf(() => { @@ -52,6 +53,8 @@ let setText = (text: string, row: Row) => { //}); }; +const PARALLAX_SUPPORTED = !isFirefox; + type ListLoaderResult = {count: number, items: any[]}; class ListLoader { public current: T; @@ -164,14 +167,16 @@ class ListLoader { } class PeerProfileAvatars { - public static BASE_CLASS = 'profile-avatars'; + private static BASE_CLASS = 'profile-avatars'; + private static SCALE = PARALLAX_SUPPORTED ? 2 : 1; + private static TRANSLATE_TEMPLATE = PARALLAX_SUPPORTED ? `translate3d({x}, 0, -1px) scale(${PeerProfileAvatars.SCALE})` : 'translate({x}, 0)'; public container: HTMLElement; public avatars: HTMLElement; public gradient: HTMLElement; public info: HTMLElement; - public tabs: HTMLDivElement; - public listLoader: ListLoader; - public peerId: number; + private tabs: HTMLDivElement; + private listLoader: ListLoader; + private peerId: number; constructor(public scrollable: Scrollable) { this.container = document.createElement('div'); @@ -266,11 +271,11 @@ class PeerProfileAvatars { element: this.avatars, onSwipe: (xDiff, yDiff) => { lastDiffX = xDiff; - let lastX = x + xDiff * -2; + let lastX = x + xDiff * -PeerProfileAvatars.SCALE; if(lastX > 0) lastX = 0; else if(lastX < minX) lastX = minX; - this.avatars.style.transform = `translate3d(${lastX}px, 0, -1px) scale(2)`; + this.avatars.style.transform = PeerProfileAvatars.TRANSLATE_TEMPLATE.replace('{x}', lastX + 'px'); //console.log(xDiff, yDiff); return false; }, @@ -294,13 +299,13 @@ class PeerProfileAvatars { x = -width * lastIndex; */ x = rect.left - this.container.getBoundingClientRect().left; - this.avatars.style.transform = `translate3d(${x}px, 0, -1px) scale(2)`; + this.avatars.style.transform = PeerProfileAvatars.TRANSLATE_TEMPLATE.replace('{x}', x + 'px'); this.avatars.classList.add('no-transition'); void this.avatars.offsetLeft; // reflow }, onReset: () => { - const addIndex = Math.ceil(Math.abs(lastDiffX) / (width / 2)) * (lastDiffX >= 0 ? 1 : -1); + const addIndex = Math.ceil(Math.abs(lastDiffX) / (width / PeerProfileAvatars.SCALE)) * (lastDiffX >= 0 ? 1 : -1); cancelNextClick(); //console.log(addIndex); @@ -372,7 +377,8 @@ class PeerProfileAvatars { onJump: (item, older) => { const id = this.listLoader.index; //const nextId = Math.max(0, id); - this.avatars.style.transform = `translate3d(-${200 * id}%, 0, -1px) scale(2)`; + const x = 100 * PeerProfileAvatars.SCALE * id; + this.avatars.style.transform = PeerProfileAvatars.TRANSLATE_TEMPLATE.replace('{x}', `-${x}%`); const activeTab = this.tabs.querySelector('.active'); if(activeTab) activeTab.classList.remove('active'); @@ -457,7 +463,9 @@ class PeerProfile { private threadId: number; constructor(public scrollable: Scrollable) { - + if(!PARALLAX_SUPPORTED) { + this.scrollable.container.classList.add('no-parallax'); + } } public init() { @@ -609,13 +617,17 @@ class PeerProfile { if(oldAvatars) oldAvatars.container.replaceWith(this.avatars.container); else this.element.prepend(this.avatars.container); - this.scrollable.container.classList.add('parallax'); + if(PARALLAX_SUPPORTED) { + this.scrollable.container.classList.add('parallax'); + } return; } } - this.scrollable.container.classList.remove('parallax'); + if(PARALLAX_SUPPORTED) { + this.scrollable.container.classList.remove('parallax'); + } if(this.avatars) { this.avatars.container.remove(); diff --git a/src/helpers/userAgent.ts b/src/helpers/userAgent.ts index 1335c8ad..d32848f1 100644 --- a/src/helpers/userAgent.ts +++ b/src/helpers/userAgent.ts @@ -25,6 +25,7 @@ export const isAppleMobile = (/iPad|iPhone|iPod/.test(navigator.platform) || !ctx.MSStream; export const isSafari = !!('safari' in ctx) || !!(userAgent && (/\b(iPad|iPhone|iPod)\b/.test(userAgent) || (!!userAgent.match('Safari') && !userAgent.match('Chrome'))))/* || true */; +export const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; export const isMobileSafari = isSafari && isAppleMobile; diff --git a/src/pages/pageSignQR.ts b/src/pages/pageSignQR.ts index 5b8d040f..9c19bc3b 100644 --- a/src/pages/pageSignQR.ts +++ b/src/pages/pageSignQR.ts @@ -161,9 +161,14 @@ let onFirstMount = async() => { break; default: console.error('pageSignQR: default error:', err); + stop = true; break; } + + return true; } + + return false; }; await iterate(false); diff --git a/src/scss/partials/_button.scss b/src/scss/partials/_button.scss index 6db9466a..eeac8582 100644 --- a/src/scss/partials/_button.scss +++ b/src/scss/partials/_button.scss @@ -366,14 +366,14 @@ } .btn-circle { + --size: 54px; border-radius: 50%; - height: 54px; - width: 54px; - line-height: 54px; + height: var(--size); + width: var(--size) !important; + line-height: var(--size); @include respond-to(handhelds) { - height: 46px; - width: 46px; + --size: 46px; } path { diff --git a/src/scss/partials/_leftSidebar.scss b/src/scss/partials/_leftSidebar.scss index 5361cf78..b810bcd2 100644 --- a/src/scss/partials/_leftSidebar.scss +++ b/src/scss/partials/_leftSidebar.scss @@ -357,8 +357,7 @@ } @include respond-to(handhelds) { - width: 54px; - height: 54px; + --size: 54px; bottom: 14px; right: 14px; diff --git a/src/scss/partials/_profile.scss b/src/scss/partials/_profile.scss index efd73732..b7777a24 100644 --- a/src/scss/partials/_profile.scss +++ b/src/scss/partials/_profile.scss @@ -33,6 +33,10 @@ transition: transform .2s ease-in-out; position: absolute; + .scrollable.no-parallax & { + transform: translate(0, 0); + } + &:before { content: " "; top: 0; diff --git a/src/scss/partials/_rightSidebar.scss b/src/scss/partials/_rightSidebar.scss index 4de4b100..359090d5 100644 --- a/src/scss/partials/_rightSidebar.scss +++ b/src/scss/partials/_rightSidebar.scss @@ -110,7 +110,7 @@ max-height: calc((var(--vh, 1vh) * 100) - 100% - 56px); } } */ - .scrollable { + .scrollable:not(.no-parallax) { perspective: 0px; perspective-origin: left top; diff --git a/src/scss/partials/_ripple.scss b/src/scss/partials/_ripple.scss index 6ec422fe..8b6d62c8 100644 --- a/src/scss/partials/_ripple.scss +++ b/src/scss/partials/_ripple.scss @@ -57,6 +57,7 @@ //animation-timing-function: ease-out; transition: .35s opacity, .35s background-color; //overflow: hidden; + pointer-events: none; .btn-menu &, .c-ripple.is-square & { animation-name: ripple-effect-handhelds; diff --git a/src/scss/partials/_slider.scss b/src/scss/partials/_slider.scss index bfb1d4b1..6b50d923 100644 --- a/src/scss/partials/_slider.scss +++ b/src/scss/partials/_slider.scss @@ -118,10 +118,12 @@ // } > div { - height: 100%; - max-height: 100%; - width: 100%; - max-width: 100%; + // * can't define these rules because of old firefox, though they don't work + //height: 100%; + //max-height: 100%; + //width: 100%; + //max-width: 100%; + display: none; flex-direction: column; position: relative;