From e6bb3c998797a04ea5ad5953c3c5f75709d635f1 Mon Sep 17 00:00:00 2001 From: Eduard Kuzmenko Date: Mon, 16 Jan 2023 23:14:20 +0400 Subject: [PATCH] swipe fixes unsupported video toast --- src/components/appMediaViewerBase.ts | 15 +++++---- src/components/chat/bubbles.ts | 2 -- src/components/swipeHandler.ts | 38 ++++++++++++++++++++-- src/components/wrappers/video.ts | 3 ++ src/config/app.ts | 2 +- src/lang.ts | 2 ++ src/lib/appManagers/appDialogsManager.ts | 13 ++++++++ src/lib/appManagers/appDocsManager.ts | 41 ++++++++++++++---------- src/scss/partials/_chatBubble.scss | 9 +++++- src/scss/partials/_selector.scss | 24 +++++++------- 10 files changed, 107 insertions(+), 42 deletions(-) diff --git a/src/components/appMediaViewerBase.ts b/src/components/appMediaViewerBase.ts index 171df1cdd..1724864ca 100644 --- a/src/components/appMediaViewerBase.ts +++ b/src/components/appMediaViewerBase.ts @@ -7,7 +7,7 @@ import deferredPromise from '../helpers/cancellablePromise'; import mediaSizes from '../helpers/mediaSizes'; import IS_TOUCH_SUPPORTED from '../environment/touchSupport'; -import {IS_MOBILE_SAFARI, IS_SAFARI} from '../environment/userAgent'; +import {IS_MOBILE, IS_MOBILE_SAFARI, IS_SAFARI} from '../environment/userAgent'; import type {MyDocument} from '../lib/appManagers/appDocsManager'; import type {MyPhoto} from '../lib/appManagers/appPhotosManager'; import {logger} from '../lib/logger'; @@ -51,6 +51,7 @@ import overlayCounter from '../helpers/overlayCounter'; import {ThumbCache} from '../lib/storages/thumbs'; import appDownloadManager from '../lib/appManagers/appDownloadManager'; import wrapPeerTitle from './wrappers/peerTitle'; +import {toastNew} from './toast'; const ZOOM_STEP = 0.5; const ZOOM_INITIAL_VALUE = 1; @@ -306,13 +307,12 @@ export default class AppMediaViewerBase< if(isFullScreen()) { return; } - // console.log(xDiff, yDiff); const percents = Math.abs(xDiff) / windowSize.width; if(percents > .2 || xDiff > 125) { // console.log('will swipe', xDiff); - if(xDiff < 0) { + if(xDiff > 0) { this.buttons.prev.click(); } else { this.buttons.next.click(); @@ -330,6 +330,7 @@ export default class AppMediaViewerBase< return false; }, verifyTouchTarget: (evt) => { + console.log('verify'); // * Fix for seek input if((evt.target as HTMLElement).tagName === 'INPUT' || findUpClassName(evt.target, 'media-viewer-caption')) { return false; @@ -1573,13 +1574,15 @@ export default class AppMediaViewerBase< const url = (await getCacheContext()).url; video.addEventListener('error', () => { + toastNew({ + langPackKey: IS_MOBILE ? 'Video.Unsupported.Mobile' : 'Video.Unsupported.Desktop' + }); + if(video.error.code !== 4) { this.log.error('Error ' + video.error.code + '; details: ' + video.error.message); } - if(preloader) { - preloader.detach(); - } + preloader?.detach(); }, {once: true}); if(target instanceof SVGSVGElement/* && (video.parentElement || !isSafari) */) { // if video exists diff --git a/src/components/chat/bubbles.ts b/src/components/chat/bubbles.ts index ab37cf089..c1504dba2 100644 --- a/src/components/chat/bubbles.ts +++ b/src/components/chat/bubbles.ts @@ -910,8 +910,6 @@ export default class ChatBubbles { return !!target; }, onSwipe: (xDiff) => { - xDiff *= -1; - shouldReply = xDiff >= replyAfter; if(shouldReply && !icon.classList.contains('is-visible')) { diff --git a/src/components/swipeHandler.ts b/src/components/swipeHandler.ts index abbaa6d25..31fd13cec 100644 --- a/src/components/swipeHandler.ts +++ b/src/components/swipeHandler.ts @@ -9,8 +9,10 @@ import IS_TOUCH_SUPPORTED from '../environment/touchSupport'; import safeAssign from '../helpers/object/safeAssign'; import contextMenuController from '../helpers/contextMenuController'; import {Middleware} from '../helpers/middleware'; -import ListenerSetter, {ListenerOptions} from '../helpers/listenerSetter'; +import ListenerSetter, {Listener, ListenerOptions} from '../helpers/listenerSetter'; import {attachContextMenuListener} from '../helpers/dom/attachContextMenuListener'; +import pause from '../helpers/schedulers/pause'; +import deferredPromise from '../helpers/cancellablePromise'; type E = { clientX: number, @@ -64,6 +66,9 @@ export default class SwipeHandler { private listenerOptions: boolean | AddEventListenerOptions = false; private setCursorTo: HTMLElement; + private isMouseDown: boolean; + private tempId: number; + private hadMove: boolean; private eventUp: E; private xDown: number; @@ -82,6 +87,7 @@ export default class SwipeHandler { this.setListeners(); this.resetValues(); + this.tempId = 0; options.middleware?.onDestroy(() => { this.reset(); @@ -130,11 +136,13 @@ export default class SwipeHandler { } protected resetValues() { + ++this.tempId; this.hadMove = false; this.xAdded = this.yAdded = 0; this.xDown = this.yDown = this.eventUp = + this.isMouseDown = undefined; } @@ -158,8 +166,12 @@ export default class SwipeHandler { }; protected handleStart = async(_e: EE) => { + if(this.isMouseDown) { + return; + } + const e = getEvent(_e); - if(e.button !== 0) { + if((e.button ?? 0) !== 0) { return; } @@ -167,6 +179,28 @@ export default class SwipeHandler { return this.reset(); } + const tempId = ++this.tempId; + this.isMouseDown = true; + + if(this.withDelay && !IS_TOUCH_SUPPORTED) { + const options = {...MOUSE_MOVE_OPTIONS, once: true}; + const deferred = deferredPromise(); + const cb = () => deferred.resolve(); + const listener = this.listenerSetter.add(attachGlobalListenerTo)('mousemove', cb, options) as any as Listener; + + await Promise.race([ + pause(300), + deferred + ]); + + deferred.resolve(); + this.listenerSetter.remove(listener); + + if(this.tempId !== tempId) { + return; + } + } + this.xDown = e.clientX; this.yDown = e.clientY; this.eventUp = e; diff --git a/src/components/wrappers/video.ts b/src/components/wrappers/video.ts index 4f384354b..803c59e5d 100644 --- a/src/components/wrappers/video.ts +++ b/src/components/wrappers/video.ts @@ -547,6 +547,9 @@ export default async function wrapVideo({doc, container, message, boxWidth, boxH renderDeferred.resolve(); }, (err) => { console.error('video load error', err); + if(spanTime) { + spanTime.classList.add('is-error'); + } renderDeferred.reject(err); }); diff --git a/src/config/app.ts b/src/config/app.ts index 09040dd90..43f721d98 100644 --- a/src/config/app.ts +++ b/src/config/app.ts @@ -21,7 +21,7 @@ const App = { version: process.env.VERSION, versionFull: process.env.VERSION_FULL, build: +process.env.BUILD, - langPackVersion: '0.7.8', + langPackVersion: '0.7.9', langPack: 'webk', langPackCode: 'en', domains: MAIN_DOMAINS, diff --git a/src/lang.ts b/src/lang.ts index 8a0d1d07c..d333c5428 100644 --- a/src/lang.ts +++ b/src/lang.ts @@ -152,6 +152,8 @@ const lang = { 'PaymentCard.Error.Incomplete': 'Incomplete card number', 'LimitReached.Ok': 'OK, GOT IT', 'Username.Purchase': '**This username is already taken.** However, it is currently available for purchase. [Learn moreā€¦]()', + 'Video.Unsupported.Desktop': '__Unfortunately, this video can\'t be played on Telegram Web. Try opening it with our [desktop app](https://getdesktop.telegram.org/) instead.__', + 'Video.Unsupported.Mobile': '__Unfortunately, this video can\'t be played on Telegram Web. Try opening it with our [mobile app](https://telegram.org/dl/) instead.__', // * android 'AccDescrEditing': 'Editing', diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts index adebb19a5..4b1b6d055 100644 --- a/src/lib/appManagers/appDialogsManager.ts +++ b/src/lib/appManagers/appDialogsManager.ts @@ -547,6 +547,16 @@ class ForumTab extends SliderSuperTabEventable { } }); + if(IS_TOUCH_SUPPORTED) { + handleTabSwipe({ + element: this.container, + onSwipe: () => { + appDialogsManager.toggleForumTab(undefined, this); + }, + middleware: this.middlewareHelper.get() + }); + } + this.header.append(btnMenu); if(!isFloating) { @@ -1673,6 +1683,9 @@ export class AppDialogsManager { onSwipe: (xDiff) => { const prevId = selectTab.prevId(); selectTab(xDiff < 0 ? prevId + 1 : prevId - 1); + }, + verifyTouchTarget: () => { + return !this.forumTab; } }); } diff --git a/src/lib/appManagers/appDocsManager.ts b/src/lib/appManagers/appDocsManager.ts index 1808de75a..67cb4ffdd 100644 --- a/src/lib/appManagers/appDocsManager.ts +++ b/src/lib/appManagers/appDocsManager.ts @@ -9,6 +9,7 @@ * https://github.com/zhukov/webogram/blob/master/LICENSE */ +import type {ThumbCache} from '../storages/thumbs'; import {AccountWallPapers, Document, DocumentAttribute, MessagesSavedGifs, PhotoSize, WallPaper} from '../../layer'; import {ReferenceContext} from '../mtproto/referenceDatabase'; import {getFullDate} from '../../helpers/date'; @@ -22,7 +23,6 @@ import {isServiceWorkerOnline} from '../mtproto/mtproto.worker'; import MTProtoMessagePort from '../mtproto/mtprotoMessagePort'; import getDocumentInputFileLocation from './utils/docs/getDocumentInputFileLocation'; import getDocumentURL from './utils/docs/getDocumentURL'; -import type {ThumbCache} from '../storages/thumbs'; import makeError from '../../helpers/makeError'; import {EXTENSION_MIME_TYPE_MAP} from '../../environment/mimeTypeMap'; import {THUMB_TYPE_FULL} from '../mtproto/mtproto_config'; @@ -107,33 +107,39 @@ export class AppDocsManager extends AppManager { // 'audioPerformer', 'sticker', 'stickerEmoji', 'stickerEmojiRaw', // 'stickerSetInput', 'stickerThumbConverted', 'animated', 'supportsStreaming']); - let type: MyDocument['type']; for(let i = 0, length = doc.attributes.length; i < length; ++i) { const attribute = doc.attributes[i]; switch(attribute._) { - case 'documentAttributeFilename': + case 'documentAttributeFilename': { doc.file_name = wrapPlainText(attribute.file_name); break; + } + + case 'documentAttributeAudio': { + if(doc.type === 'round') { + break; + } - case 'documentAttributeAudio': doc.duration = attribute.duration; - type ??= attribute.pFlags.voice && doc.mime_type === 'audio/ogg' ? 'voice' : 'audio'; + doc.type = attribute.pFlags.voice && doc.mime_type === 'audio/ogg' ? 'voice' : 'audio'; break; + } - case 'documentAttributeVideo': + case 'documentAttributeVideo': { doc.duration = attribute.duration; doc.w = attribute.w; doc.h = attribute.h; // apiDoc.supportsStreaming = attribute.pFlags?.supports_streaming/* && apiDoc.size > 524288 */; if(/* apiDoc.thumbs && */attribute.pFlags.round_message) { - type ??= 'round'; + doc.type = 'round'; } else /* if(apiDoc.thumbs) */ { - type ??= 'video'; + doc.type = 'video'; } break; + } case 'documentAttributeCustomEmoji': - case 'documentAttributeSticker': + case 'documentAttributeSticker': { if(attribute.alt !== undefined) { doc.stickerEmojiRaw = attribute.alt; } @@ -148,37 +154,38 @@ export class AppDocsManager extends AppManager { // * there can be no thumbs, then it is a document if(/* apiDoc.thumbs && */doc.mime_type === 'image/webp' && (doc.thumbs || getEnvironment().IS_WEBP_SUPPORTED)) { - type ??= 'sticker'; + doc.type = 'sticker'; doc.sticker = 1; } else if(doc.mime_type === 'video/webm') { if(!getEnvironment().IS_WEBM_SUPPORTED) { break; } - type ??= 'sticker'; + doc.type = 'sticker'; doc.sticker = 3; doc.animated = true; } break; + } - case 'documentAttributeImageSize': - type ??= 'photo'; + case 'documentAttributeImageSize': { + doc.type = 'photo'; doc.w = attribute.w; doc.h = attribute.h; break; + } - case 'documentAttributeAnimated': + case 'documentAttributeAnimated': { if((doc.mime_type === 'image/gif' || doc.mime_type === 'video/mp4')/* && apiDoc.thumbs */) { - type ??= 'gif'; + doc.type = 'gif'; } doc.animated = true; break; + } } } - doc.type = type; - if(!doc.mime_type) { const ext = (doc.file_name || '').split('.').pop(); // @ts-ignore diff --git a/src/scss/partials/_chatBubble.scss b/src/scss/partials/_chatBubble.scss index 4260f3c86..f8059c486 100644 --- a/src/scss/partials/_chatBubble.scss +++ b/src/scss/partials/_chatBubble.scss @@ -1987,9 +1987,16 @@ $bubble-border-radius-big: 12px; // * same as .iconVolume padding: 0 1px 0 3px; - font-size: 1.25rem; + font-size: calc(var(--messages-time-text-size) + 8px); color: #fff; } + + &.is-error:after { + content: $tgico-sendingerror; + font-size: calc(var(--messages-time-text-size) + 4px); + padding: 0; + margin-inline-start: 1px; + } } .extended-media-buy { diff --git a/src/scss/partials/_selector.scss b/src/scss/partials/_selector.scss index d3c01f2bf..2e5c919a5 100644 --- a/src/scss/partials/_selector.scss +++ b/src/scss/partials/_selector.scss @@ -42,7 +42,7 @@ &-search { // padding: 0 1.5rem; - padding: 0 1rem; + padding-inline: 1rem; display: flex; flex-flow: wrap; position: relative; @@ -63,9 +63,8 @@ color: var(--primary-text-color); background-color: var(--light-secondary-text-color); font-size: 1rem; - padding: 0 17px 0px 0px; - margin-left: -.25rem; - margin-right: .75rem; + padding-inline-end: 17px; + margin-inline: -.25rem .75rem; height: 2rem; line-height: 2rem; margin-bottom: 7px; @@ -104,7 +103,7 @@ &-avatar { float: left; - margin-right: 8px; + margin-inline-end: 8px; overflow: hidden; position: relative; border-radius: 50% !important; @@ -116,7 +115,7 @@ &:after { position: absolute; content: $tgico-close; - left: 0; + inset-inline-start: 0; top: 0; background-color: var(--danger-color); height: 100%; @@ -151,7 +150,7 @@ .checkbox { margin-top: 11px; - padding-left: 11px; + padding-inline-start: 11px; } .checkbox-field { @@ -165,13 +164,12 @@ z-index: 1; &:first-child { - margin-right: 1.6875rem; - margin-left: .6875rem; + margin-inline: .6875rem 1.6875rem; } } .checkbox-field-round { - right: 1.125rem; + inset-inline-end: 1.125rem; --size: 1.25rem; .checkbox-box-border { @@ -187,15 +185,15 @@ $add: 3rem; .checkbox-field { - left: 1.25rem !important; + inset-inline-start: 1.25rem !important; } .chatlist-chat.row-with-padding { - padding-left: #{4.5rem + $add} !important; // 4.5 + x + padding-inline-start: #{4.5rem + $add} !important; // 4.5 + x } .dialog-avatar { - margin-left: #{$add} !important; + margin-inline-start: #{$add} !important; } } }