Media viewer arrows & swipe
Some layout fixes in chat for mobile
This commit is contained in:
parent
8a5a91b3c4
commit
e6e1f58e56
@ -171,10 +171,10 @@
|
||||
<div class="btn-menu-item menu-menu-delete danger tgico-delete rp btn-disabled">Delete</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-viewer-switchers">
|
||||
{{!-- <div class="media-viewer-switchers"> --}}
|
||||
<div class="media-viewer-switcher media-viewer-switcher-left menu-prev"><span class="tgico-down media-viewer-prev-button"></span></div>
|
||||
<div class="media-viewer-switcher media-viewer-switcher-right menu-next"><span class="tgico-down media-viewer-next-button"></span></div>
|
||||
</div>
|
||||
{{!-- </div> --}}
|
||||
</div>
|
||||
<div class="popup popup-send-photo popup-new-media">
|
||||
<div class="popup-container z-depth-1">
|
||||
|
@ -2003,6 +2003,7 @@ export class AppImManager {
|
||||
<use xlink:href="#b13RmHDQtl" opacity="1" fill="#fff" fill-opacity="1"></use>
|
||||
</svg>`;
|
||||
bubbleContainer.append(forward);
|
||||
bubble.classList.add('with-beside-button');
|
||||
}
|
||||
}
|
||||
|
||||
@ -2589,6 +2590,7 @@ export class AppImManager {
|
||||
goto.classList.add('bubble-beside-button', 'goto-original', 'tgico-next');
|
||||
bubbleContainer.append(goto);
|
||||
bubble.dataset.savedFrom = message.savedFrom;
|
||||
bubble.classList.add('with-beside-button');
|
||||
}
|
||||
|
||||
if(!bubble.classList.contains('sticker')) {
|
||||
|
@ -11,7 +11,7 @@ import { renderImageFromUrl, parseMenuButtonsTo } from "../../components/misc";
|
||||
import AvatarElement from "../../components/avatar";
|
||||
import LazyLoadQueue from "../../components/lazyLoadQueue";
|
||||
import appForward from "../../components/appForward";
|
||||
import { isSafari, mediaSizes } from "../config";
|
||||
import { isSafari, mediaSizes, touchSupport } from "../config";
|
||||
import appAudio from "../../components/appAudio";
|
||||
import { deferredPromise } from "../polyfill";
|
||||
import { MTDocument } from "../../types";
|
||||
@ -19,6 +19,54 @@ import { MTDocument } from "../../types";
|
||||
// TODO: масштабирование картинок (не SVG) при ресайзе, и правильный возврат на исходную позицию
|
||||
// TODO: картинки "обрезаются" если возвращаются или появляются с места, где есть их перекрытие (топбар, поле ввода)
|
||||
|
||||
class SwipeHandler {
|
||||
private xDown: number;
|
||||
private yDown: number;
|
||||
|
||||
constructor(element: HTMLElement, private onSwipe: (xDiff: number, yDiff: number) => boolean) {
|
||||
element.addEventListener('touchstart', this.handleTouchStart, false);
|
||||
element.addEventListener('touchmove', this.handleTouchMove, false);
|
||||
}
|
||||
|
||||
handleTouchStart = (evt: TouchEvent) => {
|
||||
const firstTouch = evt.touches[0];
|
||||
this.xDown = firstTouch.clientX;
|
||||
this.yDown = firstTouch.clientY;
|
||||
};
|
||||
|
||||
handleTouchMove = (evt: TouchEvent) => {
|
||||
if(this.xDown == null || this.yDown == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const xUp = evt.touches[0].clientX;
|
||||
const yUp = evt.touches[0].clientY;
|
||||
|
||||
const xDiff = this.xDown - xUp;
|
||||
const yDiff = this.yDown - yUp;
|
||||
|
||||
// if(Math.abs(xDiff) > Math.abs(yDiff)) { /*most significant*/
|
||||
// if(xDiff > 0) { /* left swipe */
|
||||
|
||||
// } else { /* right swipe */
|
||||
|
||||
// }
|
||||
// } else {
|
||||
// if(yDiff > 0) { /* up swipe */
|
||||
|
||||
// } else { /* down swipe */
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
/* reset values */
|
||||
if(this.onSwipe(xDiff, yDiff)) {
|
||||
this.xDown = null;
|
||||
this.yDown = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class AppMediaViewer {
|
||||
public wholeDiv = document.querySelector('.media-viewer-whole') as HTMLDivElement;
|
||||
private overlaysDiv = this.wholeDiv.firstElementChild as HTMLDivElement;
|
||||
@ -65,6 +113,8 @@ export class AppMediaViewer {
|
||||
private setMoverAnimationPromise: Promise<void>;
|
||||
|
||||
private lazyLoadQueue: LazyLoadQueue;
|
||||
|
||||
private highlightSwitchersTimeout: number;
|
||||
|
||||
constructor() {
|
||||
this.log = logger('AMV');
|
||||
@ -152,6 +202,33 @@ export class AppMediaViewer {
|
||||
//this.content.mover.addEventListener('click', this.onClickBinded);
|
||||
//this.content.mover.append(this.buttons.prev, this.buttons.next);
|
||||
this.setNewMover();
|
||||
|
||||
if(touchSupport) {
|
||||
const swipeHandler = new SwipeHandler(this.wholeDiv, (xDiff, yDiff) => {
|
||||
//console.log(xDiff, yDiff);
|
||||
|
||||
const percents = Math.abs(xDiff) / appPhotosManager.windowW;
|
||||
if(percents > .2 || xDiff > 125) {
|
||||
//console.log('will swipe', xDiff);
|
||||
|
||||
if(xDiff < 0) {
|
||||
this.buttons.prev.click();
|
||||
} else {
|
||||
this.buttons.next.click();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const percentsY = Math.abs(yDiff) / appPhotosManager.windowH;
|
||||
if(percentsY > .2 || yDiff > 125) {
|
||||
this.buttons.close.click();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onClickDownload = (e: MouseEvent) => {
|
||||
@ -178,6 +255,21 @@ export class AppMediaViewer {
|
||||
if(target.tagName == 'A') return;
|
||||
cancelEvent(e);
|
||||
|
||||
if(touchSupport) {
|
||||
if(this.highlightSwitchersTimeout) {
|
||||
clearTimeout(this.highlightSwitchersTimeout);
|
||||
} else {
|
||||
this.wholeDiv.classList.add('highlight-switchers');
|
||||
}
|
||||
|
||||
this.highlightSwitchersTimeout = setTimeout(() => {
|
||||
this.wholeDiv.classList.remove('highlight-switchers');
|
||||
this.highlightSwitchersTimeout = 0;
|
||||
}, 3e3);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let mover: HTMLElement = null;
|
||||
['media-viewer-mover', 'media-viewer-buttons', 'media-viewer-author'].find(s => {
|
||||
try {
|
||||
|
@ -464,6 +464,7 @@ export class AppSidebarRight extends SidebarSlider {
|
||||
|
||||
let thumb: HTMLImageElement;
|
||||
const sizes = media.sizes || media.thumbs;
|
||||
|
||||
const willHaveThumb = !isDownloaded && sizes && sizes[0].bytes;
|
||||
if(willHaveThumb) {
|
||||
thumb = new Image();
|
||||
@ -495,9 +496,11 @@ export class AppSidebarRight extends SidebarSlider {
|
||||
|
||||
promises.push(promise);
|
||||
}
|
||||
|
||||
if(isDownloaded) load();
|
||||
else this.lazyLoadQueue.push({div, load});
|
||||
|
||||
if(sizes?.length) {
|
||||
if(isDownloaded) load();
|
||||
else this.lazyLoadQueue.push({div, load});
|
||||
}
|
||||
|
||||
elemsToAppend.push(div);
|
||||
this.mediaDivsByIDs[message.mid] = div;
|
||||
|
@ -1,5 +1,7 @@
|
||||
$chat-max-width: 696px;
|
||||
$time-background: rgba(0, 0, 0, .35);
|
||||
$handhelds-margin: 5.5625rem;
|
||||
$beside-button-margin: 2.875rem;
|
||||
|
||||
#bubble-contextmenu > div {
|
||||
padding: 0 84px 0 16px;
|
||||
@ -161,14 +163,13 @@ $time-background: rgba(0, 0, 0, .35);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
padding: 0 .5rem .5rem;
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
padding: 0 .5rem .5rem;
|
||||
}
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
padding-bottom: 21px;
|
||||
}
|
||||
@include respond-to(not-handhelds) {
|
||||
padding-bottom: 21px;
|
||||
}
|
||||
}
|
||||
|
||||
/* @include respond-to(handhelds) {
|
||||
@ -883,15 +884,20 @@ $time-background: rgba(0, 0, 0, .35);
|
||||
//margin-left: 3rem; #DO JS3
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
max-width: calc(100% - 3rem);
|
||||
margin-left: 45px;
|
||||
max-width: calc(100% - #{$handhelds-margin});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-channel:not(.is-chat) {
|
||||
.bubble__container {
|
||||
max-width: 100%;
|
||||
.bubble {
|
||||
&__container {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
&.with-beside-button .bubble__container {
|
||||
max-width: calc(100% - #{$beside-button-margin}) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.has-rights) {
|
||||
|
@ -45,12 +45,12 @@ $bubble-margin: .25rem;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
//@include respond-to(not-handhelds) {
|
||||
margin: 0 auto;
|
||||
}
|
||||
//}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
max-width: unquote("min(calc(100% - 46px), #{$chat-max-width})");
|
||||
max-width: unquote("min(100%, #{$chat-max-width - 16px})");
|
||||
|
||||
html.is-mac & {
|
||||
-webkit-user-select: none;
|
||||
@ -146,6 +146,10 @@ $bubble-margin: .25rem;
|
||||
max-width: 85%;
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
max-width: calc(100% - #{$handhelds-margin});
|
||||
}
|
||||
|
||||
> .user-avatar {
|
||||
position: absolute;
|
||||
left: -45px;
|
||||
@ -162,6 +166,12 @@ $bubble-margin: .25rem;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/* &.with-beside-button &__container {
|
||||
@include respond-to(handhelds) {
|
||||
max-width: calc(100% - #{$handhelds-margin}) !important;
|
||||
}
|
||||
} */
|
||||
|
||||
&.service {
|
||||
//padding: 1rem 0;
|
||||
@ -1231,7 +1241,7 @@ $bubble-margin: .25rem;
|
||||
} */
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
/* @include respond-to(handhelds) {
|
||||
.bubble.is-in {
|
||||
margin-right: auto;
|
||||
}
|
||||
@ -1239,7 +1249,7 @@ $bubble-margin: .25rem;
|
||||
.bubble.is-out {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
.bubble.is-out {
|
||||
.bubble__container {
|
||||
@ -1450,7 +1460,7 @@ $bubble-margin: .25rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.media-progress {
|
||||
.progress-line {
|
||||
&__loaded {
|
||||
background-color: #90e18d !important;
|
||||
}
|
||||
|
@ -127,44 +127,57 @@ $move-duration: .35s;
|
||||
left: 0;
|
||||
top: 60px;
|
||||
width: 7rem;
|
||||
height: 100%;
|
||||
height: calc(100% - 120px);
|
||||
cursor: pointer;
|
||||
z-index: 5;
|
||||
|
||||
html.no-touch &:hover {
|
||||
> span {
|
||||
opacity: 1;
|
||||
html.no-touch & {
|
||||
height: calc(100% - 60px);
|
||||
|
||||
&:hover {
|
||||
> span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include respond-to(handhelds) {
|
||||
width: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-switcher-right {
|
||||
left: auto;
|
||||
right: 0;
|
||||
&-right {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-prev-button, &-next-button {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
font-size: 3rem;
|
||||
left: 2rem;
|
||||
font-size: 2rem;
|
||||
left: 1rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) rotate(90deg);
|
||||
opacity: 0;
|
||||
transition: $open-duration opacity;
|
||||
z-index: 5;
|
||||
/* box-shadow: 0 1px 2px 0 rgba(16, 35, 47, 0.07); */
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
font-size: 3rem;
|
||||
left: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-next-button {
|
||||
left: auto;
|
||||
right: 2rem;
|
||||
right: 1rem;
|
||||
transform: translateY(-50%) rotate(-90deg);
|
||||
|
||||
@include respond-to(not-handhelds) {
|
||||
right: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-mover {
|
||||
@ -298,6 +311,12 @@ $move-duration: .35s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.highlight-switchers {
|
||||
.media-viewer-switcher > span {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-switchers {
|
||||
|
Loading…
x
Reference in New Issue
Block a user