diff --git a/404a.html b/404a.html index 43ca5c4..6820688 100644 --- a/404a.html +++ b/404a.html @@ -141,6 +141,7 @@ + diff --git a/index.html b/index.html index 4c1f513..d06cdd2 100644 --- a/index.html +++ b/index.html @@ -19,7 +19,6 @@ - @@ -260,6 +259,7 @@ + diff --git a/javascript/engine/event_handler.js b/javascript/engine/event_handler.js deleted file mode 100644 index 366c813..0000000 --- a/javascript/engine/event_handler.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * В этом файле будут обрабатываться внутренние события программы - * такие как первый запуск программы, первый раз зашел на страницу просмотра - * и т.д. - * Это должно облегчить путь пользователя по программу с ознакомлением функция - */ -//Этот Файл желательно вставлятьб после файла server.js - -//Текущая страница от которых будет происодить проверки событий -const app_current_page = $($(`head meta[name="page"]`)[0]).attr('content'); - -//ключ к доступу к события localhost -const key_events_handler_list = 'events_handler_list'; -const key_application_installed = 'application_installed'; -//Список событий прогрымм -let events_handler_list = { - onStart: { - completed: false, - target: 'index' - }, - version: '0.1' -}; -//Установленно ли приложение на девайс -let app_installed_device = { - installed: false, - date: '', -}; - -//Начало программы -(() => { - //Для начало нужно определить является ли это приложение или нет - LoadInstalledApplication(); - LoadEventsHandlerList(); - - //Если приложение является установленным - if (app_installed_device.installed) { - for (const key in events_handler_list) { - if (key == 'version') - continue; - - if (events_handler_list[key].completed == false && events_handler_list[key].target == app_current_page) { - CallEventHandler(key); - } - } - } - - (() => { - const key = "download-a"; - const File = "download_a.js"; - /** - * @type {[{id_ur: number, episodes: number, downloaded: [{episode: number, date:string}], duration: number}] | []} - */ - const data = JSON.parse(localStorage.getItem(key)) || []; - - if (data.length === 0) - return; - - OpenScript(File); - })(); - - function OpenScript(source) { - window.onload = function () { - const script = document.createElement('script'); - script.src = `/javascript/auto/${source}`; - script.type = "module"; - document.body.appendChild(script); - }; - } -})(); - -/** - * Возвращает информацию об установленом приложение - * @returns {Object} - обьект об информации установки - */ -function GetAppInstalled() { - return JSON.parse(localStorage.getItem(key_application_installed)); -} - -/** - * Возвращаем информацибю об внутренних событий программы - * @returns {Object} - обьект об информации внутренних событий - */ -function GetEventsHandler() { - return JSON.parse(localStorage.getItem(key_events_handler_list)); -} - -/** - * Слхранение обьекта в localStorage устройства - * @param {Object} item - записуемый обьект - * @param {String} key - ключ для сохранения елемента - */ -function SetItemLocalStorage(item, key) { - localStorage.setItem(key, JSON.stringify(item)); -} - -/** - * Загружаем данные об установке приложения - */ -function LoadInstalledApplication() { - //Проверяем сохранненые данные если они есть - let install_data = GetAppInstalled(); - if (install_data != null && install_data?.installed != false) { - //Приложение установлено на девайс - app_installed_device = install_data; - } else { - //Прилодение не установлена на устройство пользователя - //Проверяем установлен ли приложение - if (window.location.href.match('/?mode=standalone')) { - const dateObj = new Date(); - app_installed_device.installed = true; - app_installed_device.date = dateObj.getUTCFullYear() + "/" + (dateObj.getUTCMonth() + 1) + "/" + dateObj.getUTCDate(); - } - SetItemLocalStorage(app_installed_device, key_application_installed); - } -} - -/** - * Загружает данные об внутренних событий программы - */ -function LoadEventsHandlerList() { - //Проверяем данные если они есть - let events_handler_data = GetEventsHandler(); - if (events_handler_data == null) { - SetItemLocalStorage(events_handler_list, key_events_handler_list); - } else { - events_handler_list = events_handler_data; - } -} - -/** - * Вызывает событие из списка и устанавливает его выполненым - * @param {String} params - ключ к параметру - */ -function CallEventHandler(params) { - const events = { - onStart: function () { - window.location.href = "login.html"; - } - } - - events_handler_list[params].completed = true - SetItemLocalStorage(events_handler_list, key_events_handler_list); - events[params](); -} \ No newline at end of file diff --git a/javascript/engine/orientation.js b/javascript/engine/orientation.js deleted file mode 100644 index 0bea4a0..0000000 --- a/javascript/engine/orientation.js +++ /dev/null @@ -1,27 +0,0 @@ -//Текущая ориентация устройства -let current_device_orientation = "vertical"; - -(() => { - //Инидентификатор для каких елементов будет отслеживать изменение ориентации экрана - const id = "orientationchange"; - - const elements = $(`[data-engine="${id}"]`); - - if (window.orientation && window.orientation == 90 || window.orientation == -90) { - elements.addClass("landscape"); - current_device_orientation = "horizontal"; - } else { - elements.removeClass("landscape"); - current_device_orientation = "vertical"; - } - - window.addEventListener("orientationchange", function () { - if (window.orientation && window.orientation == 90 || window.orientation == -90) { - elements.addClass("landscape"); - current_device_orientation = "horizontal"; - } else { - elements.removeClass("landscape"); - current_device_orientation = "vertical"; - } - }, false); -})(); \ No newline at end of file diff --git a/javascript/menu.js b/javascript/menu.js index e71f0fc..4077e99 100644 --- a/javascript/menu.js +++ b/javascript/menu.js @@ -510,20 +510,6 @@ const IntercatMenu = { }, line: { - }, - standartcontrol: { - type: "parametr", - disabled: () => { - return false; - }, - value: () => { - return $PARAMETERS.player.autonekst; - }, - text: "Автопереключение", - icon: ``, - event: (bool) => { - setParameter('autonekst', bool); - } }, fullscreen: { type: "parametr", @@ -550,10 +536,8 @@ const IntercatMenu = { event: (bool) => { setParameter('standart', bool); }, - text: "Плеер", - icon: ` - - ` + text: "Tunime плеер", + icon: `` } } } \ No newline at end of file diff --git a/javascript/pages/player/mod_functions.js b/javascript/pages/player/mod_functions.js index 62dfc5d..549f619 100644 --- a/javascript/pages/player/mod_functions.js +++ b/javascript/pages/player/mod_functions.js @@ -6,21 +6,17 @@ * Библиотеки: rxjs.js, jqery.js * Возвращает: InitFunctions, CURSOR_WIDTH, onPlaybackRate2$ */ -import { AnimeQuery, Player, hls, onBuffered$, toggleFullScreen } from "../player.js"; +import { Player, hls, toggleFullScreen } from "../player.js"; import { AnimSkip } from "./mod_animation.js"; import { SendAPI } from "./mod_api.js"; -import { onDuration$, onTimeUpdate$ } from "./mod_event.js"; -import { ALTERNATIVE_FULLSCREEN, AUTO_NEKST } from "./mod_settings.js"; +import { onEnded$, onTimeUpdate$ } from "./mod_event.js"; +import { ALTERNATIVE_FULLSCREEN } from "./mod_settings.js"; import { InitShortcuts } from "./mod_shortcuts.js"; import { Skips } from "./mod_stream.js"; -let END_TIME = 0; //Продолжительность видео после обрезки //Настоящий размер курсора export const CURSOR_WIDTH = 33; -//Вызов события при изменения endtime -const onEndTime$ = new rxjs.Subject(); - //Вызов при воспроизведении x2 export const onPlaybackRate2$ = new rxjs.Subject(); @@ -130,36 +126,6 @@ export function InitFunctions() { } }); - - - onDuration$.subscribe({ - next: () => { - if (AUTO_NEKST && Player.duration) { - let end_time_list = localStorage.getItem('tun-end-point'); - if (!end_time_list) end_time_list = {}; else end_time_list = JSON.parse(end_time_list); - if (end_time_list && end_time_list[AnimeQuery.id]) { - END_TIME = Player.duration - end_time_list[AnimeQuery.id].time; - } else { - //Сделать проверку если видео нету обрезки то поставить на 2% - END_TIME = Player.duration - (2 / 100) * Player.duration; - } - onEndTime$.next(END_TIME); - } - } - }); - - onTimeUpdate$.subscribe({ - next: () => { - if (AUTO_NEKST && END_TIME != 0) { - if (Player.currentTime >= END_TIME && !api_nexte_called) { - Player.currentTime = 0; - SendAPI.next(); - api_nexte_called = !api_nexte_called; - } - } - } - }); - onTimeUpdate$.subscribe({ next: () => { if (Skips.list.length <= 0) { @@ -176,21 +142,15 @@ export function InitFunctions() { AnimSkip.hide(); } } - }) + }); - onBuffered$.subscribe({ - next: (time) => { - if (AUTO_NEKST && END_TIME != 0) { - if (time >= END_TIME) { - console.log('[plr] - Buffered stoped'); - hls.stopLoad(); - } - } + onEnded$.subscribe({ + next: () => { + SendAPI.next(); } }); CurrentPointScroll(); - TrimPointScroll(); InitShortcuts(); } @@ -198,17 +158,6 @@ export function ResetFunctions() { api_nexte_called = false; } -onEndTime$.subscribe({ - next: (endtime) => { - const slid = $('.player-slides > .trim-slid'); - const cursor = $('.player-cursors > .trim-cursor'); - let prcnt = ((Player.duration - endtime) / Player.duration) * 100; - slid.width(`${prcnt}%`) - cursor.css({ right: `calc(${prcnt}% - ${CURSOR_WIDTH / 2}px)` }); - hls.startLoad(); - } -}) - /** * Управление currentTime скролл */ @@ -267,71 +216,6 @@ function CurrentPointScroll() { }); } -/** - * Управление trim скролл - */ -function TrimPointScroll() { - const slid = $('.player-slides > .trim-slid'); - const cursor = $('.player-cursors > .trim-cursor'); - - cursor.on('mousedown touchstart', function (e) { - //Проверяем что видео прогрузилось и готово - if (Player.duration == 0) return; - //Координаты нажатия на cursor - let startX = e.clientX || e.originalEvent.touches[0].clientX; - let played = false; - //Останавливаем плеер если вопсроизводиться - if (!Player.paused) { - Player.pause(); - played = true; //Запоминаем что плеер воспроизводился раньше - } - - //Текущая длина slid - let curWidth = slid.width(); - //Смещение курсора - let cursorLeft = cursor.position().left; - let event = true; - - $(window).on('mousemove.ev touchmove.ev', function (e) { - //Координаты смещения - let currentX = e.clientX || e.originalEvent.touches[0].clientX || e.originalEvent.clientX; - let swipeDistance = currentX - startX; - let width = curWidth + -swipeDistance; - if ((window.innerWidth - $('.player-slides > .current-slid').width()) <= width) { - _endevent(); - return; - } - cursor.css('right', (window.innerWidth - cursorLeft) - swipeDistance); - cursor.css({ right: `calc(${(window.innerWidth - cursorLeft) - swipeDistance - (CURSOR_WIDTH / 2)}px - ${CURSOR_WIDTH / 2}px)` }); - slid.width((curWidth + -swipeDistance)); - e.preventDefault(); - }); - - $(window).on('mouseup.ev touchend.ev', function (e) { - _endevent(); - }); - - function _endevent() { - if (event) { - $(window).off('mousemove.ev touchmove.ev'); - $(window).off('mouseup.ev touchend.ev'); - event = false; - let prcnt = (slid.width() / window.innerWidth) * 100; - let timeTrim = (prcnt / 100) * Player.duration; - END_TIME = Player.duration - timeTrim; - slid.css({ width: `${prcnt}%` }); - cursor.css({ right: `calc(${prcnt}% - ${CURSOR_WIDTH / 2}px)` }); - if (played) Player.play(); - let end_time_list = localStorage.getItem('tun-end-point'); - if (!end_time_list) end_time_list = {}; else end_time_list = JSON.parse(end_time_list); - let time = Player.duration - END_TIME - end_time_list[AnimeQuery.id] = { date: new Date(), time: time }; - localStorage.setItem('tun-end-point', JSON.stringify(end_time_list)); - } - } - }); -} - /** * Переключение режима PIP */ diff --git a/javascript/pages/player/mod_settings.js b/javascript/pages/player/mod_settings.js index b8f0ec6..dd42477 100644 --- a/javascript/pages/player/mod_settings.js +++ b/javascript/pages/player/mod_settings.js @@ -4,16 +4,15 @@ * качества, Переключение на следующий эпизод, Упарвлению * громкостью видео. * Библиотеки: rxjs.js, jqery.js - * Возвращает: InitSettings, QUALITY, AUTO_NEKST, FULL_PLAYER, AUTOQUALITY, + * Возвращает: InitSettings, QUALITY, FULL_PLAYER, AUTOQUALITY, * STANDART, STANDART_CONTROLS, onQualityChange$, - * onAutoNekstChange$, ALTERNATIVE_FULLSCREEN + * ALTERNATIVE_FULLSCREEN */ import { Player, hls } from "../player.js"; import { onVolumeChange$ } from "./mod_event.js"; export let QUALITY = $PARAMETERS.player.quality; -export let AUTO_NEKST = $PARAMETERS.player.autonekst; export const FULL_PLAYER = $PARAMETERS.player.full; export const AUTOQUALITY = $PARAMETERS.player.autoquality; export const STANDART = $PARAMETERS.player.standart; @@ -27,13 +26,6 @@ export const onQualityChange$ = new rxjs.Subject().pipe( rxjs.distinctUntilChanged() ); -/** - * Измененеие параметра автопереключение - */ -export const onAutoNekstChange$ = new rxjs.Subject().pipe( - rxjs.distinctUntilChanged() -); - /** * Инициализация окна с настройками */ @@ -45,13 +37,6 @@ export function InitSettings() { onQualityChange$.next(QUALITY); }); - $(`.autonekst-setup`).on('click', function (e) { - if (e.target.type == "checkbox") { - AUTO_NEKST = e.target.checked; - onAutoNekstChange$.next(AUTO_NEKST); - } - }); - //Управление громкостью видео $(`.player-settings > .volume > .slide`).on('mousedown touchstart', function (e) { let startX = e.clientX || e.originalEvent.touches[0].clientX; @@ -95,7 +80,6 @@ export function InitSettings() { SetVolume(); $(`.quality-setup > .quality[data-q="${QUALITY}"]`).addClass('selected'); - $(`.autonekst-setup > .checkbox > input`).prop('checked', AUTO_NEKST); } //Изменение качество видеоролика diff --git a/javascript/pages/player/mod_ui.js b/javascript/pages/player/mod_ui.js index 2ee5db7..161df8d 100644 --- a/javascript/pages/player/mod_ui.js +++ b/javascript/pages/player/mod_ui.js @@ -11,7 +11,7 @@ import { Player, onBuffered$ } from "../player.js"; import { AnimButtonStatus, AnimRate, AnimSettings } from "./mod_animation.js"; import { onDuration$, onPause$, onPlay$, onTimeUpdate$, onVolumeChange$ } from "./mod_event.js"; import { CURSOR_WIDTH, onPlaybackRate2$ } from "./mod_functions.js"; -import { AUTO_NEKST, STANDART_CONTROLS, onAutoNekstChange$ } from "./mod_settings.js"; +import { STANDART_CONTROLS } from "./mod_settings.js"; import { Skips } from "./mod_stream.js"; /** @@ -24,12 +24,13 @@ export function InitUI() { $('.points-event').hide(); $('.controls-wrapper').hide(); } - //Скрыть / Показать громкость - $('.l-controls > .volume').on('click', function () { - if ($('.volume-slider').hasClass('hide')) { - $('.volume-slider').removeClass('hide'); + //Включить / Отключить звук + $('.l-controls > .volume > .icon-controls').on('click', function () { + Player.muted = !Player.muted; + if (Player.muted) { + $('.volume > .icon-controls > .mute').removeClass('hide'); } else { - $('.volume-slider').addClass('hide'); + $('.volume > .icon-controls > .mute').addClass('hide'); } }); @@ -39,7 +40,7 @@ export function InitUI() { }); //Управление громкостью - $(`.l-controls > .volume-slider > .slide`).on('mousedown touchstart', function (e) { + $(`.volume > .volume-slider > .slide`).on('mousedown touchstart', function (e) { let startX = e.clientX || e.originalEvent.touches[0].clientX; let slide = $(this).find('.current-slide'); let fullWidth = $(this).width(); @@ -50,6 +51,8 @@ export function InitUI() { let currentX = e.clientX || e.originalEvent.touches[0].clientX || e.originalEvent.clientX; let swipeDistance = currentX - startX; slide.width(width + swipeDistance); + let prcnt = (slide.width() / fullWidth) * 100; + Player.volume = prcnt / 100; if (width + swipeDistance <= 0) { return; } @@ -62,13 +65,11 @@ export function InitUI() { $(window).off('mousemove.sound touchmove.sound'); $(window).off('mouseup.sound touchend.sound'); event = false; - let prcnt = (slide.width() / fullWidth) * 100; - Player.volume = prcnt / 100; } } }); - $('.player-skip').on('click', function (){ + $('.player-skip').on('click', function () { Skips.Skip(); }); @@ -76,7 +77,6 @@ export function InitUI() { SubscribePlayerControlsEvent(); SubscribeCurrentCursorsEvents(); - SubscribeTrimCursorEvents(); } /** @@ -89,7 +89,6 @@ export function InitUICallbacks() { AnimButtonStatus.pause(); $('.l-controls > .switch-button').addClass('status-pause'); subCurrentCursor$.next(true); - subTrimCursor$.next(true); subControls$.next('p.pause'); } }); @@ -133,21 +132,7 @@ export function InitUICallbacks() { }); onVolumeChange$.subscribe({ next: () => { - let prcnt = Player.volume * 100; - $(`.l-controls > .volume-slider > .slide > .current-slide`).css({ - width: `${prcnt}%` - }) - } - }); - onAutoNekstChange$.subscribe({ - next: () => { - if (AUTO_NEKST) { - $(`.player-slides > .trim-slid`).removeClass('hide'); - $(`.trim-cursor`).removeClass('hide'); - } else { - $(`.player-slides > .trim-slid`).addClass('hide'); - $(`.trim-cursor`).addClass('hide'); - } + SetVolume(); } }); onPlaybackRate2$.subscribe({ @@ -172,7 +157,7 @@ export function ResetUI() { */ function SetVolume() { let prcnt = Player.volume * 100; - $(`.l-controls > .volume-slider > .slide > .current-slide`).css({ + $(`.volume > .volume-slider > .slide > .current-slide`).css({ width: `${prcnt}%` }) } @@ -219,11 +204,9 @@ function SubscribePlayerControlsEvent() { inControls = true; subControls$.next('c.mouseenter'); subCurrentCursor$.next(true); - subTrimCursor$.next(true); }); controls.on('mousemove', function () { subCurrentCursor$.next(true); - subTrimCursor$.next(true); }); controls.on('mouseleave', function () { inControls = false; @@ -318,40 +301,6 @@ function HideCurerentCursor() { }, 3000); } -const subTrimCursor$ = new rxjs.Subject(); - -function SubscribeTrimCursorEvents() { - $('.player-cursors > .trim-cursor').on('touchstart mouseenter', function () { - inCursor = true; - clearTimeout(timerHideTrimCursor); - clearTimeout(timerHideControls); - - clearTimeout(timerHideCurrentCursors); - $('.player-cursors > .current-cursor').addClass('hide'); - }); - $('.player-cursors > .trim-cursor').on('touchend mouseleave', function () { - inCursor = false; - subTrimCursor$.next(true); - subControls$.next('cl.mouseleave'); - }) -} - -subTrimCursor$.subscribe({ - next: () => { - if (!AUTO_NEKST) return; - HideTrimCursor(); - } -}); - -let timerHideTrimCursor; - -function HideTrimCursor() { - $('.player-cursors > .trim-cursor').removeClass('hide'); - clearTimeout(timerHideTrimCursor); - timerHideTrimCursor = setTimeout(() => { - $('.player-cursors > .trim-cursor').addClass('hide'); - }, 3000); -} export function calculatePercentageWatched(videoDuration, currentTime) { if (currentTime > videoDuration) { diff --git a/javascript/pages/watch.js b/javascript/pages/watch.js index 7d627a1..26046eb 100644 --- a/javascript/pages/watch.js +++ b/javascript/pages/watch.js @@ -139,7 +139,7 @@ Main(async (e) => { e.functional.control(e.functional.methods[10], { episode: next_episode }); e.episodes.selected_episode = next_episode; e.episodes.AnimateSelect(next_episode); - SaveLData(next_episode, e.translation.id_translation); + SaveLData(next_episode, e.translation.id); History().add(false, 0, 0, next_episode); }); diff --git a/javascript/pages/watch/mod_player.js b/javascript/pages/watch/mod_player.js index 863343c..da4b1d5 100644 --- a/javascript/pages/watch/mod_player.js +++ b/javascript/pages/watch/mod_player.js @@ -105,7 +105,7 @@ const player = { * @param {Int} id - перевода */ select: function (id, user_handler = false) { - if (this.id == id) return; + if (this.id == id || id === undefined) return; // Проверяем на существование такго обьекта в DOM const element = $(`.voice[data-id="${id}"]`)[0]; const data = player.data.find((x) => x.translation.id == id); diff --git a/javascript/parametrs.js b/javascript/parametrs.js index b3c7368..cc7d50a 100644 --- a/javascript/parametrs.js +++ b/javascript/parametrs.js @@ -29,7 +29,6 @@ const $PARAMETERS = { full: false, alternative_full: false, standart_controls: false, - autonekst: false, autoquality: true, skipmoments: true }, diff --git a/javascript/server.js b/javascript/server.js index e04220a..17926d6 100644 --- a/javascript/server.js +++ b/javascript/server.js @@ -1,6 +1,5 @@ const $SERVER = { sw: navigator.serviceWorker, - cache: caches || undefined, version: undefined, hash: undefined, dialog_key: "dialog-update", @@ -42,6 +41,10 @@ const $SERVER = { } }; +if(typeof caches !== 'undefined'){ + $SERVER.cache = caches; +} + (async () => { if ($SERVER.sw) { await $SERVER.functions.newRegistration(); @@ -51,11 +54,25 @@ const $SERVER = { ShowUIVersion(); + HasUpdate(); OnUpdate(); UpdateSystem(); } + async function HasUpdate() { + const data = await ParseSWVersion(); + if (data.ver === $SERVER.version && data.hash === $SERVER.hash) { + $SERVER.updatet = false; + + $SERVER.On.complete = true; + + $SERVER.On.subscribe.forEach(event => { + event($SERVER.updatet); + }); + } + } + // Обрабатывает обновление интерфейса function OnUpdate() { const url = new URL(window.location.href); @@ -85,32 +102,37 @@ const $SERVER = { async function UpdateSystem() { const reg = await $SERVER.functions.getRegistration(); let newServer = undefined; + let type = 'active'; if (reg) { - if (reg.installing) { - newServer = reg.installing; - } else if (reg.waiting) { - newServer = reg.waiting; - const data = await ParseSWVersion(); - $SERVER.updatet = true; - $('.app-update').css({ display: 'flex' }); - SetUIVersion(data); - $('.app-update').addClass('show'); - $('.update-progress > .progress').css({ width: '50%' }); - - const skipData = await Events().skipWaiting(); - } else if (reg.active) { - newServer = reg.active; + newServer = reg.installing || reg.waiting || reg.active; + type = reg.installing ? 'installing' : reg.waiting ? 'waiting' : 'active'; + + reg.onupdatefound = async () => { + const swr = await $SERVER.sw.getRegistration(); + newServer.removeEventListener('statechange', OnStateChange); + newServer = swr.installing || swr.waiting || swr.active; + type = swr.installing ? 'installing' : swr.waiting ? 'waiting' : 'active'; + + if (type === 'installing') { + Install(); + } + + newServer.addEventListener('statechange', (ev) => OnStateChange(ev, true)); } } - $SERVER.On.subscribe.forEach(event => { - event($SERVER.updatet); - }); + newServer.addEventListener('statechange', OnStateChange); + + if (type === 'waiting' || type === 'installing') { + Install(); + } - newServer.addEventListener('statechange', ev => { - console.log(ev.target.state); - if (ev.target.state === 'activating') { + async function OnStateChange(ev) { + if (ev.target.state === 'waiting' || ev.target.state === 'installing') { + Install(); + } + if (ev.target.state === 'activating' || ev.target.state === 'installed') { $('.update-progress > .progress').css({ width: '80%' }); } if (ev.target.state === 'activated' || ev.target.state === 'redundant') { @@ -120,7 +142,16 @@ const $SERVER = { url.searchParams.set('hash', $SERVER.hash); window.location.href = url.toString(); } - }); + } + + async function Install() { + $('.app-update').css({ display: 'flex' }); + const data = await ParseSWVersion(); + SetUIVersion(data); + $('.app-update').addClass('show'); + $('.update-progress > .progress').css({ width: '50%' }); + newServer.postMessage({ id: 221 }); + } } // Отображает версию интерфейса @@ -129,7 +160,7 @@ const $SERVER = { $('.github > .version-hash > .hash').text($SERVER.hash); let data = JSON.parse(localStorage.getItem($SERVER.dialog_key)); - if (data === undefined) { + if (data === undefined || data === null) { data = { show: false, version: $SERVER.version, hash: $SERVER.hash, update: new Date().toJSON() }; localStorage.setItem($SERVER.dialog_key, JSON.stringify(data)); } diff --git a/javascript/services/dispatcher.js b/javascript/services/dispatcher.js new file mode 100644 index 0000000..63f28b1 --- /dev/null +++ b/javascript/services/dispatcher.js @@ -0,0 +1,102 @@ +if (typeof $SERVER === 'undefined') { + import('./update.js'); +} + +import('./installing.js'); + +export const CurrentPage = $($(`head meta[name="page"]`)[0]).attr('content'); + +const handlers = { + 'pageload': (name, data, manager) => { + if(CurrentPage === data.page){ + if(data.redirect){ + manager.RemoveTask(name); + window.location.href = data.redirect; + } + } + }, + 'update': (name, data, manager) => { + if(CurrentPage === 'index'){ + url.searchParams.append('update', 'true'); + url.searchParams.append('ver', data.version); + url.searchParams.append('hash', data.hash); + window.history.replaceState(null, '', url.toString()); + manager.RemoveTask(name); + } + } +}; + +class Dispatcher { + constructor() { + this.name = 'dispatcher'; + this.tasks = JSON.parse(localStorage.getItem(this.name)) || []; + + //Проверка задач на статус pending и выполнение + this.tasks.forEach(task => { + if (task.status === 'pending') { + handlers[task.type](task.name, task.data, this); + } + }); + } + + /** + * Создать новую задачу + * @param {string} name - название задачи + * @param {'pageload'|'update'} type - тип задачи + * @param {object} data - данные задачи + */ + NewTask(name, type) { + if (type === 'pageload') { + return { + data: ({ page, redirect = undefined } = {}) => { + const Task = { + type: 'pageload', + name: name, + data: { + page: page, + redirect: redirect + } + } + this.#AddTask(Task); + } + } + } else if (type === 'update') { + return { + data: ({ version = '', hash = ''} = {}) => { + const Task = { + type: 'update', + name: name, + data: { + version: version, + hash: hash + } + } + this.#AddTask(Task); + } + } + } + } + + #AddTask({ name, type, data } = {}) { + this.tasks = this.tasks.filter(task => task.name !== name || task.status !== 'pending'); + this.tasks.push({ + type: type, + name: name, + status: 'pending', + data: data + }); + localStorage.setItem(this.name, JSON.stringify(this.tasks)); + } + + RemoveTask(name){ + this.tasks = this.tasks.filter(task => task.name !== name); + if(this.tasks.length === 0){ + localStorage.removeItem(this.name); + } else { + localStorage.setItem(this.name, JSON.stringify(this.tasks)); + } + } +} + +console.log(`[service] - Dispatcher`); +export const Manager = new Dispatcher(); \ No newline at end of file diff --git a/javascript/services/installing.js b/javascript/services/installing.js new file mode 100644 index 0000000..3effba3 --- /dev/null +++ b/javascript/services/installing.js @@ -0,0 +1,16 @@ +const key = 'application_installed'; + +let app = JSON.parse(localStorage.getItem(key)) || { + installed: false, + date: '' +}; + +(() => { + console.log(`[service] - App Installing`); + if (!app.installed && window.location.href.match('/?mode=standalone')) { + app.installed = true; + app.date = new Date().toISOString(); + localStorage.setItem(key, JSON.stringify(app)); + window.location.href = 'login.html'; + } +})(); \ No newline at end of file diff --git a/javascript/services/update.js b/javascript/services/update.js new file mode 100644 index 0000000..fb2a2bc --- /dev/null +++ b/javascript/services/update.js @@ -0,0 +1,55 @@ +import { Manager } from './dispatcher.js'; +//В этом файле нужно сделать наблюдателя на service worker для не основных стрнаиц +//и если он был активирован новый service worker то на главной странице отобразить про обновление +//Попробывать роеализовать проверку на обновления для Tunime Api auto update + +(async () => { + if (typeof navigator.serviceWorker === 'undefined') { + return; + } + + console.log(`[service] - Update`); + + const reg = await navigator.serviceWorker.getRegistration(); + + let newServer = undefined; + + if (reg !== undefined) { + newServer = reg.installing || reg.waiting || reg.active; + + reg.onupdatefound = async () => { + const swr = await navigator.serviceWorker.getRegistration(); + newServer.removeEventListener('statechange', OnStateChange); + newServer = swr.installing || swr.waiting || swr.active; + newServer.addEventListener('statechange', OnStateChange); + } + + newServer.addEventListener('statechange', OnStateChange); + } + + async function OnStateChange(ev) { + if (ev.target.state === 'activated') { + //Получить новую версию + const newVersion = await GetVersionSW(ev.target); + Manager.NewTask('bg-update', 'update').data({ version: newVersion.version, hash: newVersion.hash }); + } + } +})(); + + +function GetVersionSW(sw) { + return new Promise((resolve) => { + navigator.serviceWorker.addEventListener('message', (event) => { + try { + const data = JSON.parse(event.data); + if (data.id === 220) { + navigator.serviceWorker.removeEventListener('message', event); + resolve({ version: data.val.ver, hash: data.val.hash }); + } + } catch (error) { + console.log(error); + } + }); + sw.postMessage({ id: 220 }); + }) +} \ No newline at end of file diff --git a/list.html b/list.html index ad9e7f7..a0396ea 100644 --- a/list.html +++ b/list.html @@ -57,7 +57,7 @@

Tunime

- + diff --git a/login.html b/login.html index 9566161..9a57b21 100644 --- a/login.html +++ b/login.html @@ -6,6 +6,7 @@ + TUN - Авторизация diff --git a/player.html b/player.html index cbe172a..2c68696 100644 --- a/player.html +++ b/player.html @@ -30,14 +30,6 @@
720p
- -