Browse Source

Fix audio player content overflow with sidebar

Always display .gif as video
Restrict jumping from webpage media to regular
Fix displaying round video in webpage
master
morethanwords 3 years ago
parent
commit
1a39932068
  1. 4
      src/components/appMediaPlaybackController.ts
  2. 28
      src/components/audio.ts
  3. 24
      src/components/chat/bubbles.ts
  4. 15
      src/components/chat/pinnedContainer.ts
  5. 2
      src/components/chat/topbar.ts
  6. 13
      src/components/wrappers.ts
  7. 11
      src/lib/appManagers/appDocsManager.ts
  8. 2
      src/lib/appManagers/appMessagesManager.ts
  9. 17
      src/scss/partials/_chatBubble.scss
  10. 6
      src/scss/partials/_chatPinned.scss

4
src/components/appMediaPlaybackController.ts

@ -360,7 +360,7 @@ class AppMediaPlaybackController {
private async setNewMediadata(message: Message.message, playingMedia = this.playingMedia) { private async setNewMediadata(message: Message.message, playingMedia = this.playingMedia) {
await onMediaLoad(playingMedia, undefined, false); // have to wait for load, otherwise on macOS won't set await onMediaLoad(playingMedia, undefined, false); // have to wait for load, otherwise on macOS won't set
const doc = (message.media as MessageMedia.messageMediaDocument).document as MyDocument; const doc = appMessagesManager.getMediaFromMessage(message) as MyDocument;
const artwork: MediaImage[] = []; const artwork: MediaImage[] = [];
@ -624,7 +624,7 @@ class AppMediaPlaybackController {
public previous = () => { public previous = () => {
const media = this.playingMedia; const media = this.playingMedia;
if(media && media.currentTime > 5) { if(media && (media.currentTime > 5 || !this.listLoader.previous.length)) {
media.currentTime = 0; media.currentTime = 0;
this.toggle(true); this.toggle(true);
return; return;

28
src/components/audio.ts

@ -28,6 +28,7 @@ import htmlToSpan from "../helpers/dom/htmlToSpan";
import { formatFullSentTime } from "../helpers/date"; import { formatFullSentTime } from "../helpers/date";
import { clamp, formatBytes } from "../helpers/number"; import { clamp, formatBytes } from "../helpers/number";
import throttleWithRaf from "../helpers/schedulers/throttleWithRaf"; import throttleWithRaf from "../helpers/schedulers/throttleWithRaf";
import { NULL_PEER_ID } from "../lib/mtproto/mtproto_config";
rootScope.addEventListener('messages_media_read', ({mids, peerId}) => { rootScope.addEventListener('messages_media_read', ({mids, peerId}) => {
mids.forEach(mid => { mids.forEach(mid => {
@ -340,20 +341,28 @@ function constructDownloadPreloader(tryAgainOnFail = true) {
return preloader; return preloader;
} }
export const findAudioTargets = (anchor: HTMLElement, useSearch: boolean) => { export const findMediaTargets = (anchor: HTMLElement/* , useSearch: boolean */) => {
let prev: MediaItem[], next: MediaItem[]; let prev: MediaItem[], next: MediaItem[];
// if(anchor.classList.contains('search-super-item') || !useSearch) { // if(anchor.classList.contains('search-super-item') || !useSearch) {
const container = findUpClassName(anchor, anchor.classList.contains('search-super-item') ? 'tabs-tab' : 'bubbles-inner'); const isBubbles = !anchor.classList.contains('search-super-item');
const container = findUpClassName(anchor, !isBubbles ? 'tabs-tab' : 'bubbles-inner');
if(container) { if(container) {
const attr = `:not([data-is-outgoing="1"])`; const attr = `:not([data-is-outgoing="1"])`;
const justAudioSelector = `.audio:not(.is-voice)${attr}`; const justAudioSelector = `.audio:not(.is-voice)${attr}`;
let selector: string; let selectors: string[];
if(!anchor.matches(justAudioSelector)) { if(!anchor.matches(justAudioSelector)) {
selector = `.audio.is-voice${attr}, .media-round${attr}`; selectors = [`.audio.is-voice${attr}`, `.media-round${attr}`];
} else { } else {
selector = justAudioSelector; selectors = [justAudioSelector];
} }
if(isBubbles) {
const prefix = '.bubble:not(.webpage) ';
selectors = selectors.map(s => prefix + s);
}
const selector = selectors.join(', ');
const elements = Array.from(container.querySelectorAll(selector)) as HTMLElement[]; const elements = Array.from(container.querySelectorAll(selector)) as HTMLElement[];
const idx = elements.indexOf(anchor); const idx = elements.indexOf(anchor);
@ -454,8 +463,13 @@ export default class AudioElement extends HTMLElement {
e && cancelEvent(e); e && cancelEvent(e);
if(paused) { if(paused) {
if(appMediaPlaybackController.setSearchContext(this.searchContext)) { const hadSearchContext = !!this.searchContext;
const [prev, next] = findAudioTargets(this, this.searchContext.useSearch); if(appMediaPlaybackController.setSearchContext(this.searchContext || {
peerId: NULL_PEER_ID,
inputFilter: {_: 'inputMessagesFilterEmpty'},
useSearch: false
})) {
const [prev, next] = !hadSearchContext ? [] : findMediaTargets(this/* , this.searchContext.useSearch */);
appMediaPlaybackController.setTargets({peerId: this.message.peerId, mid: this.message.mid}, prev, next); appMediaPlaybackController.setTargets({peerId: this.message.peerId, mid: this.message.mid}, prev, next);
} }

24
src/components/chat/bubbles.ts

@ -1042,6 +1042,9 @@ export default class ChatBubbles {
return; return;
} }
const SINGLE_MEDIA_CLASSNAME = 'webpage';
const isSingleMedia = bubble.classList.contains(SINGLE_MEDIA_CLASSNAME);
const f = documentDiv ? (media: any) => { const f = documentDiv ? (media: any) => {
return AppMediaViewer.isMediaCompatibleForDocumentViewer(media); return AppMediaViewer.isMediaCompatibleForDocumentViewer(media);
} : (media: any) => { } : (media: any) => {
@ -1049,7 +1052,10 @@ export default class ChatBubbles {
}; };
const targets: {element: HTMLElement, mid: number, peerId: PeerId}[] = []; const targets: {element: HTMLElement, mid: number, peerId: PeerId}[] = [];
const ids = Object.keys(this.bubbles).map(k => +k).filter(id => { const ids = isSingleMedia ? [messageId] : Object.keys(this.bubbles).map(k => +k).filter(id => {
/* if(isSingleMedia && !this.bubbles[id].classList.contains(SINGLE_MEDIA_CLASSNAME)) {
return false;
} */
//if(!this.scrollable.visibleElements.find(e => e.element === this.bubbles[id])) return false; //if(!this.scrollable.visibleElements.find(e => e.element === this.bubbles[id])) return false;
const message = this.chat.getMessage(id); const message = this.chat.getMessage(id);
@ -1117,7 +1123,7 @@ export default class ChatBubbles {
threadId: this.chat.threadId, threadId: this.chat.threadId,
peerId: this.peerId, peerId: this.peerId,
inputFilter: {_: documentDiv ? 'inputMessagesFilterDocument' : 'inputMessagesFilterPhotoVideo'}, inputFilter: {_: documentDiv ? 'inputMessagesFilterDocument' : 'inputMessagesFilterPhotoVideo'},
useSearch: this.chat.type !== 'scheduled', useSearch: this.chat.type !== 'scheduled' && !isSingleMedia,
isScheduled: this.chat.type === 'scheduled' isScheduled: this.chat.type === 'scheduled'
}) })
.openMedia(message, targets[idx].element, 0, true, targets.slice(0, idx), targets.slice(idx + 1)); .openMedia(message, targets[idx].element, 0, true, targets.slice(0, idx), targets.slice(idx + 1));
@ -2707,15 +2713,21 @@ export default class ChatBubbles {
const doc = webpage.document as MyDocument; const doc = webpage.document as MyDocument;
if(doc) { if(doc) {
if(doc.type === 'gif' || doc.type === 'video') { if(doc.type === 'gif' || doc.type === 'video' || doc.type === 'round') {
//if(doc.size <= 20e6) { //if(doc.size <= 20e6) {
bubble.classList.add('video'); const mediaSize = doc.type === 'round' ? mediaSizes.active.round : mediaSizes.active.webpage;
if(doc.type === 'round') {
bubble.classList.add('round');
preview.classList.add('is-round');
} else {
bubble.classList.add('video');
}
wrapVideo({ wrapVideo({
doc, doc,
container: preview, container: preview,
message, message,
boxWidth: mediaSizes.active.webpage.width, boxWidth: mediaSize.width,
boxHeight: mediaSizes.active.webpage.height, boxHeight: mediaSize.height,
lazyLoadQueue: this.lazyLoadQueue, lazyLoadQueue: this.lazyLoadQueue,
middleware: this.getMiddleware(), middleware: this.getMiddleware(),
isOut, isOut,

15
src/components/chat/pinnedContainer.ts

@ -89,10 +89,10 @@ export default class PinnedContainer {
return; return;
} }
const scrollable = this.chat.bubbles.scrollable; // const scrollable = this.chat.bubbles.scrollable;
const isFloating = (this.floating || mediaSizes.isMobile) && !hide; const isFloating = (this.floating || mediaSizes.isMobile) && !hide;
const scrollTop = isFloating || this.divAndCaption.container.classList.contains('is-floating') ? scrollable.scrollTop : undefined; // const scrollTop = isFloating || this.divAndCaption.container.classList.contains('is-floating') ? scrollable.scrollTop : undefined;
this.divAndCaption.container.classList.toggle('is-floating', isFloating); this.divAndCaption.container.classList.toggle('is-floating', isFloating);
this.divAndCaption.container.classList.toggle('hide', hide); this.divAndCaption.container.classList.toggle('hide', hide);
@ -100,12 +100,13 @@ export default class PinnedContainer {
this.topbar.container.classList.toggle('is-pinned-floating', isFloating); this.topbar.container.classList.toggle('is-pinned-floating', isFloating);
this.topbar.container.classList.toggle(`is-pinned-${this.className}-shown`, !hide); this.topbar.container.classList.toggle(`is-pinned-${this.className}-shown`, !hide);
const active = classNames.filter(className => this.topbar.container.classList.contains(className)); // const active = classNames.filter(className => this.topbar.container.classList.contains(className));
const maxActive = hide ? 0 : 1; // const maxActive = hide ? 0 : 1;
if(scrollTop !== undefined && active.length <= maxActive/* && !scrollable.isScrolledDown */) { // * not sure when it became unneeded
scrollable.scrollTop = scrollTop + ((hide ? -1 : 1) * HEIGHT); // if(scrollTop !== undefined && active.length <= maxActive/* && !scrollable.isScrolledDown */) {
} // scrollable.scrollTop = scrollTop + ((hide ? -1 : 1) * HEIGHT);
// }
this.topbar.setFloating(); this.topbar.setFloating();
this.topbar.setUtilsWidth(); this.topbar.setUtilsWidth();

2
src/components/chat/topbar.ts

@ -728,7 +728,7 @@ export default class ChatTopbar {
void this.chatInfo.offsetLeft; // reflow */ void this.chatInfo.offsetLeft; // reflow */
const width = /* chatUtils.scrollWidth */this.chatUtils.getBoundingClientRect().width; const width = /* chatUtils.scrollWidth */this.chatUtils.getBoundingClientRect().width;
this.chat.log('utils width:', width); this.chat.log('utils width:', width);
this.chatInfo.style.setProperty('--utils-width', width + 'px'); this.container.style.setProperty('--utils-width', width + 'px');
//this.chatInfo.classList.toggle('have-utils-width', !!width); //this.chatInfo.classList.toggle('have-utils-width', !!width);
//}, 0); //}, 0);

13
src/components/wrappers.ts

@ -20,7 +20,7 @@ import LottieLoader from '../lib/lottieLoader';
import webpWorkerController from '../lib/webp/webpWorkerController'; import webpWorkerController from '../lib/webp/webpWorkerController';
import animationIntersector from './animationIntersector'; import animationIntersector from './animationIntersector';
import appMediaPlaybackController, { MediaSearchContext } from './appMediaPlaybackController'; import appMediaPlaybackController, { MediaSearchContext } from './appMediaPlaybackController';
import AudioElement, { findAudioTargets as findMediaTargets } from './audio'; import AudioElement, { findMediaTargets } from './audio';
import ReplyContainer from './chat/replyContainer'; import ReplyContainer from './chat/replyContainer';
import { Layouter, RectPart } from './groupedLayout'; import { Layouter, RectPart } from './groupedLayout';
import LazyLoadQueue from './lazyLoadQueue'; import LazyLoadQueue from './lazyLoadQueue';
@ -29,7 +29,6 @@ import ProgressivePreloader from './preloader';
import './middleEllipsis'; import './middleEllipsis';
import RichTextProcessor from '../lib/richtextprocessor'; import RichTextProcessor from '../lib/richtextprocessor';
import appImManager from '../lib/appManagers/appImManager'; import appImManager from '../lib/appManagers/appImManager';
import { SearchSuperContext } from './appSearchSuper.';
import rootScope from '../lib/rootScope'; import rootScope from '../lib/rootScope';
import { onMediaLoad } from '../helpers/files'; import { onMediaLoad } from '../helpers/files';
import { animateSingle } from '../helpers/animation'; import { animateSingle } from '../helpers/animation';
@ -49,6 +48,7 @@ import MEDIA_MIME_TYPES_SUPPORTED from '../environment/mediaMimeTypesSupport';
import { MiddleEllipsisElement } from './middleEllipsis'; import { MiddleEllipsisElement } from './middleEllipsis';
import { joinElementsWith } from '../lib/langPack'; import { joinElementsWith } from '../lib/langPack';
import throttleWithRaf from '../helpers/schedulers/throttleWithRaf'; import throttleWithRaf from '../helpers/schedulers/throttleWithRaf';
import { NULL_PEER_ID } from '../lib/mtproto/mtproto_config';
const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB const MAX_VIDEO_AUTOPLAY_SIZE = 50 * 1024 * 1024; // 50 MB
@ -305,8 +305,13 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
} */ } */
if(globalVideo.paused) { if(globalVideo.paused) {
if(appMediaPlaybackController.setSearchContext(searchContext)) { const hadSearchContext = !!searchContext;
const [prev, next] = findMediaTargets(divRound, searchContext.useSearch); if(appMediaPlaybackController.setSearchContext(searchContext || {
peerId: NULL_PEER_ID,
inputFilter: {_: 'inputMessagesFilterEmpty'},
useSearch: false
})) {
const [prev, next] = !hadSearchContext ? [] : findMediaTargets(divRound/* , searchContext.useSearch */);
appMediaPlaybackController.setTargets({peerId: message.peerId, mid: message.mid}, prev, next); appMediaPlaybackController.setTargets({peerId: message.peerId, mid: message.mid}, prev, next);
} }

11
src/lib/appManagers/appDocsManager.ts

@ -28,8 +28,10 @@ export type MyDocument = Document.document;
// TODO: если залить картинку файлом, а потом перезайти в диалог - превьюшка заново скачается // TODO: если залить картинку файлом, а потом перезайти в диалог - превьюшка заново скачается
const EXTENSION_MIME_TYPE_MAP: {[key: string]: string} = { const EXTENSION_MIME_TYPE_MAP = {
mov: 'video/quicktime' mov: 'video/quicktime',
gif: 'image/gif',
pdf: 'application/pdf',
}; };
export class AppDocsManager { export class AppDocsManager {
@ -163,6 +165,7 @@ export class AppDocsManager {
if(!doc.mime_type) { if(!doc.mime_type) {
const ext = (doc.file_name || '').split('.').pop(); const ext = (doc.file_name || '').split('.').pop();
// @ts-ignore
const mappedMimeType = ext && EXTENSION_MIME_TYPE_MAP[ext.toLowerCase()]; const mappedMimeType = ext && EXTENSION_MIME_TYPE_MAP[ext.toLowerCase()];
if(mappedMimeType) { if(mappedMimeType) {
doc.mime_type = mappedMimeType; doc.mime_type = mappedMimeType;
@ -187,8 +190,10 @@ export class AppDocsManager {
break; break;
} }
} }
} else if(doc.mime_type === 'application/pdf') { } else if(doc.mime_type === EXTENSION_MIME_TYPE_MAP.pdf) {
doc.type = 'pdf'; doc.type = 'pdf';
} else if(doc.mime_type === EXTENSION_MIME_TYPE_MAP.gif) {
doc.type = 'gif';
} }
if(doc.type === 'voice' || doc.type === 'round') { if(doc.type === 'voice' || doc.type === 'round') {

2
src/lib/appManagers/appMessagesManager.ts

@ -3696,7 +3696,7 @@ export class AppMessagesManager {
const foundCount: number = searchResult.count || (foundMsgs.length + searchResult.messages.length); const foundCount: number = searchResult.count || (foundMsgs.length + searchResult.messages.length);
searchResult.messages.forEach((message: any) => { searchResult.messages.forEach((message: MyMessage) => {
const peerId = this.getMessagePeer(message); const peerId = this.getMessagePeer(message);
if(peerId.isAnyChat()) { if(peerId.isAnyChat()) {
const chat: Chat.chat = appChatsManager.getChat(peerId.toChatId()); const chat: Chat.chat = appChatsManager.getChat(peerId.toChatId());

17
src/scss/partials/_chatBubble.scss

@ -597,12 +597,12 @@ $bubble-beside-button-width: 38px;
max-height: var(--round-video-size) !important; max-height: var(--round-video-size) !important;
width: var(--round-video-size) !important; width: var(--round-video-size) !important;
height: var(--round-video-size) !important; height: var(--round-video-size) !important;
}
.media-photo, .media-photo,
.media-video { .media-video {
border-radius: 50%; border-radius: 50%;
pointer-events: none; pointer-events: none;
}
} }
} }
@ -922,6 +922,13 @@ $bubble-beside-button-width: 38px;
} }
} }
} }
&.is-round {
.media-photo,
.media-video {
border-radius: 50%;
}
}
} }
&.no-text { &.no-text {

6
src/scss/partials/_chatPinned.scss

@ -285,6 +285,12 @@
.pinned-container-content { .pinned-container-content {
margin-right: .5rem; margin-right: .5rem;
@include respond-to(medium-screens) {
body.is-right-column-shown & {
padding-right: var(--right-column-width);
}
}
} }
/* &:before { /* &:before {

Loading…
Cancel
Save