Browse Source

FF64 fixes:

Fix grid (slider) layout
Fix button dropdowns
Fix ripple
Disabled parallax
master
Eduard Kuzmenko 4 years ago
parent
commit
aae32daf16
  1. 14
      src/components/button.ts
  2. 2
      src/components/buttonIcon.ts
  3. 3
      src/components/buttonMenuToggle.ts
  4. 22
      src/components/ripple.ts
  5. 32
      src/components/sidebarRight/tabs/sharedMedia.ts
  6. 1
      src/helpers/userAgent.ts
  7. 5
      src/pages/pageSignQR.ts
  8. 10
      src/scss/partials/_button.scss
  9. 3
      src/scss/partials/_leftSidebar.scss
  10. 4
      src/scss/partials/_profile.scss
  11. 2
      src/scss/partials/_rightSidebar.scss
  12. 1
      src/scss/partials/_ripple.scss
  13. 10
      src/scss/partials/_slider.scss

14
src/components/button.ts

@ -7,8 +7,16 @@
import { i18n, LangPackKey } from "../lib/langPack"; import { i18n, LangPackKey } from "../lib/langPack";
import { ripple } from "./ripple"; import { ripple } from "./ripple";
const Button = (className: string, options: Partial<{noRipple: true, onlyMobile: true, icon: string, rippleSquare: true, text: LangPackKey, disabled: boolean}> = {}) => { const Button = (className: string, options: Partial<{
const button = document.createElement('button'); 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 : ''); button.className = className + (options.icon ? ' tgico-' + options.icon : '');
if(!options.noRipple) { if(!options.noRipple) {
@ -24,7 +32,7 @@ const Button = (className: string, options: Partial<{noRipple: true, onlyMobile:
} }
if(options.disabled) { if(options.disabled) {
button.disabled = true; button.setAttribute('disabled', 'true');
} }
if(options.text) { if(options.text) {

2
src/components/buttonIcon.ts

@ -6,7 +6,7 @@
import Button from "./button"; 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}); const button = Button('btn-icon', {icon: className, ...options});
return button; return button;
}; };

3
src/components/buttonMenuToggle.ts

@ -10,7 +10,8 @@ import ButtonIcon from "./buttonIcon";
import ButtonMenu, { ButtonMenuItemOptions } from "./buttonMenu"; import ButtonMenu, { ButtonMenuItemOptions } from "./buttonMenu";
import { closeBtnMenu, openBtnMenu } from "./misc"; 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 button = ButtonIcon('more btn-menu-toggle', options);
const btnMenu = ButtonMenu(buttons, options.listenerSetter); const btnMenu = ButtonMenu(buttons, options.listenerSetter);

22
src/components/ripple.ts

@ -129,6 +129,11 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
//}); //});
}; };
const isRippleUnneeded = (e: Event) => e.target !== elem && (
['BUTTON', 'A'].includes((e.target as HTMLElement).tagName)
|| findUpClassName(e.target as HTMLElement, 'c-ripple') !== r
);
// TODO: rename this variable // TODO: rename this variable
let touchStartFired = false; let touchStartFired = false;
if(isTouchSupported) { if(isTouchSupported) {
@ -142,10 +147,7 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
} }
//console.log('ripple touchstart', e); //console.log('ripple touchstart', e);
if(e.touches.length > 1 if(e.touches.length > 1 || touchStartFired || isRippleUnneeded(e)) {
|| touchStartFired
|| (['BUTTON', 'A'].includes((e.target as HTMLElement).tagName) && e.target !== elem)
|| findUpClassName(e.target as HTMLElement, 'c-ripple') !== r) {
return; return;
} }
@ -174,17 +176,17 @@ export function ripple(elem: HTMLElement, callback: (id: number) => Promise<bool
} }
//console.log('ripple mousedown', e, e.target, findUpClassName(e.target as HTMLElement, 'c-ripple') === r); //console.log('ripple mousedown', e, e.target, findUpClassName(e.target as HTMLElement, 'c-ripple') === r);
if(elem.dataset.ripple === '0' || findUpClassName(e.target as HTMLElement, 'c-ripple') !== r || (e.target as HTMLElement).tagName === 'A') { if(elem.dataset.ripple === '0' || isRippleUnneeded(e)) {
return false; return;
} else if(touchStartFired) { } else if(touchStartFired) {
touchStartFired = false; touchStartFired = false;
return false; return;
} }
let {clientX, clientY} = e; let {clientX, clientY} = e;
drawRipple(clientX, clientY); drawRipple(clientX, clientY);
window.addEventListener('mouseup', handler, {once: true}); window.addEventListener('mouseup', handler, {once: true, passive: true});
window.addEventListener('contextmenu', handler, {once: true}); window.addEventListener('contextmenu', handler, {once: true, passive: true});
}); }, {passive: true});
} }
} }

32
src/components/sidebarRight/tabs/sharedMedia.ts

@ -44,6 +44,7 @@ import PopupPickUser from "../../popups/pickUser";
import PopupPeer from "../../popups/peer"; import PopupPeer from "../../popups/peer";
import Scrollable from "../../scrollable"; import Scrollable from "../../scrollable";
import { isTouchSupported } from "../../../helpers/touchSupport"; import { isTouchSupported } from "../../../helpers/touchSupport";
import { isFirefox } from "../../../helpers/userAgent";
let setText = (text: string, row: Row) => { let setText = (text: string, row: Row) => {
//fastRaf(() => { //fastRaf(() => {
@ -52,6 +53,8 @@ let setText = (text: string, row: Row) => {
//}); //});
}; };
const PARALLAX_SUPPORTED = !isFirefox;
type ListLoaderResult<T> = {count: number, items: any[]}; type ListLoaderResult<T> = {count: number, items: any[]};
class ListLoader<T> { class ListLoader<T> {
public current: T; public current: T;
@ -164,14 +167,16 @@ class ListLoader<T> {
} }
class PeerProfileAvatars { 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 container: HTMLElement;
public avatars: HTMLElement; public avatars: HTMLElement;
public gradient: HTMLElement; public gradient: HTMLElement;
public info: HTMLElement; public info: HTMLElement;
public tabs: HTMLDivElement; private tabs: HTMLDivElement;
public listLoader: ListLoader<string | Message.messageService>; private listLoader: ListLoader<string | Message.messageService>;
public peerId: number; private peerId: number;
constructor(public scrollable: Scrollable) { constructor(public scrollable: Scrollable) {
this.container = document.createElement('div'); this.container = document.createElement('div');
@ -266,11 +271,11 @@ class PeerProfileAvatars {
element: this.avatars, element: this.avatars,
onSwipe: (xDiff, yDiff) => { onSwipe: (xDiff, yDiff) => {
lastDiffX = xDiff; lastDiffX = xDiff;
let lastX = x + xDiff * -2; let lastX = x + xDiff * -PeerProfileAvatars.SCALE;
if(lastX > 0) lastX = 0; if(lastX > 0) lastX = 0;
else if(lastX < minX) lastX = minX; 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); //console.log(xDiff, yDiff);
return false; return false;
}, },
@ -294,13 +299,13 @@ class PeerProfileAvatars {
x = -width * lastIndex; */ x = -width * lastIndex; */
x = rect.left - this.container.getBoundingClientRect().left; 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'); this.avatars.classList.add('no-transition');
void this.avatars.offsetLeft; // reflow void this.avatars.offsetLeft; // reflow
}, },
onReset: () => { 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(); cancelNextClick();
//console.log(addIndex); //console.log(addIndex);
@ -372,7 +377,8 @@ class PeerProfileAvatars {
onJump: (item, older) => { onJump: (item, older) => {
const id = this.listLoader.index; const id = this.listLoader.index;
//const nextId = Math.max(0, id); //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'); const activeTab = this.tabs.querySelector('.active');
if(activeTab) activeTab.classList.remove('active'); if(activeTab) activeTab.classList.remove('active');
@ -457,7 +463,9 @@ class PeerProfile {
private threadId: number; private threadId: number;
constructor(public scrollable: Scrollable) { constructor(public scrollable: Scrollable) {
if(!PARALLAX_SUPPORTED) {
this.scrollable.container.classList.add('no-parallax');
}
} }
public init() { public init() {
@ -609,13 +617,17 @@ class PeerProfile {
if(oldAvatars) oldAvatars.container.replaceWith(this.avatars.container); if(oldAvatars) oldAvatars.container.replaceWith(this.avatars.container);
else this.element.prepend(this.avatars.container); else this.element.prepend(this.avatars.container);
if(PARALLAX_SUPPORTED) {
this.scrollable.container.classList.add('parallax'); this.scrollable.container.classList.add('parallax');
}
return; return;
} }
} }
if(PARALLAX_SUPPORTED) {
this.scrollable.container.classList.remove('parallax'); this.scrollable.container.classList.remove('parallax');
}
if(this.avatars) { if(this.avatars) {
this.avatars.container.remove(); this.avatars.container.remove();

1
src/helpers/userAgent.ts

@ -25,6 +25,7 @@ export const isAppleMobile = (/iPad|iPhone|iPod/.test(navigator.platform) ||
!ctx.MSStream; !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 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; export const isMobileSafari = isSafari && isAppleMobile;

5
src/pages/pageSignQR.ts

@ -161,9 +161,14 @@ let onFirstMount = async() => {
break; break;
default: default:
console.error('pageSignQR: default error:', err); console.error('pageSignQR: default error:', err);
stop = true;
break; break;
} }
return true;
} }
return false;
}; };
await iterate(false); await iterate(false);

10
src/scss/partials/_button.scss

@ -366,14 +366,14 @@
} }
.btn-circle { .btn-circle {
--size: 54px;
border-radius: 50%; border-radius: 50%;
height: 54px; height: var(--size);
width: 54px; width: var(--size) !important;
line-height: 54px; line-height: var(--size);
@include respond-to(handhelds) { @include respond-to(handhelds) {
height: 46px; --size: 46px;
width: 46px;
} }
path { path {

3
src/scss/partials/_leftSidebar.scss

@ -357,8 +357,7 @@
} }
@include respond-to(handhelds) { @include respond-to(handhelds) {
width: 54px; --size: 54px;
height: 54px;
bottom: 14px; bottom: 14px;
right: 14px; right: 14px;

4
src/scss/partials/_profile.scss

@ -33,6 +33,10 @@
transition: transform .2s ease-in-out; transition: transform .2s ease-in-out;
position: absolute; position: absolute;
.scrollable.no-parallax & {
transform: translate(0, 0);
}
&:before { &:before {
content: " "; content: " ";
top: 0; top: 0;

2
src/scss/partials/_rightSidebar.scss

@ -110,7 +110,7 @@
max-height: calc((var(--vh, 1vh) * 100) - 100% - 56px); max-height: calc((var(--vh, 1vh) * 100) - 100% - 56px);
} }
} */ } */
.scrollable { .scrollable:not(.no-parallax) {
perspective: 0px; perspective: 0px;
perspective-origin: left top; perspective-origin: left top;

1
src/scss/partials/_ripple.scss

@ -57,6 +57,7 @@
//animation-timing-function: ease-out; //animation-timing-function: ease-out;
transition: .35s opacity, .35s background-color; transition: .35s opacity, .35s background-color;
//overflow: hidden; //overflow: hidden;
pointer-events: none;
.btn-menu &, .c-ripple.is-square & { .btn-menu &, .c-ripple.is-square & {
animation-name: ripple-effect-handhelds; animation-name: ripple-effect-handhelds;

10
src/scss/partials/_slider.scss

@ -118,10 +118,12 @@
// } // }
> div { > div {
height: 100%; // * can't define these rules because of old firefox, though they don't work
max-height: 100%; //height: 100%;
width: 100%; //max-height: 100%;
max-width: 100%; //width: 100%;
//max-width: 100%;
display: none; display: none;
flex-direction: column; flex-direction: column;
position: relative; position: relative;

Loading…
Cancel
Save