Browse Source

Media viewer arrows & swipe

Some layout fixes in chat for mobile
master
morethanwords 4 years ago
parent
commit
e6e1f58e56
  1. 4
      src/index.hbs
  2. 2
      src/lib/appManagers/appImManager.ts
  3. 94
      src/lib/appManagers/appMediaViewer.ts
  4. 9
      src/lib/appManagers/appSidebarRight.ts
  5. 28
      src/scss/partials/_chat.scss
  6. 22
      src/scss/partials/_chatBubble.scss
  7. 41
      src/scss/partials/_mediaViewer.scss

4
src/index.hbs

@ -171,10 +171,10 @@ @@ -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">

2
src/lib/appManagers/appImManager.ts

@ -2003,6 +2003,7 @@ export class AppImManager { @@ -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 { @@ -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')) {

94
src/lib/appManagers/appMediaViewer.ts

@ -11,7 +11,7 @@ import { renderImageFromUrl, parseMenuButtonsTo } from "../../components/misc"; @@ -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"; @@ -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 { @@ -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 { @@ -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 { @@ -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 {

9
src/lib/appManagers/appSidebarRight.ts

@ -464,6 +464,7 @@ export class AppSidebarRight extends SidebarSlider { @@ -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 { @@ -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;

28
src/scss/partials/_chat.scss

@ -1,5 +1,7 @@ @@ -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); @@ -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); @@ -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) {

22
src/scss/partials/_chatBubble.scss

@ -45,12 +45,12 @@ $bubble-margin: .25rem; @@ -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; @@ -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; @@ -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; @@ -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; @@ -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; @@ -1450,7 +1460,7 @@ $bubble-margin: .25rem;
pointer-events: none;
}
.media-progress {
.progress-line {
&__loaded {
background-color: #90e18d !important;
}

41
src/scss/partials/_mediaViewer.scss

@ -127,44 +127,57 @@ $move-duration: .35s; @@ -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; @@ -298,6 +311,12 @@ $move-duration: .35s;
}
}
}
&.highlight-switchers {
.media-viewer-switcher > span {
opacity: 1;
}
}
}
&-switchers {

Loading…
Cancel
Save