Browse Source

Fix video streaming chunk in Safari iOS

Fix round video iOS overflow
Fix album layout for iOS Safari
master
morethanwords 4 years ago
parent
commit
2202b6507a
  1. 2
      src/components/appMediaPlaybackController.ts
  2. 4
      src/components/appMediaViewer.ts
  3. 2
      src/components/chat/contextMenu.ts
  4. 2
      src/components/popupNewMedia.ts
  5. 6
      src/components/wrappers.ts
  6. 30
      src/index.hbs
  7. 8
      src/lib/mtproto/mtproto.service.ts
  8. 28
      src/pages/pageSignIn.ts
  9. 2
      src/scss/partials/_chat.scss
  10. 2
      src/scss/partials/_ckin.scss
  11. 3
      src/scss/partials/_leftSidebar.scss
  12. 5
      src/scss/partials/pages/_chats.scss
  13. 15
      src/scss/style.scss

2
src/components/appMediaPlaybackController.ts

@ -42,7 +42,7 @@ class AppMediaPlaybackController {
//source.type = doc.type == 'voice' && !opusDecodeController.isPlaySupported() ? 'audio/wav' : doc.mime_type; //source.type = doc.type == 'voice' && !opusDecodeController.isPlaySupported() ? 'audio/wav' : doc.mime_type;
if(doc.type == 'round') { if(doc.type == 'round') {
media.setAttribute('playsinline', ''); media.setAttribute('playsinline', 'true');
} }
media.dataset.mid = '' + mid; media.dataset.mid = '' + mid;

4
src/components/appMediaViewer.ts

@ -886,7 +886,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
//video.src = ''; //video.src = '';
video.setAttribute('playsinline', ''); video.setAttribute('playsinline', 'true');
// * fix for playing video if viewer is closed (https://contest.com/javascript-web-bonus/entry1425#issue11629) // * fix for playing video if viewer is closed (https://contest.com/javascript-web-bonus/entry1425#issue11629)
video.addEventListener('timeupdate', () => { video.addEventListener('timeupdate', () => {
@ -896,6 +896,8 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
}); });
if(isSafari) { if(isSafari) {
// test stream
// video.controls = true;
video.autoplay = true; video.autoplay = true;
} }

2
src/components/chat/contextMenu.ts

@ -77,6 +77,8 @@ export default class ChatContextMenu {
attachTo.addEventListener('click', (e) => { attachTo.addEventListener('click', (e) => {
//const good = !!findUpClassName(e.target, 'message') || !!findUpClassName(e.target, 'bubble__container'); //const good = !!findUpClassName(e.target, 'message') || !!findUpClassName(e.target, 'bubble__container');
const className = (e.target as HTMLElement).className; const className = (e.target as HTMLElement).className;
if(!className || !className.includes) return;
const good = ['bubble', 'bubble__container', 'message', 'time', 'inner'].find(c => className.includes(c)); const good = ['bubble', 'bubble__container', 'message', 'time', 'inner'].find(c => className.includes(c));
if(good) { if(good) {
onContextMenu(e); onContextMenu(e);

2
src/components/popupNewMedia.ts

@ -142,7 +142,7 @@ export default class PopupNewMedia extends PopupElement {
video.autoplay = false; video.autoplay = false;
video.controls = false; video.controls = false;
video.muted = true; video.muted = true;
video.setAttribute('playsinline', ''); video.setAttribute('playsinline', 'true');
video.onloadeddata = () => { video.onloadeddata = () => {
params.width = video.videoWidth; params.width = video.videoWidth;

6
src/components/wrappers.ts

@ -2,7 +2,7 @@ import { readBlobAsText } from '../helpers/blob';
import { deferredPromise } from '../helpers/cancellablePromise'; import { deferredPromise } from '../helpers/cancellablePromise';
import { months } from '../helpers/date'; import { months } from '../helpers/date';
import mediaSizes from '../helpers/mediaSizes'; import mediaSizes from '../helpers/mediaSizes';
import { isSafari } from '../helpers/userAgent'; import { isAppleMobile, isSafari } from '../helpers/userAgent';
import { PhotoSize } from '../layer'; import { PhotoSize } from '../layer';
import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager"; import appDocsManager, { MyDocument } from "../lib/appManagers/appDocsManager";
import { DownloadBlob } from '../lib/appManagers/appDownloadManager'; import { DownloadBlob } from '../lib/appManagers/appDownloadManager';
@ -74,7 +74,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
const video = document.createElement('video'); const video = document.createElement('video');
video.muted = true; video.muted = true;
video.setAttribute('playsinline', ''); video.setAttribute('playsinline', 'true');
if(doc.type == 'round') { if(doc.type == 'round') {
//video.muted = true; //video.muted = true;
const globalVideo = appMediaPlaybackController.addMedia(doc, message.mid); const globalVideo = appMediaPlaybackController.addMedia(doc, message.mid);
@ -224,7 +224,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
const deferred = deferredPromise<void>(); const deferred = deferredPromise<void>();
//if(doc.type == 'gif'/* || true */) { //if(doc.type == 'gif'/* || true */) {
video.addEventListener('canplay', () => { video.addEventListener(isAppleMobile ? 'loadeddata' : 'canplay', () => {
if(img?.parentElement) { if(img?.parentElement) {
img.remove(); img.remove();
} }

30
src/index.hbs

@ -40,20 +40,22 @@
<h4>Sign in to Telegram</h4> <h4>Sign in to Telegram</h4>
<p class="subtitle">Please confirm your country and<br> enter your phone number.</p> <p class="subtitle">Please confirm your country and<br> enter your phone number.</p>
<div class="input-wrapper"> <div class="input-wrapper">
<div class="input-field input-select"> {{!-- <form action=""> --}}
<input type="text" name="countryCode" id="countryCode" autocomplete="rrRandomRR" required /> <div class="input-field input-select">
<label for="countryCode">Country</label> <input type="text" name="countryCode" id="countryCode" autocomplete="rrRandomRR" required />
<span class="arrow arrow-down"></span> <label for="countryCode">Country</label>
</div> <span class="arrow arrow-down"></span>
<div class="input-field"> </div>
<input type="tel" name="phone" id="phone" autocomplete="rr55RandomRR55" required /> <div class="input-field">
<label for="phone">Phone Number</label> <input type="tel" name="phone" id="phone" autocomplete="rr55RandomRR55" required />
</div> <label for="phone">Phone Number</label>
<label class="checkbox-field"> </div>
<input type="checkbox" id="keepSigned" checked="checked"> <label class="checkbox-field">
<span>Keep me signed in</span> <input type="checkbox" id="keepSigned" checked="checked">
</label> <span>Keep me signed in</span>
<button class="btn-primary rp" style="visibility: hidden;">NEXT</button> </label>
<button class="btn-primary rp" style="visibility: hidden;">NEXT</button>
{{!-- </form> --}}
<div class="qr"><a href="#" class="a-qr">Quick log in using QR code</a></div> <div class="qr"><a href="#" class="a-qr">Quick log in using QR code</a></div>
</div> </div>
</div> </div>

8
src/lib/mtproto/mtproto.service.ts

@ -51,7 +51,8 @@ const onFetch = (event: FetchEvent): void => {
const info: DownloadOptions = JSON.parse(decodeURIComponent(params)); const info: DownloadOptions = JSON.parse(decodeURIComponent(params));
//const fileName = getFileNameByLocation(info.location); //const fileName = getFileNameByLocation(info.location);
const limitPart = STREAM_CHUNK_UPPER_LIMIT; // ! если грузить очень большое видео чанками по 512Кб в мобильном Safari, то стрим не запустится
const limitPart = info.size > (75 * 1024 * 1024) ? STREAM_CHUNK_UPPER_LIMIT : STREAM_CHUNK_MIDDLE_LIMIT;
/* if(info.size > limitPart && isSafari && offset == limitPart) { /* if(info.size > limitPart && isSafari && offset == limitPart) {
//end = info.size - 1; //end = info.size - 1;
@ -197,13 +198,12 @@ ctx.onoffline = ctx.ononline = onChangeState;
onChangeState(); onChangeState();
const DOWNLOAD_CHUNK_LIMIT = 512 * 1024;
/* const STREAM_CHUNK_UPPER_LIMIT = 256 * 1024; /* const STREAM_CHUNK_UPPER_LIMIT = 256 * 1024;
const SMALLEST_CHUNK_LIMIT = 256 * 4; */ const SMALLEST_CHUNK_LIMIT = 256 * 4; */
/* const STREAM_CHUNK_UPPER_LIMIT = 1024 * 1024; /* const STREAM_CHUNK_UPPER_LIMIT = 1024 * 1024;
const SMALLEST_CHUNK_LIMIT = 1024 * 4; */ const SMALLEST_CHUNK_LIMIT = 1024 * 4; */
const STREAM_CHUNK_UPPER_LIMIT = 512 * 1024; const STREAM_CHUNK_MIDDLE_LIMIT = 512 * 1024;
const STREAM_CHUNK_UPPER_LIMIT = 1024 * 1024;
const SMALLEST_CHUNK_LIMIT = 512 * 4; const SMALLEST_CHUNK_LIMIT = 512 * 4;
function parseRange(header: string): [number, number] { function parseRange(header: string): [number, number] {

28
src/pages/pageSignIn.ts

@ -103,7 +103,7 @@ let onFirstMount = () => {
selectCountryCode.value = countryName; selectCountryCode.value = countryName;
lastCountrySelected = countries.find(c => c.name == countryName); lastCountrySelected = countries.find(c => c.name == countryName);
telEl.value = phoneCode; telEl.value = lastValue = phoneCode;
setTimeout(() => telEl.focus(), 0); setTimeout(() => telEl.focus(), 0);
//console.log('clicked', e, countryName, phoneCode); //console.log('clicked', e, countryName, phoneCode);
}); });
@ -176,17 +176,25 @@ let onFirstMount = () => {
else selectCountryCode.focus(); else selectCountryCode.focus();
}); });
let sortedCountries = countries.slice().sort((a, b) => b.phoneCode.length - a.phoneCode.length); let pasted = false;
let lastValue = '';
let telEl = page.pageEl.querySelector('input[name="phone"]') as HTMLInputElement; let telEl = page.pageEl.querySelector('input[name="phone"]') as HTMLInputElement;
const telLabel = telEl.nextElementSibling as HTMLLabelElement; const telLabel = telEl.nextElementSibling as HTMLLabelElement;
telEl.addEventListener('input', function(this: typeof telEl, e) { telEl.addEventListener('input', function(this: typeof telEl, e) {
//console.log('input', this.value);
this.classList.remove('error'); this.classList.remove('error');
const diff = Math.abs(this.value.length - lastValue.length);
if(diff > 1 && !pasted) {
this.value = lastValue + this.value;
}
pasted = false;
telLabel.innerText = 'Phone Number'; telLabel.innerText = 'Phone Number';
let {formatted, country} = formatPhoneNumber(this.value); let {formatted, country} = formatPhoneNumber(this.value);
this.value = formatted ? '+' + formatted : ''; this.value = lastValue = formatted ? '+' + formatted : '';
//console.log(formatted, country); //console.log(formatted, country);
@ -204,7 +212,17 @@ let onFirstMount = () => {
} }
}); });
telEl.addEventListener('paste', (e) => {
pasted = true;
//console.log('paste', telEl.value);
});
/* telEl.addEventListener('change', (e) => {
console.log('change', telEl.value);
}); */
telEl.addEventListener('keypress', function(this: typeof telEl, e) { telEl.addEventListener('keypress', function(this: typeof telEl, e) {
console.log('keypress', this.value);
if(!btnNext.style.visibility &&/* this.value.length >= 9 && */ e.key == 'Enter') { if(!btnNext.style.visibility &&/* this.value.length >= 9 && */ e.key == 'Enter') {
return btnNext.click(); return btnNext.click();
} else if(/\D/.test(e.key)) { } else if(/\D/.test(e.key)) {
@ -286,7 +304,7 @@ let onFirstMount = () => {
if(!selectCountryCode.value.length && !telEl.value.length) { if(!selectCountryCode.value.length && !telEl.value.length) {
selectCountryCode.value = country.name; selectCountryCode.value = country.name;
lastCountrySelected = country; lastCountrySelected = country;
telEl.value = '+' + country.phoneCode.split(' and ').shift(); telEl.value = lastValue = '+' + country.phoneCode.split(' and ').shift();
} }
} }

2
src/scss/partials/_chat.scss

@ -641,7 +641,7 @@ $chat-helper-size: 39px;
flex: 3; flex: 3;
@include respond-to(floating-left-sidebar) { @include respond-to(floating-left-sidebar) {
position: fixed; position: fixed !important;
left: 0; left: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;

2
src/scss/partials/_ckin.scss

@ -416,6 +416,8 @@ input[type=range] {
video[data-ckin="circle"] { video[data-ckin="circle"] {
border-radius: 50%; border-radius: 50%;
overflow: hidden; overflow: hidden;
position: relative;
z-index: -1;
} }
.progress-ring { .progress-ring {
position: absolute; position: absolute;

3
src/scss/partials/_leftSidebar.scss

@ -16,7 +16,8 @@
position: fixed; position: fixed;
left: 0; left: 0;
top: 0; top: 0;
height: calc(var(--vh, 1vh) * 100); /* height: calc(var(--vh, 1vh) * 100);
min-height: calc(var(--vh, 1vh) * 100) !important; */
width: 26.5rem; width: 26.5rem;
transform: translate3d(-5rem, 0, 0); transform: translate3d(-5rem, 0, 0);
transition: transform var(--layer-transition); transition: transform var(--layer-transition);

5
src/scss/partials/pages/_chats.scss

@ -62,11 +62,12 @@
} }
} }
@include respond-to(floating-left-sidebar) { /* @include respond-to(floating-left-sidebar) {
.main-column { .main-column {
height: calc(var(--vh, 1vh) * 100) !important; height: calc(var(--vh, 1vh) * 100) !important;
min-height: calc(var(--vh, 1vh) * 100) !important;
} }
} } */
/* @include respond-to(until-floating-left-sidebar) { /* @include respond-to(until-floating-left-sidebar) {
.main-column { .main-column {

15
src/scss/style.scss

@ -73,6 +73,7 @@ $messages-container-width: 728px;
} }
:root { :root {
--vh: 1vh;
--z-below: -1; --z-below: -1;
--color-gray: #c4c9cc; --color-gray: #c4c9cc;
--color-gray-hover: rgba(112, 117, 121, .08); --color-gray-hover: rgba(112, 117, 121, .08);
@ -199,11 +200,13 @@ $messages-container-width: 728px;
html, body { html, body {
height: 100%; height: 100%;
width: 100%; width: 100%;
-webkit-font-smoothing: antialiased; margin: 0;
padding: 0;
//@include respond-to(handhelds) { @include respond-to(handhelds) {
overflow: hidden;
height: calc(var(--vh, 1vh) * 100); height: calc(var(--vh, 1vh) * 100);
//} }
/* @include respond-to(handhelds) { /* @include respond-to(handhelds) {
//overflow-y: auto; //overflow-y: auto;
@ -220,7 +223,11 @@ html, body {
html { html {
font-size: 16px; font-size: 16px;
overflow: hidden; //overflow: hidden;
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
text-rendering: optimizeSpeed;
} }
/* body { /* body {

Loading…
Cancel
Save