morethanwords 4 years ago
parent
commit
0c875ccbaf
  1. 25
      src/components/appNavigationController.ts
  2. 5
      src/components/chat/bubbles.ts
  3. 4
      src/components/chat/input.ts
  4. 2
      src/components/popups/datePicker.ts
  5. 33
      src/components/popups/index.ts
  6. 2
      src/components/popups/newMedia.ts
  7. 2
      src/helpers/userAgent.ts

25
src/components/appNavigationController.ts

@ -1,9 +1,12 @@ @@ -1,9 +1,12 @@
import { MOUNT_CLASS_TO } from "../config/debug";
import { isSafari } from "../helpers/userAgent";
import { isSafari, isAppleMobile } from "../helpers/userAgent";
import { cancelEvent } from "../helpers/dom";
export type NavigationItem = {
type: 'left' | 'right' | 'im' | 'chat' | 'popup' | 'media' | 'menu' | 'esg',
onPop: (canAnimate: boolean) => boolean | void
onPop: (canAnimate: boolean) => boolean | void,
onEscape?: () => boolean,
noHistory?: boolean,
};
export class AppNavigationController {
@ -26,7 +29,7 @@ export class AppNavigationController { @@ -26,7 +29,7 @@ export class AppNavigationController {
return;
}
const good = item.onPop(isSafari ? false : undefined);
const good = item.onPop(isSafari && isAppleMobile ? false : undefined);
console.log('[NC]: popstate, navigation:', item, this.navigations);
if(good === false) {
this.pushItem(item);
@ -35,6 +38,15 @@ export class AppNavigationController { @@ -35,6 +38,15 @@ export class AppNavigationController {
//this.pushState(); // * prevent adding forward arrow
});
window.addEventListener('keydown', (e) => {
const item = this.navigations[this.navigations.length - 1];
if(!item) return;
if(e.key === 'Escape' && (item.onEscape ? item.onEscape() : true)) {
cancelEvent(e);
this.back();
}
}, {capture: true});
this.pushState(); // * push init state
}
@ -45,8 +57,11 @@ export class AppNavigationController { @@ -45,8 +57,11 @@ export class AppNavigationController {
public pushItem(item: NavigationItem) {
this.navigations.push(item);
console.log('[NC]: pushstate', item, this.navigations);
if(!item.noHistory) {
this.pushState();
}
}
private pushState() {
history.pushState(this.id, '');
@ -55,6 +70,10 @@ export class AppNavigationController { @@ -55,6 +70,10 @@ export class AppNavigationController {
public replaceState() {
history.replaceState(this.id, '');
}
public removeItem(item: NavigationItem) {
this.navigations.findAndSplice(i => i === item);
}
}
const appNavigationController = new AppNavigationController();

5
src/components/chat/bubbles.ts

@ -1654,7 +1654,8 @@ export default class ChatBubbles { @@ -1654,7 +1654,8 @@ 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') {
let children = Array.from(dateMessage.container.children).slice(2) as HTMLElement[];
const offset = this.stickyIntersector ? 2 : 1;
let children = Array.from(dateMessage.container.children).slice(offset) as HTMLElement[];
let i = 0, foundMidOnSameTimestamp = 0;
for(; i < children.length; ++i) {
const t = children[i];
@ -1671,7 +1672,7 @@ export default class ChatBubbles { @@ -1671,7 +1672,7 @@ export default class ChatBubbles {
}
// * 1 for date, 1 for date sentinel
let index = this.stickyIntersector ? 2 + i : 1 + i;
let index = offset + i;
/* if(bubble.parentElement) { // * if already mounted
const currentIndex = whichChild(bubble);
if(index > currentIndex) {

4
src/components/chat/input.ts

@ -556,7 +556,7 @@ export default class ChatInput { @@ -556,7 +556,7 @@ export default class ChatInput {
}
public saveDraft() {
if(!this.chat.peerId || this.editMsgId) return;
if(!this.chat.peerId || this.editMsgId || this.chat.type === 'scheduled') return;
const entities: MessageEntity[] = [];
const str = getRichValue(this.messageInputField.input, entities);
@ -604,7 +604,7 @@ export default class ChatInput { @@ -604,7 +604,7 @@ export default class ChatInput {
}
public setDraft(draft?: MyDraftMessage, fromUpdate = true) {
if(!isInputEmpty(this.messageInput)) return false;
if(!isInputEmpty(this.messageInput) || this.chat.type === 'scheduled') return false;
if(!draft) {
draft = this.appDraftsManager.getDraft(this.chat.peerId, this.chat.threadId);

2
src/components/popups/datePicker.ts

@ -141,7 +141,7 @@ export default class PopupDatePicker extends PopupElement { @@ -141,7 +141,7 @@ export default class PopupDatePicker extends PopupElement {
this.onPick(this.selectedDate.getTime() / 1000 | 0);
}
this.destroy();
this.hide();
}, {once: true});
this.body.append(this.timeDiv);

33
src/components/popups/index.ts

@ -2,6 +2,8 @@ import rootScope from "../../lib/rootScope"; @@ -2,6 +2,8 @@ import rootScope from "../../lib/rootScope";
import { blurActiveElement, cancelEvent, findUpClassName } from "../../helpers/dom";
import { ripple } from "../ripple";
import animationIntersector from "../animationIntersector";
import appNavigationController, { NavigationItem } from "../appNavigationController";
import { isMobileSafari, isSafari } from "../../helpers/userAgent";
export type PopupOptions = Partial<{closable: true, overlayClosable: true, withConfirm: string, body: true}>;
export default class PopupElement {
@ -17,6 +19,8 @@ export default class PopupElement { @@ -17,6 +19,8 @@ export default class PopupElement {
protected onCloseAfterTimeout: () => void;
protected onEscape: () => boolean = () => true;
protected navigationItem: NavigationItem;
constructor(className: string, buttons?: Array<PopupButton>, options: PopupOptions = {}) {
this.element.classList.add('popup');
this.element.className = 'popup' + (className ? ' ' + className : '');
@ -33,7 +37,7 @@ export default class PopupElement { @@ -33,7 +37,7 @@ export default class PopupElement {
//ripple(this.closeBtn);
this.header.prepend(this.btnClose);
this.btnClose.addEventListener('click', this.destroy, {once: true});
this.btnClose.addEventListener('click', this.hide, {once: true});
if(options.overlayClosable) {
const onOverlayClick = (e: MouseEvent) => {
@ -46,8 +50,6 @@ export default class PopupElement { @@ -46,8 +50,6 @@ export default class PopupElement {
}
}
window.addEventListener('keydown', this._onKeyDown, {capture: true});
if(options.withConfirm) {
this.btnConfirm = document.createElement('button');
this.btnConfirm.classList.add('btn-primary');
@ -98,14 +100,15 @@ export default class PopupElement { @@ -98,14 +100,15 @@ export default class PopupElement {
this.element.append(this.container);
}
private _onKeyDown = (e: KeyboardEvent) => {
if(e.key === 'Escape' && this.onEscape()) {
cancelEvent(e);
this.destroy();
}
public show() {
this.navigationItem = {
type: 'popup',
onPop: this.destroy,
onEscape: this.onEscape
};
public show() {
appNavigationController.pushItem(this.navigationItem);
blurActiveElement(); // * hide mobile keyboard
document.body.append(this.element);
void this.element.offsetWidth; // reflow
@ -114,15 +117,21 @@ export default class PopupElement { @@ -114,15 +117,21 @@ export default class PopupElement {
animationIntersector.checkAnimations(true);
}
public destroy = () => {
public hide = () => {
appNavigationController.back();
};
private destroy = () => {
this.onClose && this.onClose();
this.element.classList.add('hiding');
this.element.classList.remove('active');
window.removeEventListener('keydown', this._onKeyDown, {capture: true});
if(this.btnClose) this.btnClose.removeEventListener('click', this.destroy);
if(this.btnClose) this.btnClose.removeEventListener('click', this.hide);
rootScope.overlayIsActive = false;
appNavigationController.removeItem(this.navigationItem);
this.navigationItem = undefined;
setTimeout(() => {
this.element.remove();
this.onCloseAfterTimeout && this.onCloseAfterTimeout();

2
src/components/popups/newMedia.ts

@ -142,7 +142,7 @@ export default class PopupNewMedia extends PopupElement { @@ -142,7 +142,7 @@ export default class PopupNewMedia extends PopupElement {
return;
}
this.destroy();
this.hide();
const willAttach = this.willAttach;
willAttach.isMedia = willAttach.type === 'media' ? true : undefined;

2
src/helpers/userAgent.ts

@ -19,3 +19,5 @@ export const isAppleMobile = (/iPad|iPhone|iPod/.test(navigator.platform) || @@ -19,3 +19,5 @@ 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 isMobileSafari = isSafari && isAppleMobile;

Loading…
Cancel
Save