Browse Source

Fix media viewer closening when clicking on t.me/

Fix media viewer keydown capture with active popups
master
morethanwords 3 years ago
parent
commit
ac4340b97c
  1. 25
      src/components/appMediaViewer.ts
  2. 2
      src/components/chat/selection.ts
  3. 4
      src/components/popups/createPoll.ts
  4. 4
      src/components/popups/index.ts
  5. 2
      src/components/sidebarLeft/tabs/editProfile.ts
  6. 4
      src/index.ts
  7. 10
      src/lang.ts
  8. 4
      src/lib/appManagers/appImManager.ts
  9. 11
      src/lib/mediaPlayer.ts
  10. 12
      src/lib/rootScope.ts
  11. 1
      src/scss/partials/_chat.scss

25
src/components/appMediaViewer.ts

@ -276,7 +276,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
cancelEvent(e); cancelEvent(e);
} }
if(this.setMoverAnimationPromise) return; if(this.setMoverAnimationPromise) return Promise.reject();
appNavigationController.removeByType('media'); appNavigationController.removeByType('media');
@ -302,7 +302,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
promise.finally(() => { promise.finally(() => {
this.wholeDiv.remove(); this.wholeDiv.remove();
rootScope.overlayIsActive = false; rootScope.isOverlayActive = false;
animationIntersector.checkAnimations(false); animationIntersector.checkAnimations(false);
}); });
@ -983,7 +983,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
this.pageEl.insertBefore(this.wholeDiv, mainColumns); this.pageEl.insertBefore(this.wholeDiv, mainColumns);
void this.wholeDiv.offsetLeft; // reflow void this.wholeDiv.offsetLeft; // reflow
this.wholeDiv.classList.add('active'); this.wholeDiv.classList.add('active');
rootScope.overlayIsActive = true; rootScope.isOverlayActive = true;
animationIntersector.checkAnimations(true); animationIntersector.checkAnimations(true);
if(!isMobileSafari) { if(!isMobileSafari) {
@ -1329,6 +1329,25 @@ export default class AppMediaViewer extends AppMediaViewerBase<'caption', 'delet
super.setListeners(); super.setListeners();
this.buttons.forward.addEventListener('click', this.onForwardClick); this.buttons.forward.addEventListener('click', this.onForwardClick);
this.author.container.addEventListener('click', this.onAuthorClick); this.author.container.addEventListener('click', this.onAuthorClick);
const onCaptionClick = (e: MouseEvent) => {
if(e.target instanceof HTMLAnchorElement) { // close viewer if it's t.me/ redirect
const onclick = (e.target as HTMLElement).getAttribute('onclick');
if(!onclick || onclick.includes('showMaskedAlert')) {
return;
}
cancelEvent(e);
this.close().then(() => {
this.content.caption.removeEventListener('click', onCaptionClick, {capture: true});
(e.target as HTMLAnchorElement).click();
});
return false;
}
};
this.content.caption.addEventListener('click', onCaptionClick, {capture: true});
} }
/* public close(e?: MouseEvent) { /* public close(e?: MouseEvent) {

2
src/components/chat/selection.ts

@ -228,7 +228,7 @@ export default class ChatSelection {
private updateContainer(forceSelection = false) { private updateContainer(forceSelection = false) {
if(!this.selectedMids.size && !forceSelection) return; if(!this.selectedMids.size && !forceSelection) return;
this.selectionCountEl.textContent = ''; this.selectionCountEl.textContent = '';
this.selectionCountEl.append(i18n('Chat.Selection.MessagesCount', [this.selectedMids.size])); this.selectionCountEl.append(i18n('messages', [this.selectedMids.size]));
let cantForward = !this.selectedMids.size, cantDelete = !this.selectedMids.size, cantSend = !this.selectedMids.size; let cantForward = !this.selectedMids.size, cantDelete = !this.selectedMids.size, cantSend = !this.selectedMids.size;
for(const mid of this.selectedMids.values()) { for(const mid of this.selectedMids.values()) {

4
src/components/popups/createPoll.ts

@ -12,7 +12,7 @@ import InputField from "../inputField";
import RadioField from "../radioField"; import RadioField from "../radioField";
import Scrollable from "../scrollable"; import Scrollable from "../scrollable";
import SendContextMenu from "../chat/sendContextMenu"; import SendContextMenu from "../chat/sendContextMenu";
import I18n, { _i18n, i18n } from "../../lib/langPack"; import I18n, { _i18n } from "../../lib/langPack";
import findUpTag from "../../helpers/dom/findUpTag"; import findUpTag from "../../helpers/dom/findUpTag";
import { cancelEvent } from "../../helpers/dom/cancelEvent"; import { cancelEvent } from "../../helpers/dom/cancelEvent";
import getRichValue from "../../helpers/dom/getRichValue"; import getRichValue from "../../helpers/dom/getRichValue";
@ -38,7 +38,7 @@ export default class PopupCreatePoll extends PopupElement {
private optionInputFields: InputField[]; private optionInputFields: InputField[];
constructor(private chat: Chat) { constructor(private chat: Chat) {
super('popup-create-poll popup-new-media', null, {closable: true, withConfirm: 'NewPoll.Create', body: true}); super('popup-create-poll popup-new-media', null, {closable: true, withConfirm: 'Create', body: true});
_i18n(this.title, 'NewPoll'); _i18n(this.title, 'NewPoll');

4
src/components/popups/index.ts

@ -144,7 +144,7 @@ export default class PopupElement {
document.body.append(this.element); document.body.append(this.element);
void this.element.offsetWidth; // reflow void this.element.offsetWidth; // reflow
this.element.classList.add('active'); this.element.classList.add('active');
rootScope.overlayIsActive = true; rootScope.isOverlayActive = true;
animationIntersector.checkAnimations(true); animationIntersector.checkAnimations(true);
} }
@ -158,7 +158,7 @@ export default class PopupElement {
this.element.classList.remove('active'); this.element.classList.remove('active');
if(this.btnClose) this.btnClose.removeEventListener('click', this.hide); if(this.btnClose) this.btnClose.removeEventListener('click', this.hide);
rootScope.overlayIsActive = false; rootScope.isOverlayActive = false;
appNavigationController.removeItem(this.navigationItem); appNavigationController.removeItem(this.navigationItem);
this.navigationItem = undefined; this.navigationItem = undefined;

2
src/components/sidebarLeft/tabs/editProfile.ts

@ -99,7 +99,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
const caption = document.createElement('div'); const caption = document.createElement('div');
caption.classList.add('caption'); caption.classList.add('caption');
caption.append(i18n('EditProfile.Username.Help')); caption.append(i18n('UsernameSettings.ChangeDescription'));
caption.append(document.createElement('br'), document.createElement('br')); caption.append(document.createElement('br'), document.createElement('br'));
const profileUrlContainer = this.profileUrlContainer = document.createElement('div'); const profileUrlContainer = this.profileUrlContainer = document.createElement('div');

4
src/index.ts

@ -65,7 +65,7 @@ console.timeEnd('get storage1'); */
let lastVH: number; let lastVH: number;
const setVH = () => { const setVH = () => {
// @ts-ignore // @ts-ignore
const vh = (setViewportVH && !rootScope.default.overlayIsActive ? w.height || w.innerHeight : window.innerHeight) * 0.01; const vh = (setViewportVH && !rootScope.default.isOverlayActive ? w.height || w.innerHeight : window.innerHeight) * 0.01;
if(lastVH === vh) { if(lastVH === vh) {
return; return;
} else if(lastVH < vh) { } else if(lastVH < vh) {
@ -116,7 +116,7 @@ console.timeEnd('get storage1'); */
//console.log(new Uint8Array([255, 200, 145]).hex); //console.log(new Uint8Array([255, 200, 145]).hex);
const toggleResizeMode = () => { const toggleResizeMode = () => {
setViewportVH = tabId === 1 && userAgent.isSafari && touchSupport.isTouchSupported && !rootScope.default.overlayIsActive; setViewportVH = tabId === 1 && userAgent.isSafari && touchSupport.isTouchSupported && !rootScope.default.isOverlayActive;
setVH(); setVH();
if(w !== window) { if(w !== window) {

10
src/lang.ts

@ -23,7 +23,6 @@ const lang = {
"EditProfile.Username.Available": "Username is available", "EditProfile.Username.Available": "Username is available",
"EditProfile.Username.Taken": "Username is already taken", "EditProfile.Username.Taken": "Username is already taken",
"EditProfile.Username.Invalid": "Username is invalid", "EditProfile.Username.Invalid": "Username is invalid",
"EditProfile.Username.Help": "You can choose a username on Telegram. If you do, people will be able to find you by this username and contact you without needing your phone number.\n\nYou can use a–z, 0–9 and underscores. Minimum length is 5 characters.",
"ExceptionModal.Search.Placeholder": "Add exception...", "ExceptionModal.Search.Placeholder": "Add exception...",
"Chat.Menu.SelectMessages": "Select Messages", "Chat.Menu.SelectMessages": "Select Messages",
"Chat.Menu.ClearSelection": "Clear Selection", "Chat.Menu.ClearSelection": "Clear Selection",
@ -32,10 +31,6 @@ const lang = {
"Chat.Input.Attach.PhotoOrVideo": "Photo or Video", "Chat.Input.Attach.PhotoOrVideo": "Photo or Video",
"Chat.Input.Attach.Document": "Document", "Chat.Input.Attach.Document": "Document",
"Chat.Subscribe": "SUBSCRIBE", "Chat.Subscribe": "SUBSCRIBE",
"Chat.Selection.MessagesCount": {
"one_value": "%d Message",
"other_value": "%d Messages"
},
"Chat.Selection.LimitToast": "Max selection count reached.", "Chat.Selection.LimitToast": "Max selection count reached.",
"Chat.Search.MessagesFound": { "Chat.Search.MessagesFound": {
"one_value": "%d message found", "one_value": "%d message found",
@ -79,7 +74,6 @@ const lang = {
"Notifications.MessagePreview": "Message preview", "Notifications.MessagePreview": "Message preview",
"NewPrivateChat": "New Private Chat", "NewPrivateChat": "New Private Chat",
"NewPoll.OptionLabel": "Option %d", "NewPoll.OptionLabel": "Option %d",
"NewPoll.Create": "CREATE",
"Message.Context.Selection.Copy": "Copy selected", "Message.Context.Selection.Copy": "Copy selected",
"Message.Context.Selection.Clear": "Clear selection", "Message.Context.Selection.Clear": "Clear selection",
"Message.Context.Selection.Delete": "Delete selected", "Message.Context.Selection.Delete": "Delete selected",
@ -552,6 +546,7 @@ const lang = {
"LeaveAComment": "Leave a comment", "LeaveAComment": "Leave a comment",
"ViewInChat": "View in chat", "ViewInChat": "View in chat",
"LinkNotFound": "Unfortunately, you can\'t access this message. You are not a member of the chat where it was posted.", "LinkNotFound": "Unfortunately, you can\'t access this message. You are not a member of the chat where it was posted.",
"Create": "Create",
// * macos // * macos
"AccountSettings.Filters": "Chat Folders", "AccountSettings.Filters": "Chat Folders",
@ -811,7 +806,8 @@ const lang = {
"TwoStepAuth.RecoveryCodeInvalid": "Invalid code. Please try again.", "TwoStepAuth.RecoveryCodeInvalid": "Invalid code. Please try again.",
"TwoStepAuth.RecoveryCodeExpired": "Code Expired", "TwoStepAuth.RecoveryCodeExpired": "Code Expired",
"TwoStepAuth.SetupHintTitle": "Password Hint", "TwoStepAuth.SetupHintTitle": "Password Hint",
"TwoStepAuth.SetupHintPlaceholder": "Hint" "TwoStepAuth.SetupHintPlaceholder": "Hint",
"UsernameSettings.ChangeDescription": "You can choose a username on Telegram. If you do, people will be able to find you by this username and contact you without needing your phone number.\n\n\nYou can use a-z, 0-9 and underscores. Minimum length is 5 characters."
}; };
export default lang; export default lang;

4
src/lib/appManagers/appImManager.ts

@ -645,7 +645,7 @@ export class AppImManager {
const IGNORE_KEYS = new Set(['PageUp', 'PageDown', 'Meta', 'Control']); const IGNORE_KEYS = new Set(['PageUp', 'PageDown', 'Meta', 'Control']);
const onKeyDown = (e: KeyboardEvent) => { const onKeyDown = (e: KeyboardEvent) => {
if(rootScope.overlayIsActive || IGNORE_KEYS.has(e.key)) return; if(rootScope.isOverlayActive || IGNORE_KEYS.has(e.key)) return;
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
@ -845,7 +845,7 @@ export class AppImManager {
private canDrag() { private canDrag() {
const peerId = this.chat?.peerId; const peerId = this.chat?.peerId;
return !(!peerId || rootScope.overlayIsActive || (peerId < 0 && !appChatsManager.hasRights(peerId, 'send_media'))); return !(!peerId || rootScope.isOverlayActive || (peerId < 0 && !appChatsManager.hasRights(peerId, 'send_media')));
} }
private onDocumentPaste = (e: ClipboardEvent | DragEvent, attachType?: 'media' | 'document') => { private onDocumentPaste = (e: ClipboardEvent | DragEvent, attachType?: 'media' | 'document') => {

11
src/lib/mediaPlayer.ts

@ -14,6 +14,7 @@ import ListenerSetter from "../helpers/listenerSetter";
import ButtonMenu from "../components/buttonMenu"; import ButtonMenu from "../components/buttonMenu";
import { ButtonMenuToggleHandler } from "../components/buttonMenuToggle"; import { ButtonMenuToggleHandler } from "../components/buttonMenuToggle";
import EventListenerBase from "../helpers/eventListenerBase"; import EventListenerBase from "../helpers/eventListenerBase";
import rootScope from "./rootScope";
export class MediaProgressLine extends RangeSelector { export class MediaProgressLine extends RangeSelector {
private filledLoad: HTMLDivElement; private filledLoad: HTMLDivElement;
@ -370,10 +371,11 @@ export default class VideoPlayer extends EventListenerBase<{
}); });
this.listenerSetter.add(document)('keydown', (e: KeyboardEvent) => { this.listenerSetter.add(document)('keydown', (e: KeyboardEvent) => {
if((e.target as HTMLElement) === document.activeElement) { if(rootScope.overlaysActive > 1) { // forward popup is active, etc
return; return;
} }
let good = true;
if(e.code === 'KeyF') { if(e.code === 'KeyF') {
this.toggleFullScreen(fullScreenButton); this.toggleFullScreen(fullScreenButton);
} else if(e.code === 'KeyM') { } else if(e.code === 'KeyM') {
@ -384,6 +386,13 @@ export default class VideoPlayer extends EventListenerBase<{
this.video.playbackRate += 0.25; this.video.playbackRate += 0.25;
} else if(e.altKey && e.code === 'Minus') { } else if(e.altKey && e.code === 'Minus') {
this.video.playbackRate -= 0.25; this.video.playbackRate -= 0.25;
} else {
good = false;
}
if(good) {
cancelEvent(e);
return false;
} }
}); });
} }

12
src/lib/rootScope.ts

@ -132,7 +132,7 @@ export class RootScope extends EventListenerBase<{
} & { } & {
[name in keyof BroadcastEvents]: (e: BroadcastEvents[name]) => void [name in keyof BroadcastEvents]: (e: BroadcastEvents[name]) => void
}> { }> {
private _overlayIsActive: boolean = false; public overlaysActive = 0;
public myId = 0; public myId = 0;
public idle = { public idle = {
isIDLE: true, isIDLE: true,
@ -217,13 +217,13 @@ export class RootScope extends EventListenerBase<{
document.documentElement.classList.toggle('night', isNight); document.documentElement.classList.toggle('night', isNight);
} }
get overlayIsActive() { get isOverlayActive() {
return this._overlayIsActive; return this.overlaysActive > 0;
} }
set overlayIsActive(value: boolean) { set isOverlayActive(value: boolean) {
this._overlayIsActive = value; this.overlaysActive += value ? 1 : -1;
this.dispatchEvent('overlay_toggle', value); this.dispatchEvent('overlay_toggle', this.isOverlayActive);
} }
public getTheme(name: Theme['name'] = this.settings.theme === 'system' ? this.systemTheme : this.settings.theme) { public getTheme(name: Theme['name'] = this.settings.theme === 'system' ? this.systemTheme : this.settings.theme) {

1
src/scss/partials/_chat.scss

@ -701,6 +701,7 @@ $chat-helper-size: 36px;
flex-grow: 1; flex-grow: 1;
white-space: nowrap; white-space: nowrap;
//padding-left: .5rem; //padding-left: .5rem;
text-transform: capitalize;
} }
.btn-icon { .btn-icon {

Loading…
Cancel
Save