Browse Source

Media viewer: fix mobile controls

master
Eduard Kuzmenko 3 years ago
parent
commit
730bc668e4
  1. 2
      .gitmodules
  2. 13
      src/components/appMediaViewer.ts
  3. 2
      src/lib/appManagers/apiUpdatesManager.ts
  4. 4
      src/lib/logger.ts
  5. 12
      src/lib/mediaPlayer.ts
  6. 35
      src/lib/mtproto/referenceDatabase.ts
  7. 74
      src/scss/partials/_ckin.scss
  8. 57
      src/scss/partials/_mediaViewer.scss

2
.gitmodules vendored

@ -4,6 +4,6 @@ @@ -4,6 +4,6 @@
[submodule "tweb-design"]
path = tweb-design
url = https://github.com/morethanwords/tweb-design
[submodule "rlottie-web"]
[submodule "src/rlottie-web"]
path = src/rlottie-web
url = https://github.com/morethanwords/rlottie-web

13
src/components/appMediaViewer.ts

@ -117,16 +117,18 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType @@ -117,16 +117,18 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
mainDiv.classList.add(MEDIA_VIEWER_CLASSNAME);
const topbar = this.topbar = document.createElement('div');
topbar.classList.add(MEDIA_VIEWER_CLASSNAME + '-topbar');
topbar.classList.add(MEDIA_VIEWER_CLASSNAME + '-topbar', MEDIA_VIEWER_CLASSNAME + '-appear');
const topbarLeft = document.createElement('div');
topbarLeft.classList.add(MEDIA_VIEWER_CLASSNAME + '-topbar-left');
this.buttons['mobile-close'] = ButtonIcon('close', {onlyMobile: true});
// * author
this.author.container = document.createElement('div');
this.author.container.classList.add(MEDIA_VIEWER_CLASSNAME + '-author', 'no-select');
const authorRight = document.createElement('div');
this.author.avatarEl = new AvatarElement();
this.author.avatarEl.classList.add(MEDIA_VIEWER_CLASSNAME + '-userpic', 'avatar-44');
@ -137,7 +139,9 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType @@ -137,7 +139,9 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
this.author.date = document.createElement('div');
this.author.date.classList.add(MEDIA_VIEWER_CLASSNAME + '-date');
this.author.container.append(this.author.avatarEl, this.author.nameEl, this.author.date);
authorRight.append(this.author.nameEl, this.author.date);
this.author.container.append(this.author.avatarEl, authorRight);
// * buttons
const buttonsDiv = document.createElement('div');
@ -974,7 +978,8 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType @@ -974,7 +978,8 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
//const maxWidth = appPhotosManager.windowW - 16;
const maxWidth = mediaSizes.isMobile ? this.pageEl.scrollWidth : this.pageEl.scrollWidth - 16;
const maxHeight = mediaSizes.isMobile ? appPhotosManager.windowH : appPhotosManager.windowH - 100;
// TODO: const maxHeight = mediaSizes.isMobile ? appPhotosManager.windowH : appPhotosManager.windowH - 100;
const maxHeight = appPhotosManager.windowH - 120;
let thumbPromise: Promise<any> = Promise.resolve();
const size = appPhotosManager.setAttachmentSize(media, container, maxWidth, maxHeight, mediaSizes.isMobile ? false : true).photoSize;
if(useContainerAsTarget) {

2
src/lib/appManagers/apiUpdatesManager.ts

@ -467,7 +467,7 @@ export class ApiUpdatesManager { @@ -467,7 +467,7 @@ export class ApiUpdatesManager {
}
break;
default:
if('channel_id' in update) {
if('channel_id' in update && 'pts' in update) {
channelId = update.channel_id;
}
break;

4
src/lib/logger.ts

@ -21,8 +21,8 @@ function dT() { @@ -21,8 +21,8 @@ function dT() {
return '[' + ((Date.now() - _logTimer) / 1000).toFixed(3) + ']';
}
export function logger(prefix: string, type: LogTypes = LogTypes.Log | LogTypes.Warn | LogTypes.Error) {
if(!DEBUG/* || true */) {
export function logger(prefix: string, type: LogTypes = LogTypes.Log | LogTypes.Warn | LogTypes.Error, ignoreDebugReset = false) {
if(!DEBUG && !ignoreDebugReset/* || true */) {
type = LogTypes.Error;
}

12
src/lib/mediaPlayer.ts

@ -170,7 +170,7 @@ let lastVolume = 1, muted = !lastVolume; @@ -170,7 +170,7 @@ let lastVolume = 1, muted = !lastVolume;
export default class VideoPlayer {
private wrapper: HTMLDivElement;
private progress: MediaProgressLine;
private skin: string;
private skin: 'default';
private listenerSetter: ListenerSetter;
@ -186,10 +186,10 @@ export default class VideoPlayer { @@ -186,10 +186,10 @@ export default class VideoPlayer {
video.parentNode.insertBefore(this.wrapper, video);
this.wrapper.appendChild(video);
this.skin = video.dataset.ckin ?? 'default';
this.skin = 'default';
this.stylePlayer(duration);
this.setBtnMenuToggle();
// this.setBtnMenuToggle();
if(this.skin === 'default') {
const controls = this.wrapper.querySelector('.default__controls.ckin__controls') as HTMLDivElement;
@ -402,7 +402,7 @@ export default class VideoPlayer { @@ -402,7 +402,7 @@ export default class VideoPlayer {
}
}
public togglePlay() {
protected togglePlay() {
this.video[this.video.paused ? 'play' : 'pause']();
}
@ -450,7 +450,7 @@ export default class VideoPlayer { @@ -450,7 +450,7 @@ export default class VideoPlayer {
return !!(document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement);
}
public toggleFullScreen(fullScreenButton: HTMLElement) {
protected toggleFullScreen(fullScreenButton: HTMLElement) {
// alternative standard method
const player = this.wrapper;
@ -533,7 +533,7 @@ export default class VideoPlayer { @@ -533,7 +533,7 @@ export default class VideoPlayer {
}
}
onFullScreen = () => {
protected onFullScreen = () => {
// @ts-ignore
const isFullscreenNow = document.webkitFullscreenElement !== null;
if(!isFullscreenNow) {

35
src/lib/mtproto/referenceDatabase.ts

@ -12,6 +12,7 @@ import { deepEqual } from "../../helpers/object"; @@ -12,6 +12,7 @@ import { deepEqual } from "../../helpers/object";
import { MOUNT_CLASS_TO } from "../../config/debug";
import apiManager from "./mtprotoworker";
import assumeType from "../../helpers/assumeType";
import { logger } from "../logger";
export type ReferenceContext = ReferenceContext.referenceContextProfilePhoto | ReferenceContext.referenceContextMessage;
export namespace ReferenceContext {
@ -36,21 +37,20 @@ class ReferenceDatabase { @@ -36,21 +37,20 @@ class ReferenceDatabase {
private contexts: Map<ReferenceBytes, ReferenceContexts> = new Map();
//private references: Map<ReferenceBytes, number[]> = new Map();
private links: {[hex: string]: ReferenceBytes} = {};
private log = logger('RD', undefined, true);
constructor() {
apiManager.addTaskListener('refreshReference', (task: RefreshReferenceTask) => {
const bytes = task.payload;
const originalPayload = task.payload;
assumeType<RefreshReferenceTaskResponse>(task);
task.originalPayload = bytes;
task.originalPayload = originalPayload;
this.refreshReference(bytes).then(() => {
task.payload = this.getReferenceByLink(bytes);
apiManager.postMessage(task);
this.refreshReference(originalPayload).then((bytes) => {
task.payload = bytes;
}, (err) => {
task.error = err;
apiManager.postMessage(task);
});
}).then(() => apiManager.postMessage(task));
});
}
@ -103,10 +103,12 @@ class ReferenceDatabase { @@ -103,10 +103,12 @@ class ReferenceDatabase {
return false;
}
public refreshReference(reference: ReferenceBytes, context?: ReferenceContext): Promise<void> {
public refreshReference(reference: ReferenceBytes, context?: ReferenceContext): Promise<Uint8Array | number[]> {
this.log('refreshReference: start', reference.slice(), context);
if(!context) {
const c = this.getContext(reference);
if(!c) {
this.log('refreshReference: got no context for reference:', reference.slice());
return Promise.reject('NO_CONTEXT');
}
@ -124,16 +126,18 @@ class ReferenceDatabase { @@ -124,16 +126,18 @@ class ReferenceDatabase {
}
default: {
console.warn('FILE_REFERENCE_EXPIRED: not implemented context', context);
this.log.warn('refreshReference: not implemented context', context);
return Promise.reject();
}
}
const hex = bytesToHex(reference);
this.log('refreshReference: refreshing reference:', hex);
return promise.then(() => {
const newHex = bytesToHex(reference);
this.log('refreshReference: refreshed, reference before:', hex, 'after:', newHex);
if(hex !== newHex) {
return;
return reference;
}
this.deleteContext(reference, context);
@ -147,17 +151,6 @@ class ReferenceDatabase { @@ -147,17 +151,6 @@ class ReferenceDatabase {
});
}
/* handleReferenceError = (reference: ReferenceBytes, error: ApiError) => {
switch(error.type) {
case 'FILE_REFERENCE_EXPIRED': {
return this.refreshReference(reference);
}
default:
return Promise.reject(error);
}
}; */
/* public replaceReference(oldReference: ReferenceBytes, newReference: ReferenceBytes) {
const contexts = this.contexts.get(oldReference);
if(contexts) {

74
src/scss/partials/_ckin.scss

@ -42,18 +42,6 @@ @@ -42,18 +42,6 @@
}
}
}
&__overlay {
position: relative;
&:before {
background: radial-gradient(ellipse at center, transparent 0%, rgba(0, 0, 0, .5) 100%);
}
&--2:before {
background: rgba(24, 24, 24, .8);
}
}
}
.default {
@ -71,7 +59,7 @@ @@ -71,7 +59,7 @@
cursor: pointer;
}
&:before {
/* &:before {
content: '';
position: absolute;
top: 0;
@ -81,27 +69,11 @@ @@ -81,27 +69,11 @@
transition: opacity .2s;
opacity: 1;
visibility: visible;
}
&__title {
position: absolute;
left: 20px;
top: 20px;
z-index: 1;
font-size: 24px;
color: rgba(255, 255, 255, .8);
font-style: italic;
}
} */
&__button {
width: 2rem;
height: 2rem;
color: #fff;
padding: 0 .625rem;
@include respond-to(handhelds) {
font-size: 1.375rem;
}
padding: .375rem;
i {
align-self: center;
@ -139,11 +111,6 @@ @@ -139,11 +111,6 @@
}
}
&__slider {
width: 10px;
height: 30px;
}
&__controls {
position: absolute;
bottom: 0;
@ -183,6 +150,12 @@ @@ -183,6 +150,12 @@
pointer-events: none;
}
&:not(.ckin__fullscreen) .default__gradient-bottom {
@include respond-to(handhelds) {
display: none;
}
}
.toggle:before {
content: $tgico-play;
}
@ -194,6 +167,10 @@ @@ -194,6 +167,10 @@
.default__controls {
transform: translate3d(0, 52px, 0);
@include respond-to(handhelds) {
transform: translate3d(0, 65px, 0);
}
}
/* html.no-touch &:hover,*/
@ -240,15 +217,11 @@ @@ -240,15 +217,11 @@
&__icon {
fill: #fff;
width: 1.5rem;
height: 1.5rem;
width: 2.25rem;
height: 2.25rem;
margin-right: .5rem;
cursor: pointer;
@include respond-to(handhelds) {
width: 1.25rem;
height: 1.25rem;
}
padding: .375rem;
}
.progress-line {
@ -416,26 +389,21 @@ input[type=range] { @@ -416,26 +389,21 @@ input[type=range] {
}
}
.left-controls {
.left-controls,
.right-controls {
display: flex;
align-items: center;
}
.right-controls {
display: flex;
align-items: center;
float: right;
}
.bottom-controls {
padding: 0 .25rem;
height: 2rem;
padding: 0 .625rem;
height: 2.25rem;
display: flex;
justify-content: space-between;
align-items: center;
@include respond-to(handhelds) {
height: 3.5rem;
padding: 0 .375rem;
padding: 0 .5rem;
}
}

57
src/scss/partials/_mediaViewer.scss

@ -23,6 +23,8 @@ @@ -23,6 +23,8 @@
&-author {
height: 100%;
cursor: pointer;
display: flex;
align-items: center;
@include respond-to(handhelds) {
margin-left: 1.5rem;
@ -30,9 +32,7 @@ @@ -30,9 +32,7 @@
}
&-userpic {
position: absolute;
top: .5rem;
left: 1.25rem;
margin-right: 1rem;
@include respond-to(handhelds) {
display: none;
@ -43,6 +43,10 @@ @@ -43,6 +43,10 @@
line-height: var(--line-height);
font-weight: 500;
margin: .0625rem 0;
@include respond-to(not-handhelds) {
margin: .0625rem 0 .125rem;
}
}
&-date {
@ -56,7 +60,7 @@ @@ -56,7 +60,7 @@
right: 0;
display: flex;
flex-flow: row nowrap;
padding: .5rem;
padding: .5rem .75rem;
.btn-icon {
margin: 0 .25rem;
@ -220,7 +224,10 @@ @@ -220,7 +224,10 @@
overflow: hidden;
transform: translateZ(0) scale3d(1, 1, 1);
border-radius: 0;
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); // fix border-radius overflow
&:not(.center) {
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%); // fix border-radius overflow
}
// эти значения должны быть такими же, как при установке maxWidth и maxHeight в openMedia!
//max-width: 100%;
@ -300,13 +307,13 @@ @@ -300,13 +307,13 @@
top: 50% !important;
transform: translate3d(-50%, -50%, 0) !important;
max-width: calc(100vw - 16px);
max-height: calc((var(--vh, 1vh) * 100) - 100px);
max-height: calc((var(--vh, 1vh) * 100) - 120px);
@include respond-to(handhelds) {
width: 100% !important;
height: 100% !important;
max-width: 100vw !important;
max-height: 100vh !important;
// max-height: 100vh !important;
// TODO: max-height: calc((var(--vh, 1vh) * 100));
//height: calc(100% - 100px) !important;
/* height: calc(100% - 50px) !important;
@ -320,15 +327,12 @@ @@ -320,15 +327,12 @@
max-height: calc(100% - 100px);
} */
/* .ckin__player:not(.ckin__fullscreen) {
.default__controls {
bottom: -50px;
.ckin__player:not(.ckin__fullscreen) {
.default__controls/* ,
.default__gradient-bottom */ {
bottom: -61px;
}
.default__gradient-bottom {
bottom: -50px;
}
} */
}
}
/* @include respond-to(handhelds) {
@ -341,9 +345,10 @@ @@ -341,9 +345,10 @@
}
} */
img:not(.thumbnail), video {
height: auto;
width: auto;
img:not(.thumbnail),
video {
/* height: auto;
width: auto; */
object-fit: contain;
//max-height: calc(100% - 100px);
}
@ -361,6 +366,12 @@ @@ -361,6 +366,12 @@
}
}
}
&-appear {
opacity: 0;
visibility: hidden;
transition: opacity var(--open-duration) 0s, visibility 0s var(--open-duration);
}
&-topbar {
position: absolute;
@ -372,7 +383,7 @@ @@ -372,7 +383,7 @@
align-items: center;
justify-content: space-between;
z-index: 5;
padding: 0 .5rem;
padding: 0 1.25rem;
.btn-icon, .media-viewer-author {
color: #8b8b8b;
@ -392,12 +403,13 @@ @@ -392,12 +403,13 @@
}
@include respond-to(handhelds) {
padding: 0 .5rem;
// transform: translateY(-3.5rem);
// background: rgba(0, 0, 0, .2);
@include animation-level(2) {
/* @include animation-level(2) {
transition: transform var(--open-duration) ease-in-out;
}
} */
}
}
@ -442,7 +454,8 @@ @@ -442,7 +454,8 @@
visibility: visible;
transition-delay: 0s;
.overlays/* ,
.overlays,
.media-viewer-appear/* ,
> .btn-icon */ {
opacity: 1;
visibility: visible;

Loading…
Cancel
Save