{"version":3,"file":"main.8c6fdef4813404936fed.js","mappings":"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","sources":["webpack://seplis/webpack/runtime/chunk loaded","webpack://seplis/webpack/runtime/create fake namespace object","webpack://seplis/./seplis/web/ui/components/slider.less","webpack://seplis/./seplis/web/ui/index.less","webpack://seplis/./seplis/web/ui/index.less?a6c5","webpack://seplis/./seplis/web/ui/components/error.tsx","webpack://seplis/./seplis/web/ui/api.tsx","webpack://seplis/./seplis/web/ui/pages/login.tsx","webpack://seplis/./seplis/web/ui/utils/utils.tsx","webpack://seplis/./seplis/web/ui/utils/browser.tsx","webpack://seplis/./seplis/web/ui/components/poster.tsx","webpack://seplis/./seplis/web/ui/styles.tsx","webpack://seplis/./seplis/web/ui/events.tsx","webpack://seplis/./seplis/web/ui/components/movie/watchlist-button.tsx","webpack://seplis/./seplis/web/ui/components/movie/settings.tsx","webpack://seplis/./seplis/web/ui/components/player/request-play-servers.tsx","webpack://seplis/./seplis/web/ui/components/player/pick-quality.tsx","webpack://seplis/./seplis/web/ui/components/player/pick-source.tsx","webpack://seplis/./seplis/web/ui/components/player/react-cast-sender/context/CastContext.ts","webpack://seplis/./seplis/web/ui/components/player/react-cast-sender/utils/utils.ts","webpack://seplis/./seplis/web/ui/components/player/react-cast-sender/utils/CastLoader.ts","webpack://seplis/./seplis/web/ui/components/player/react-cast-sender/context/CastProvider.tsx","webpack://seplis/./seplis/web/ui/components/player/react-cast-sender/components/CastButton/CastButton.tsx","webpack://seplis/./seplis/web/ui/components/player/react-cast-sender/hooks/useCast/useCast.ts","webpack://seplis/./seplis/web/ui/components/player/react-cast-sender/hooks/useCastPlayer/useCastPlayer.ts","webpack://seplis/./seplis/web/ui/components/player/pick-subtitle-source.tsx","webpack://seplis/./seplis/web/ui/components/player/pick-audio-source.tsx","webpack://seplis/./seplis/web/ui/components/play-button-menu.tsx","webpack://seplis/./seplis/web/ui/components/play-button.tsx","webpack://seplis/./seplis/web/ui/components/movie/play-button.tsx","webpack://seplis/./seplis/web/ui/components/watched-button.tsx","webpack://seplis/./seplis/web/ui/components/movie/watched-button.tsx","webpack://seplis/./seplis/web/ui/interfaces/movie.tsx","webpack://seplis/./seplis/web/ui/components/movie/skeleton.tsx","webpack://seplis/./seplis/web/ui/components/series/episode-play-button.tsx","webpack://seplis/./seplis/web/ui/components/full-page-error.tsx","webpack://seplis/./seplis/web/ui/components/player/pick-subtitle-offset.tsx","webpack://seplis/./seplis/web/ui/components/player/settings.tsx","webpack://seplis/./seplis/web/ui/components/player/slider.tsx","webpack://seplis/./seplis/web/ui/components/player/video.tsx","webpack://seplis/./seplis/web/ui/components/player/volume-bar.tsx","webpack://seplis/./seplis/web/ui/components/player/player.tsx","webpack://seplis/./seplis/web/ui/components/player/chromecast-controls.tsx","webpack://seplis/./seplis/web/ui/components/movie/collection.tsx","webpack://seplis/./seplis/web/ui/components/movie/favorite-button.tsx","webpack://seplis/./seplis/web/ui/components/movie/cast-card.tsx","webpack://seplis/./seplis/web/ui/components/movie/cast-featured.tsx","webpack://seplis/./seplis/web/ui/components/movie/movie.tsx","webpack://seplis/./seplis/web/ui/components/change_password_form.tsx","webpack://seplis/./seplis/web/ui/components/player/chromecast-icon.tsx","webpack://seplis/./seplis/web/ui/components/search.tsx","webpack://seplis/./seplis/web/ui/components/series/settings.tsx","webpack://seplis/./seplis/web/ui/components/main-menu.tsx","webpack://seplis/./seplis/web/ui/pages/movie.tsx","webpack://seplis/./seplis/web/ui/components/series/episode-watched-button.tsx","webpack://seplis/./seplis/web/ui/interfaces/episode.tsx","webpack://seplis/./seplis/web/ui/components/series/episode-card.tsx","webpack://seplis/./seplis/web/ui/components/series/episode-card-skeleton.tsx","webpack://seplis/./seplis/web/ui/components/series/episode-last-watched.tsx","webpack://seplis/./seplis/web/ui/components/series/episode-next-to-air.tsx","webpack://seplis/./seplis/web/ui/components/series/episode-to-watch.tsx","webpack://seplis/./seplis/web/ui/components/series/season-select.tsx","webpack://seplis/./seplis/web/ui/components/series/episodes.tsx","webpack://seplis/./seplis/web/ui/components/series/watchlist-button.tsx","webpack://seplis/./seplis/web/ui/components/series/skeleton.tsx","webpack://seplis/./seplis/web/ui/components/series/favorite-button.tsx","webpack://seplis/./seplis/web/ui/components/series/cast-card.tsx","webpack://seplis/./seplis/web/ui/components/series/cast-featured.tsx","webpack://seplis/./seplis/web/ui/components/series/series.tsx","webpack://seplis/./seplis/web/ui/pages/series.tsx","webpack://seplis/./seplis/web/ui/components/slider.less?1e30","webpack://seplis/./seplis/web/ui/components/slider.tsx","webpack://seplis/./seplis/web/ui/pages/series/home.tsx","webpack://seplis/./seplis/web/ui/components/list.tsx","webpack://seplis/./seplis/web/ui/components/select-genre.tsx","webpack://seplis/./seplis/web/ui/components/series/user-sort-select.tsx","webpack://seplis/./seplis/web/ui/components/select-language.tsx","webpack://seplis/./seplis/web/ui/components/switch-radio-group.tsx","webpack://seplis/./seplis/web/ui/components/series/user-filter.tsx","webpack://seplis/./seplis/web/ui/components/series/user-list.tsx","webpack://seplis/./seplis/web/ui/pages/series/browse.tsx","webpack://seplis/./seplis/web/ui/pages/series/watchlist.tsx","webpack://seplis/./seplis/web/ui/pages/series/favorites.tsx","webpack://seplis/./seplis/web/ui/pages/series/watched.tsx","webpack://seplis/./seplis/web/ui/components/movie/user-sort-select.tsx","webpack://seplis/./seplis/web/ui/components/movie/user-filter.tsx","webpack://seplis/./seplis/web/ui/components/movie/user-list.tsx","webpack://seplis/./seplis/web/ui/pages/movies/browse.tsx","webpack://seplis/./seplis/web/ui/pages/movies/watchlist.tsx","webpack://seplis/./seplis/web/ui/pages/movies/favorites.tsx","webpack://seplis/./seplis/web/ui/pages/movies/watched.tsx","webpack://seplis/./seplis/web/ui/pages/series/play-episode.tsx","webpack://seplis/./seplis/web/ui/pages/movies/play.tsx","webpack://seplis/./seplis/web/ui/pages/signup.tsx","webpack://seplis/./seplis/web/ui/pages/logout.tsx","webpack://seplis/./seplis/web/ui/pages/send-reset-password.tsx","webpack://seplis/./seplis/web/ui/pages/reset-password.tsx","webpack://seplis/./seplis/web/ui/pages/watch/home.tsx","webpack://seplis/./seplis/web/ui/pages/series/countdown.tsx","webpack://seplis/./seplis/web/ui/pages/series/recently-aired.tsx","webpack://seplis/./seplis/web/ui/pages/series/series-to-watch.tsx","webpack://seplis/./seplis/web/ui/index.tsx","webpack://seplis/webpack/bootstrap","webpack://seplis/webpack/runtime/compat get default export","webpack://seplis/webpack/runtime/define property getters","webpack://seplis/webpack/runtime/global","webpack://seplis/webpack/runtime/hasOwnProperty shorthand","webpack://seplis/webpack/runtime/make namespace object","webpack://seplis/webpack/runtime/node module decorator","webpack://seplis/webpack/runtime/publicPath","webpack://seplis/webpack/runtime/jsonp chunk loading","webpack://seplis/webpack/runtime/nonce","webpack://seplis/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);\nvar leafPrototypes;\n// create a fake namespace object\n// mode & 1: value is a module id, require it\n// mode & 2: merge all properties of value into the ns\n// mode & 4: return value when already ns object\n// mode & 16: return value when it's Promise-like\n// mode & 8|1: behave like require\n__webpack_require__.t = function(value, mode) {\n\tif(mode & 1) value = this(value);\n\tif(mode & 8) return value;\n\tif(typeof value === 'object' && value) {\n\t\tif((mode & 4) && value.__esModule) return value;\n\t\tif((mode & 16) && typeof value.then === 'function') return value;\n\t}\n\tvar ns = Object.create(null);\n\t__webpack_require__.r(ns);\n\tvar def = {};\n\tleafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];\n\tfor(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {\n\t\tObject.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));\n\t}\n\tdef['default'] = () => (value);\n\t__webpack_require__.d(ns, def);\n\treturn ns;\n};","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.row-header {\n font-size: 1.5rem !important;\n font-weight: 600 !important;\n}\n.row-margin {\n margin: 0 2.785vw 0.3rem 2.785vw !important;\n}\n@media screen and (max-width: 1099px) {\n .row-margin {\n font-size: 1rem !important;\n }\n}\n@media screen and (min-width: 1100px) and (max-width: 1599px) {\n .row-margin {\n margin: 5px 4.5vw !important;\n }\n}\n@media screen and (min-width: 600px) and (max-width: 1099px) {\n .row-margin {\n margin: 5px 5vw !important;\n }\n}\n@media screen and (max-width: 599px) {\n .row-margin {\n margin: 5px 40px !important;\n }\n}\n.slider {\n position: relative;\n padding: 0 2.785vw;\n user-select: none;\n overflow: hidden;\n width: 100%;\n}\n.slider .slider-item {\n overflow: hidden;\n flex-grow: 1;\n}\n.slider .slider-item.focused {\n border: 7px solid #fff;\n}\n@media screen and (min-width: 1600px) {\n .slider .slider-item {\n width: 8.3%;\n }\n}\n@media screen and (min-width: 1100px) and (max-width: 1599px) {\n .slider .slider-item {\n width: 14.285%;\n }\n}\n@media screen and (min-width: 600px) and (max-width: 1099px) {\n .slider .slider-item {\n width: 16.6667%;\n }\n}\n@media screen and (max-width: 599px) {\n .slider .slider-item {\n width: 33.333%;\n }\n}\n@media screen and (min-width: 1100px) and (max-width: 1599px) {\n .slider {\n padding: 0 4.5vw;\n }\n}\n@media screen and (min-width: 600px) and (max-width: 1099px) {\n .slider {\n padding: 0 5vw;\n }\n}\n@media screen and (max-width: 599px) {\n .slider {\n padding: 0 40px;\n }\n}\n.slider .slider-peek {\n position: absolute;\n width: 2.5vw;\n height: 100%;\n cursor: pointer;\n overflow: hidden;\n}\n@media screen and (min-width: 1100px) and (max-width: 1599px) {\n .slider .slider-peek {\n width: 3.9vw;\n }\n}\n@media screen and (min-width: 600px) and (max-width: 1099px) {\n .slider .slider-peek {\n width: 4.5vw;\n }\n}\n@media screen and (max-width: 599px) {\n .slider .slider-peek {\n width: 35px;\n }\n}\n.slider .slider-peek .image {\n position: absolute;\n display: flex;\n width: 100%;\n height: 100%;\n aspect-ratio: auto 603 / 887;\n}\n.slider .slider-peek .image img {\n object-fit: cover;\n}\n.slider .slider-peek .background {\n position: absolute;\n background: hsla(0, 0%, 8%, 0.5);\n height: 100%;\n width: 100%;\n}\n.slider .slider-peek .button {\n position: absolute;\n height: 100%;\n width: 100%;\n color: #fff;\n cursor: pointer;\n font-size: 1.4vw;\n display: flex;\n justify-content: center;\n align-items: center;\n visibility: hidden;\n}\n@media (pointer: coarse) {\n .slider .slider-peek .button {\n visibility: visible;\n }\n}\n.slider .slider-peek .button:hover,\n.slider .slider-peek .button:focus {\n visibility: visible;\n font-size: 2.4vw;\n}\n@media screen and (min-width: 1100px) and (max-width: 1599px) {\n .slider .slider-peek .button {\n font-size: 2.4vw;\n }\n .slider .slider-peek .button:hover,\n .slider .slider-peek .button:focus {\n visibility: visible;\n font-size: 3.4vw;\n }\n}\n@media screen and (min-width: 600px) and (max-width: 1099px) {\n .slider .slider-peek .button {\n font-size: 3.4vw;\n }\n .slider .slider-peek .button:hover,\n .slider .slider-peek .button:focus {\n visibility: visible;\n font-size: 4.4vw;\n }\n}\n@media screen and (max-width: 599px) {\n .slider .slider-peek .button {\n font-size: 35px;\n }\n .slider .slider-peek .button:hover,\n .slider .slider-peek .button:focus {\n visibility: visible;\n font-size: 40px;\n }\n}\n.slider:hover .slider-peek .button {\n visibility: visible;\n}\n.slider .prev {\n left: -0.5rem;\n}\n.slider .next {\n right: 0px;\n}\n.slider .slider-peek.prev {\n border-top-right-radius: var(--chakra-radii-md);\n border-bottom-right-radius: var(--chakra-radii-md);\n}\n.slider .slider-peek.next {\n border-top-left-radius: var(--chakra-radii-md);\n border-bottom-left-radius: var(--chakra-radii-md);\n}\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./seplis/web/ui/components/slider.less\"],\"names\":[],\"mappings\":\"AAAA;EACI,4BAAA;EACA,2BAAA;AACJ;AAEA;EACI,2CAAA;AAAJ;AAEI;EAAA;IACI,0BAAA;EACN;AACF;AACI;EAAA;IACI,4BAAA;EAEN;AACF;AAAI;EAAA;IACI,0BAAA;EAGN;AACF;AADI;EAAA;IACI,2BAAA;EAIN;AACF;AAAA;EACI,kBAAA;EACA,kBAAA;EACA,iBAAA;EACA,gBAAA;EACA,WAAA;AAEJ;AAPA;EAQQ,gBAAA;EACA,YAAA;AAER;AAAQ;EACI,sBAAA;AAEZ;AACQ;EAAA;IACI,WAAA;EAEV;AACF;AAAQ;EAAA;IACI,cAAA;EAGV;AACF;AADQ;EAAA;IACI,eAAA;EAIV;AACF;AAFQ;EAAA;IACI,cAAA;EAKV;AACF;AAFI;EAAA;IACI,gBAAA;EAKN;AACF;AAHI;EAAA;IACI,cAAA;EAMN;AACF;AAJI;EAAA;IACI,eAAA;EAON;AACF;AAjDA;EA6CQ,kBAAA;EACA,YAAA;EACA,YAAA;EACA,eAAA;EACA,gBAAA;AAOR;AALQ;EAAA;IACI,YAAA;EAQV;AACF;AANQ;EAAA;IACI,YAAA;EASV;AACF;AAPQ;EAAA;IACI,WAAA;EAUV;AACF;AAvEA;EAgEY,kBAAA;EACA,aAAA;EACA,WAAA;EACA,YAAA;EACA,4BAAA;AAUZ;AA9EA;EAsEgB,iBAAA;AAWhB;AAjFA;EA2EY,kBAAA;EACA,gCAAA;EACA,YAAA;EACA,WAAA;AASZ;AAvFA;EAkFY,kBAAA;EACA,YAAA;EACA,WAAA;EACA,WAAA;EACA,eAAA;EACA,gBAAA;EACA,aAAA;EACA,uBAAA;EACA,mBAAA;EACA,kBAAA;AAQZ;AANY;EAAA;IACI,mBAAA;EASd;AACF;AAPY;;EACI,mBAAA;EACA,gBAAA;AAUhB;AAPY;EAAA;IACI,gBAAA;EAUd;EARc;;IACI,mBAAA;IACA,gBAAA;EAWlB;AACF;AARY;EAAA;IACI,gBAAA;EAWd;EAVc;;IACI,mBAAA;IACA,gBAAA;EAalB;AACF;AAVY;EAAA;IACI,eAAA;EAad;EAXc;;IACI,mBAAA;IACA,eAAA;EAclB;AACF;AAPI;EACI,mBAAA;AASR;AA9IA;EAyIQ,aAAA;AAQR;AAjJA;EA6IQ,UAAA;AAOR;AApJA;EAiJQ,+CAAA;EACA,kDAAA;AAMR;AAxJA;EAsJQ,8CAAA;EACA,iDAAA;AAKR\",\"sourcesContent\":[\".row-header {\\n font-size: 1.5rem !important;\\n font-weight: 600 !important;\\n}\\n\\n.row-margin {\\n margin: 0 2.785vw 0.3rem 2.785vw !important;\\n\\n @media screen and (max-width: 1099px) {\\n font-size: 1rem !important;\\n }\\n\\n @media screen and (min-width: 1100px) and (max-width: 1599px) {\\n margin: 5px 4.5vw !important;\\n }\\n\\n @media screen and (min-width: 600px) and (max-width: 1099px) {\\n margin: 5px 5vw !important;\\n }\\n\\n @media screen and (max-width: 599px) {\\n margin: 5px 40px !important;\\n }\\n}\\n\\n\\n.slider {\\n position: relative;\\n padding: 0 2.785vw;\\n user-select: none;\\n overflow: hidden;\\n width: 100%;\\n\\n .slider-item {\\n overflow: hidden;\\n flex-grow: 1;\\n\\n &.focused { \\n border: 7px solid #fff;\\n }\\n\\n @media screen and (min-width: 1600px) {\\n width: 8.3%;\\n }\\n\\n @media screen and (min-width: 1100px) and (max-width: 1599px) {\\n width: 14.285%;\\n }\\n\\n @media screen and (min-width: 600px) and (max-width: 1099px) {\\n width: 16.6667%;\\n }\\n\\n @media screen and (max-width: 599px) {\\n width: 33.333%;\\n }\\n }\\n\\n @media screen and (min-width: 1100px) and (max-width: 1599px) {\\n padding: 0 4.5vw;\\n }\\n\\n @media screen and (min-width: 600px) and (max-width: 1099px) {\\n padding: 0 5vw;\\n }\\n\\n @media screen and (max-width: 599px) {\\n padding: 0 40px;\\n }\\n\\n .slider-peek {\\n position: absolute;\\n width: 2.5vw;\\n height: 100%;\\n cursor: pointer;\\n overflow: hidden;\\n\\n @media screen and (min-width: 1100px) and (max-width: 1599px) {\\n width: 3.9vw;\\n }\\n\\n @media screen and (min-width: 600px) and (max-width: 1099px) {\\n width: 4.5vw;\\n }\\n\\n @media screen and (max-width: 599px) {\\n width: 35px;\\n }\\n\\n .image {\\n position: absolute;\\n display: flex;\\n width: 100%;\\n height: 100%;\\n aspect-ratio: auto 603 / 887;\\n img {\\n object-fit: cover;\\n }\\n }\\n\\n .background {\\n position: absolute;\\n background: hsla(0,0%,8%,.5);\\n height: 100%;\\n width: 100%;\\n }\\n\\n .button {\\n position: absolute;\\n height: 100%;\\n width: 100%;\\n color: #fff;\\n cursor: pointer;\\n font-size: 1.4vw;\\n display: flex;\\n justify-content: center;\\n align-items: center;\\n visibility: hidden;\\n\\n @media (pointer:coarse) {\\n visibility: visible;\\n }\\n\\n &:hover, &:focus {\\n visibility: visible;\\n font-size: 2.4vw;\\n }\\n\\n @media screen and (min-width: 1100px) and (max-width: 1599px) {\\n font-size: 2.4vw; \\n \\n &:hover, &:focus {\\n visibility: visible;\\n font-size: 3.4vw;\\n }\\n }\\n \\n @media screen and (min-width: 600px) and (max-width: 1099px) {\\n font-size: 3.4vw; \\n &:hover, &:focus {\\n visibility: visible;\\n font-size: 4.4vw;\\n }\\n }\\n \\n @media screen and (max-width: 599px) {\\n font-size: 35px; \\n \\n &:hover, &:focus {\\n visibility: visible;\\n font-size: 40px;\\n }\\n }\\n }\\n\\n\\n } \\n \\n &:hover .slider-peek .button {\\n visibility: visible;\\n }\\n\\n .prev {\\n left: -0.5rem;\\n }\\n \\n .next {\\n right: 0px;\\n }\\n\\n .slider-peek.prev { \\n border-top-right-radius: var(--chakra-radii-md);\\n border-bottom-right-radius: var(--chakra-radii-md);\\n }\\n\\n .slider-peek.next { \\n border-top-left-radius: var(--chakra-radii-md);\\n border-bottom-left-radius: var(--chakra-radii-md);\\n }\\n \\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.poster-container {\n border-radius: var(--chakra-radii-md);\n aspect-ratio: auto 603 / 887;\n overflow: hidden;\n}\n@supports not (aspect-ratio: 1/1) {\n .poster-container {\n height: 100%;\n }\n}\n.poster-container img {\n object-fit: cover;\n width: 100%;\n height: 100%;\n}\n@media screen and (min-width: 1600px) {\n .poster-container-sizing {\n width: 10vw;\n }\n}\n@media screen and (min-width: 1100px) and (max-width: 1599px) {\n .poster-container-sizing {\n width: 20vw;\n }\n}\n@media screen and (min-width: 600px) and (max-width: 1099px) {\n .poster-container-sizing {\n width: 30vw;\n }\n}\n@media screen and (max-width: 599px) {\n .poster-container-sizing {\n width: 100vw;\n }\n}\n.focused-filled-white {\n background-color: #fff;\n color: #000;\n}\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./seplis/web/ui/index.less\"],\"names\":[],\"mappings\":\"AAAA;EACI,qCAAA;EACA,4BAAA;EACA,gBAAA;AACJ;AACI;EAAA;IACI,YAAA;EAEN;AACF;AATA;EAUQ,iBAAA;EACA,WAAA;EACA,YAAA;AAER;AAGI;EAAA;IACI,WAAA;EAAN;AACF;AAEI;EAAA;IACI,WAAA;EACN;AACF;AACI;EAAA;IACI,WAAA;EAEN;AACF;AAAI;EAAA;IACI,YAAA;EAGN;AACF;AAAA;EACI,sBAAA;EACA,WAAA;AAEJ\",\"sourcesContent\":[\".poster-container {\\n border-radius: var(--chakra-radii-md);\\n aspect-ratio: auto 603 / 887;\\n overflow: hidden;\\n \\n @supports not (aspect-ratio: 1/1) {\\n height: 100%;\\n }\\n \\n img {\\n object-fit: cover;\\n width: 100%;\\n height: 100%;\\n }\\n}\\n\\n.poster-container-sizing {\\n @media screen and (min-width: 1600px) {\\n width: 10vw;\\n }\\n\\n @media screen and (min-width: 1100px) and (max-width: 1599px) { \\n width: 20vw;\\n }\\n\\n @media screen and (min-width: 600px) and (max-width: 1099px) {\\n width: 30vw;\\n }\\n\\n @media screen and (max-width: 599px) {\\n width: 100vw;\\n }\\n}\\n\\n.focused-filled-white {\\n background-color: #fff;\\n color: #000;\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/less-loader/dist/cjs.js??ruleSet[1].rules[2].use[2]!./index.less\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!../../../node_modules/less-loader/dist/cjs.js??ruleSet[1].rules[2].use[2]!./index.less\";\n export default content && content.locals ? content.locals : undefined;\n","import { AxiosError } from \"axios\"\n\nexport function ErrorMessageFromResponse(errorObj: any): JSX.Element {\n if (!errorObj)\n return <>Unknown error\n\n if (typeof errorObj === 'string')\n return <>{errorObj}\n\n if (errorObj.isAxiosError) {\n const e: AxiosError = errorObj\n const data = (e.response?.data as any)\n if (data?.code == 1001) {\n return <>\n {data.errors.length > 0 && (\n \n )}\n \n } \n else if (data?.detail)\n return data.detail\n else if (data?.message)\n return data.message\n return <>{e.message}\n }\n return <>{errorObj.message}\n}","import Axios, { AxiosError, AxiosRequestConfig } from 'axios'\nimport { IPageCursorResult } from './interfaces/page'\n\n\nconst api = Axios.create({\n baseURL: (window as any).seplisAPI,\n paramsSerializer: {\n indexes: null,\n }\n})\n\nexport function setAuthorizationHeader() {\n if (localStorage.getItem('accessToken'))\n api.defaults.headers['Authorization'] = `Bearer ${localStorage.getItem('accessToken')}`\n else\n api.defaults.headers['Authorization'] = null\n}\n\nsetAuthorizationHeader()\n\napi.interceptors.response.use((response) => response, (error: AxiosError) => {\n if (error?.response?.status == 401) \n location.href = `/login?next=${encodeURIComponent(location.pathname + location.search)}`\n throw error\n})\n\nexport default api\n\nexport async function GetAllCursor(url: string, config?: AxiosRequestConfig) {\n let result = await api.get>(url, config)\n if (!config.params)\n config.params = {}\n const items = result.data.items\n if (result.data.cursor)\n do {\n config.params['cursor'] = result.data.cursor\n result = await api.get>(url, config)\n items.push(...result.data.items)\n } while (result.data.cursor !== null)\n return items\n}\n\n","import { Flex, Heading, Input, Button, InputGroup, Stack, InputLeftElement, Box, Avatar, FormControl, FormHelperText, Alert, AlertTitle, AlertIcon } from '@chakra-ui/react'\nimport { FaUserAlt, FaLock } from 'react-icons/fa'\nimport { useForm } from 'react-hook-form'\nimport axios from 'axios'\nimport { useEffect, useState } from 'react'\nimport { Link, useNavigate } from 'react-router-dom'\nimport { StringParam, useQueryParam } from 'use-query-params'\nimport { IToken } from '@seplis/interfaces/token'\nimport { ErrorMessageFromResponse } from '@seplis/components/error'\nimport api, { setAuthorizationHeader } from '@seplis/api'\nimport { IUser, IUsersLoggedIn } from '@seplis/interfaces/user'\n\n\ninterface ILogin {\n login: string\n password: string\n next: string\n}\n\nexport default function Login() {\n const { handleSubmit, register, formState: { isSubmitting }, resetField, setFocus, setValue } = useForm()\n const [error, setError] = useState(null)\n const [next] = useQueryParam('next', StringParam)\n const navigate = useNavigate()\n\n useEffect(() => {\n document.title = 'Log in | SEPLIS'\n setValue('next', next)\n setFocus('login')\n }, [])\n\n const submit = async (data: ILogin) => {\n try {\n setError(null)\n const r = await axios.post('/api/token', {\n login: data.login,\n password: data.password,\n })\n localStorage.setItem('accessToken', r.data.access_token)\n setAuthorizationHeader()\n const user = await api.get('/2/users/me')\n const users: IUsersLoggedIn = JSON.parse(localStorage.getItem('users')) || {}\n users[user.data.id] = {\n ...user.data,\n token: r.data.access_token\n }\n localStorage.setItem('users', JSON.stringify(users))\n localStorage.setItem('activeUser', JSON.stringify(user.data))\n\n navigate(data.next ? data.next : '/')\n } catch (e) {\n setError(ErrorMessageFromResponse(e))\n resetField('password')\n setFocus('password')\n }\n }\n\n return \n \n \n \n {\n if (event.key === \"Enter\")\n handleSubmit(submit)()\n }}\n >\n \n Log in to SEPLIS\n\n {error && \n \n {error}\n }\n\n \n \n } />\n \n \n \n\n \n \n } />\n \n \n \n Reset password\n \n \n\n \n\n \n \n Login\n \n \n \n \n \n \n \n Sign up\n \n \n \n \n}","import dayjs from 'dayjs'\nimport { IEpisode } from '../interfaces/episode'\n\n\nexport function isAuthed() {\n return (localStorage.getItem('accessToken') !== null)\n}\n\n\nexport function requireAuthed() {\n if (!isAuthed()) {\n location.href = '/sign-in'\n throw 'Not authed!'\n }\n return true;\n}\n\n\nexport function getUserId() {\n requireAuthed();\n return localStorage.getItem('user_id') || 0;\n}\n\n\nexport function getUserLevel() {\n return localStorage.getItem('user_level') || null;\n}\n\n\nexport function pad(str: string | number, max: number): string {\n str = str.toString()\n return str.length < max ? pad(\"0\" + str, max) : str\n}\n\n\nexport function episodeNumber(episode: IEpisode) {\n if (!episode)\n return null\n if (!episode.season || !episode.episode)\n return `Episode ${episode.number}`\n \n if (episode.episode != episode.number)\n return `S${pad(episode.season,2)}E${pad(episode.episode, 2)} (${episode.number})`\n\n return `S${pad(episode.season,2)}E${pad(episode.episode, 2)}`\n}\n\n\nexport function episodeTitle(episode: IEpisode) {\n return `${episodeNumber(episode)}: ${episode.title}`\n}\n\n\nexport function EpisodeAirdate(episode: IEpisode) {\n if (episode.air_datetime)\n return {dayjs(episode.air_datetime).format('YYYY-MM-DD')}\n return episode.air_date || 'Unknown airdate'\n}\n\n\nexport function EpisodeAirdatetime(episode: IEpisode) {\n if (episode.air_datetime)\n return {dayjs(episode.air_datetime).format('YYYY-MM-DD HH:mm')}\n return 'Unknown airdate'\n}\n\n\nexport function secondsToTime(secs: number) {\n const hours = Math.floor(secs / 3600);\n const minutes = Math.floor((secs - (hours * 3600)) / 60);\n const seconds = Math.floor(secs - (hours * 3600) - (minutes * 60));\n \n return (hours>0?pad(hours, 2)+':':'')+pad(minutes, 2)+':'+pad(seconds, 2);\n}\n\n\nexport function dateInDays(dt: Date | string) {\n if (typeof(dt) == \"string\")\n dt = new Date(dt)\n let seconds = Math.abs(dt.getTime()-new Date().getTime())/1000\n let minutes, hours, days\n let l = [];\n [minutes, seconds] = divmod(seconds, 60);\n [hours, minutes] = divmod(minutes, 60);\n [days, hours] = divmod(hours, 24);\n if (days > 0) l.push(pluralize(days, 'day'))\n if (hours > 0) l.push(pluralize(hours, 'hour'))\n if ((minutes > 0) && (hours < 1) && (days < 1)) \n l.push(pluralize(minutes, 'minute'))\n return l.join(' ')\n}\n\n\nexport function dateCountdown(dt: string) {\n const m = (new Date(dt).getTime() - new Date().getTime())\n if (m > 0)\n return <>in {dateInDays(dt)}\n return <>{dateInDays(dt)} ago\n}\n\n\nexport function secondsToPretty(seconds: number, showTotalHours: boolean) {\n let totalHours = Math.round((((seconds/60)/60)*10))/10;\n if (seconds < 60) return pluralize(seconds, 'second');\n let minutes, hours, days, months, years;\n [minutes, seconds] = divmod(seconds, 60);\n [hours, minutes] = divmod(minutes, 60);\n [days, hours] = divmod(hours, 24);\n [months, days] = divmod(days, 30.42);\n [years, months] = divmod(months, 12);\n let l = [];\n if (years > 0) l.push(pluralize(Math.round(years), 'year'));\n if (months > 0) l.push(pluralize(Math.round(months), 'month'));\n if (days > 0) l.push(pluralize(Math.round(days), 'day'));\n if (hours > 0) l.push(pluralize(Math.round(hours), 'hour'));\n if (minutes > 0) l.push(pluralize(Math.round(minutes), 'minute'));\n let r = l.join(', ');\n if ((showTotalHours) && (totalHours >= 24)) {\n let h = pluralize(totalHours, 'hour');\n r = r + ` (${h})`;\n }\n return r;\n}\n\n\nexport function pluralize(num: number, word: string) {\n if (num != 1) word = word + 's';\n return `${num} ${word}`\n}\n\n\nexport function divmod(a: number, b: number) {\n return [Math.floor(a / b), a % b];\n}\n\n\nexport function setTitle(title: string) {\n document.title = `${title} | SEPLIS`\n}\n\n\nexport function secondsToHourMin(minutes: number) {\n if (!minutes)\n return\n const hours = Math.floor(minutes / 60)\n const minutesLeft = minutes % 60\n let s = ''\n if (hours > 0)\n s += `${hours}h`\n if (minutesLeft > 0)\n s += ` ${minutesLeft}m`\n return s.trim()\n}\n\n\nexport function langCodeToLang(code: string) {\n try {\n return new Intl.DisplayNames(['en'], { type: 'language' }).of(code)\n } catch (e) {\n return code\n }\n}\n\n\nexport function removeEmpty(obj: Object) {\n return Object.entries(obj)\n .filter(([_, v]) => (v != null) && (v != '') && (v != 0))\n .reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});\n}","import { detect } from 'detect-browser'\nimport mobile from 'is-mobile'\n\nexport const browser = detect()\n\nexport const isMobile = mobile()","import { AspectRatio, Center, Image, Text } from \"@chakra-ui/react\"\n\ninterface IProps {\n url: string\n title: string\n onClick?: () => void\n}\n\nexport function Poster({ url, title, onClick }: IProps) {\n return \n {title || 'No title'}\n }\n />\n}\n\n\nexport function PosterAspectRatio({ url, title, onClick }: IProps) {\n return \n \n {title || 'No title'}\n }\n objectFit=\"cover\"\n />\n \n}","\nexport const focusedBorder: React.CSSProperties = {\n borderColor: '#fff', \n borderWidth:'1px',\n}","import { DependencyList, useEffect } from 'react'\nimport { IEpisodeWatched, IEventEpisodeWatched } from './interfaces/episode'\nimport { IEventMovieWatched, IMovieWatched } from './interfaces/movie'\n\nexport const EVENT_EPISODE_WATCHED = 'EpisodeWatched'\nexport function TriggerEpisodeWatched(seriesId: number, episodeNumber: number, watched: IEpisodeWatched) {\n const e = new CustomEvent(EVENT_EPISODE_WATCHED, {\n detail: {\n seriesId: seriesId,\n episodeNumber: episodeNumber,\n watched: watched,\n }\n })\n window.dispatchEvent(e)\n}\n\n\nexport const EVENT_MOVIE_WATCHED = 'MovieWatched'\nexport function TriggerMovieWatched(movieId: number, watched: IMovieWatched) {\n const e = new CustomEvent(EVENT_MOVIE_WATCHED, {\n detail: {\n movieId: movieId,\n watched: watched,\n }\n })\n window.dispatchEvent(e)\n}\n\n\n\nexport function useEventListener(eventName: string, handler: (data: T) => void, deps?: DependencyList) {\n useEffect(() => {\n const handleEvent = (event: CustomEvent) => {\n handler(event.detail)\n }\n window.addEventListener(eventName, (handleEvent as EventListener))\n return () => {\n window.removeEventListener(eventName, (handleEvent as EventListener))\n }\n }, deps)\n}","import { Button, useToast } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IEventMovieWatched, IMovieWatchlist } from '@seplis/interfaces/movie'\nimport { isAuthed } from '@seplis/utils'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { ErrorMessageFromResponse } from '../error'\nimport { useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport { focusedBorder } from '@seplis/styles'\nimport { FaBookmark } from 'react-icons/fa'\nimport { EVENT_MOVIE_WATCHED, useEventListener } from '@seplis/events'\n\ninterface IProps {\n movieId: number\n}\n\nexport default function WatchlistButton({ movieId }: IProps) {\n const toast = useToast()\n const queryClient = useQueryClient()\n\n const toggleWatchlist = useMutation(async (onWatchlist: boolean) => {\n await queryClient.cancelQueries(['movie', 'watchlist-button', movieId])\n let data: IMovieWatchlist\n if (onWatchlist) {\n data = await api.delete(`/2/movies/${movieId}/watchlist`)\n } else {\n data = await api.put(`/2/movies/${movieId}/watchlist`)\n }\n queryClient.setQueryData(['movie', 'watchlist-button', movieId], { on_watchlist: !onWatchlist })\n }, {\n onError: (e) => {\n toast({\n title: ErrorMessageFromResponse(e),\n status: 'error',\n isClosable: true,\n position: 'top',\n })\n }\n })\n\n useEventListener(EVENT_MOVIE_WATCHED, ((data) => {\n if (data.movieId == movieId)\n queryClient.setQueryData(['movie', 'watchlist-button', movieId], { on_watchlist: false })\n }), [movieId])\n\n const { isInitialLoading, data } = useQuery(['movie', 'watchlist-button', movieId], async () => {\n const result = await api.get(`/2/movies/${movieId}/watchlist`)\n return result.data\n }, {\n enabled: isAuthed(),\n })\n const handleClick = async () => {\n toggleWatchlist.mutate(data.on_watchlist)\n }\n const { ref, focused } = useFocusable({\n onEnterPress: () => handleClick()\n })\n\n return }\n style={focused ? focusedBorder : null}\n >\n Watchlist\n \n}","import { Alert, AlertDialog, AlertDialogBody, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, Box, Button, Flex, FormControl, FormLabel, Heading, Input, Stack, useDisclosure, useToast } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IMovie } from '@seplis/interfaces/movie'\nimport { TExternals } from '@seplis/interfaces/types'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useRef, useState } from 'react'\nimport { useForm } from 'react-hook-form'\nimport { ErrorMessageFromResponse } from '../error'\nimport { IError } from '@seplis/interfaces/error'\n\n\nexport function MovieNew({ onDone }: { onDone?: (seriesId: number) => void }) {\n const onSave = async (data: IData) => {\n const result = await api.post('/2/movies', data)\n if (onDone)\n onDone(result.data.id)\n return result.data\n }\n\n return \n}\n\nexport function MovieUpdate({ movie }: { movie: IMovie }) {\n const onSave = async (data: IData) => {\n const result = await api.patch(`/2/movies/${movie.id}`, data)\n api.post(`/2/movies/${movie.id}/update`)\n return result.data\n }\n\n return \n}\n\n\ninterface IData {\n externals: TExternals\n onSave: (data: IData) => Promise\n movieId?: number\n}\n\nexport default function SettingsForm({ externals, onSave, movieId }: IData) {\n const { handleSubmit, register, formState: { isSubmitting } } = useForm({\n defaultValues: {\n externals: { ...externals }\n }\n })\n const [error, setError] = useState(null)\n const toast = useToast()\n const queryClient = useQueryClient()\n\n const onSubmit = handleSubmit(async (data) => {\n try {\n setError(null)\n const movie = await onSave(data)\n toast({\n title: 'Movie saved',\n status: 'success',\n isClosable: true,\n position: 'top',\n })\n queryClient.setQueryData(['movie', movie.id], movie)\n } catch (e) {\n setError(ErrorMessageFromResponse(e))\n }\n })\n\n return \n
\n \n {error && \n {error}\n }\n\n Externals\n \n IMDb\n \n \n\n \n TMDb\n \n \n\n \n {movieId && }\n \n \n \n
\n
\n}\n\n\nfunction DeleteConfirm({ movieId }: { movieId: number }) {\n const { isOpen, onOpen, onClose } = useDisclosure()\n const cancelRef = useRef()\n const toast = useToast()\n\n const onDelete = async () => {\n try {\n await api.delete(`/2/movies/${movieId}`)\n location.reload()\n toast({\n title: 'Movie deleted',\n status: 'success',\n duration: 5000,\n isClosable: true,\n position: 'top',\n })\n } catch (e) {\n toast({\n title: 'Failed to delete the movie',\n description: (e.response.data as IError).message,\n status: 'error',\n duration: 9000,\n isClosable: true,\n position: 'top',\n })\n }\n onClose()\n }\n\n return <>\n \n\n \n \n \n \n Delete Movie\n \n\n \n Are you sure? You can't undo this action afterwards.\n \n\n \n \n \n \n \n \n \n \n}","import api from '@seplis/api'\nimport { IPlayRequest, IPlayServerRequestSources, IPlaySource } from '@seplis/interfaces/play-server'\nimport { useQuery } from '@tanstack/react-query'\nimport axios from 'axios'\n\n\nexport function useGetPlayServers(url: string, enabled: boolean = true) {\n return useQuery(['play-server', url], async () => {\n return await getPlayServers(url)\n }, {\n enabled: enabled,\n })\n}\n\n\nexport async function getPlayServers(url: string) {\n const result = await api.get(url)\n const sourcePromises: Promise[] = []\n for (const request of result.data) \n sourcePromises.push(getPlayServerSources(request))\n const requestSources = await Promise.all(sourcePromises)\n return requestSources.filter(item => item !== null)\n} \n\n\nasync function getPlayServerSources(playRequest: IPlayRequest) {\n try {\n const result = await axios.get(playRequest.play_url + '/sources', {\n params: {\n 'play_id': playRequest.play_id,\n },\n timeout: 5000,\n\n })\n const data: IPlayServerRequestSources = {\n request: playRequest,\n sources: result.data,\n }\n return data\n } catch (e) {\n console.log(e)\n return null\n }\n}","import { Box, Flex } from '@chakra-ui/react'\nimport { IPlaySource } from '@seplis/interfaces/play-server'\n\n\ninterface IProps {\n source: IPlaySource,\n selectedWidth?: number\n onChange: (width: number) => void\n}\n\nexport function PickQuality({ source, selectedWidth, onChange }: IProps) {\n return \n {Object.entries(resolutionNames).sort((a, b) => parseInt(b[0]) - parseInt(a[0])).map(([width, value]) => {\n const w = parseInt(width)\n if (source.width >= w)\n return {\n localStorage.setItem('resolutionWidth', w.toString())\n onChange?.(w)\n }}\n >\n {value}\n \n })}\n \n}\n\n\nexport function getDefaultResolutionWidth() {\n const w = localStorage.getItem('resolutionWidth')\n // Fix for old error that would set the requested resolution to requestedResolution - 200\n if (w && parseInt(w) == 1720)\n return 1920\n if (w)\n return parseInt(w)\n return 1920\n}\n\n\nexport function getResolutionWidth(source: IPlaySource) {\n const w = getDefaultResolutionWidth()\n return (w > source.width) ? source.width : w\n}\n\n\nconst resolutionNames: { [key: string]: string } = {\n '7680': '8K',\n '3840': '4K',\n '2560': '1440p',\n '1920': '1080p',\n '1280': '720p',\n '854': '480p',\n '640': '360p',\n '256': '144p',\n}\n\n\nexport function resolutionToText(width: number) {\n if (!width) return 'Auto'\n if (width <= 256)\n return '144p'\n else if (width <= 426)\n return '240p'\n else if (width <= 640)\n return '360p'\n else if (width <= 854)\n return '480p'\n else if (width <= 1280)\n return '720p'\n else if (width <= 1920)\n return '1080p'\n else if (width <= 2560)\n return '1440p'\n else if (width <= 4096)\n return '4K'\n else if (width <= 8192)\n return '8K'\n return `W: ${width}`\n}\n\n","import { Box, Flex } from '@chakra-ui/react'\nimport { IPlayRequest, IPlayServerRequestSource, IPlayServerRequestSources, IPlaySource } from '@seplis/interfaces/play-server'\nimport { getDefaultResolutionWidth } from './pick-quality'\n\ninterface IProps {\n playServers: IPlayServerRequestSources[],\n selected: IPlayServerRequestSource,\n onChange: (requestSource: IPlayServerRequestSource) => void,\n}\n\nexport function PickSource({ playServers, selected, onChange }: IProps) {\n return \n {playServers.map(server => (\n server.sources.sort((a, b) => b.width - a.width).map(source => (\n {\n const r: IPlayServerRequestSource = {\n request: server.request,\n source: source,\n }\n localStorage.setItem('resolutionWidth', source.width.toString())\n if (onChange) onChange(r)\n }}\n >\n {renderPlaySource(source)}\n \n ))\n ))}\n \n}\n\n\nexport function renderPlaySource(source: IPlaySource) {\n let s = `${source.resolution} ${source.codec.toUpperCase()}`\n if (source.video_color_range == 'hdr')\n if (source.video_color_range_type == 'dovi')\n s += ' Dolby Vision'\n else\n s += ` HDR`\n return s\n}\n\n\nfunction isSelected(selected: IPlayServerRequestSource, request: IPlayRequest, source: IPlaySource) {\n return ((selected.request.play_id == request.play_id) &&\n (source.index == selected.source.index))\n}\n\n\nexport function pickStartSource(playServers: IPlayServerRequestSources[], defaultResolutionWidth?: number) {\n let s: IPlayServerRequestSource = {\n request: playServers[0].request,\n source: playServers[0].sources[0],\n }\n const w = defaultResolutionWidth || getDefaultResolutionWidth()\n for (const playServer of playServers.reverse())\n for (const source of playServer.sources)\n if (source.width <= w)\n s = {\n request: playServer.request,\n source: source,\n }\n return s\n}","import { createContext } from 'react';\n\nconst CastContext = createContext<{\n initialized: boolean;\n connected: boolean;\n deviceName: string;\n player: cast.framework.RemotePlayer | null;\n playerController: cast.framework.RemotePlayerController | null;\n}>({\n initialized: false,\n connected: false,\n deviceName: '',\n player: null,\n playerController: null\n});\nexport default CastContext;\n","export function loadScriptAsync(url: string): Promise {\n return new Promise((resolve, reject) => {\n let r = false,\n t = document.getElementsByTagName('script')[0],\n s = document.createElement('script');\n s.type = 'text/javascript';\n s.src = url;\n s.async = true;\n //@ts-ignore\n s.onload = s.onreadystatechange = function() {\n //@ts-ignore\n if (!r && (!this.readyState || this.readyState === 'complete')) {\n r = true;\n resolve(this);\n }\n };\n s.onerror = s.onabort = reject;\n if (t && t.parentNode) {\n t.parentNode.insertBefore(s, t);\n }\n });\n}\n\nexport const getDisplayTime = (time: number) => {\n const showHour = time >= 3600;\n const h = Math.floor(time / 3600);\n const m = Math.floor((time / 60) % 60);\n let s: any = Math.floor(time % 60);\n if (s < 10) s = `0${s}`;\n let text = `${m}:${s}`;\n if (showHour || h > 0) {\n if (m < 10) {\n text = `0${text}`;\n }\n text = `${h}:${text}`;\n }\n return text;\n};\n\nexport const getDefaultTrackStyling = () => {\n const style = new window.chrome.cast.media.TextTrackStyle();\n style.fontGenericFamily =\n window.chrome.cast.media.TextTrackFontGenericFamily.SANS_SERIF;\n return style;\n};\n","import { loadScriptAsync } from './utils';\n\nconst SENDER_SDK_URL: string =\n '//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1';\n\nclass CastLoader {\n static load(): Promise {\n return new Promise((resolve, reject) => {\n // @ts-ignore\n window['__onGCastApiAvailable'] = (isAvailable: boolean) =>\n CastLoader.onGCastApiAvailable(isAvailable, resolve);\n CastLoader.loadCastSDK()\n .then(() => {\n // Loaded\n })\n .catch(e => {\n console.warn('Cast sender lib loading failed', e);\n reject(e);\n });\n });\n }\n\n static loadCastSDK(): Promise {\n if (window['cast'] && window['cast']['framework']) {\n return Promise.resolve();\n }\n return loadScriptAsync(SENDER_SDK_URL);\n }\n\n static onGCastApiAvailable(isAvailable: boolean, resolve: Function): void {\n if (isAvailable) {\n resolve();\n } else {\n console.log(`Google cast API isn't available yet`);\n }\n }\n}\n\nexport { CastLoader };\n","/* global chrome */\n\nimport React, {\n ReactNode,\n useEffect,\n useState,\n useMemo,\n useCallback\n} from 'react';\nimport get from 'lodash/get';\nimport CastContext from './CastContext';\nimport { CastLoader } from '../utils/CastLoader';\n\ninterface CastProviderProps extends Partial {\n children?: ReactNode | ReactNode[];\n autoJoinPolicy?: chrome.cast.AutoJoinPolicy;\n}\n\nconst CastProvider = ({\n children,\n receiverApplicationId,\n autoJoinPolicy = get(\n window.chrome,\n 'cast.AutoJoinPolicy.ORIGIN_SCOPED',\n 'origin_scoped' as chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED\n ),\n language,\n resumeSavedSession\n}: CastProviderProps) => {\n const [connected, setConnected] = useState(false);\n const [deviceName, setDeviceName] = useState('');\n const [castInitialized, setCastInititalized] = useState(false);\n const [player, setPlayer] = useState(\n null\n );\n const [\n playerController,\n setPlayerController\n ] = useState(null);\n\n useEffect(() => {\n CastLoader.load().then(() => {\n setCastInititalized(true);\n });\n }, []);\n\n const resetCast = useCallback(() => {\n setConnected(false);\n setDeviceName('');\n }, []);\n\n /* onCast Initalized */\n useEffect(() => {\n const onSessionStateChange = (\n data: cast.framework.SessionStateEventData\n ) => {\n if (\n data.sessionState ===\n window.cast.framework.SessionState.SESSION_RESUMED ||\n data.sessionState === window.cast.framework.SessionState.SESSION_STARTED\n ) {\n setConnected(true);\n }\n if (\n data.sessionState === window.cast.framework.SessionState.SESSION_ENDED\n ) {\n resetCast();\n setConnected(false);\n }\n };\n\n if ((window.chrome && window.chrome.cast) && window.cast) {\n window.cast.framework.CastContext.getInstance().setOptions({\n receiverApplicationId,\n resumeSavedSession,\n autoJoinPolicy,\n language\n });\n const player = new window.cast.framework.RemotePlayer();\n setPlayer(player);\n setPlayerController(\n new window.cast.framework.RemotePlayerController(player)\n );\n\n window.cast.framework.CastContext.getInstance().addEventListener(\n window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED,\n onSessionStateChange\n );\n }\n }, [\n autoJoinPolicy,\n castInitialized,\n language,\n receiverApplicationId,\n resetCast,\n resumeSavedSession\n ]);\n\n useEffect(() => {\n const onConnectedChange = (\n _data: cast.framework.RemotePlayerChangedEvent\n ) => {\n if(_data.value){\n\n setConnected(true);\n const session = window.cast.framework.CastContext.getInstance().getCurrentSession();\n if (session) {\n setDeviceName(session.getSessionObj().receiver.friendlyName);\n }\n } else {\n setConnected(false);\n }\n };\n if (playerController) {\n playerController.addEventListener(\n window.cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,\n onConnectedChange\n );\n }\n return () => {\n if (playerController) {\n playerController.removeEventListener(\n window.cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,\n onConnectedChange\n );\n }\n };\n }, [playerController]);\n\n const value = useMemo(() => {\n const value = {\n connected,\n initialized: castInitialized,\n deviceName,\n player,\n playerController\n };\n return value;\n }, [castInitialized, connected, deviceName, player, playerController]);\n\n return {children};\n};\n\nexport default CastProvider;\n","/* eslint-disable @typescript-eslint/no-namespace */\nimport * as React from 'react';\n\ndeclare global {\n namespace JSX {\n interface IntrinsicElements {\n 'google-cast-launcher': any;\n }\n }\n}\n\nconst CastButton = ({ ...props }) => {\n return ;\n};\n\nCastButton.propTypes = {};\n\nexport default CastButton;\n","import { useContext } from 'react';\nimport CastContext from '../../context/CastContext';\n\nconst useCast = () => {\n const context = useContext(CastContext);\n return { ...context };\n};\n\nexport default useCast;\n","import { useMemo, useCallback, useState, useEffect } from 'react';\nimport get from 'lodash/get';\nimport { getDefaultTrackStyling } from '../../utils/utils';\nimport useCast from '../useCast/useCast';\n\nconst useCastPlayer = () => {\n const { connected, player, playerController } = useCast();\n const [tracks, setTracks] = useState([]);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [isMediaLoaded, setIsMediaLoaded] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const [isMuted, setIsMuted] = useState(false);\n const [title, setTitle] = useState('No title');\n\n function resetValues() {\n setTracks([]);\n setCurrentTime(0);\n setDuration(0);\n setIsMediaLoaded(false);\n setIsPaused(false);\n setIsMuted(false);\n setTitle('No title');\n }\n\n useEffect(() => {\n if (!connected) {\n resetValues();\n }\n }, [connected]);\n\n /*\n * CurrentTime Event Listener\n */\n useEffect(() => {\n function onCurrentTimeChange(\n data: cast.framework.RemotePlayerChangedEvent\n ) {\n setCurrentTime(data.value);\n }\n\n if (playerController) {\n playerController.addEventListener(\n window.cast.framework.RemotePlayerEventType.CURRENT_TIME_CHANGED,\n onCurrentTimeChange\n );\n }\n return () => {\n if (playerController) {\n playerController.removeEventListener(\n window.cast.framework.RemotePlayerEventType.CURRENT_TIME_CHANGED,\n onCurrentTimeChange\n );\n }\n };\n }, [playerController, setCurrentTime]);\n\n /*\n * Duration Event Listener\n */\n useEffect(() => {\n function onDurationChange(data: cast.framework.RemotePlayerChangedEvent) {\n setDuration(data.value);\n }\n if (playerController) {\n playerController.addEventListener(\n window.cast.framework.RemotePlayerEventType.DURATION_CHANGED,\n onDurationChange\n );\n }\n return () => {\n if (playerController) {\n playerController.removeEventListener(\n window.cast.framework.RemotePlayerEventType.DURATION_CHANGED,\n onDurationChange\n );\n }\n };\n }, [playerController, setDuration]);\n\n /*\n * IsMediaLoaded Event Listener\n */\n useEffect(() => {\n function onMediaLoadedChange(\n data: cast.framework.RemotePlayerChangedEvent\n ) {\n setIsMediaLoaded(data.value);\n }\n if (playerController) {\n playerController.addEventListener(\n window.cast.framework.RemotePlayerEventType.IS_MEDIA_LOADED_CHANGED,\n onMediaLoadedChange\n );\n }\n return () => {\n if (playerController) {\n playerController.removeEventListener(\n window.cast.framework.RemotePlayerEventType.IS_MEDIA_LOADED_CHANGED,\n onMediaLoadedChange\n );\n }\n };\n }, [playerController, setIsMediaLoaded]);\n\n /*\n * isPaused Event Listener\n */\n useEffect(() => {\n function onIsPausedChange(data: cast.framework.RemotePlayerChangedEvent) {\n setIsPaused(data.value);\n }\n if (playerController) {\n playerController.addEventListener(\n window.cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,\n onIsPausedChange\n );\n }\n return () => {\n if (playerController) {\n playerController.removeEventListener(\n window.cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,\n onIsPausedChange\n );\n }\n };\n }, [playerController, setIsPaused]);\n /*\n * isMuted Event Listener\n */\n useEffect(() => {\n function onIsMutedChange(data: cast.framework.RemotePlayerChangedEvent) {\n setIsMuted(data.value);\n }\n if (playerController) {\n playerController.addEventListener(\n window.cast.framework.RemotePlayerEventType.IS_MUTED_CHANGED,\n onIsMutedChange\n );\n }\n return () => {\n if (playerController) {\n playerController.removeEventListener(\n window.cast.framework.RemotePlayerEventType.IS_MUTED_CHANGED,\n onIsMutedChange\n );\n }\n };\n }, [playerController, setIsMuted]);\n\n useEffect(() => {\n function onMediaInfoChanged(data: cast.framework.RemotePlayerChangedEvent) {\n // We make the check what we update so we dont update on every player changed event since it happens often\n const newTitle = get(data, 'value.metadata.title', 'No title');\n const newTracks = get(data, 'value.tracks', []);\n if (tracks.length !== newTracks.length) {\n setTracks(newTracks);\n }\n if (title !== newTitle) {\n setTitle(newTitle);\n }\n }\n\n if (playerController) {\n playerController.addEventListener(\n window.cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED,\n onMediaInfoChanged\n );\n }\n return () => {\n if (playerController) {\n playerController.removeEventListener(\n window.cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED,\n onMediaInfoChanged\n );\n }\n };\n }, [\n playerController,\n setTitle,\n title,\n setTracks,\n tracks,\n ]);\n\n const loadMedia = useCallback((request: chrome.cast.media.LoadRequest) => {\n const castSession = window.cast.framework.CastContext.getInstance().getCurrentSession();\n if (castSession) {\n return castSession.loadMedia(request);\n } else {\n return Promise.reject('No CastSession has been created');\n }\n }, []);\n\n const togglePlay = useCallback(() => {\n if (playerController) {\n playerController.playOrPause();\n }\n }, [playerController]);\n\n const toggleMute = useCallback(() => {\n if (playerController) {\n playerController.muteOrUnmute();\n }\n }, [playerController]);\n\n const seek = useCallback(\n (time: number) => {\n if (player && playerController) {\n player.currentTime = time;\n playerController.seek();\n setCurrentTime(time);\n }\n },\n [player, playerController]\n );\n\n const setVolume = useCallback(\n (volume: number) => {\n if (player && playerController) {\n player.volumeLevel = volume;\n playerController.setVolumeLevel();\n }\n },\n [player, playerController]\n );\n\n const editTracks = useCallback(\n (\n activeTrackIds: number[],\n textTrackStyle?: chrome.cast.media.TextTrackStyle\n ) => {\n const castSession = window.cast.framework.CastContext.getInstance().getCurrentSession();\n if (castSession) {\n const trackStyle = textTrackStyle || getDefaultTrackStyling();\n const tracksInfoRequest = new window.chrome.cast.media.EditTracksInfoRequest(\n activeTrackIds,\n trackStyle\n );\n const media = castSession.getMediaSession();\n if (media) {\n return new Promise((resolve, reject) => {\n media.editTracksInfo(tracksInfoRequest, resolve, reject);\n });\n } else {\n return Promise.reject('No active media');\n }\n }\n return Promise.reject('No active cast session');\n },\n []\n );\n\n const sendMessage = useCallback(\n (\n namespace: string,\n data: any\n ) => { \n const castSession = window.cast.framework.CastContext.getInstance().getCurrentSession();\n if (castSession) \n return castSession.sendMessage(namespace, data)\n else\n return Promise.reject('No CastSession has been created');\n },\n []\n );\n\n const value = useMemo(\n () => ({\n loadMedia,\n tracks,\n editTracks,\n currentTime,\n duration,\n toggleMute,\n setVolume,\n togglePlay,\n seek,\n isMediaLoaded,\n isPaused,\n isMuted,\n title,\n playerController,\n sendMessage,\n }),\n [\n loadMedia,\n tracks,\n editTracks,\n currentTime,\n duration,\n toggleMute,\n setVolume,\n togglePlay,\n seek,\n isMediaLoaded,\n isPaused,\n isMuted,\n title,\n playerController,\n sendMessage,\n ]\n );\n return value;\n};\nexport default useCastPlayer;\n","import { Box, Flex } from '@chakra-ui/react'\nimport { IPlaySourceStream } from '@seplis/interfaces/play-server'\nimport { langCodeToLang } from '@seplis/utils'\n\n\ninterface IProps {\n subtitleSources: IPlaySourceStream[],\n selected?: IPlaySourceStream,\n onChange: (subtitleSource: IPlaySourceStream) => void\n}\n\n\nexport function PickSubtitleSource({ subtitleSources, selected, onChange }: IProps) {\n return \n onChange && onChange(null)}\n >\n Off\n \n {subtitleSources.map(subtitle => (\n onChange && onChange(subtitle)}\n >\n {subtitleSourceToName(subtitle)}\n \n ))}\n \n}\n\n\nexport function subtitleSourceToName(source: IPlaySourceStream) {\n if (!source) return 'Off'\n \n if (!source.language && !source.title)\n return 'Unknown language'\n else if (source.language && \n (source.title === source.language) || (source.title === langCodeToLang(source.language)) || !source.title)\n return `${langCodeToLang(source.language)}`\n else if (!source.language)\n return source.title\n else\n return `${langCodeToLang(source.language)} (${source.title})`\n}\n\n\nexport function pickStartSubtitle(sourceStreams: IPlaySourceStream[], defaultSubtitle?: string) {\n if (defaultSubtitle == 'off')\n return\n const s = stringToSourceStream(defaultSubtitle, sourceStreams)\n if (s) return s\n for (const sub of sourceStreams) {\n if (sub.default || sub.forced)\n return sub\n }\n}\n\n\nexport function stringToSourceStream(s: string, streams: IPlaySourceStream[]) {\n if (!s) return null\n const [lang, index] = s.toLowerCase().split(':')\n if (index !== undefined) {\n for (const stream of streams) {\n const l = stream?.language ?? stream?.title\n if (stream.index === parseInt(index) && (l) && (l.toLowerCase() === lang)) {\n return stream\n }\n }\n }\n for (const stream of streams) {\n const l = stream?.language ?? stream?.title\n if (l.toLowerCase() === lang) {\n return stream\n }\n }\n return null\n}","import { Box, Flex } from '@chakra-ui/react'\nimport { IPlaySourceStream } from '@seplis/interfaces/play-server'\nimport { langCodeToLang } from '@seplis/utils'\nimport { stringToSourceStream } from './pick-subtitle-source'\n\n\ninterface IProps {\n audioSources: IPlaySourceStream[],\n selected?: IPlaySourceStream,\n onChange: (audioSource: IPlaySourceStream) => void\n}\n\nexport function PickAudioSource({ audioSources, selected, onChange }: IProps) {\n return \n {audioSources.map(audio => (\n onChange && onChange(audio)}\n >\n {audioSourceToName(audio)}\n \n ))}\n \n}\n\n\nexport function audioSourceToName(source: IPlaySourceStream) {\n if (!source) \n return 'Unknown audio'\n else if (source.language && \n (source.title === source.language) || (source.title === langCodeToLang(source.language) || !source.title))\n return `${langCodeToLang(source.language)}`\n else if (!source.language)\n return source.title\n else\n return `${langCodeToLang(source.language)} ${source.title}`\n}\n\n\nexport function pickStartAudio(sourceStreams: IPlaySourceStream[], defaultAudio?: string) {\n const s = stringToSourceStream(defaultAudio, sourceStreams)\n if (s) return s\n for (const sub of sourceStreams) {\n if (sub.default || sub.forced)\n return sub\n }\n if (sourceStreams.length > 0)\n return sourceStreams[0]\n}\n","import { IconButton, Menu, MenuButton, MenuGroup, MenuItem, MenuList } from '@chakra-ui/react'\nimport { useGetPlayServers } from './player/request-play-servers'\nimport { ChevronDownIcon } from '@chakra-ui/icons'\nimport { renderPlaySource } from './player/pick-source'\nimport prettyBytes from 'pretty-bytes'\n\ninterface IProps {\n playServersUrl: string,\n}\n\nexport function PlayButtonMenu({ playServersUrl }: IProps) {\n\n return \n {({ isOpen }) => (\n <>\n } variant=\"outline\" />\n \n \n \n \n )}\n \n}\n\nfunction PlayButtonMenuItems({ playServersUrl, isOpen }: { playServersUrl: string, isOpen: boolean }) { \n const playServers = useGetPlayServers(playServersUrl, isOpen)\n\n if (playServers.isLoading || playServers.isFetching)\n return Loading...\n\n if (!playServers.data || (playServers.data.length === 0))\n return Error loading play servers\n\n return \n {playServers.data.map(playServer => (playServer.sources.map(source => (\n \n Download ({renderPlaySource(source)} - {prettyBytes(source.size)})\n \n ))))}\n \n}","import { Button, ButtonGroup } from '@chakra-ui/react'\nimport { FaPlay } from 'react-icons/fa'\nimport { PlayButtonMenu } from './play-button-menu'\n\ninterface IProps {\n playServersUrl: string,\n isLoading?: boolean,\n onPlayClick: () => void,\n}\n\nexport function PlayButton({ onPlayClick, playServersUrl, isLoading }: IProps) {\n return \n }\n onClick={onPlayClick}\n isLoading={isLoading}\n >\n Play\n \n \n \n}","import api from '@seplis/api'\nimport { v4 as uuidv4 } from 'uuid'\nimport { IMovie } from '@seplis/interfaces/movie'\nimport { IPlayRequest, IPlayServerRequestMedia, IPlayServerRequestSource } from '@seplis/interfaces/play-server'\nimport { IToken } from '@seplis/interfaces/token'\nimport { useNavigate } from 'react-router-dom'\nimport { getPlayServers } from '../player/request-play-servers'\nimport { pickStartSource } from '../player/pick-source'\nimport { useCast, useCastPlayer } from '../player/react-cast-sender'\nimport { pickStartSubtitle } from '../player/pick-subtitle-source'\nimport { pickStartAudio } from '../player/pick-audio-source'\nimport { getDefaultTrackStyling } from '../player/react-cast-sender/utils/utils'\nimport { PlayButton } from '../play-button'\nimport { isAuthed } from '@seplis/utils'\nimport { useQuery } from '@tanstack/react-query'\nimport axios from 'axios'\n\n\nexport default function MoviePlayButton({ movieId }: { movieId: number }) {\n const { isInitialLoading, data } = useQuery(['movie', 'play-button', movieId], async () => {\n const result = await api.get(`/2/movies/${movieId}/play-servers`)\n return result.data.length > 0\n }, {\n enabled: isAuthed()\n })\n const navigate = useNavigate()\n const { connected } = useCast()\n const { loadMedia } = useCastPlayer()\n\n return data && {\n if (connected) {\n const r = await castMovieRequest(movieId)\n await loadMedia(r)\n } else\n navigate(`/movies/${movieId}/play`)\n }}\n />\n}\n\n\nexport function castMovieRequest(\n movieId: number,\n startTime?: number,\n requestSource?: IPlayServerRequestSource,\n audioLang?: string,\n subtitleLang?: string,\n subtitleOffset?: number,\n resolutionWidth?: number) {\n return new Promise((resolve, reject) => {\n Promise.all([\n getPlayServers(`/2/movies/${movieId}/play-servers`),\n api.post('/2/progress-token'),\n api.get(`/2/movies/${movieId}?expand=user_watched`),\n ]).then(async (result) => {\n const session = uuidv4()\n if (!startTime) {\n if (result[2].data)\n startTime = result[2].data.user_watched?.position\n }\n\n if (!startTime)\n startTime = 0\n\n if (!requestSource)\n requestSource = pickStartSource(result[0])\n\n if (!audioLang) {\n const audio = pickStartAudio(requestSource.source.subtitles)\n if (audio)\n audioLang = `${audio.language}:${audio.index}`\n }\n\n if (!subtitleLang) {\n const sub = pickStartSubtitle(requestSource.source.subtitles)\n if (sub)\n subtitleLang = `${sub.language}:${sub.index}`\n }\n\n\n const r = await axios.get(`${requestSource.request.play_url}/request-media` +\n `?play_id=${requestSource.request.play_id}` +\n `&source_index=${requestSource.source.index}` +\n `&session=${session}` +\n `&start_time=${startTime}` +\n `&supported_video_codecs=h264` +\n `&transcode_video_codec=h264` +\n `&supported_audio_codecs=aac` +\n `&transcode_audio_codec=aac` +\n `&max_audio_channels=2` +\n `&format=hls` +\n `&audio_lang=${audioLang || ''}` +\n `&max_width=${resolutionWidth || ''}` +\n `&supported_video_containers=mp4`\n )\n const requestMedia = r.data\n requestMedia.hls_url = requestSource.request.play_url + r.data.hls_url\n requestMedia.direct_play_url = requestSource.request.play_url + r.data.direct_play_url\n\n const mediaInfo = new chrome.cast.media.MediaInfo(requestMedia.hls_url, 'application/x-mpegURL')\n // @ts-ignore\n mediaInfo.hlsVideoSegmentFormat = chrome.cast.media.HlsSegmentFormat.FMP4\n mediaInfo.streamType = chrome.cast.media.StreamType.OTHER\n\n mediaInfo.metadata = new chrome.cast.media.MovieMediaMetadata()\n mediaInfo.metadata.title = result[2].data.title\n mediaInfo.metadata.releaseDate = result[2].data.release_date\n mediaInfo.metadata.images = [\n { url: result[2].data.poster_image != null ? result[2].data.poster_image.url + '@SX180.jpg' : '' },\n ]\n mediaInfo.textTrackStyle = getDefaultTrackStyling()\n\n const customData = {\n session: session,\n selectedRequestSource: requestSource,\n requestSources: result[0],\n requestMedia: requestMedia,\n token: result[1].data['access_token'],\n type: 'movie',\n movie: {\n id: result[2].data['id'],\n title: result[2].data['title'],\n },\n startTime: startTime,\n audioLang: audioLang || '',\n subtitleLang: subtitleLang || '',\n subtitleOffset: subtitleOffset || 0,\n apiUrl: (window as any).seplisAPI,\n resolutionWidth: resolutionWidth,\n }\n\n if (subtitleLang) {\n const track = new chrome.cast.media.Track(1, chrome.cast.media.TrackType.TEXT)\n track.language = subtitleLang\n track.name = subtitleLang\n track.subtype = chrome.cast.media.TextTrackType.CAPTIONS\n track.trackContentType = 'text/vtt'\n track.trackContentId = `${customData.selectedRequestSource.request.play_url}/subtitle-file` +\n `?play_id=${customData.selectedRequestSource.request.play_id}` +\n `&source_index=${customData.selectedRequestSource.source.index}` +\n `&lang=${subtitleLang}`\n if (subtitleOffset)\n track.trackContentId = track.trackContentId + `&offset=${subtitleOffset}`\n mediaInfo.tracks = [track]\n }\n const request = new chrome.cast.media.LoadRequest(mediaInfo)\n if (subtitleLang)\n request.activeTrackIds = [1]\n request.customData = customData\n request.currentTime = startTime\n resolve(request)\n }).catch(e => {\n reject(e)\n })\n })\n}","import { AddIcon, MinusIcon } from \"@chakra-ui/icons\"\nimport { Box, Button, ButtonGroup, IconButton, Popover, PopoverContent, PopoverTrigger, Stack, useDisclosure } from \"@chakra-ui/react\"\nimport { forwardRef } from \"react\"\n\ninterface IProps {\n times?: number\n position?: number\n isUpdating?: boolean\n onIncrement?: () => void\n onDecrement?: () => void\n}\n\nexport function WatchedButton({ onIncrement, onDecrement, times = 0, position = 0, isUpdating = false }: IProps) {\n const { onOpen, onClose, isOpen } = useDisclosure()\n\n return \n \n \n \n \n \n \n }\n onClick={() => {\n onClose()\n onDecrement()\n }}\n isLoading={isUpdating}\n />\n }\n onClick={() => {\n onIncrement()\n onClose()\n }}\n isLoading={isUpdating}\n />\n \n \n \n \n}\n\ninterface IButton {\n times: number\n position: number\n onClick?: () => void\n isUpdating: boolean\n}\n\nconst BaseButton = forwardRef((props, ref) => {\n\n return \n 0 ? \"green\" : null}\n style={props.position > 0 ? props.times > 0 ? {\n background: \"linear-gradient(90deg, #428bca 56%, var(--chakra-colors-green-200) 44%)\",\n color: '#000' \n } : {\n background: \"linear-gradient(90deg, #428bca 56%, var(--chakra-colors-whiteAlpha-200) 44%)\",\n color: '#fff' \n } : null}\n onClick={props.onClick}\n isLoading={props.isUpdating}\n >\n Watched\n \n \n \n})","import { useToast } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { EVENT_MOVIE_WATCHED, TriggerMovieWatched, useEventListener } from '@seplis/events'\nimport { useEffect, useState } from 'react'\nimport { ErrorMessageFromResponse } from '../error'\nimport { IEventMovieWatched, IMovieWatched, IMovieWatchedDefault } from '@seplis/interfaces/movie'\nimport { WatchedButton } from '../watched-button'\nimport { useQuery } from '@tanstack/react-query'\nimport { isAuthed } from '@seplis/utils'\n\n\nexport function MovieWatchedButtonData({ movieId, data }: { movieId: number, data: IMovieWatched }) {\n if (!data) data = IMovieWatchedDefault(0)\n const toast = useToast()\n const [watched, setWatched] = useState(data)\n const [isUpdating, setUpdating] = useState(false)\n \n useEventListener(EVENT_MOVIE_WATCHED, ((data) => {\n if (data.movieId == movieId)\n setWatched({ ...data.watched })\n }), [movieId])\n\n useEffect(() => {\n if (data != watched)\n setWatched({ ...data })\n }, [data])\n\n const increment = async () => {\n try {\n setUpdating(true)\n const r = await api.post(`/2/movies/${movieId}/watched`)\n TriggerMovieWatched(movieId, r.data)\n } catch (e) {\n toast({\n title: ErrorMessageFromResponse(e),\n status: 'error',\n isClosable: true,\n position: 'top',\n })\n } finally {\n setUpdating(false)\n }\n }\n\n const decrement = async () => {\n try {\n setUpdating(true)\n const r = await api.delete(`/2/movies/${movieId}/watched`)\n TriggerMovieWatched(movieId, r.data)\n } catch (e) {\n toast({\n title: ErrorMessageFromResponse(e),\n status: 'error',\n isClosable: true,\n position: 'top',\n })\n } finally {\n setUpdating(false)\n }\n }\n\n return \n}\n\nexport function MovieWatchedButton({ movieId }: { movieId: number }) {\n const { isInitialLoading, data } = useQuery(['movie', movieId, 'watched'], async () => {\n const result = await api.get(`/2/movies/${movieId}/watched`)\n return result.data\n }, {\n enabled: isAuthed(),\n })\n return <>{isInitialLoading ?\n : }\n \n}","import { IGenre } from \"./genre\"\nimport { IImage } from \"./image\"\nimport { IMovieCollection } from \"./movie-collection\"\nimport { TExternals } from \"./types\"\n\nexport interface IMovie {\n id: number\n poster_image: IImage | null\n title: string | null\n original_title: string | null\n alternative_titles: string[]\n status: number | null\n plot: string | null\n tagline: string | null\n externals: TExternals\n language: string | null\n runtime: number | null\n release_date: string | null\n budget: number | null\n revenue: number | null\n popularity: number | null\n rating: number | null\n rating_votes: number | null\n collection: IMovieCollection | null\n genres: IGenre[]\n user_watched: IMovieWatched\n}\n\n\nexport interface IMovieWatched {\n times: number\n position: number\n watched_at: string\n}\nexport function IMovieWatchedDefault(EpisodeNumber: number): IMovieWatched {\n return {\n times: 0,\n position: 0,\n watched_at: null,\n }\n}\n\n\nexport interface IMovieWatchlist {\n on_watchlist: boolean\n created_at: string\n}\n\nexport interface IMovieFavorite {\n favorite: boolean\n created_at: string\n}\n\n\nexport interface IEventMovieWatched {\n movieId: number\n watched: IMovieWatched\n}","import { Skeleton, Stack } from \"@chakra-ui/react\";\n\nexport function MovieSkeleton() {\n return \n
\n
\n \n
\n
\n \n \n \n \n
\n}","import api from '@seplis/api'\nimport { IPlayServerRequestMedia, IPlayServerRequestSource } from '@seplis/interfaces/play-server'\nimport { useNavigate } from 'react-router-dom'\nimport { useCast, useCastPlayer } from '../player/react-cast-sender'\nimport { getPlayServers } from '../player/request-play-servers'\nimport { v4 as uuidv4 } from 'uuid'\nimport { IToken } from '@seplis/interfaces/token'\nimport { ISeries, ISeriesUserSettings } from '@seplis/interfaces/series'\nimport { IEpisode } from '@seplis/interfaces/episode'\nimport { pickStartSource } from '../player/pick-source'\nimport { pickStartAudio } from '../player/pick-audio-source'\nimport { pickStartSubtitle } from '../player/pick-subtitle-source'\nimport { getDefaultTrackStyling } from '../player/react-cast-sender/utils/utils'\nimport { PlayButton } from '../play-button'\nimport axios from 'axios'\n\nexport function EpisodePlayButton({ seriesId, episodeNumber, canPlay }: { seriesId: number, episodeNumber: number, canPlay: boolean }) {\n const navigate = useNavigate()\n const { connected } = useCast()\n const { loadMedia } = useCastPlayer()\n\n if (!canPlay)\n return null\n\n return {\n if (connected) {\n const r = await castEpisodeRequest(seriesId, episodeNumber)\n await loadMedia(r)\n } else\n navigate(`/series/${seriesId}/episodes/${episodeNumber}/play`)\n }}\n />\n}\n\n\nexport function castEpisodeRequest(\n seriesId: number, \n episodeNumber: number, \n startTime?: number, \n requestSource?: IPlayServerRequestSource, \n audioLang?: string, \n subtitleLang?: string, \n subtitleOffset?: number,\n resolutionWidth?: number) {\n return new Promise((resolve, reject) => {\n Promise.all([\n getPlayServers(`/2/series/${seriesId}/episodes/${episodeNumber}/play-servers`),\n api.post('/2/progress-token'),\n api.get(`/2/series/${seriesId}`),\n api.get(`/2/series/${seriesId}/episodes/${episodeNumber}?expand=user_watched`),\n api.get(`/2/series/${seriesId}/user-settings`),\n ]).then(async (result) => {\n const session = uuidv4()\n\n if (!startTime)\n startTime = result[3].data.user_watched?.position\n\n if (!startTime)\n startTime = 0\n\n if (!requestSource)\n requestSource = pickStartSource(result[0])\n\n if (!audioLang) {\n const audio = pickStartAudio(requestSource.source.audio, result[4].data?.audio_lang)\n if (audio)\n audioLang = `${audio.language}:${audio.index}`\n }\n\n if (!subtitleLang) {\n const sub = pickStartSubtitle(requestSource.source.subtitles, result[4].data?.subtitle_lang)\n if (sub)\n subtitleLang = `${sub.language}:${sub.index}`\n }\n\n const r = await axios.get(`${requestSource.request.play_url}/request-media` +\n `?play_id=${requestSource.request.play_id}` +\n `&source_index=${requestSource.source.index}` +\n `&session=${session}` +\n `&start_time=${startTime}` +\n `&supported_video_codecs=h264` +\n `&transcode_video_codec=h264` +\n `&supported_audio_codecs=aac` +\n `&transcode_audio_codec=aac` +\n `&max_audio_channels=2` +\n `&format=hls` +\n `&audio_lang=${audioLang || ''}` +\n `&max_width=${resolutionWidth || ''}` +\n `&supported_video_containers=mp4`\n )\n const requestMedia = r.data\n requestMedia.hls_url = requestSource.request.play_url + r.data.hls_url\n requestMedia.direct_play_url = requestSource.request.play_url + r.data.direct_play_url\n\n const mediaInfo = new chrome.cast.media.MediaInfo(requestMedia.hls_url, 'application/x-mpegURL')\n // @ts-ignore\n mediaInfo.hlsVideoSegmentFormat = chrome.cast.media.HlsSegmentFormat.FMP4\n mediaInfo.streamType = chrome.cast.media.StreamType.OTHER\n mediaInfo.metadata = new chrome.cast.media.TvShowMediaMetadata()\n mediaInfo.metadata.seriesTitle = result[2].data.title\n mediaInfo.metadata.title = result[3].data.title\n mediaInfo.metadata.episode = result[3].data.episode || result[3].data.number\n mediaInfo.metadata.season = result[3].data.season\n mediaInfo.metadata.originalAirdate = result[3].data.air_date\n mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.TV_SHOW\n mediaInfo.metadata.images = [\n { url: result[2].data.poster_image != null ? result[2].data.poster_image.url + '@SX180.jpg' : '' },\n ]\n mediaInfo.textTrackStyle = getDefaultTrackStyling()\n\n const customData = {\n session: session,\n selectedRequestSource: requestSource,\n requestSources: result[0],\n requestMedia: requestMedia,\n token: result[1].data['access_token'],\n type: 'episode',\n series: {\n id: result[2].data['id'],\n title: result[2].data['title'],\n episode_type: result[2].data['episode_type'],\n },\n episode: {\n number: result[3].data['number'],\n title: result[3].data['title'],\n season: result[3].data['season'],\n episode: result[3].data['episode'],\n },\n startTime: startTime,\n audioLang: audioLang,\n subtitleLang: subtitleLang || '',\n subtitleOffset: subtitleOffset || 0,\n apiUrl: (window as any).seplisAPI,\n resolutionWidth: resolutionWidth,\n }\n\n if (subtitleLang) {\n const track = new chrome.cast.media.Track(1, chrome.cast.media.TrackType.TEXT)\n track.language = subtitleLang\n track.name = subtitleLang\n track.subtype = chrome.cast.media.TextTrackType.CAPTIONS\n track.trackContentType = 'text/vtt'\n track.trackContentId = `${customData.selectedRequestSource.request.play_url}/subtitle-file` +\n `?play_id=${customData.selectedRequestSource.request.play_id}` +\n `&source_index=${customData.selectedRequestSource.source.index}` +\n `&lang=${subtitleLang}`\n if (subtitleOffset)\n track.trackContentId = track.trackContentId + `&offset=${subtitleOffset}`\n mediaInfo.tracks = [track]\n }\n const request = new chrome.cast.media.LoadRequest(mediaInfo)\n if (subtitleLang)\n request.activeTrackIds = [1]\n request.customData = customData\n request.currentTime = startTime\n resolve(request)\n }).catch(e => {\n reject(e)\n })\n })\n}","import { Avatar, Box, Button, Flex, Heading, Text } from '@chakra-ui/react'\nimport { useNavigate } from 'react-router-dom'\n\nexport default function FullErrorPage({ message }: { message: string }) {\n const navigate = useNavigate()\n return \n \n \n \n \n \n \n \n Sorry!\n \n \n {message}\n \n \n Please try again later.\n \n \n \n \n \n \n \n}","import { Box, Button, Flex, Select, Slider, SliderMark, SliderThumb, SliderTrack, Text } from '@chakra-ui/react'\nimport { useEffect, useState } from 'react'\n\nexport function PickSubtitleOffset({ selected = 0, onChange }: { selected: number, onChange: (offset: number) => void }) {\n const [value, setValue] = useState(selected * -1)\n\n useEffect(() => {\n if (value !== selected)\n setValue(selected * -1)\n }, [selected])\n\n const labelStyles = {\n mt: '20px',\n ml: '-1',\n }\n\n const labelStylesMinus = {\n mt: '20px',\n ml: '-2',\n }\n\n return \n onChange(v * -1)}>\n \n -10\n \n \n -4\n \n \n -2\n \n \n 0\n \n \n 2\n \n \n 4\n \n \n 10\n \n \n {value} seconds\n \n \n \n \n\n \n \n \n \n}\n\nexport function SubtitleOffsetToText(offset: number) {\n const v = (offset * -1) || 0\n return `${v} ${Math.abs(v) == 1 ? 'sec' : 'secs'}`\n}","import {\n Box,\n IconButton,\n Menu,\n MenuButton,\n MenuItem,\n MenuList,\n Modal,\n ModalBody,\n ModalCloseButton,\n ModalContent,\n ModalHeader,\n Popover,\n PopoverAnchor,\n PopoverBody,\n PopoverCloseButton,\n PopoverContent,\n PopoverHeader,\n} from '@chakra-ui/react'\nimport {\n IPlayServerRequestSource,\n IPlayServerRequestSources,\n IPlaySourceStream,\n} from '@seplis/interfaces/play-server'\nimport { useState } from 'react'\nimport { FaCog } from 'react-icons/fa'\nimport { audioSourceToName, PickAudioSource } from './pick-audio-source'\nimport { PickQuality, resolutionToText } from './pick-quality'\nimport { PickSource, renderPlaySource } from './pick-source'\nimport {\n PickSubtitleOffset,\n SubtitleOffsetToText,\n} from './pick-subtitle-offset'\nimport {\n PickSubtitleSource,\n subtitleSourceToName,\n} from './pick-subtitle-source'\n\nexport interface ISettingsProps {\n playServers: IPlayServerRequestSources[]\n requestSource: IPlayServerRequestSource\n resolutionWidth?: number\n audioSource?: IPlaySourceStream\n subtitleSource?: IPlaySourceStream\n subtitleOffset?: number\n forceTranscode?: boolean\n onRequestSourceChange?: (requestSource: IPlayServerRequestSource) => void\n onResolutionWidthChange?: (width: number) => void\n onAudioSourceChange?: (audioSource: IPlaySourceStream) => void\n onSubtitleSourceChange?: (subtitleSource: IPlaySourceStream) => void\n onSubtitleOffsetChange?: (offset: number) => void\n onForceTranscodeChange?: (forceTranscode: boolean) => void\n containerRef?: React.RefObject\n}\n\nexport function SettingsMenu({\n playServers,\n requestSource,\n resolutionWidth,\n audioSource,\n subtitleSource,\n subtitleOffset,\n forceTranscode,\n onRequestSourceChange,\n onResolutionWidthChange,\n onAudioSourceChange,\n onSubtitleSourceChange,\n onSubtitleOffsetChange,\n onForceTranscodeChange,\n containerRef,\n}: ISettingsProps) {\n const [nested, setNested] = useState(null)\n const [showModal, setShowModal] = useState(null)\n return (\n <>\n setNested(null)}>\n \n \n }\n size=\"lg\"\n fontSize=\"28px\"\n />\n \n \n 1 ||\n playServers[0]?.sources?.length > 1\n )\n }\n command={renderPlaySource(requestSource.source)}\n onClick={() => setNested('sources')}\n >\n Source\n \n setNested('quality')}\n >\n Quality\n \n setNested('audio')}\n isDisabled={\n !(requestSource.source?.audio?.length > 1)\n }\n >\n Audio\n \n setNested('subtitles')}\n >\n Subtitle\n \n setShowModal('subtitle_offset')}\n >\n Subtitle offset\n \n \n onForceTranscodeChange?.(!forceTranscode)\n }\n >\n Force transcode\n \n \n \n\n \n \n\n {nested == 'sources' && (\n <>\n Sources\n \n {\n onRequestSourceChange(s)\n setNested(null)\n }}\n />\n \n \n )}\n\n {nested == 'quality' && (\n <>\n Quality\n \n {\n onResolutionWidthChange(width)\n setNested(null)\n }}\n />\n \n \n )}\n\n {nested == 'audio' && (\n <>\n Audio\n \n \n {\n onAudioSourceChange(s)\n setNested(null)\n }}\n />\n \n \n \n )}\n\n {nested == 'subtitles' && (\n <>\n Subtitles\n \n \n {\n onSubtitleSourceChange(s)\n setNested(null)\n }}\n />\n \n \n \n )}\n \n \n\n {showModal == 'subtitle_offset' && (\n setShowModal(null)}\n portalProps={{ containerRef: containerRef }}\n >\n \n Subtitle offset\n \n \n {\n if (v !== null) onSubtitleOffsetChange(v)\n else setShowModal(null)\n }}\n />\n \n \n \n )}\n \n )\n}\n","import { Box, Flex } from '@chakra-ui/react'\nimport { IPlayRequest } from '@seplis/interfaces/play-server'\nimport { secondsToTime } from '@seplis/utils'\nimport { ReactNode, useState } from 'react'\n\n\ninterface IProps {\n duration: number\n currentTime: number\n onTimeChange: (newTime: number) => void\n playRequest: IPlayRequest\n}\n\nexport default function Slider({ duration, currentTime, onTimeChange, playRequest }: IProps) {\n const [hoverTime, setHoverTime] = useState(null)\n\n return setHoverTime(eventToTime(e, duration))}\n onTouchMove={(e) => setHoverTime(eventToTime(e, duration))}\n onMouseLeave={() => setHoverTime(null)}\n onTouchCancel={() => setHoverTime(null)}\n onTouchEnd={(e) => {\n onTimeChange(eventToTime(e, duration))\n setHoverTime(null)\n }}\n onClick={(e) => {\n onTimeChange(eventToTime(e, duration))\n setHoverTime(null)\n }}\n >\n {hoverTime !== null && }\n \n \n \n \n}\n\n\nfunction SliderTrack({ children }: { children: ReactNode }) {\n return \n {children}\n \n}\n\nfunction SliderTrackProgress({ progress }: { progress: number }) {\n return \n}\n\n\nfunction SliderHoverTime({ time, position }: { time: number, position: number }) {\n return \n {secondsToTime(time)}\n \n}\n\n\nfunction eventToTime(event: any, duration: number) {\n if (event.type.match('^touch')) {\n if (event.originalEvent)\n event = event.originalEvent\n event = event.touches[0] || event.changedTouches[0]\n }\n const r = event.target.getBoundingClientRect()\n const x = event.clientX - r.left\n const norm = duration / (r.right - r.left)\n let time = Math.trunc(norm * x)\n if (time > duration)\n time = duration\n if (time < 0)\n time = 0\n return time\n}\n\n\nfunction percentage(currentTime: number, duration: number) {\n const p = (currentTime / duration) * 100\n return p > 100 ? 100 : p\n}","import { useToast } from '@chakra-ui/react'\nimport {\n IPlayServerRequestMedia,\n IPlayServerRequestSource,\n IPlaySourceStream,\n} from '@seplis/interfaces/play-server'\nimport { browser } from '@seplis/utils'\nimport axios from 'axios'\nimport Hls from 'hls.js'\nimport JASSUB from 'jassub'\nimport { forwardRef, useEffect, useImperativeHandle, useRef } from 'react'\n\ninterface IProps {\n requestSource: IPlayServerRequestSource\n startTime?: number\n audioSource?: IPlaySourceStream\n resolutionWidth?: number\n subtitleSource?: IPlaySourceStream\n children?: React.ReactNode\n subtitleOffset?: number\n subtitleLinePosition?: number\n forceTranscode?: boolean\n onAutoPlayFailed?: () => void\n onTimeUpdate?: (time: number) => void\n onPause?: () => void\n onPlay?: () => void\n onLoadingState?: (loading: boolean) => void\n onAirplayAvailabilityChange?: (available: boolean) => void\n}\n\ndeclare global {\n interface HTMLMediaElement {\n /**\n * @see {@link https://developer.apple.com/documentation/webkitjs/htmlmediaelement/1632172-webkitshowplaybacktargetpicker}\n */\n webkitShowPlaybackTargetPicker?(): void\n }\n\n interface Event {\n availability: 'available' | 'not-available'\n }\n}\n\nexport interface IVideoControls {\n setCurrentTime: (time: number) => void\n getCurrentTime: () => number\n skipSeconds: (seconds?: number) => void\n togglePlay: () => void\n toggleFullscreen: () => void\n paused: () => boolean\n setVolume: (volume: number) => void\n getVolume: () => number\n showAirplayPicker: () => void\n}\n\nexport const Video = forwardRef(\n (\n {\n requestSource,\n startTime = 0,\n audioSource,\n resolutionWidth,\n subtitleSource,\n children,\n subtitleOffset,\n subtitleLinePosition,\n forceTranscode,\n onAutoPlayFailed,\n onTimeUpdate,\n onPause,\n onPlay,\n onLoadingState,\n onAirplayAvailabilityChange,\n }: IProps,\n ref\n ) => {\n const videoElement = useRef(null)\n const hls = useRef(null)\n const requestMedia = useRef(null)\n\n useImperativeHandle(\n ref,\n () => ({\n setCurrentTime: (time: number) => {\n videoElement.current.currentTime = time\n videoElement.current\n .play()\n .catch(() => onAutoPlayFailed && onAutoPlayFailed())\n onTimeUpdate?.(time)\n },\n getCurrentTime: () => videoElement.current.currentTime,\n skipSeconds: (seconds: number = 15) => {\n videoElement.current.currentTime =\n videoElement.current.currentTime + seconds\n videoElement.current\n .play()\n .catch(() => onAutoPlayFailed && onAutoPlayFailed())\n onTimeUpdate?.(videoElement.current.currentTime)\n },\n togglePlay: () => togglePlay(videoElement.current),\n paused: () => videoElement.current.paused,\n setVolume: (volume: number) =>\n (videoElement.current.volume = volume),\n getVolume: () => videoElement.current.volume,\n toggleFullscreen: () => toggleFullscreen(videoElement.current),\n showAirplayPicker: () =>\n videoElement.current.webkitShowPlaybackTargetPicker(),\n }),\n [videoElement.current]\n )\n\n useEffect(() => {\n if (videoElement.current.webkitShowPlaybackTargetPicker) {\n // The webkitplaybacktargetavailabilitychanged event seems inconsistent\n // just say it's available if the method exists\n onAirplayAvailabilityChange?.(true)\n }\n }, [])\n\n useEffect(() => {\n const start = async () => {\n requestMedia.current = await getPlayRequestMedia({\n videoElement: videoElement.current,\n resolutionWidth: resolutionWidth,\n audio:\n audioSource &&\n `${audioSource.language}:${audioSource.index}`,\n requestSource: requestSource,\n startTime: startTime,\n forceTranscode: forceTranscode,\n })\n if (\n !Hls.isSupported() ||\n requestMedia.current.can_direct_play\n ) {\n if (requestMedia.current.can_direct_play) {\n videoElement.current.src =\n requestMedia.current.direct_play_url\n } else {\n videoElement.current.src = requestMedia.current.hls_url\n }\n videoElement.current.currentTime = startTime\n videoElement.current.load()\n videoElement.current\n .play()\n .catch(() => onAutoPlayFailed && onAutoPlayFailed())\n } else {\n hls.current = new Hls({\n startPosition: startTime,\n manifestLoadingTimeOut: 30000,\n enableWorker: true,\n lowLatencyMode: true,\n backBufferLength: 90,\n })\n hls.current.loadSource(requestMedia.current.hls_url)\n hls.current.attachMedia(videoElement.current)\n\n // AirPlay fix - https://github.com/video-dev/hls.js/issues/5989#issuecomment-1825916766\n const airPlayHlsSource = document.createElement('source')\n airPlayHlsSource.src = requestMedia.current.hls_url\n videoElement.current.appendChild(airPlayHlsSource)\n videoElement.current.disableRemotePlayback = false\n videoElement.current.currentTime = startTime\n\n hls.current.on(Hls.Events.MANIFEST_PARSED, () =>\n videoElement.current\n .play()\n .catch(() => onAutoPlayFailed && onAutoPlayFailed())\n )\n hls.current.on(Hls.Events.ERROR, (e, data) => {\n console.warn(data)\n switch (data.type) {\n case Hls.ErrorTypes.NETWORK_ERROR:\n if (!data.fatal) return\n console.log(\n 'hls.js fatal network error encountered, try to recover'\n )\n break\n case Hls.ErrorTypes.MEDIA_ERROR:\n if (!data.fatal) return\n console.log(\n 'hls.js fatal media error encountered'\n )\n break\n default:\n if (!data.fatal) return\n console.log('hls.js could not recover')\n break\n }\n })\n }\n }\n start().catch((e) => {\n console.error(e)\n })\n\n const t = setInterval(() => {\n if (\n requestMedia.current &&\n !requestMedia.current?.can_direct_play\n )\n axios\n .get(requestMedia.current.keep_alive_url)\n .catch(() => {})\n }, 4000)\n\n return () => {\n if (hls.current) {\n hls.current.destroy()\n hls.current = null\n }\n if (videoElement.current) {\n videoElement.current.pause()\n videoElement.current.removeAttribute('src')\n for (const source of videoElement.current.childNodes)\n if (source instanceof HTMLSourceElement)\n videoElement.current.removeChild(source)\n }\n clearInterval(t)\n if (\n requestMedia.current &&\n !requestMedia.current.can_direct_play\n )\n axios\n .get(requestMedia.current.close_session_url)\n .catch(() => {})\n }\n }, [requestSource, audioSource, resolutionWidth, forceTranscode])\n\n return (\n <>\n {\n if (videoElement.current.readyState === 4)\n onTimeUpdate?.(videoElement.current.currentTime)\n }}\n onPause={() => {\n onPause?.()\n }}\n onPlay={() => {\n onPlay?.()\n onLoadingState?.(false)\n }}\n onWaiting={() => onLoadingState?.(true)}\n onLoadStart={() => onLoadingState?.(true)}\n onPlaying={() => onLoadingState?.(false)}\n onCanPlayThrough={() => onLoadingState?.(false)}\n onLoadedData={() => onLoadingState?.(false)}\n onError={(event) => {\n if (\n event.currentTarget.error.code ==\n event.currentTarget.error.MEDIA_ERR_DECODE\n )\n hls.current.recoverMediaError()\n }}\n width=\"100%\"\n style={{ position: 'fixed', height: '100%' }}\n controls={false}\n preload=\"none\"\n crossOrigin=\"anonymous\"\n playsInline\n >\n {children}\n\n \n \n \n )\n }\n)\n\nfunction togglePlay(video: HTMLVideoElement) {\n if (video.paused) video.play()\n else video.pause()\n}\n\nfunction toggleFullscreen(video: HTMLVideoElement) {\n if (!document.fullscreenElement) {\n if (video.requestFullscreen) {\n video.requestFullscreen()\n } else if ((video as any).webkitEnterFullscreen) {\n ;(video as any).webkitEnterFullscreen()\n }\n } else {\n if ((document as any).cancelFullScreen) {\n ;(document as any).cancelFullScreen()\n } else if ((document as any).webkitCancelFullScreen) {\n ;(document as any).webkitCancelFullScreen()\n }\n }\n}\n\nasync function getPlayRequestMedia({\n videoElement,\n requestSource,\n startTime,\n audio,\n resolutionWidth,\n forceTranscode,\n}: {\n videoElement: HTMLVideoElement\n requestSource: IPlayServerRequestSource\n startTime: number\n audio: string\n resolutionWidth: number\n forceTranscode: boolean\n}) {\n const videoCodecs = getSupportedVideoCodecs(videoElement)\n if (videoCodecs.length == 0) throw new Error('No supported codecs')\n\n const r = await axios.get(\n `${requestSource.request.play_url}/request-media` +\n `?play_id=${requestSource.request.play_id}` +\n `&source_index=${requestSource.source.index}` +\n `&start_time=${startTime || 0}` +\n `&audio_lang=${audio || ''}` +\n `&max_width=${resolutionWidth || ''}` +\n `&supported_video_codecs=${String(videoCodecs)}` +\n `&transcode_video_codec=${videoCodecs[0]}` +\n `&supported_audio_codecs=${String(\n getSupportedAudioCodecs(videoElement)\n )}` +\n `&transcode_audio_codec=aac` +\n `&format=${Hls.isSupported() ? 'hls.js' : 'hls'}` +\n `&max_audio_channels=6` +\n `&supported_video_containers=${String(\n getSupportedVideoContainers()\n )}` +\n `&force_transcode=${forceTranscode ? 'true' : 'false'}`\n )\n if (r.data.hls_url.startsWith('/')) {\n r.data.hls_url = requestSource.request.play_url + r.data.hls_url\n r.data.direct_play_url =\n requestSource.request.play_url + r.data.direct_play_url\n r.data.keep_alive_url =\n requestSource.request.play_url + r.data.keep_alive_url\n r.data.close_session_url =\n requestSource.request.play_url + r.data.close_session_url\n }\n return r.data\n}\n\nfunction getSupportedVideoCodecs(videoElement: HTMLVideoElement) {\n const types: { [key: string]: string } = {\n 'video/mp4; codecs=\"hvc1\"': 'hevc',\n 'video/mp4; codecs=\"hev1.1.6.L93.90\"': 'hevc',\n 'video/mp4; codecs=\"avc1.42E01E\"': 'h264',\n 'video/mp4; codecs=\"av01.0.08M.08\"': 'av1',\n }\n const codecs: string[] = []\n for (const key in types)\n if (videoElement.canPlayType(key)) codecs.push(types[key])\n return [...new Set(codecs)]\n}\n\nfunction getSupportedVideoContainers() {\n switch (browser.name) {\n case 'chrome':\n case 'edge-chromium':\n return ['webm', 'mp4']\n }\n return ['mp4']\n}\n\nfunction getSupportedAudioCodecs(videoElement: HTMLVideoElement) {\n const types: { [key: string]: string } = {\n 'audio/aac': 'aac',\n 'audio/mp4; codecs=\"ec-3\"': 'eac3',\n 'audio/mp4; codecs=\"ac-3\"': 'ac3',\n 'audio/mp4; codecs=\"ac-4\"': 'ac4',\n 'audio/mp4; codecs=\"opus\"': 'opus',\n 'audio/mp4; codecs=\"flac\"': 'flac',\n 'audio/mp4; codecs=\"dtsc\"': 'dtsc',\n 'audio/mp4; codecs=\"dtse\"': 'dtse',\n 'audio/mp4; codecs=\"dtsx\"': 'dtsx',\n }\n const codecs: string[] = []\n for (const key in types)\n if (videoElement.canPlayType(key)) codecs.push(types[key])\n return [...new Set(codecs)]\n}\n\nfunction getSupportedHdrFormats(videoElement: HTMLVideoElement) {}\n\ninterface IPropsSubtitle {\n videoElement: HTMLVideoElement\n requestSource: IPlayServerRequestSource\n subtitleSource?: IPlaySourceStream\n subtitleOffset?: number\n subtitleLinePosition?: number\n}\n\nfunction SetSubtitle({\n videoElement,\n requestSource,\n subtitleSource,\n subtitleOffset = 0,\n subtitleLinePosition = 16,\n}: IPropsSubtitle) {\n const toast = useToast()\n const track = useRef(null)\n const firstTrackLoad = useRef(true)\n const useJASSUB =\n ['chrome', 'edge-chromium', 'firefox'].includes(browser.name) &&\n subtitleSource?.codec == 'ass'\n\n useEffect(() => {\n if (!videoElement) return\n for (const track of videoElement.textTracks) {\n if (track.mode == 'showing')\n for (const cue of track.cues)\n (cue as VTTCue).line = subtitleLinePosition\n }\n }, [subtitleLinePosition])\n\n useEffect(() => {\n firstTrackLoad.current = true\n }, [track])\n\n useEffect(() => {\n if (firstTrackLoad.current) {\n firstTrackLoad.current = false\n return\n }\n if (!track.current) return\n const id = toast({\n title: 'Loading subtitle',\n status: 'loading',\n duration: null,\n isClosable: true,\n position: 'top-right',\n variant: 'subtle',\n })\n track.current.onload = () => {\n toast.close(id)\n }\n return () => {\n toast.close(id)\n }\n }, [track, subtitleSource, requestSource, subtitleOffset])\n\n useEffect(() => {\n if (!videoElement) return\n if (!useJASSUB) return\n\n const sub = new JASSUB({\n video: videoElement,\n subUrl:\n `${requestSource.request.play_url}/subtitle-file` +\n `?play_id=${requestSource.request.play_id}` +\n `&source_index=${requestSource.source.index}` +\n `&lang=${`${subtitleSource.language}:${subtitleSource.index}`}` +\n `&output_format=ass`,\n workerUrl: new URL('jassub/dist/jassub-worker.js', import.meta.url)\n .href,\n wasmUrl: new URL('jassub/dist/jassub-worker.wasm', import.meta.url)\n .href,\n legacyWasmUrl: new URL(\n 'jassub/dist/jassub-worker.wasm.js',\n import.meta.url\n ).href,\n availableFonts: {\n 'liberation sans': new URL(\n 'jassub/dist/default.woff2',\n import.meta.url\n ).href,\n },\n timeOffset: subtitleOffset,\n // https://github.com/ThaUnknown/jassub/issues/50\n offscreenRender: browser.os != 'Android OS',\n })\n return () => {\n sub.destroy()\n }\n }, [videoElement, requestSource, subtitleSource, subtitleOffset])\n\n return (\n <>\n {subtitleSource && !useJASSUB && (\n \n )}\n \n )\n}\n","import { Slider, SliderFilledTrack, SliderThumb, SliderTrack } from '@chakra-ui/react'\n\nexport default function VolumeBar({ defaultVolume, onChange }: { defaultVolume: number, onChange: (volume: number) => void }) {\n return onChange(value/10)}\n >\n \n \n \n \n \n}","import {\n Box,\n Flex,\n forwardRef,\n Heading,\n IconButton,\n IconButtonProps,\n Popover,\n PopoverArrow,\n PopoverBody,\n PopoverContent,\n PopoverTrigger,\n Spinner,\n} from '@chakra-ui/react'\nimport {\n IPlayServerRequestSource,\n IPlayServerRequestSources,\n IPlaySourceStream,\n} from '@seplis/interfaces/play-server'\nimport { ReactNode, useCallback, useEffect, useRef, useState } from 'react'\nimport {\n FaArrowsAlt,\n FaExpand,\n FaPause,\n FaPlay,\n FaRedo,\n FaStepForward,\n FaTimes,\n FaUndo,\n FaVolumeDown,\n FaVolumeOff,\n FaVolumeUp,\n} from 'react-icons/fa'\nimport { TbShareplay } from 'react-icons/tb'\n\nimport { isMobile, secondsToTime } from '@seplis/utils'\nimport { Link } from 'react-router-dom'\nimport FullErrorPage from '../full-page-error'\nimport { pickStartAudio } from './pick-audio-source'\nimport { getResolutionWidth } from './pick-quality'\nimport { pickStartSource } from './pick-source'\nimport { pickStartSubtitle } from './pick-subtitle-source'\nimport { useGetPlayServers } from './request-play-servers'\nimport { SettingsMenu } from './settings'\nimport Slider from './slider'\nimport { IVideoControls, Video } from './video'\nimport VolumeBar from './volume-bar'\n\nexport interface IPlayNextProps {\n title: string\n url: string\n}\n\nexport interface IPlayerProps {\n getPlayServersUrl: string\n startTime: number\n loading: boolean\n title?: string\n playNext?: IPlayNextProps\n defaultAudio?: string\n defaultSubtitle?: string\n onClose?: () => void\n onTimeUpdate?: (time: number, duration: number) => void\n onAudioChange?: (source: IPlaySourceStream) => void\n onSubtitleChange?: (source: IPlaySourceStream) => void\n}\n\nexport default function Player({\n getPlayServersUrl,\n title,\n startTime = 0,\n playNext,\n loading,\n defaultAudio,\n defaultSubtitle,\n onClose,\n onTimeUpdate,\n onAudioChange,\n onSubtitleChange,\n}: IPlayerProps) {\n const playServers = useGetPlayServers(getPlayServersUrl)\n\n if (playServers.isLoading || playServers.isFetching || loading)\n return \n\n if (!playServers.data || playServers.data.length === 0)\n return (\n \n )\n\n return (\n \n )\n}\n\ninterface IVideoPlayerProps {\n playServers: IPlayServerRequestSources[]\n title: string\n startTime: number\n playNext: IPlayNextProps\n defaultAudio?: string\n defaultSubtitle?: string\n onClose?: () => void\n onTimeUpdate: (time: number, duration: number) => void\n onAudioChange?: (source: IPlaySourceStream) => void\n onSubtitleChange?: (source: IPlaySourceStream) => void\n}\n\nfunction VideoPlayer({\n playServers,\n title,\n startTime,\n playNext,\n defaultAudio,\n defaultSubtitle,\n onClose,\n onTimeUpdate,\n onAudioChange,\n onSubtitleChange,\n}: IVideoPlayerProps) {\n const [requestSource, setRequestSource] =\n useState(() => pickStartSource(playServers))\n const [resolutionWidth, setResolutionWidth] = useState(\n getResolutionWidth(requestSource.source)\n )\n const [audioSource, setAudioSource] = useState(() =>\n pickStartAudio(requestSource.source.audio, defaultAudio)\n )\n const [subtitleSource, setSubtitleSource] = useState(\n () => pickStartSubtitle(requestSource.source.subtitles, defaultSubtitle)\n )\n const [forceTranscode, setForceTranscode] = useState(\n getDefaultForceTranscode()\n )\n const [subtitleOffset, setSubtitleOffset] = useState(0)\n const [time, setTime] = useState(startTime)\n const [paused, setPaused] = useState(false)\n const [loading, setLoading] = useState(true)\n const [showBigPlay, setShowBigPlay] = useState(false)\n const [controlsVisible, setControlsVisible] = useState(true)\n const hideControlsTimer = useRef()\n const videoControls = useRef()\n const boxRef = useRef(null)\n const [airplayAvailable, setAirplayAvailable] = useState(false)\n\n const showControls = () => {\n setControlsVisible(true)\n clearTimeout(hideControlsTimer.current)\n hideControlsTimer.current = setTimeout(() => {\n setControlsVisible(false)\n }, 4000)\n return () => {\n clearTimeout(hideControlsTimer.current)\n }\n }\n\n const requestSourceChange = useCallback(\n (newRequestSource: IPlayServerRequestSource) => {\n setRequestSource(newRequestSource)\n setResolutionWidth(getResolutionWidth(newRequestSource.source))\n setAudioSource(\n pickStartAudio(newRequestSource.source.audio, defaultAudio)\n )\n setSubtitleSource(\n pickStartSubtitle(\n newRequestSource.source.subtitles,\n defaultSubtitle\n )\n )\n },\n [defaultAudio, defaultSubtitle]\n )\n\n useEffect(() => {\n videoControls.current.setVolume(\n parseFloat(localStorage.getItem('volume')) || 0.5\n )\n\n const keyDown = (e: globalThis.KeyboardEvent) => {\n showControls()\n if (e.code == 'Space') {\n videoControls.current.togglePlay()\n e.preventDefault()\n }\n if (e.code == 'ArrowLeft') {\n videoControls.current.skipSeconds(-15)\n e.preventDefault()\n }\n if (e.code == 'ArrowRight') {\n videoControls.current.skipSeconds(15)\n e.preventDefault()\n }\n }\n document.addEventListener('keydown', keyDown)\n return () => document.removeEventListener('keydown', keyDown)\n }, [])\n\n return (\n {\n showControls()\n }}\n onTouchMove={() => {\n showControls()\n }}\n onClick={() => {\n if (paused) return\n if (controlsVisible) setControlsVisible(false)\n else showControls()\n }}\n >\n {\n onTimeUpdate?.(time, requestSource.source.duration)\n setTime(time)\n if (controlsVisible && !hideControlsTimer.current)\n showControls()\n if (loading) setLoading(false)\n }}\n onPause={() => setPaused(true)}\n onPlay={() => {\n setPaused(false)\n setShowBigPlay(false)\n }}\n onAutoPlayFailed={() => {\n setPaused(true)\n setShowBigPlay(true)\n }}\n onLoadingState={(loading) => setLoading(loading)}\n onAirplayAvailabilityChange={(available) =>\n setAirplayAvailable(available)\n }\n />\n\n {!paused && loading && }\n {showBigPlay && (\n videoControls.current.togglePlay()} />\n )}\n\n {(controlsVisible || paused) && (\n \n \n }\n onClick={() => {\n onClose && onClose()\n }}\n />\n\n {airplayAvailable && (\n
\n }\n onClick={() => {\n videoControls.current.showAirplayPicker()\n }}\n />\n
\n )}\n
\n
\n )}\n\n {(controlsVisible || paused) && (\n \n \n {title}\n \n\n \n {secondsToTime(time)}\n \n {\n videoControls.current.setCurrentTime(time)\n }}\n />\n \n \n {secondsToTime(requestSource.source.duration)}\n \n \n\n \n : }\n onClick={() => videoControls.current.togglePlay()}\n />\n }\n onClick={() => {\n videoControls.current.skipSeconds(-15)\n }}\n />\n }\n onClick={() => {\n videoControls.current.skipSeconds(15)\n }}\n />\n {!isMobile && (\n \n )}\n\n \n {playNext && }\n {\n setAudioSource(source)\n if (onAudioChange) onAudioChange(source)\n }}\n onSubtitleSourceChange={(source) => {\n setSubtitleSource(source)\n if (onSubtitleChange)\n onSubtitleChange(source)\n }}\n onSubtitleOffsetChange={setSubtitleOffset}\n onForceTranscodeChange={setForceTranscode}\n containerRef={boxRef}\n />\n \n \n \n \n )}\n \n )\n}\n\nfunction FullscreenButton({\n videoControls,\n}: {\n videoControls: IVideoControls\n}) {\n const [fullscreen, setFullscreen] = useState(false)\n return fullscreen ? (\n }\n onClick={() =>\n fullscreenToggle(\n document.getElementById('player'),\n videoControls,\n setFullscreen\n )\n }\n />\n ) : (\n }\n onClick={() =>\n fullscreenToggle(\n document.getElementById('player'),\n videoControls,\n setFullscreen\n )\n }\n />\n )\n}\n\nfunction VolumeButton({ videoControls }: { videoControls: IVideoControls }) {\n const [volume, setVolume] = useState(\n parseFloat(localStorage.getItem('volume')) || 0.5\n )\n\n function volumeIcon() {\n if (volume >= 0.5) return \n if (volume >= 0.1) return \n return \n }\n return (\n \n \n \n \n \n \n \n {\n localStorage.setItem('volume', volume.toString())\n videoControls.setVolume(volume)\n setVolume(volume)\n }}\n />\n \n \n \n )\n}\n\nfunction PlayNext({ title, url }: IPlayNextProps) {\n return (\n \n } />\n \n )\n}\n\nexport const PlayButton = forwardRef(\n (props, ref) => {\n return \n }\n)\n\nfunction ControlsTop({ children }: { children: ReactNode }) {\n return (\n e.stopPropagation()}\n >\n {children}\n \n )\n}\n\nfunction ControlsBottom({ children }: { children: ReactNode }) {\n return (\n e.stopPropagation()}\n >\n {children}\n \n )\n}\n\nfunction Loading() {\n return (\n \n \n \n )\n}\n\nfunction BigPlay({ onClick }: { onClick: () => void }) {\n return (\n \n }\n onClick={onClick}\n fontSize=\"100px\"\n />\n \n )\n}\n\nfunction fullscreenToggle(\n element: HTMLElement,\n videoControls: IVideoControls,\n setFullscreen: (fullscreen: boolean) => void\n) {\n if (!document.fullscreenElement) {\n if ((element as any).enterFullscreen) {\n ;(element as any).enterFullscreen()\n } else if ((element as any).requestFullScreen) {\n ;(element as any).requestFullScreen()\n } else if ((element as any).mozRequestFullScreen) {\n ;(element as any).mozRequestFullScreen()\n } else if ((element as any).webkitRequestFullScreen) {\n ;(element as any).webkitRequestFullScreen(\n (Element as any).ALLOW_KEYBOARD_INPUT\n )\n } else {\n videoControls.toggleFullscreen()\n }\n setFullscreen(true)\n } else {\n if ((document as any).cancelFullScreen) {\n ;(document as any).cancelFullScreen()\n } else if ((document as any).mozCancelFullScreen) {\n ;(document as any).mozCancelFullScreen()\n } else if ((document as any).webkitCancelFullScreen) {\n ;(document as any).webkitCancelFullScreen()\n }\n setFullscreen(false)\n }\n}\n\nfunction getDefaultForceTranscode() {\n // Currently there is an issue where Firefox won't start the video\n // if start time is above 0 and the video is not transcoded.\n return navigator.userAgent.includes('Firefox')\n}\n","import { Box, Flex } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { episodeTitle, secondsToTime } from '@seplis/utils'\nimport { useEffect, useState } from 'react'\nimport { FaPause, FaPlay } from 'react-icons/fa'\nimport { castMovieRequest } from '../movie/play-button'\nimport { castEpisodeRequest } from '../series/episode-play-button'\nimport { pickStartAudio } from './pick-audio-source'\nimport { pickStartSubtitle } from './pick-subtitle-source'\nimport { PlayButton } from './player'\nimport { useCast, useCastPlayer } from './react-cast-sender'\nimport { SettingsMenu } from './settings'\nimport Slider from './slider'\n\n\nexport default function ChromecastControls() {\n const { connected } = useCast()\n const { currentTime, togglePlay, isPaused, sendMessage, loadMedia, seek, isMediaLoaded } = useCastPlayer()\n const [info, setInfo] = useState()\n\n useEffect(() => {\n try {\n const castSession = window.cast.framework.CastContext.getInstance().getCurrentSession()\n if (castSession) {\n castSession.addMessageListener(\n 'urn:x-cast:net.seplis.cast.get_custom_data',\n infoReceived,\n )\n }\n return () => {\n if (castSession) {\n castSession.removeMessageListener(\n 'urn:x-cast:net.seplis.cast.get_custom_data',\n infoReceived\n )\n }\n }\n } catch { }\n }, [connected])\n\n const infoReceived = (namespace: string, message: any) => {\n if (message)\n setInfo(JSON.parse(message))\n }\n\n if (!info)\n return\n\n return \n {isMediaLoaded && (currentTime > 0) && \n {secondsToTime(currentTime)}\n \n {\n seek(time)\n }}\n />\n \n {secondsToTime(info.selectedRequestSource.source.duration)}\n }\n \n : } onClick={() => togglePlay()} />\n\n {info.type == 'episode' ? `${info.series.title} ${episodeTitle(info.episode)}` : info.movie.title}\n\n \n\n {\n if (info.type == 'episode')\n loadMedia(await castEpisodeRequest(info.series.id, info.episode.number, currentTime, source, info.audioLang, info.subtitleLang, info.subtitleOffset, info.resolutionWidth))\n else if (info.type == 'movie')\n loadMedia(await castMovieRequest(info.movie.id, currentTime, source, info.audioLang, info.subtitleLang, info.subtitleOffset, info.resolutionWidth))\n }}\n onResolutionWidthChange={async (resolutionWidth) => {\n if (info.type == 'episode')\n loadMedia(await castEpisodeRequest(info.series.id, info.episode.number, currentTime, info.selectedRequestSource, info.audioLang, info.subtitleLang, info.subtitleOffset, resolutionWidth))\n else if (info.type == 'movie')\n loadMedia(await castMovieRequest(info.movie.id, currentTime, info.selectedRequestSource, info.audioLang, info.subtitleLang, info.subtitleOffset, resolutionWidth))\n\n }}\n onAudioSourceChange={async (source) => {\n if (info.type == 'episode') {\n api.put(`/2/series/${info.series.id}/user-settings`, {\n 'audio_lang': source ? `${source.language || source.title}:${source.index}` : null,\n })\n loadMedia(await castEpisodeRequest(info.series.id, info.episode.number, currentTime, info.selectedRequestSource, source ? `${source.language}:${source.index}` : '', info.subtitleLang, info.subtitleOffset, info.resolutionWidth))\n } else if (info.type == 'movie')\n loadMedia(await castMovieRequest(info.movie.id, currentTime, info.selectedRequestSource, source ? `${source.language}:${source.index}` : '', info.subtitleLang, info.subtitleOffset, info.resolutionWidth))\n }}\n onSubtitleSourceChange={(source) => {\n let url = ''\n let lang = ''\n if (info.type === 'episode')\n api.put(`/2/series/${info.series.id}/user-settings`, {\n 'subtitle_lang': source ? `${source.language || source.title}:${source.index}` : 'off',\n })\n if (source) {\n lang = `${source.language}:${source.index}`\n url = `${info.selectedRequestSource.request.play_url}/subtitle-file` +\n `?play_id=${info.selectedRequestSource.request.play_id}` +\n `&source_index=${info.selectedRequestSource.source.index}` +\n `&lang=${lang}`\n if (info.subtitleOffset)\n url = url + `&offset=${info.subtitleOffset}`\n }\n sendMessage('urn:x-cast:net.seplis.cast.new_track', {\n url: url,\n lang: lang,\n offset: info.subtitleOffset,\n })\n setInfo({\n ...info,\n subtitleLang: lang\n })\n }}\n onSubtitleOffsetChange={(offset) => {\n if (info.subtitleLang) {\n let url = `${info.selectedRequestSource.request.play_url}/subtitle-file` +\n `?play_id=${info.selectedRequestSource.request.play_id}` +\n `&source_index=${info.selectedRequestSource.source.index}` +\n `&lang=${info.subtitleLang}`\n if (offset)\n url = url + `&offset=${offset}`\n sendMessage('urn:x-cast:net.seplis.cast.new_track', {\n url: url,\n lang: info.subtitleLang,\n offset: offset,\n })\n setInfo({\n ...info,\n subtitleOffset: offset\n })\n }\n }}\n />\n \n \n \n}","import { Box, Flex, Heading, Stack, Wrap, WrapItem } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IMovie } from '@seplis/interfaces/movie'\nimport { IMovieCollection } from '@seplis/interfaces/movie-collection'\nimport { IPageCursorResult } from '@seplis/interfaces/page'\nimport { useQuery } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport { useLocation, useNavigate } from 'react-router-dom'\nimport { PosterAspectRatio } from '../poster'\n\nexport default function MovieCollection({ collection }: { collection: IMovieCollection }) {\n const navigate = useNavigate()\n const location = useLocation()\n const selected = useCallback((movie: IMovie) => {\n navigate(`/movies/${movie.id}`, \n { state: { background: location.state?.background || null } })\n }, [])\n\n const { data, isLoading } = useQuery(['movie-collection', collection.id], async () => {\n const r = await api.get>('/2/movies', {\n params: {\n collection_id: collection.id,\n sort: 'release_date_asc',\n per_page: 100,\n }\n })\n return r.data\n })\n if (isLoading)\n return null\n return \n {collection.name}\n \n {data.items.map((r) => \n \n {\n selected(r)\n }}\n />\n \n {r.release_date ? r.release_date.substring(0, 4) : 'TBA'}\n \n \n )}\n \n \n}","import { StarIcon } from '@chakra-ui/icons'\nimport { Button, useToast } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IMovieFavorite, IMovieWatchlist } from '@seplis/interfaces/movie'\nimport { isAuthed } from '@seplis/utils'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { ErrorMessageFromResponse } from '../error'\nimport { useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport { focusedBorder } from '@seplis/styles'\n\ninterface IProps {\n movieId: number\n}\n\nexport default function WatchlistButton({ movieId }: IProps) {\n const toast = useToast()\n const queryClient = useQueryClient()\n\n const toggleWatchlist = useMutation(async (favorite: boolean) => {\n await queryClient.cancelQueries(['movie', 'favorite-button', movieId])\n let data: IMovieWatchlist\n if (favorite) {\n data = await api.delete(`/2/movies/${movieId}/favorite`)\n } else {\n data = await api.put(`/2/movies/${movieId}/favorite`)\n }\n queryClient.setQueryData(['movie', 'favorite-button', movieId], { favorite: !favorite })\n }, {\n onError: (e) => {\n toast({\n title: ErrorMessageFromResponse(e),\n status: 'error',\n isClosable: true,\n position: 'top',\n })\n }\n })\n\n const { isInitialLoading, data } = useQuery(['movie', 'favorite-button', movieId], async () => {\n const result = await api.get(`/2/movies/${movieId}/favorite`)\n return result.data\n }, {\n enabled: isAuthed(),\n })\n const handleClick = async () => {\n toggleWatchlist.mutate(data.favorite)\n }\n const { ref, focused } = useFocusable({\n onEnterPress: () => handleClick()\n })\n\n return }\n style={focused ? focusedBorder : null}\n >\n Favorite\n \n}","import { Text, Flex, Box, Skeleton } from '@chakra-ui/react'\nimport { IMovieCastPerson } from '@seplis/interfaces/movie-cast'\nimport { PosterAspectRatio } from '../poster'\n\nexport default function CastCard({ castPerson }: { castPerson: IMovieCastPerson }) {\n return \n \n \n \n \n {castPerson.person.name}\n {castPerson.character}\n \n \n}\n\nexport function CastCardSkeleton() {\n return \n \n \n \n \n \n \n \n \n}","import { Heading, SimpleGrid, Stack, Text } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IMovieCastPerson } from '@seplis/interfaces/movie-cast'\nimport { IPageCursorResult } from '@seplis/interfaces/page'\nimport { useQuery } from '@tanstack/react-query'\nimport CastCard, { CastCardSkeleton } from './cast-card'\n\nexport default function CastFeatured({ movieId }: { movieId: number }) {\n const { isInitialLoading, data } = useQuery(['movie', movieId, 'featured'], async () => {\n const result = await api.get>(`/2/movies/${movieId}/cast`, {\n params: {\n per_page: 12,\n order_le: 100,\n },\n })\n return result.data\n })\n return \n Top cast\n\n \n {isInitialLoading ? [...Array(3)].map((_, i) => (\n \n )) : data?.items.length > 0 ? data?.items.map(member => (\n \n )) : No cast specified.}\n \n \n}","import { StarIcon } from '@chakra-ui/icons'\nimport { Text, Box, Button, Heading, Link, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Tag, useDisclosure, Stack, Wrap, WrapItem, Flex, Alert } from '@chakra-ui/react'\nimport { IMovie } from '@seplis/interfaces/movie'\nimport { Poster } from '../poster'\nimport { langCodeToLang, secondsToHourMin } from '@seplis/utils'\nimport WatchlistButton from './watchlist-button'\nimport { IGenre } from '@seplis/interfaces/genre'\nimport { FaCog } from 'react-icons/fa'\nimport { MovieUpdate } from './settings'\nimport { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport { useEffect, useState } from 'react'\nimport { focusedBorder } from '@seplis/styles'\nimport MoviePlayButton from './play-button'\nimport { MovieWatchedButton } from './watched-button'\nimport api from '@seplis/api'\nimport { useQuery } from '@tanstack/react-query'\nimport { MovieSkeleton } from './skeleton'\nimport ChromecastControls from '../player/chromecast-controls'\nimport MovieCollection from './collection'\nimport FavoriteButton from './favorite-button'\nimport CastFeatured from './cast-featured'\n\n\nexport function MovieLoad({ movieId, onLoaded }: { movieId: number, onLoaded?: (movie: IMovie) => void }) {\n const { isInitialLoading, data } = useQuery(['movie', movieId], async () => {\n const data = await api.get(`/2/movies/${movieId}`)\n if (onLoaded) onLoaded(data.data)\n return data.data\n })\n\n if (isInitialLoading)\n return \n\n if (!data)\n return <>\n Unknown movie\n \n This movie doesn't exist.\n \n \n\n if (!data?.title)\n return \n\n return \n}\n\n\nexport default function Movie({ movie }: { movie: IMovie }) {\n const { ref, focusKey, setFocus } = useFocusable()\n\n useEffect(() => {\n setFocus('MOVIE_PLAY')\n }, [])\n\n return \n \n \n \n \n \n <BaseInfo movie={movie} />\n <Genres genres={movie.genres} />\n <ListButtons movie={movie} />\n <Plot movie={movie} />\n <ExternalLinks movie={movie} />\n <WatchButtons movie={movie} />\n </Stack>\n </Stack>\n <ChromecastControls />\n \n <CastFeatured movieId={movie.id} />\n\n {movie.collection && <MovieCollection collection={movie.collection} />}\n </Stack>\n </FocusContext.Provider>\n}\n\n\nfunction SeriesWaitingForData({ movie }: { movie: IMovie }) {\n return <Flex direction=\"column\" align=\"center\" gap=\"1rem\">\n <Heading>Movie hasn't been updated, waiting for data</Heading>\n <Heading>Refresh to update</Heading>\n <DisplaySettings movie={movie} />\n </Flex>\n}\n\n\nfunction ListButtons({ movie }: { movie: IMovie }) {\n return <Flex gap=\"0.5rem\" padding=\"0.25rem 0\" wrap=\"wrap\">\n <WatchlistButton movieId={movie.id} />\n <FavoriteButton movieId={movie.id} />\n <DisplaySettings movie={movie} />\n </Flex>\n}\n\n\nfunction WatchButtons({ movie }: { movie: IMovie }) {\n return <Flex gap=\"0.5rem\" padding=\"0.25rem 0\" wrap=\"wrap\">\n <MoviePlayButton movieId={movie.id} />\n <MovieWatchedButton movieId={movie.id} />\n </Flex>\n}\n\n\nfunction Genres({ genres }: { genres: IGenre[] }) {\n if (!genres || (genres.length < 0))\n return null\n\n return <Wrap padding=\"0.25rem 0\">\n {genres.map(genre => (\n <WrapItem key={genre.id}><Genre genre={genre} /></WrapItem>\n ))}\n </Wrap>\n}\n\n\nfunction Genre({ genre }: { genre: IGenre }) {\n const { ref, focused } = useFocusable()\n return <Tag\n ref={ref}\n style={focused ? focusedBorder : {}}\n >\n {genre.name}\n </Tag>\n}\n\n\nfunction BaseInfo({ movie }: { movie: IMovie }) {\n return <Wrap spacingX=\"0.75rem\" lineHeight=\"1.3\">\n {movie.release_date ? <WrapItem><strong title={movie.release_date}>{movie.release_date.substring(0, 4)}</strong></WrapItem> : null}\n {movie.language ? <WrapItem>{langCodeToLang(movie.language)}</WrapItem> : null}\n {movie.runtime ? <WrapItem>{secondsToHourMin(movie.runtime)}</WrapItem> : null}\n {movie.rating ? <WrapItem title=\"IMDb rating\"><StarIcon mr=\"0.2rem\" boxSize={3} color=\"yellow.400\" mt=\"4px\" />{movie.rating} IMDb</WrapItem> : null}\n </Wrap>\n}\n\n\nfunction Plot({ movie }: { movie: IMovie }) {\n const [expand, setExpand] = useState(false)\n if (!movie.plot)\n return\n return <Text cursor=\"pointer\" noOfLines={expand ? null : 3} onClick={() => {\n setExpand(!expand)\n }}>\n {movie.plot}\n </Text>\n}\n\n\nfunction Title({ movie }: { movie: IMovie }) {\n return <Box marginTop=\"-7px\" lineHeight=\"1.3\">\n <Heading as=\"h1\">{movie.title || '<Missing title>'}</Heading>\n {movie.original_title != movie.title &&\n <Heading as=\"h2\" fontSize=\"1.5rem\" color=\"RGBA(255, 255, 255, 0.36)\">{movie.original_title}</Heading>}\n\n {movie.tagline && <Text><i>{movie.tagline}</i></Text>}\n </Box>\n}\n\n\nfunction MoviePoster({ movie }: { movie: IMovie }) {\n return <div className=\"poster-container-sizing\">\n <div className=\"poster-container\" style={{ 'flexShrink': '0' }}>\n <Poster url={`${movie.poster_image?.url}@SX320.webp`} title={movie.title} />\n </div>\n </div>\n}\n\n\nfunction ExternalLinks({ movie }: { movie: IMovie }) {\n if (!movie.externals.imdb && !movie.externals.themoviedb)\n return\n return <Wrap>\n {movie.externals.imdb && <WrapItem><Link href={`https://imdb.com/title/${movie.externals.imdb}`} isExternal>IMDb</Link></WrapItem>}\n {movie.externals.themoviedb && <WrapItem><Link href={`https://www.themoviedb.org/movie/${movie.externals.themoviedb}`} isExternal>TMDb</Link></WrapItem>}\n </Wrap>\n}\n\n\nfunction DisplaySettings({ movie }: { movie: IMovie }) {\n const { isOpen, onOpen, onClose } = useDisclosure()\n const { ref, focused } = useFocusable({\n onEnterPress: () => onOpen()\n })\n\n return <>\n <Button\n ref={ref}\n onClick={onOpen}\n leftIcon={<FaCog />}\n style={focused ? focusedBorder : null}\n >\n Settings\n </Button>\n\n <Modal onClose={onClose} isOpen={isOpen}>\n <ModalOverlay />\n <ModalContent>\n <ModalHeader>Settings</ModalHeader>\n <ModalCloseButton />\n <ModalBody>\n <Box marginBottom=\"1rem\">\n <MovieUpdate movie={movie} />\n </Box>\n </ModalBody>\n </ModalContent>\n </Modal>\n </>\n}","import { Flex, Heading, Input, Button, Stack, Box, FormControl, Alert, AlertIcon, FormLabel, FormErrorMessage } from '@chakra-ui/react'\nimport { useForm } from 'react-hook-form'\nimport { useEffect, useState } from 'react'\nimport { ErrorMessageFromResponse } from '@seplis/components/error'\nimport api from '@seplis/api'\nimport { IError, IValidationError } from '@seplis/interfaces/error'\n\n\ninterface IChangePassword {\n [key: string]: any\n current_password: string\n new_password: string\n}\n\nexport default function ChangePasswordForm() {\n const { handleSubmit, register, formState: { isSubmitting, errors, isSubmitSuccessful }, setError, setFocus } = useForm<IChangePassword>()\n const [rootError, setRootError] = useState<JSX.Element>()\n\n useEffect(() => {\n setFocus('current_password')\n }, [])\n\n const submit = async (data: IChangePassword) => {\n try {\n setRootError(null)\n await api.post<IChangePassword>('/2/users/me/change-password', data)\n } catch (e) {\n const data = e.response.data as IError<IValidationError>\n if (data?.errors) {\n for (const e of data?.errors) {\n setError(e.field[1], { message: e.message })\n }\n } else {\n setRootError(ErrorMessageFromResponse(e))\n }\n }\n }\n\n if (!rootError && isSubmitSuccessful)\n return <Alert status=\"success\" rounded=\"md\">\n <AlertIcon /> Your password has been changed.\n </Alert>\n\n return <form\n onSubmit={handleSubmit(submit)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\")\n handleSubmit(submit)()\n }}\n >\n <Stack spacing=\"1rem\">\n {rootError && <Alert status=\"error\" rounded=\"md\">\n <AlertIcon /> {rootError}\n </Alert>}\n\n <FormControl isInvalid={!!errors?.current_password}>\n <FormLabel>Current password</FormLabel>\n <Input {...register('current_password', { required: true })} type=\"password\" />\n <FormErrorMessage>\n {errors.current_password?.message}\n </FormErrorMessage>\n </FormControl>\n\n <FormControl isInvalid={!!errors?.new_password}>\n <FormLabel>New password</FormLabel>\n <Input {...register('new_password', { required: true })} type=\"password\" />\n <FormErrorMessage>\n {errors.new_password?.message}\n </FormErrorMessage>\n </FormControl>\n\n <Flex>\n <Button\n marginLeft=\"auto\"\n type=\"submit\"\n colorScheme=\"blue\"\n isLoading={isSubmitting}\n loadingText='Changing password'\n paddingLeft=\"2rem\"\n paddingRight=\"2rem\">\n Change password\n </Button>\n </Flex>\n </Stack>\n </form>\n}","import { Box} from '@chakra-ui/react'\nimport { CastButton, useCast } from './react-cast-sender'\n\nexport default function ChromecastIcon() {\n const { initialized } = useCast()\n return initialized && <Box width=\"24px\" height=\"24px\" mr=\"1.25rem\">\n <CastButton />\n </Box>\n}","import { SearchIcon } from '@chakra-ui/icons'\nimport { Text, Button, Input, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, useDisclosure, FormControl, FormLabel, Switch, Box, AspectRatio, Skeleton, Heading, Tag, Stack, Flex } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { ITitleSearchResult as ISearchTitleResult } from '@seplis/interfaces/search'\nimport { langCodeToLang, secondsToHourMin } from '@seplis/utils'\nimport { useQuery } from '@tanstack/react-query'\nimport { useEffect, useState } from 'react'\nimport { useForm } from 'react-hook-form'\nimport { useLocation, useNavigate } from 'react-router-dom'\nimport { useDebounce } from 'usehooks-ts'\nimport { Poster } from './poster'\n\n\nexport function SearchButtonDialog() {\n const { isOpen, onOpen, onClose } = useDisclosure()\n return <>\n <Button variant='ghost' leftIcon={<SearchIcon />} onClick={onOpen}>Search</Button>\n\n <Modal isOpen={isOpen} onClose={onClose}>\n <ModalOverlay />\n <ModalContent backgroundColor=\"seplis.modalBackgroundColor\" maxWidth=\"800px\" paddingBottom=\"1rem\">\n <ModalHeader>Search</ModalHeader>\n <ModalCloseButton />\n <ModalBody>\n <Search afterSelected={onClose} />\n </ModalBody>\n </ModalContent>\n </Modal>\n </>\n}\n\nexport function Search({ afterSelected }: { afterSelected?: (item: ISearchTitleResult) => void }) {\n const [value, setValue] = useState('')\n const query = useDebounce(value, 200)\n const navigate = useNavigate()\n const location = useLocation()\n const { data, isFetching } = useQuery(['search-suggestions', query], async ({ signal }) => {\n const r = await api.get<ISearchTitleResult[]>('/2/search', {\n params: {\n 'query': query,\n },\n signal: signal,\n })\n return r.data\n }, {\n enabled: query.length > 0,\n keepPreviousData: false,\n })\n\n return <Stack direction=\"column\">\n <SearchInput onChange={setValue} />\n\n {isFetching && <RenderItemSkeleton />}\n\n {!isFetching && <RenderItems items={data} onSelected={(item) => {\n if (item.type == 'movie')\n navigate(`/${item.type}s/${item.id}`, {\n state: {\n background: location\n }\n })\n else if (item.type == 'series')\n navigate(`/series/${item.id}`, {\n state: {\n background: location\n }\n })\n if (afterSelected)\n afterSelected(item)\n }} />}\n </Stack>\n}\n\n\nfunction RenderItems({ items, onSelected }: { items: ISearchTitleResult[], onSelected: (item: ISearchTitleResult) => void }) {\n if (!items)\n return null\n if (items.length === 0)\n return <Heading as=\"h2\" fontSize=\"1.25rem\" fontWeight=\"600\">No results</Heading>\n return <Stack direction=\"column\">\n {items.map(item => (\n <RenderItem key={`${item.type}-${item.id}`} item={item} onSelected={onSelected} />\n ))}\n </Stack>\n}\n\n\nfunction RenderItem({ item, onSelected }: { item: ISearchTitleResult, onSelected: (item: ISearchTitleResult) => void }) {\n return <Stack\n direction=\"row\"\n backgroundColor=\"blackAlpha.500\"\n padding=\"0.5rem\"\n rounded=\"md\"\n cursor=\"pointer\"\n onClick={() => {\n onSelected(item)\n }}\n >\n <AspectRatio width=\"15%\" ratio={603 / 887} rounded=\"sm\" overflow=\"hidden\">\n <Poster url={`${item.poster_image?.url}@SX320.webp`} title={item.title} />\n </AspectRatio>\n <Stack direction=\"column\" lineHeight=\"1.3\" spacing=\"0.25rem\">\n <Text fontWeight=\"600\" fontSize=\"1.1rem\">{item.title}</Text>\n <Stack direction=\"row\" spacing=\"0.75rem\">\n {item.release_date && <Text fontWeight=\"bolder\" title={item.release_date}>{item.release_date.substring(0, 4)}</Text>}\n {item?.language ? <Text>{langCodeToLang(item.language)}</Text> : null}\n {item?.runtime ? <Text>{secondsToHourMin(item.runtime)}</Text> : null}\n {item?.rating ? <Text title=\"IMDb rating\">{item.rating} IMDb</Text> : null}\n </Stack>\n <Flex direction=\"row\" pt=\"0.25rem\" gap=\"0.25rem\" wrap=\"wrap\">\n <ShowType type={item.type} />\n {item.genres?.map(genre => <Tag key={genre.id}>{genre.name}</Tag>)}\n </Flex>\n </Stack>\n </Stack>\n}\n\n\nfunction ShowType({ type }: { type: string }) {\n if (type === 'movie')\n return <Tag colorScheme=\"green\">Movie</Tag>\n else if (type === 'series')\n return <Tag colorScheme=\"blue\">Series</Tag>\n return null\n}\n\n\nfunction RenderItemSkeleton() {\n return <Stack\n direction=\"row\"\n backgroundColor=\"blackAlpha.500\"\n padding=\"0.5rem\"\n rounded=\"md\"\n >\n <AspectRatio width=\"15%\" ratio={603 / 887} rounded=\"sm\" overflow=\"hidden\">\n <Skeleton height=\"100%\" />\n </AspectRatio>\n <Stack width=\"100%\">\n <Skeleton height=\"30px\" width=\"45%\" />\n <Skeleton height=\"30px\" width=\"27%\" />\n </Stack>\n </Stack>\n}\n\n\nfunction SearchInput({ onChange }: { onChange: (value: string) => void }) {\n const { register, setFocus } = useForm()\n useEffect(() => {\n setFocus('query')\n })\n return <form>\n <Input\n {...register('query')}\n onChange={(e) => onChange(e.currentTarget.value)}\n type=\"text\"\n placeholder=\"Search title\" size=\"lg\"\n />\n </form>\n}","import { Alert, AlertDialog, AlertDialogBody, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, Button, Flex, FormControl, FormLabel, Heading, Input, Select, useDisclosure, useToast } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { ISeries, ISeriesRequest } from '@seplis/interfaces/series'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { useRef, useState } from 'react'\nimport { useForm, UseFormRegister } from 'react-hook-form'\nimport { ErrorMessageFromResponse } from '../error'\nimport { IError } from '@seplis/interfaces/error'\n\n\nexport function SeriesNew({ onDone }: { onDone?: (seriesId: number) => void }) {\n const onSave = async (data: ISeriesRequest) => {\n const result = await api.post<ISeries>('/2/series', data)\n if (onDone)\n onDone(result.data.id)\n return result.data\n }\n\n return <SeriesForm\n request={{\n externals: {},\n importers: { info: '', episodes: '' },\n episode_type: 2,\n }}\n onSave={onSave}\n />\n}\n\n\nexport function SeriesUpdate({ series }: { series: ISeries }) {\n const onSave = async (data: ISeriesRequest) => {\n const result = await api.patch<ISeries>(`/2/series/${series.id}`, data)\n api.post(`/2/series/${series.id}/update`)\n return result.data\n }\n\n return <SeriesForm\n seriesId={series.id}\n request={{\n externals: { ...series.externals },\n importers: { ...series.importers },\n episode_type: series.episode_type,\n }}\n onSave={onSave}\n />\n}\n\nexport function SeriesForm({ request, onSave, onDelete, seriesId }: { request: ISeriesRequest, onSave: (request: ISeriesRequest) => Promise<ISeries>, onDelete?: () => void, seriesId?: number }) {\n const { handleSubmit, register, formState: { isSubmitting } } = useForm<ISeriesRequest>({\n defaultValues: { ...request }\n })\n const [error, setError] = useState<JSX.Element>(null)\n const toast = useToast()\n const queryClient = useQueryClient()\n\n const onSubmit = handleSubmit(async (data) => {\n try {\n setError(null)\n const series = await onSave(data)\n toast({\n title: 'Series saved',\n status: 'success',\n isClosable: true,\n position: 'top',\n })\n queryClient.setQueryData(['series', series.id], series)\n } catch (e) {\n setError(ErrorMessageFromResponse(e))\n }\n })\n\n return <form onSubmit={onSubmit}>\n <Flex wrap=\"wrap\" gap=\"1rem\">\n {error && <Alert status=\"error\" rounded=\"md\">\n {error}\n </Alert>}\n\n <Flex wrap=\"wrap\" gap=\"1rem\">\n <Flex direction=\"column\" gap=\"1rem\" grow=\"1\">\n <Heading fontSize=\"1.25rem\" fontWeight=\"600\">Externals</Heading>\n <Externals register={register} />\n </Flex>\n\n <Flex direction=\"column\" gap=\"0.5rem\" grow=\"1\">\n <Heading fontSize=\"1.25rem\" fontWeight=\"600\">Importers</Heading>\n <Importers register={register} />\n </Flex>\n\n <Flex direction=\"column\" gap=\"0.5rem\" grow=\"1\">\n <Heading fontSize=\"1.25rem\" fontWeight=\"600\">Extra</Heading>\n <EpisodeType register={register} />\n </Flex>\n </Flex>\n\n\n <Flex align=\"end\" justifyContent=\"end\" gap=\"1rem\" basis=\"100%\">\n {seriesId && <DeleteConfirm seriesId={seriesId} />}\n <Button type=\"submit\" colorScheme=\"blue\" isLoading={isSubmitting} loadingText='Saving'>Save</Button>\n </Flex>\n </Flex>\n </form >\n}\n\n\nfunction Importers({ register }: { register: UseFormRegister<ISeriesRequest> }) {\n return <Flex gap=\"0.5rem\" wrap=\"wrap\">\n <Flex grow=\"1\">\n <FormControl>\n <FormLabel>Info</FormLabel>\n <Select {...register('importers.info')}>\n <option value=\"themoviedb\">TMDb</option>\n <option value=\"thetvdb\">TheTVDB</option>\n <option value=\"tvmaze\">TVMaze</option>\n </Select>\n </FormControl>\n </Flex>\n\n <Flex grow=\"1\">\n <FormControl>\n <FormLabel>Episodes</FormLabel>\n <Select {...register('importers.episodes')}>\n <option value=\"themoviedb\">TMDb</option>\n <option value=\"thetvdb\">TheTVDB</option>\n <option value=\"tvmaze\">TVMaze</option>\n </Select>\n </FormControl>\n </Flex>\n </Flex>\n}\n\n\nfunction Externals({ register }: { register: UseFormRegister<ISeriesRequest> }) {\n return <Flex gap=\"0.5rem\" grow=\"1\" wrap=\"wrap\">\n <FormControl>\n <FormLabel>IMDb</FormLabel>\n <Input {...register('externals.imdb', { required: true })} type='text' />\n </FormControl>\n\n <FormControl>\n <FormLabel>TMDb</FormLabel>\n <Input {...register('externals.themoviedb')} type='text' />\n </FormControl>\n\n <FormControl>\n <FormLabel>TVMaze</FormLabel>\n <Input {...register('externals.tvmaze')} type='text' />\n </FormControl>\n\n <FormControl>\n <FormLabel>TheTVDB</FormLabel>\n <Input {...register('externals.thetvdb')} type='text' />\n </FormControl>\n </Flex>\n}\n\n\nfunction EpisodeType({ register }: { register: UseFormRegister<ISeriesRequest> }) {\n return <Flex gap=\"0.5rem\" grow=\"1\" direction=\"column\">\n <FormControl>\n <FormLabel>Episode type</FormLabel>\n <Select {...register('episode_type')}>\n <option value={1}>Absolute number</option>\n <option value={2}>Season episode</option>\n <option value={3}>Air date</option>\n </Select>\n </FormControl>\n </Flex>\n}\n\nfunction DeleteConfirm({ seriesId }: { seriesId: number }) {\n const { isOpen, onOpen, onClose } = useDisclosure()\n const cancelRef = useRef()\n const toast = useToast()\n\n const onDelete = async () => {\n try {\n await api.delete(`/2/series/${seriesId}`)\n location.reload()\n } catch (e) {\n toast({\n title: 'Failed to delete series',\n description: (e.response.data as IError).message,\n status: 'error',\n duration: 9000,\n isClosable: true,\n position: 'top',\n })\n }\n onClose()\n }\n\n return <>\n <Button colorScheme='red' onClick={onOpen}>\n Delete\n </Button>\n\n <AlertDialog\n isOpen={isOpen}\n leastDestructiveRef={cancelRef}\n onClose={onClose}\n isCentered\n >\n <AlertDialogOverlay>\n <AlertDialogContent>\n <AlertDialogHeader fontSize='lg' fontWeight='bold'>\n Delete Series\n </AlertDialogHeader>\n\n <AlertDialogBody>\n Are you sure? You can't undo this action afterwards.\n </AlertDialogBody>\n\n <AlertDialogFooter>\n <Button ref={cancelRef} onClick={onClose}>\n Cancel\n </Button>\n <Button colorScheme='red' onClick={onDelete} ml={3}>\n Delete\n </Button>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialogOverlay>\n </AlertDialog>\n </>\n}","import { ChevronDownIcon, HamburgerIcon } from '@chakra-ui/icons'\nimport { Avatar, Box, Button, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerHeader, DrawerOverlay, Flex, IconButton, Menu, MenuButton, MenuDivider, MenuItem, MenuList, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, useDisclosure } from '@chakra-ui/react'\nimport { IUser } from '@seplis/interfaces/user'\nimport { useState } from 'react'\nimport { Link, useNavigate, } from 'react-router-dom'\nimport ChangePasswordForm from './change_password_form'\nimport { MovieNew } from './movie/settings'\nimport ChromecastIcon from './player/chromecast-icon'\nimport { SearchButtonDialog } from './search'\nimport { SeriesNew } from './series/settings'\n\nexport default function MainMenu({ active }: { active?: string }) {\n return <Flex\n backgroundColor=\"blackAlpha.500\"\n padding=\"0.6rem\"\n paddingLeft=\"1rem\"\n paddingRight=\"1rem\"\n alignItems=\"center\"\n >\n <Link to=\"/\">\n <Flex\n fontSize=\"2xl\"\n color=\"seplis.100\"\n fontWeight=\"600\"\n marginRight=\"0.75rem\"\n >\n SEPLIS\n </Flex>\n </Link>\n\n <Flex display={['none', 'flex']}>\n <MenuItems active={active} />\n </Flex>\n\n <Box display={['block', 'none']} marginRight=\"0.75rem\">\n <MobileMenu active={active} />\n </Box>\n\n <Box marginRight=\"0.75rem\">\n <SearchButtonDialog />\n </Box>\n\n <Flex\n marginLeft=\"auto\"\n alignItems=\"center\"\n >\n <ChromecastIcon />\n <Menu autoSelect={false}>\n <MenuButton>\n <UserAvatar />\n </MenuButton>\n <MenuList>\n {ChangePasswordMenuItem()}\n <Link to=\"/logout\"><MenuItem>Logout</MenuItem></Link>\n </MenuList>\n </Menu>\n </Flex>\n </Flex>\n}\n\nfunction MobileMenu({ active }: { active?: string }) {\n const { isOpen, onOpen, onClose } = useDisclosure()\n return <>\n <IconButton\n aria-label=\"Menu\"\n icon={<HamburgerIcon />}\n onClick={onOpen}\n />\n <Drawer\n isOpen={isOpen}\n placement='right'\n onClose={onClose}\n >\n <DrawerOverlay />\n <DrawerContent>\n <DrawerCloseButton />\n <DrawerHeader>SEPLIS</DrawerHeader>\n <DrawerBody>\n {isOpen &&\n <Flex direction=\"column\" gap=\"1rem\" justifyContent=\"center\">\n <MenuItems active={active} />\n </Flex>}\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n </>\n}\n\n\nfunction MenuItems({ active }: { active?: string }) {\n return <>\n <Box marginRight={[\"0\", \"0.75rem\"]}>\n <Link to=\"/watch\">\n <Button\n variant={active == 'watch' ? 'solid' : 'ghost'}\n width={['100%', 'auto']}\n >\n Watch\n </Button>\n </Link>\n </Box>\n\n <Menu autoSelect={false}>\n <MenuButton\n variant={active == 'series' ? 'solid' : 'ghost'}\n marginRight={[\"0\", \"0.75rem\"]}\n as={Button}\n rightIcon={<ChevronDownIcon />}\n >\n Series\n </MenuButton>\n <MenuList>\n <Link to=\"/series?sort=popularity_desc\"><MenuItem>Popular</MenuItem></Link>\n <Link to=\"/series?sort=rating_desc\"><MenuItem>Top Rated</MenuItem></Link>\n <Link to=\"/series/home\"><MenuItem>Home</MenuItem></Link>\n <Link to=\"/series/watchlist\"><MenuItem>Watchlist</MenuItem></Link>\n <Link to=\"/series/favorites\"><MenuItem>Favorites</MenuItem></Link>\n <Link to=\"/series/watched\"><MenuItem>Watched</MenuItem></Link>\n <Link to=\"/series/countdown\"><MenuItem>Countdown</MenuItem></Link>\n <Link to=\"/series/recently-aired\"><MenuItem>Recently aired</MenuItem></Link>\n <Link to=\"/series/to-watch\"><MenuItem>To watch</MenuItem></Link>\n <MenuDivider />\n <SeriesNewMenuItem />\n </MenuList>\n </Menu>\n\n\n <Menu autoSelect={false}>\n <MenuButton\n variant={active == 'movies' ? 'solid' : 'ghost'}\n marginRight={[\"0\", \"0.75rem\"]}\n as={Button}\n rightIcon={<ChevronDownIcon />}\n >\n Movies\n </MenuButton>\n <MenuList>\n <Link to=\"/movies?sort=popularity_desc\"><MenuItem>Popular</MenuItem></Link>\n <Link to=\"/movies?sort=rating_desc\"><MenuItem>Top Rated</MenuItem></Link>\n <Link to=\"/movies/watchlist\"><MenuItem>Watchlist</MenuItem></Link>\n <Link to=\"/movies/favorites\"><MenuItem>Favorites</MenuItem></Link>\n <Link to=\"/movies/watched\"><MenuItem>Watched</MenuItem></Link>\n <MenuDivider />\n <MovieNewMenuItem />\n </MenuList>\n </Menu>\n </>\n}\n\n\nfunction SeriesNewMenuItem() {\n const { isOpen, onOpen, onClose } = useDisclosure()\n const navigate = useNavigate()\n\n return <>\n <MenuItem onClick={onOpen}>New series</MenuItem>\n <Modal onClose={onClose} isOpen={isOpen}>\n <ModalOverlay />\n <ModalContent>\n <ModalHeader>New series</ModalHeader>\n <ModalCloseButton />\n <ModalBody paddingBottom=\"1.5rem\">\n <SeriesNew onDone={(seriesId) => {\n onClose()\n navigate(`/series/${seriesId}`)\n }} />\n </ModalBody>\n </ModalContent>\n </Modal>\n </>\n}\n\n\nfunction MovieNewMenuItem() {\n const { isOpen, onOpen, onClose } = useDisclosure()\n const navigate = useNavigate()\n\n return <>\n <MenuItem onClick={onOpen}>New movie</MenuItem>\n <Modal onClose={onClose} isOpen={isOpen}>\n <ModalOverlay />\n <ModalContent>\n <ModalHeader>New movie</ModalHeader>\n <ModalCloseButton />\n <ModalBody paddingBottom=\"1.5rem\">\n <MovieNew onDone={(movieId) => {\n onClose()\n navigate(`/movies/${movieId}`)\n }} />\n </ModalBody>\n </ModalContent>\n </Modal>\n </>\n}\n\n\nfunction ChangePasswordMenuItem() {\n const { isOpen, onOpen, onClose } = useDisclosure()\n\n return <>\n <MenuItem onClick={onOpen}>Change password</MenuItem>\n <Modal onClose={onClose} isOpen={isOpen}>\n <ModalOverlay />\n <ModalContent>\n <ModalHeader>Change password</ModalHeader>\n <ModalCloseButton />\n <ModalBody>\n <ChangePasswordForm />\n </ModalBody>\n <ModalFooter></ModalFooter>\n </ModalContent>\n </Modal>\n </>\n}\n\n\nfunction UserAvatar() {\n const [user, setUser] = useState<IUser>(() => {\n const s = localStorage.getItem('activeUser')\n return JSON.parse(s)\n })\n if (!user)\n return null\n return <Avatar size=\"md\" name={user?.username} />\n}","import { setTitle } from '@seplis/utils'\nimport { useLocation, useNavigate, useParams } from 'react-router-dom'\nimport { MovieLoad } from '@seplis/components/movie/movie'\nimport { Box, Modal, ModalBody, ModalCloseButton, ModalContent, ModalOverlay } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\n\n\nexport default function MoviePage() {\n const { movieId } = useParams()\n\n return <>\n <MainMenu active=\"movies\" />\n <Box margin=\"1rem\">\n <MovieLoad movieId={parseInt(movieId)} onLoaded={(movie) => {\n setTitle(movie.title)\n }} />\n </Box>\n </>\n}\n\n\nexport function MovieModalPage() {\n const { movieId } = useParams()\n const navigate = useNavigate()\n const location = useLocation()\n\n return <Modal\n isOpen={true}\n onClose={() => {\n navigate(location.state?.background?.pathname + location.state?.background?.search || '/')\n }}\n autoFocus={true}\n >\n <ModalOverlay />\n <ModalContent layerStyle=\"baseModal\">\n <ModalCloseButton />\n <ModalBody>\n <MovieLoad movieId={parseInt(movieId)} onLoaded={(movie) => {\n setTitle(movie.title)\n }} />\n </ModalBody>\n </ModalContent>\n </Modal>\n}","import { useToast } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IEpisodeWatched, IEpisodeWatchedDefault, IEventEpisodeWatched } from '@seplis/interfaces/episode'\nimport { EVENT_EPISODE_WATCHED, TriggerEpisodeWatched, useEventListener } from '@seplis/events'\nimport { useEffect, useState } from 'react'\nimport { ErrorMessageFromResponse } from '../error'\nimport { WatchedButton } from '../watched-button'\n\nexport default function EpisodeWatchedButton({ seriesId, episodeNumber, data }: { seriesId: number, episodeNumber: number, data?: IEpisodeWatched }) {\n if (!data) data = IEpisodeWatchedDefault(0)\n const toast = useToast()\n const [watched, setWatched] = useState<IEpisodeWatched>(data)\n const [isUpdating, setUpdating] = useState(false)\n\n useEventListener<IEventEpisodeWatched>(EVENT_EPISODE_WATCHED, ((data) => {\n if ((data.seriesId == seriesId) && (data.episodeNumber == episodeNumber))\n setWatched({ ...data.watched })\n }), [seriesId, episodeNumber])\n\n useEffect(() => {\n if (data != watched)\n setWatched({ ...data })\n }, [data])\n\n const increment = async () => {\n try {\n setUpdating(true)\n const r = await api.post<IEpisodeWatched>(`/2/series/${seriesId}/episodes/${episodeNumber}/watched`)\n TriggerEpisodeWatched(seriesId, episodeNumber, r.data)\n } catch (e) {\n toast({\n title: ErrorMessageFromResponse(e),\n status: 'error',\n isClosable: true,\n position: 'top',\n })\n } finally {\n setUpdating(false)\n }\n }\n\n const decrement = async () => {\n try {\n setUpdating(true)\n const r = await api.delete(`/2/series/${seriesId}/episodes/${episodeNumber}/watched`)\n TriggerEpisodeWatched(seriesId, episodeNumber, r.data)\n } catch (e) {\n toast({\n title: ErrorMessageFromResponse(e),\n status: 'error',\n isClosable: true,\n position: 'top',\n })\n } finally {\n setUpdating(false)\n }\n }\n\n return <WatchedButton \n times={watched.times}\n position={watched.position}\n onIncrement={increment}\n onDecrement={decrement}\n isUpdating={isUpdating}\n />\n}","export interface IEpisodeCreate {\n title: string\n original_title: string | null\n number: number\n season: number | null\n episode: number | null\n air_date: Date | null\n air_datetime: Date | null\n plot: string | null\n runtime: number | null\n rating: number | null\n}\n \n\nexport interface IEpisodeUpdate extends IEpisodeCreate {\n title: string | null\n}\n\n\nexport interface IEpisodeWatched {\n episode_number: number\n times: number\n position: number\n watched_at: string | null\n}\nexport function IEpisodeWatchedDefault(EpisodeNumber: number): IEpisodeWatched {\n return {\n episode_number: EpisodeNumber,\n times: 0,\n position: 0,\n watched_at: null,\n }\n}\n\n\nexport interface IUserCanWatchEpisode {\n on_play_server: boolean\n}\n\n\nexport interface IEpisode {\n title: string | null\n original_title: string | null\n number: number\n season: number | null\n episode: number | null\n plot: string | null\n runtime: number | null\n rating: number | null\n air_date: string | null\n air_datetime: string | null\n user_watched: IEpisodeWatched | null\n user_can_watch: IUserCanWatchEpisode | null\n}\n\n\nexport interface IEpisodeWatchedIncrement {\n watched_at: Date\n}\n\n\nexport interface IEventEpisodeWatched {\n seriesId: number\n episodeNumber: number\n watched: IEpisodeWatched\n}","import { Box, Flex, Stack, Text } from '@chakra-ui/react'\nimport { IEpisode } from '@seplis/interfaces/episode'\nimport { EpisodeAirdate, episodeNumber } from '@seplis/utils'\nimport { ReactNode } from 'react'\nimport { EpisodePlayButton } from './episode-play-button'\nimport EpisodeWatchedButton from './episode-watched-button'\n\nexport default function EpisodeCard({ seriesId, episode }: { seriesId: number, episode: IEpisode }) {\n return <EpisodeCardWrapper>\n <Text noOfLines={1} lineHeight=\"1.3\">{episode.title || 'TBA'}</Text> \n <Text noOfLines={1} lineHeight=\"1.3\">{episodeNumber(episode)} · {EpisodeAirdate(episode)}</Text>\n <Flex>\n <EpisodeWatchedButton seriesId={seriesId} episodeNumber={episode.number} data={episode.user_watched} />\n <Box marginLeft=\"auto\"><EpisodePlayButton seriesId={seriesId} episodeNumber={episode.number} canPlay={episode.user_can_watch?.on_play_server} /></Box>\n </Flex>\n </EpisodeCardWrapper>\n}\n\nexport function EpisodeCardWrapper({ children }: { children: ReactNode }) {\n return <Flex \n direction=\"column\"\n grow=\"1\"\n layerStyle=\"episodeCard\"\n align=\"stretch\"\n gap=\"0.4rem\"\n >\n {children}\n </Flex>\n}","import { Skeleton } from '@chakra-ui/react'\nimport { EpisodeCardWrapper } from './episode-card'\n\n\nexport default function EpisodeSkeleton() {\n return <EpisodeCardWrapper>\n <Skeleton height=\"20px\" width=\"325px\" />\n <Skeleton height=\"20px\" width=\"222px\" />\n <Skeleton height=\"30px\" width=\"150px\" />\n </EpisodeCardWrapper>\n}","import { Text, Heading, Flex } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IEpisode, IEventEpisodeWatched } from '@seplis/interfaces/episode'\nimport { EVENT_EPISODE_WATCHED, useEventListener } from '@seplis/events'\nimport { isAuthed } from '@seplis/utils'\nimport { useQuery } from '@tanstack/react-query'\nimport EpisodeCard, { EpisodeCardWrapper } from './episode-card'\nimport EpisodeSkeleton from './episode-card-skeleton'\n\nexport default function EpisodeLastWatched({ seriesId }: { seriesId: number }) {\n const { data, isInitialLoading, refetch } = useQuery(['series', seriesId, 'episode-last-watched'], async () => {\n const r = await api.get<IEpisode>(`/2/series/${seriesId}/episode-last-watched`)\n return r.data\n }, {\n refetchOnWindowFocus: true,\n enabled: isAuthed(),\n })\n\n useEventListener<IEventEpisodeWatched>(EVENT_EPISODE_WATCHED, ((data) => {\n if (data.seriesId == seriesId)\n refetch()\n }), [])\n\n return <Flex direction=\"column\" grow=\"1\" minW=\"300px\">\n <Heading fontWeight=\"600\" fontSize=\"2xl\" marginBottom=\"0.25rem\">Previously watched</Heading>\n {isInitialLoading ? <EpisodeSkeleton /> : <>\n {data && <EpisodeCard seriesId={seriesId} episode={data} />}\n {!data && <EpisodeCardWrapper><Text color=\"gray.400\">You haven't watched an episode yet</Text></EpisodeCardWrapper>}\n </>}\n </Flex>\n}","import { Text } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IEpisode } from '@seplis/interfaces/episode'\nimport { IPageCursorResult } from '@seplis/interfaces/page'\nimport { dateCountdown, dateInDays, episodeNumber } from '@seplis/utils'\nimport { useQuery } from '@tanstack/react-query'\n\n\nexport default function EpisodeNextToAir({ seriesId }: { seriesId: number }) {\n const { data } = useQuery<IEpisode>(['series', seriesId, 'episode-next-to-air'], async () => {\n const r = await api.get<IPageCursorResult<IEpisode>>(`/2/series/${seriesId}/episodes`, {\n params: {\n 'air_date_ge': new Date().toISOString().substring(0, 10),\n 'first': 1,\n }\n })\n if (r.data.items.length >= 1)\n return r.data.items[0]\n else\n return null\n })\n if (!data)\n return\n return <Text>Next episode: {episodeNumber(data)} - {data.title}{countdown(data.air_datetime)}</Text>\n}\n\n\nfunction countdown(air_datetime: string) {\n if (!air_datetime)\n return ''\n return <>, {dateCountdown(air_datetime)}</>\n}","import { Flex, Heading, Text } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IEpisode, IEventEpisodeWatched } from '@seplis/interfaces/episode'\nimport { EVENT_EPISODE_WATCHED, useEventListener } from '@seplis/events'\nimport { isAuthed } from '@seplis/utils'\nimport { useQuery } from '@tanstack/react-query'\nimport EpisodeCard, { EpisodeCardWrapper } from './episode-card'\nimport EpisodeSkeleton from './episode-card-skeleton'\n\nexport default function EpisodeToWatch({ seriesId }: { seriesId: number }) {\n const { data, isInitialLoading, refetch } = useQuery(['series', seriesId, 'episode-to-watch'], async () => {\n const r = await api.get<IEpisode>(`/2/series/${seriesId}/episode-to-watch`)\n return r.data\n }, {\n refetchOnWindowFocus: true,\n enabled: isAuthed(),\n })\n\n useEventListener<IEventEpisodeWatched>(EVENT_EPISODE_WATCHED, ((data) => {\n if (data.seriesId == seriesId)\n refetch()\n }), [])\n\n return <Flex direction=\"column\" grow=\"1\" minW=\"300px\">\n <Heading fontWeight=\"600\" fontSize=\"2xl\" marginBottom=\"0.25rem\">To watch</Heading>\n {isInitialLoading ? <EpisodeSkeleton /> : <>\n {data && <EpisodeCard seriesId={seriesId} episode={data} />}\n {!data && <EpisodeCardWrapper><Text color=\"gray.400\">No episodes to watch</Text></EpisodeCardWrapper>}\n </>}\n </Flex>\n}","import { Select } from '@chakra-ui/react'\nimport { ISeriesSeason } from '@seplis/interfaces/series'\n\ninterface IProps {\n seasons: ISeriesSeason[]\n onSelect?: (season: number) => void,\n season: number\n}\n\nexport default function SeasonSelect({ seasons, onSelect, season }: IProps) {\n if (!seasons || (seasons.length == 0))\n return null\n return <Select value={season} onChange={(value) => {\n if (onSelect)\n onSelect(parseInt(value.currentTarget.value))\n }}>\n {seasons.map(season => (\n <option key={season.season} value={season.season}>Season {season.season}</option>\n ))}\n </Select>\n}","import { Flex, Stack, Wrap, WrapItem } from '@chakra-ui/react'\nimport { GetAllCursor } from '@seplis/api'\nimport { IEpisode } from '@seplis/interfaces/episode'\nimport { ISeries } from '@seplis/interfaces/series'\nimport { isAuthed } from '@seplis/utils'\nimport { useQuery } from '@tanstack/react-query'\nimport { useEffect, useState } from 'react'\nimport EpisodeCard from './episode-card'\nimport EpisodeSkeleton from './episode-card-skeleton'\nimport SeasonSelect from './season-select'\n\n\ninterface IProps {\n series: ISeries\n defaultSeason?: number\n}\n\nexport default function Episodes({ series, defaultSeason = 1 }: IProps) {\n const [season, setSeason] = useState(defaultSeason)\n useEffect(() => {\n if (season != defaultSeason)\n setSeason(defaultSeason)\n }, [series.id])\n return <Stack>\n <SeasonSelect seasons={series.seasons} season={season} onSelect={setSeason} />\n <RenderEpisodes seriesId={series.id} season={season} />\n </Stack>\n}\n\n\nexport function RenderEpisodes({ seriesId, season }: { seriesId: number, season?: number }) {\n const { data, isFetching } = useQuery(['series', seriesId, 'episodes', season], async () => {\n const result = await GetAllCursor<IEpisode>(`/2/series/${seriesId}/episodes`, {\n params: {\n 'expand': isAuthed() ? 'user_watched,user_can_watch' : null,\n 'season': season ? season : null,\n 'per_page': 100,\n }\n })\n return result\n })\n \n if (isFetching)\n return <LoadingEpisodes />\n\n return <Wrap>\n {data.map(episode => (\n <Flex key={`episode-${episode.number}`} grow=\"1\" basis=\"300px\"><WrapItem width=\"100%\"><EpisodeCard\n seriesId={seriesId}\n episode={episode}\n /></WrapItem></Flex>\n ))}\n <Flex height=\"0px\" grow=\"1\" basis=\"300px\"><WrapItem width=\"100%\"></WrapItem></Flex>\n <Flex height=\"0px\" grow=\"1\" basis=\"300px\"><WrapItem width=\"100%\"></WrapItem></Flex>\n <Flex height=\"0px\" grow=\"1\" basis=\"300px\"><WrapItem width=\"100%\"></WrapItem></Flex>\n </Wrap>\n}\n\n\nexport function LoadingEpisodes({ number = 6 }: { number?: number }) {\n return <>\n <Wrap>\n {[...Array(number)].map((_, i) => (\n <Flex key={i} grow=\"1\" basis=\"300px\"><WrapItem width=\"100%\"><EpisodeSkeleton /></WrapItem></Flex>\n ))}\n </Wrap>\n </>\n}\n","import { Button, useToast } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { isAuthed } from '@seplis/utils'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { ErrorMessageFromResponse } from '../error'\nimport { useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport { focusedBorder } from '@seplis/styles'\nimport { ISeriesWatchlist } from '@seplis/interfaces/series'\nimport { FaBookmark } from 'react-icons/fa'\n\n\nexport default function WatchlistButton({ seriesId }: { seriesId: number }) {\n const toast = useToast()\n const queryClient = useQueryClient()\n\n const toggleWatchlist = useMutation(async (watchlist: boolean) => {\n await queryClient.cancelQueries(['series', 'watchlist-button', seriesId])\n if (watchlist) {\n await api.delete(`/2/series/${seriesId}/watchlist`)\n } else {\n await api.put(`/2/series/${seriesId}/watchlist`)\n }\n queryClient.setQueryData(['series', 'watchlist-button', seriesId], { on_watchlist: !watchlist })\n }, {\n onError: (e) => {\n toast({\n title: ErrorMessageFromResponse(e),\n status: 'error',\n isClosable: true,\n position: 'top',\n })\n }\n })\n\n const { isInitialLoading, data } = useQuery(['series', 'watchlist-button', seriesId], async () => {\n const result = await api.get<ISeriesWatchlist>(`/2/series/${seriesId}/watchlist`)\n return result.data\n }, {\n enabled: isAuthed()\n })\n\n const handleClick = () => {\n toggleWatchlist.mutate(data.on_watchlist)\n }\n\n const { ref, focused } = useFocusable({\n onEnterPress: () => handleClick,\n })\n\n return <Button\n ref={ref}\n isLoading={isInitialLoading || toggleWatchlist.isLoading}\n colorScheme={data?.on_watchlist ? 'yellow' : null}\n onClick={handleClick}\n leftIcon={<FaBookmark />}\n style={focused ? focusedBorder : null}\n >\n Watchlist\n </Button>\n}","import { Box, Skeleton, Stack } from \"@chakra-ui/react\"\n\nexport default function SeriesSkeleton() {\n return <Stack direction=\"column\" spacing=\"1rem\" maxWidth=\"1100px\">\n <Stack direction=\"row\" spacing=\"1rem\">\n <Box className=\"poster-container-sizing\">\n <Box className=\"poster-container\" flexShrink=\"1\">\n <Skeleton height=\"100%\" borderRadius=\"md\" />\n </Box>\n </Box>\n <Stack spacing=\"0.5rem\" direction=\"column\" width=\"100%\">\n <Skeleton height=\"40px\" borderRadius=\"md\" />\n <Skeleton flex=\"1 1 auto\" borderRadius=\"md\" />\n </Stack>\n </Stack>\n <Skeleton height=\"120px\" borderRadius=\"md\" />\n </Stack>\n}","import { Button, useToast } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { isAuthed } from '@seplis/utils'\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'\nimport { ErrorMessageFromResponse } from '../error'\nimport { useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport { focusedBorder } from '@seplis/styles'\nimport { ISeriesFavorite } from '@seplis/interfaces/series'\nimport { StarIcon } from '@chakra-ui/icons'\n\n\nexport default function FavoriteButton({ seriesId }: { seriesId: number }) {\n const toast = useToast()\n const queryClient = useQueryClient()\n\n const toggleFavorite = useMutation(async (favorite: boolean) => {\n await queryClient.cancelQueries(['series', 'favorite-button', seriesId])\n if (favorite) {\n await api.delete(`/2/series/${seriesId}/favorite`)\n } else {\n await api.put(`/2/series/${seriesId}/favorite`)\n }\n queryClient.setQueryData(['series', 'favorite-button', seriesId], { favorite: !favorite })\n }, {\n onError: (e) => {\n toast({\n title: ErrorMessageFromResponse(e),\n status: 'error',\n isClosable: true,\n position: 'top',\n })\n }\n })\n\n const { isInitialLoading, data } = useQuery(['series', 'favorite-button', seriesId], async () => {\n const result = await api.get<ISeriesFavorite>(`/2/series/${seriesId}/favorite`)\n return result.data\n }, {\n enabled: isAuthed()\n })\n\n const handleClick = () => {\n toggleFavorite.mutate(data.favorite)\n }\n\n const { ref, focused } = useFocusable({\n onEnterPress: () => handleClick,\n })\n\n return <Button\n ref={ref}\n isLoading={isInitialLoading || toggleFavorite.isLoading}\n colorScheme={data?.favorite ? 'blue' : null}\n onClick={handleClick}\n leftIcon={<StarIcon />}\n style={focused ? focusedBorder : null}\n >\n Favorite\n </Button>\n}","import { Text, Flex, Box, Skeleton } from '@chakra-ui/react'\nimport { ISeriesCastPerson } from '@seplis/interfaces/series-cast'\nimport { PosterAspectRatio } from '../poster'\n\nexport default function CastCard({ castPerson }: { castPerson: ISeriesCastPerson }) {\n return <Flex gap=\"0.5rem\" layerStyle=\"episodeCard\">\n <Box width=\"70px\" rounded=\"md\" overflow=\"hidden\">\n <PosterAspectRatio\n url={castPerson.person.profile_image?.url+'@SX140.webp'}\n title={castPerson.person.name}\n />\n </Box>\n <Flex direction=\"column\" gap=\"0.25rem\">\n <Text fontWeight=\"600\" lineHeight=\"0.7rem\">{castPerson.person.name}</Text>\n {castPerson.roles.slice(0, 1).map(role => (\n <Text key={role.character}>{role.character}</Text>\n ))}\n </Flex>\n </Flex>\n}\n\nexport function CastCardSkeleton() {\n return <Flex gap=\"0.5rem\" layerStyle=\"episodeCard\">\n <Box width=\"70px\" rounded=\"md\" overflow=\"hidden\"> \n <Skeleton />\n </Box>\n <Flex direction=\"column\" gap=\"0.25rem\">\n <Skeleton height=\"20px\" width=\"175px\" />\n <Skeleton height=\"20px\" width=\"150px\" />\n </Flex>\n </Flex>\n}","import { Heading, SimpleGrid, Stack, Text } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IPageCursorResult } from '@seplis/interfaces/page'\nimport { ISeriesCastPerson } from '@seplis/interfaces/series-cast'\nimport { useQuery } from '@tanstack/react-query'\nimport CastCard, { CastCardSkeleton } from './cast-card'\n\nexport default function CastFeatured({ seriesId }: { seriesId: number }) {\n const { isInitialLoading, data } = useQuery(['movie', seriesId, 'featured'], async () => {\n const result = await api.get<IPageCursorResult<ISeriesCastPerson>>(`/2/series/${seriesId}/cast`, {\n params: {\n per_page: 12,\n order_le: 99,\n },\n })\n return result.data\n })\n return <Stack spacing=\"0.5rem\">\n <Heading fontSize=\"2xl\" fontWeight=\"600\">Top cast</Heading>\n <SimpleGrid minChildWidth={'300px'} spacing=\"0.5rem\">\n {isInitialLoading ? [...Array(3)].map((_, i) => (\n <CastCardSkeleton key={i} />\n )) : data?.items.length > 0 ? data?.items.map(member => (\n <CastCard key={member.person.id} castPerson={member} />\n )) : <Text>No cast specified.</Text>}\n </SimpleGrid>\n </Stack>\n}","import { StarIcon } from '@chakra-ui/icons'\nimport { Alert, AlertTitle, Box, Button, Flex, Heading, Link, Modal, ModalBody, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay, Stack, Tag, Text, useDisclosure, Wrap, WrapItem } from '@chakra-ui/react'\nimport { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport api from '@seplis/api'\nimport { IGenre } from '@seplis/interfaces/genre'\nimport { ISeries, ISeriesSeason } from '@seplis/interfaces/series'\nimport { focusedBorder } from '@seplis/styles'\nimport { isAuthed, langCodeToLang, secondsToHourMin } from '@seplis/utils'\nimport { useQuery } from '@tanstack/react-query'\nimport { useEffect, useState } from 'react'\nimport { FaCog } from 'react-icons/fa'\nimport ChromecastControls from '../player/chromecast-controls'\nimport { Poster } from '../poster'\nimport EpisodeLastWatched from './episode-last-watched'\nimport EpisodeNextToAir from './episode-next-to-air'\nimport EpisodeToWatch from './episode-to-watch'\nimport Episodes from './episodes'\nimport WatchlistButton from './watchlist-button'\nimport { SeriesUpdate } from './settings'\nimport SeriesSkeleton from './skeleton'\nimport FavoriteButton from './favorite-button'\nimport CastFeatured from './cast-featured'\n\n\nexport function SeriesLoad({ seriesId, onLoaded }: { seriesId: number, onLoaded?: (movie: ISeries) => void }) {\n const { isInitialLoading, data } = useQuery<ISeries>(['series', seriesId], async () => {\n const data = await api.get<ISeries>(`/2/series/${seriesId}`)\n if (onLoaded) onLoaded(data.data)\n return data.data\n })\n\n if (isInitialLoading)\n return <SeriesSkeleton />\n\n if (!data)\n return <>\n <Heading as=\"h2\" mb=\"1rem\">Unknown series</Heading>\n <Alert status=\"error\" rounded=\"md\">\n This series doesn't exist.\n </Alert>\n </>\n\n if (!data?.title)\n return <SeriesWaitingForData series={data} />\n\n return <Series series={data} />\n}\n\n\nexport default function Series({ series }: { series: ISeries }) {\n const { ref, focusKey, setFocus } = useFocusable()\n\n useEffect(() => {\n setFocus('SERIES_PLAY')\n }, [])\n\n return <FocusContext.Provider value={focusKey}>\n <Stack direction=\"column\" spacing=\"1rem\" maxWidth=\"1100px\">\n <Stack spacing=\"1rem\" direction=\"row\" >\n <SeriesPoster series={series} />\n <Stack spacing=\"0.5rem\" direction=\"column\" maxWidth=\"800px\" ref={ref}>\n <Title series={series} />\n <BaseInfo series={series} />\n <Genres genres={series.genres} />\n <Buttons series={series} />\n <Plot series={series} />\n <ExternalLinks series={series} />\n <EpisodeNextToAir seriesId={series.id} />\n </Stack>\n </Stack>\n\n <ChromecastControls />\n\n <UserEpisodes series={series} />\n\n <CastFeatured seriesId={series.id} />\n\n <SeasonEpisodes series={series} />\n\n </Stack>\n </FocusContext.Provider>\n}\n\n\nfunction SeriesWaitingForData({ series }: { series: ISeries }) {\n return <Flex direction=\"column\" align=\"center\" gap=\"1rem\">\n <Heading>Series hasn't been updated, waiting for data</Heading>\n <Heading>Refresh to update</Heading>\n <DisplaySettings series={series} />\n </Flex>\n}\n\n\nfunction SeriesPoster({ series: series }: { series: ISeries }) {\n return <div className=\"poster-container-sizing\">\n <div className=\"poster-container\" style={{ 'flexShrink': '0' }}>\n <Poster url={`${series.poster_image?.url}@SX320.webp`} title={series.title} />\n </div>\n </div>\n}\n\n\nfunction Title({ series }: { series: ISeries }) {\n return <Box marginTop=\"-7px\" lineHeight=\"1.3\">\n <Heading as=\"h1\">{series.title || '<Missing title>'}</Heading>\n {series.original_title != series.title &&\n <Heading as=\"h2\" fontSize=\"1.5rem\" color=\"RGBA(255, 255, 255, 0.36)\">{series.original_title}</Heading>}\n\n {series.tagline && <Text><i>{series.tagline}</i></Text>}\n </Box>\n}\n\n\nfunction Plot({ series }: { series: ISeries }) {\n const [expand, setExpand] = useState(false)\n if (!series.plot)\n return\n return <Text cursor=\"pointer\" noOfLines={expand ? null : 3} onClick={() => {\n setExpand(!expand)\n }}>{series.plot}</Text>\n}\n\n\nfunction BaseInfo({ series }: { series: ISeries }) {\n return <Wrap spacingX=\"0.75rem\" lineHeight=\"1.3\">\n {series.premiered && <WrapItem><strong title={series.premiered}>{series.premiered.substring(0, 4)}</strong></WrapItem>}\n {series.language && <WrapItem>{langCodeToLang(series.language)}</WrapItem>}\n {series.runtime ? <WrapItem>{secondsToHourMin(series.runtime)}</WrapItem> : null}\n <SeasonsText seasons={series.seasons} />\n <EpisodesText seasons={series.seasons} />\n {series.rating ? <WrapItem title=\"IMDb rating\"><StarIcon mr=\"0.2rem\" boxSize={3} color=\"yellow.400\" mt=\"4px\" />{series.rating} IMDb</WrapItem> : null}\n </Wrap>\n}\n\n\nfunction SeasonsText({ seasons }: { seasons: ISeriesSeason[] }) {\n return <>\n {seasons?.length > 0 && <Text>{seasons.length} {seasons.length == 1 ? 'season' : 'seasons'}</Text>}\n </>\n}\n\nfunction EpisodesText({ seasons }: { seasons: ISeriesSeason[] }) {\n let episodes = 0\n if (seasons)\n for (const season of seasons) {\n episodes += season.total\n }\n return <>\n <Text>{episodes} {episodes == 1 ? 'episode' : 'episodes'}</Text>\n </>\n}\n\n\nfunction Genres({ genres }: { genres: IGenre[] }) {\n if (!genres || (genres.length < 0))\n return null\n return <Wrap padding=\"0.25rem 0\">\n {genres.map(genre => (\n <WrapItem key={genre.id}><Genre genre={genre} /></WrapItem>\n ))}\n </Wrap>\n}\n\n\nfunction Genre({ genre }: { genre: IGenre }) {\n const { ref, focused } = useFocusable()\n return <Tag\n ref={ref}\n style={focused ? focusedBorder : {}}\n >\n {genre.name}\n </Tag>\n}\n\n\nfunction Buttons({ series }: { series: ISeries }) {\n return <Wrap padding=\"0.25rem 0\">\n <WrapItem><WatchlistButton seriesId={series.id} /></WrapItem>\n <WrapItem><FavoriteButton seriesId={series.id} /></WrapItem>\n <WrapItem><DisplaySettings series={series} /></WrapItem>\n </Wrap>\n}\n\n\nfunction ExternalLinks({ series }: { series: ISeries }) {\n if (!series.externals.imdb && !series.externals.themoviedb)\n return\n return <Wrap>\n <WrapItem>\n {series.externals.imdb && <Link href={`https://imdb.com/title/${series.externals.imdb}`} isExternal>IMDb</Link>}\n </WrapItem>\n <WrapItem>\n {series.externals.themoviedb && <Link href={`https://www.themoviedb.org/tv/${series.externals.themoviedb}`} isExternal>TMDb</Link>}\n </WrapItem>\n </Wrap>\n}\n\n\nfunction DisplaySettings({ series }: { series: ISeries }) {\n const { isOpen, onOpen, onClose } = useDisclosure()\n const { ref, focused } = useFocusable({\n onEnterPress: () => onOpen()\n })\n\n return <>\n <Button\n ref={ref}\n onClick={onOpen}\n leftIcon={<FaCog />}\n style={focused ? focusedBorder : null}\n >\n Settings\n </Button>\n\n <Modal onClose={onClose} isOpen={isOpen}>\n <ModalOverlay />\n <ModalContent>\n <ModalHeader>Settings</ModalHeader>\n <ModalCloseButton />\n <ModalBody paddingBottom=\"1.5rem\">\n <SeriesUpdate series={series} />\n </ModalBody>\n </ModalContent>\n </Modal>\n </>\n}\n\n\nfunction UserEpisodes({ series }: { series: ISeries }) {\n if (series.seasons.length == 0)\n return\n if (!isAuthed())\n return\n return <Flex gap=\"0.5rem\" align=\"stretch\" wrap=\"wrap\" direction=\"row\">\n <EpisodeToWatch seriesId={series.id} />\n <EpisodeLastWatched seriesId={series.id} />\n </Flex>\n}\n\n\nfunction SeasonEpisodes({ series }: { series: ISeries }) {\n return <>\n {series.seasons.length > 0 && <Stack>\n <Heading fontSize=\"2xl\" fontWeight=\"600\">Episodes</Heading>\n <Episodes series={series} defaultSeason={series.seasons[series.seasons.length - 1].season} />\n </Stack>}\n </>\n}","import { Box, Modal, ModalBody, ModalCloseButton, ModalContent, ModalOverlay } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport { SeriesLoad } from '@seplis/components/series/series'\nimport { setTitle } from '@seplis/utils'\nimport { useLocation, useNavigate, useParams } from 'react-router-dom'\n\nexport default function SeriesPage() {\n const { seriesId } = useParams()\n\n return <>\n <MainMenu active=\"series\" />\n <Box margin='1rem'>\n <SeriesLoad seriesId={parseInt(seriesId)} onLoaded={(series) => {\n setTitle(series.title)\n }} />\n </Box>\n </>\n}\n\n\nexport function SeriesModalPage() {\n const { seriesId } = useParams()\n const navigate = useNavigate()\n const location = useLocation()\n\n return <Modal\n isOpen={true}\n onClose={() => {\n navigate(location.state?.background?.pathname + location.state?.background?.search || '/')\n }}\n autoFocus={false}\n >\n <ModalOverlay />\n <ModalContent layerStyle=\"baseModal\">\n <ModalCloseButton />\n <ModalBody>\n <SeriesLoad seriesId={parseInt(seriesId)} onLoaded={(series) => {\n setTitle(series.title)\n }} />\n </ModalBody>\n </ModalContent>\n </Modal>\n}","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/less-loader/dist/cjs.js??ruleSet[1].rules[2].use[2]!./slider.less\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\n\n options.insert = insertFn.bind(null, \"head\");\n \noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/less-loader/dist/cjs.js??ruleSet[1].rules[2].use[2]!./slider.less\";\n export default content && content.locals ? content.locals : undefined;\n","import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons'\nimport { Text, Alert, AlertIcon, Box, Flex, Heading, HStack, Image, Skeleton } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IPageCursorResult } from '@seplis/interfaces/page'\nimport { ISliderItem } from '@seplis/interfaces/slider'\nimport { useInfiniteQuery } from '@tanstack/react-query'\nimport { ReactNode, useEffect, useState } from 'react'\nimport { useFocusable, FocusContext, FocusHandler } from '@noriginmedia/norigin-spatial-navigation'\nimport { Poster } from './poster'\nimport './slider.less'\n\ninterface IProps<S = undefined> {\n title?: string,\n url: string,\n hideIfEmpty?: boolean,\n emptyMessage?: string | null,\n onFocus?: FocusHandler,\n onItemSelected?: (item: S) => void\n parseItem: (item: S) => ISliderItem\n}\n\nexport default function Slider<S = undefined>({ \n title, \n url, \n hideIfEmpty = false, \n emptyMessage,\n parseItem, \n onFocus, \n onItemSelected,\n}: IProps<S>) {\n const [items, setItems] = useState<ISliderItem[]>([])\n const [index, setIndex] = useState(0)\n const [displayItemCount, setDisplayItemCount] = useState(() => (rowWidthItems()))\n const { ref, focusKey } = useFocusable({ onFocus })\n const loadPerPage = 12\n\n const { data, isInitialLoading, fetchNextPage } = useInfiniteQuery(['slider', title, url], async ({ pageParam = null }) => {\n const data = await api.get<IPageCursorResult<S>>(url, {\n params: {\n per_page: loadPerPage * 2,\n cursor: pageParam,\n }\n })\n return data.data\n }, {\n getNextPageParam: (lastPage) => { return lastPage.cursor ?? undefined },\n })\n\n useEffect(() => {\n const items = data?.pages.flatMap((page) => page.items.map((item) => {\n const i = parseItem(item)\n i.data = item\n return i\n })) ?? []\n setItems(items)\n }, [data])\n\n const onCardFocus = (layout: any, props: any, details: any) => {\n const event = details.event as KeyboardEvent\n if (event?.code == 'ArrowRight') {\n if (items.length - index >= displayItemCount) {\n if (layout.node.getAttribute('data-view-index') > 1)\n setIndex(index + 1)\n if ((index % loadPerPage) === 0)\n fetchNextPage()\n }\n } else if (!event || event?.code == 'ArrowLeft') {\n if (index > 0)\n setIndex(index - 1)\n }\n }\n\n function handleResize() {\n setDisplayItemCount(rowWidthItems())\n }\n useEffect(() => {\n window.addEventListener('resize', handleResize)\n return () => {\n return window.removeEventListener('resize', handleResize)\n }\n }, [])\n\n if (hideIfEmpty && !isInitialLoading && items.length === 0)\n return null\n\n return <FocusContext.Provider value={focusKey}>\n <Box ref={ref}>\n {title && <Heading className=\"row-header row-margin\">{title}</Heading>}\n {(!isInitialLoading && data?.pages[0].items?.length === 0) && emptyMessage && <div className=\"row-margin\">\n <Alert status='info'>\n <AlertIcon /> <Text>{emptyMessage}</Text>\n </Alert> \n </div>}\n\n <HStack className=\"slider\" alignItems=\"stretch\">\n {(!isInitialLoading && items) ? <>\n <Cards<S>\n items={items.slice(index, index + displayItemCount)}\n onFocus={onCardFocus}\n onItemSelected={onItemSelected}\n />\n <PeekCard index={index} items={items} next={false} setIndex={setIndex} fetchNextPage={fetchNextPage} />\n <PeekCard index={index} items={items} next={true} setIndex={setIndex} fetchNextPage={fetchNextPage} />\n </> : <SkeletonCards />}\n </HStack>\n </Box>\n </FocusContext.Provider>\n}\n\n\nexport function Cards<S = any>({ items, onFocus, onItemSelected }: { items: ISliderItem[], onFocus: FocusHandler, onItemSelected: (item: S) => void }) {\n const { ref, focusKey } = useFocusable()\n return <FocusContext.Provider value={focusKey}>\n <HStack ref={ref} width=\"100%\">\n {items.map((item, index) => <Card<S>\n key={item.key}\n item={item}\n onFocus={onFocus}\n onItemSelected={onItemSelected}\n viewItemIndex={index}\n />)}\n {items.length > 0 && [...Array(rowWidthItems() - items.length).keys()].map(\n i => <EmptyCard key={`empty-${i}`} />)}\n </HStack>\n </FocusContext.Provider>\n}\n\n\nexport function Card<S = any>({ item, onFocus, onItemSelected, viewItemIndex }: { item: ISliderItem, onFocus: FocusHandler, onItemSelected: (item: S) => void, viewItemIndex?: number }) {\n const { ref, focused } = useFocusable({\n onFocus: onFocus,\n onEnterPress: () => {\n onItemSelected(item.data)\n },\n })\n return <Flex\n className={`slider-item ${focused ? 'focused' : ''}`}\n key={item.key} ref={ref}\n data-view-index={viewItemIndex}\n borderRadius=\"md\"\n cursor=\"pointer\"\n overflow=\"hidden\"\n grow=\"1\"\n direction=\"column\"\n onClick={() => {\n onItemSelected(item.data)\n }}\n >\n {item.topText !== undefined && <TextBox>{item.topText}</TextBox>}\n <Box className=\"poster-container\" borderRadius=\"0\">\n <Poster url={`${item.img}@SX320.webp`} title={item.title} />\n </Box>\n {item.bottomText !== undefined && <TextBox>{item.bottomText}</TextBox>}\n </Flex>\n}\n\n\nfunction TextBox({ children }: { children: ReactNode }) {\n return <Box\n backgroundColor=\"black\"\n textAlign=\"center\"\n padding=\"0.25rem\"\n fontSize={['0.7rem', '1rem']}\n >\n {children}\n </Box>\n}\n\n\nfunction EmptyCard() {\n return <Box className=\"poster-container slider-item\"></Box>\n}\n\n\nexport function SkeletonCards() {\n return <>\n {[...Array(rowWidthItems()).keys()].map((key) => (\n <Skeleton key={`skeleton-${key}`} className=\"poster-container slider-item\" rounded=\"md\" width=\"100%\" height=\"100%\" />\n ))}\n </>\n}\n\n\ninterface IPeekCardProps {\n index: number\n items: ISliderItem[]\n setIndex: React.Dispatch<React.SetStateAction<number>>\n fetchNextPage: () => void\n next: boolean\n}\nfunction PeekCard({ index, items, next, setIndex, fetchNextPage }: IPeekCardProps) {\n const displayCount = rowWidthItems()\n let itemIndex = 0\n if (next) {\n itemIndex = index + displayCount\n if (items.length <= index + displayCount)\n return\n } else {\n itemIndex = index - 1\n if (index < 1)\n return\n }\n\n const prevClick = () => {\n setIndex((index) => {\n let i = index - displayCount\n if (i < 0)\n i = 0\n return i\n })\n }\n\n const nextClick = () => {\n setIndex((index) => {\n fetchNextPage()\n let i = index + displayCount\n if (i > (items.length - 1))\n i = (items.length - 1) - displayCount\n return i\n })\n }\n\n return <div className={`slider-peek ${next ? 'next' : 'prev'}`}>\n {(items[itemIndex]?.img) &&\n <div className=\"image\">\n <Image\n src={`${items[itemIndex].img}@SX320.webp`}\n />\n </div>}\n\n <div className=\"background\"></div>\n <div className=\"button\" onClick={next ? nextClick : prevClick}>\n {next ? <ChevronRightIcon /> : <ChevronLeftIcon />}\n </div>\n </div>\n}\n\n\nfunction rowWidthItems() {\n const width = window.innerWidth\n if (width >= 1600)\n return 12\n else if (width >= 1100)\n return 7\n else if (width >= 600)\n return 6\n else\n return 3\n}","import { Alert, AlertIcon, Stack, Text } from '@chakra-ui/react'\nimport { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport MainMenu from '@seplis/components/main-menu'\nimport Slider from '@seplis/components/slider'\nimport { ISeries, ISeriesAndEpisode } from '@seplis/interfaces/series'\nimport { dateCountdown, episodeNumber, setTitle } from '@seplis/utils'\nimport { useCallback, useEffect } from 'react'\nimport { useLocation, useNavigate } from 'react-router-dom'\n\n\nexport default function SeriesHome() {\n const { ref, focusKey, focusSelf } = useFocusable()\n const navigate = useNavigate()\n const location = useLocation()\n\n useEffect(() => {\n setTitle('Series Home')\n }, [location.pathname])\n\n useEffect(() => {\n focusSelf()\n }, [focusSelf])\n\n const onRowFocus = useCallback(({ y }: { y: number }) => {\n window.scrollTo({\n top: y,\n behavior: 'smooth'\n });\n }, [ref])\n\n const itemSelected = (item: ISeriesAndEpisode) => {\n navigate(`/series/${item.series.id}`, {state: {\n background: location\n }})\n }\n const seriesSelected = (series: ISeries) => {\n navigate(`/series/${series.id}`, {state: {\n background: location\n }})\n }\n\n return <>\n <MainMenu active=\"series\" />\n \n <FocusContext.Provider value={focusKey}>\n\n <Stack ref={ref} marginTop=\"0.5rem\" marginBottom=\"0.5rem\">\n\n <Slider<ISeries>\n title=\"Watched\"\n url=\"/2/series?user_has_watched=true&sort=user_last_episode_watched_at_desc\"\n parseItem={(series) => (\n {\n key: `series-${series.id}`,\n title: series.title,\n img: series.poster_image?.url,\n bottomText: episodeNumber(series.user_last_episode_watched),\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={seriesSelected}\n emptyMessage={`You haven't watched anything.`}\n />\n\n <Slider<ISeriesAndEpisode>\n title=\"Recently Aired\"\n url=\"/2/series/recently-aired?user_watchlist=true\"\n parseItem={(item) => (\n {\n key: `series-${item.series.id}`,\n title: item.series.title,\n img: item.series.poster_image?.url,\n bottomText: episodeNumber(item.episode),\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={itemSelected}\n emptyMessage={`No series you follow has aired recently.`}\n />\n\n\n <Slider<ISeriesAndEpisode>\n title=\"Countdown\"\n url=\"/2/series/countdown\"\n parseItem={(item) => (\n {\n key: `series-${item.series.id}`,\n title: item.series.title,\n img: item.series.poster_image?.url,\n bottomText: episodeNumber(item.episode),\n topText: dateCountdown(item.episode.air_datetime),\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={itemSelected}\n hideIfEmpty={true}\n />\n\n <Slider<ISeriesAndEpisode>\n title=\"Series to Watch\"\n url=\"/2/series/to-watch\"\n parseItem={(item) => (\n {\n key: `series-${item.series.id}`,\n title: item.series.title,\n img: item.series.poster_image?.url,\n bottomText: episodeNumber(item.episode),\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={itemSelected}\n emptyMessage={`You have no series to watch, go explore!`}\n />\n \n </Stack>\n </FocusContext.Provider>\n </>\n}","import { Alert, AlertIcon, AlertTitle, Box, Button, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerHeader, DrawerOverlay, Flex, Heading, Skeleton, useDisclosure, AlertDescription } from '@chakra-ui/react'\nimport { FocusHandler } from '@noriginmedia/norigin-spatial-navigation'\nimport api from '@seplis/api'\nimport { IPageCursorTotalResult } from '@seplis/interfaces/page'\nimport { ISliderItem } from '@seplis/interfaces/slider'\nimport { useInfiniteQuery } from '@tanstack/react-query'\nimport { useEffect, useState } from 'react'\nimport { FaFilter } from 'react-icons/fa'\nimport { ErrorMessageFromResponse } from './error'\nimport { Card } from './slider'\nimport { removeEmpty } from '@seplis/utils'\n\ninterface IProps<S = any> {\n title: string\n url: string\n urlParams?: Object\n emptyMessage?: string | null,\n filtersActive?: boolean,\n showFilterButton?: boolean,\n onFocus?: FocusHandler,\n onItemSelected?: (item: S) => void\n parseItem: (item: S) => ISliderItem\n renderFilter?: TRenderFilter\n}\n\ntype TRenderFilter = (options?: {\n onClose: () => void\n}) => JSX.Element\n\nconst SplitWidths = ['100px', '125px', null, '175px', null, '200px']\n\nexport default function List<S = any>({ \n title, \n url, \n urlParams,\n emptyMessage,\n filtersActive = false,\n showFilterButton = true,\n renderFilter, \n onFocus, \n onItemSelected, \n parseItem\n}: IProps) {\n const [items, setItems] = useState<ISliderItem[]>([])\n const { isFetching, isInitialLoading, data, error, fetchNextPage, isFetchingNextPage, hasNextPage } = useInfiniteQuery(['list', title, url, urlParams], async ({ pageParam = null }) => {\n const r = await api.get<IPageCursorTotalResult<S>>(url, {\n params: {\n ...removeEmpty(urlParams),\n cursor: pageParam,\n },\n })\n return r.data\n }, {\n getNextPageParam: (lastPage) => lastPage.cursor ?? undefined,\n })\n\n useEffect(() => {\n const items = data?.pages.flatMap((page) => page.items.map((item) => {\n const i = parseItem(item)\n i.data = item\n return i\n })) ?? []\n setItems(items)\n }, [data])\n\n if (error)\n return <Alert status=\"error\" rounded=\"md\">\n <AlertIcon />\n <AlertTitle>{ErrorMessageFromResponse(error)}</AlertTitle>\n </Alert>\n const loading = (isInitialLoading || isFetchingNextPage || (isFetching && data?.pages?.length == 1))\n return <>\n <Flex wrap=\"wrap\">\n <Heading as=\"h1\" marginBottom=\"1rem\" fontSize={['1.5rem', '2rem']}>{title.replace('{total}', data?.pages?.[0]?.total?.toString() || '...')}</Heading>\n {showFilterButton && <Box marginLeft=\"auto\"><FilterButton renderFilter={renderFilter} /></Box>}\n </Flex>\n \n {!loading && items.length == 0 && data?.pages[0]?.items?.length == 0 && emptyMessage && <Alert status='info' variant='top-accent'>\n <AlertIcon /> \n <AlertTitle>{emptyMessage}</AlertTitle>\n {filtersActive && <AlertDescription>\n You have filters active!\n </AlertDescription>}\n </Alert>}\n\n <Flex gap=\"0.75rem\" wrap=\"wrap\">\n {(isFetchingNextPage || !loading) && items && items.map((item, i) => {\n return <Flex key={item.key} grow=\"1\" basis={SplitWidths}>\n <Card\n item={item}\n onFocus={onFocus}\n onItemSelected={onItemSelected}\n viewItemIndex={i}\n />\n </Flex>\n })}\n {loading && <SkeletonCards amount={24} />}\n <BlankCards amount={12} />\n </Flex>\n\n {hasNextPage && <Flex marginBottom=\"2rem\" alignItems=\"center\" justifyContent=\"center\">\n <Button onClick={() => fetchNextPage()} size=\"lg\">Load more</Button>\n </Flex>}\n </>\n}\n\n\nfunction SkeletonCards({ amount }: { amount: number }) {\n return <>\n {[...Array(amount).keys()].map((key) => (\n <Flex key={`skeleton-${key}`} grow=\"1\" basis={SplitWidths} >\n <Skeleton className=\"poster-container\" rounded=\"md\" width=\"100%\" height=\"100%\" />\n </Flex>\n ))}\n </>\n}\n\n\nfunction BlankCards({ amount }: { amount: number }) {\n return <>\n {[...Array(amount).keys()].map((key) => (\n <Flex key={`blank-${key}`} height=\"0px\" grow=\"1\" basis={SplitWidths}></Flex>\n ))}\n </>\n}\n\n\nfunction FilterButton({ renderFilter }: { renderFilter: TRenderFilter }) {\n const { isOpen, onOpen, onClose } = useDisclosure()\n return <>\n <Button colorScheme=\"blue\" rightIcon={<FaFilter />} onClick={onOpen}>Filter</Button>\n <Drawer\n isOpen={isOpen}\n placement='right'\n onClose={onClose}\n >\n <DrawerOverlay />\n <DrawerContent>\n <DrawerCloseButton />\n <DrawerHeader>Filter</DrawerHeader>\n\n <DrawerBody>\n {renderFilter({\n onClose: onClose,\n })}\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n </>\n}","import { Box, FormControl, FormLabel, Stack, Switch } from '@chakra-ui/react'\nimport api from '@seplis/api'\nimport { IGenre } from '@seplis/interfaces/genre'\nimport { useQuery } from '@tanstack/react-query'\nimport { useState } from 'react'\nimport { useController, Control } from 'react-hook-form'\n\nexport const SelectGenre = ({ control, name, type }: { control: Control<any, any>, name: string, type: 'series' | 'movie'}) => {\n const { isInitialLoading, data } = useQuery(['genres', type], async () => {\n const result = await api.get<IGenre[]>('/2/genres', {\n params: {\n type: type,\n },\n })\n return result.data\n })\n const { field } = useController({ control, name })\n\n const [value, setValue] = useState<number[]>(field.value || [])\n\n if (isInitialLoading) return <Box>Loading Genres</Box>\n\n return <Stack spacing=\"0.25rem\">\n {data && data.map(genre => (\n <FormControl key={`genre-${genre.id}`} display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor={`genre-${genre.id}`} flexGrow={1} mb='0' cursor='pointer' fontWeight='normal'>\n {genre.name}\n </FormLabel>\n <Switch \n id={`genre-${genre.id}`} \n size='lg' \n value={genre.id} \n isChecked={value.includes(genre.id)}\n onChange={(e) => {\n let v: number[]\n if (e.target.checked) {\n v = [...value, genre.id]\n } else {\n v = value.filter(v => v !== genre.id)\n }\n setValue(v)\n field.onChange(v)\n }}\n />\n </FormControl>\n ))}\n </Stack>\n\n}","import { Select, SelectProps } from '@chakra-ui/react'\nimport { forwardRef } from 'react'\n\n\nexport const SelectSeriesUserSort = forwardRef<any, SelectProps>((props, ref) => {\n return <Select ref={ref} {...props}>\n <option value=\"popularity_desc\">Popularity</option>\n <option value=\"rating_desc\">IMDb Rating</option>\n <option value=\"user_rating_desc\">Your rating</option>\n <option value=\"premiered_desc\">Premiered DESC</option>\n <option value=\"premiered_asc\">Premiered ASC</option>\n <option value=\"user_watchlist_added_at_desc\">Added to watchlist at DESC</option>\n <option value=\"user_watchlist_added_at_asc\">Added to watchlist at ASC</option>\n <option value=\"user_favorite_added_at_desc\">Added to favorites at DESC</option>\n <option value=\"user_favorite_added_at_asc\">Added to favorites at ASC</option>\n <option value=\"user_last_episode_watched_at_desc\">Watched at DESC</option>\n <option value=\"user_last_episode_watched_at_asc\">Watched at ASC</option>\n </Select>\n})","import { Select, SelectProps } from '@chakra-ui/react'\nimport { forwardRef, useMemo } from 'react'\nimport ISO6391 from 'iso-639-1'\n\n\n// Extend the Select component\nexport const SelectLanguage = forwardRef<any, SelectProps>((props, ref) => {\n const languages = useMemo(() => {\n return <>{ISO6391.getLanguages(ISO6391.getAllCodes()).map((language) => {\n return <option key={language.code} value={language.code}>{language.name}</option>\n })}\n </>\n }, [])\n\n return <Select ref={ref} {...props} placeholder=\"Select a language\">\n {languages}\n </Select>\n})\n","import { FormControl, FormLabel, Stack, Switch } from '@chakra-ui/react'\nimport { useState } from 'react'\nimport { useController, Control } from 'react-hook-form'\n\nexport interface ISwitchRadioGroupOption {\n name: string\n value: string\n}\n\nexport const SwitchRadioGroup = ({ control, name, options }: { control: Control<any, any>, name: string, options: ISwitchRadioGroupOption[] }) => {\n const { field } = useController({ control, name })\n\n const [value, setValue] = useState<string>(field.value || '')\n\n return <Stack spacing=\"0.25rem\">\n {options && options.map(option => (\n <FormControl key={option.name} display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor={`${name}-${option.name}-${option.value}`} flexGrow={1} mb='0' cursor='pointer' color='blue.300'>\n {option.name}\n </FormLabel>\n <Switch \n id={`${name}-${option.name}-${option.value}`} \n size='lg' \n value={option.value}\n isChecked={value === option.value}\n onChange={(e) => {\n let v: string = ''\n if (e.target.checked) {\n v = option.value\n }\n setValue(v)\n field.onChange(v)\n }}\n />\n </FormControl>\n ))}\n </Stack>\n}","import { FormControl, FormLabel, Input, Select, Stack, Switch } from '@chakra-ui/react'\nimport { SelectGenre } from '@seplis/components/select-genre'\nimport { useForm } from 'react-hook-form'\nimport { SelectSeriesUserSort } from './user-sort-select'\nimport { useEffect } from 'react'\nimport { SelectLanguage } from '../select-language'\nimport { SwitchRadioGroup } from '../switch-radio-group'\n\nexport interface IUserFilterData {\n genre_id?: number[]\n sort?: string | null\n user_can_watch?: boolean | null\n premiered_gt?: string | null\n premiered_lt?: string | null\n rating_gt?: number | null\n rating_lt?: number | null\n rating_votes_gt?: number | null\n language?: string | null\n user_has_watched?: string | null\n}\n\nexport function SeriesUserFilter({ defaultValue, onSubmit }: { defaultValue?: IUserFilterData, onSubmit?: (data: IUserFilterData) => void }) {\n const { register, handleSubmit, control, watch } = useForm<IUserFilterData>({\n defaultValues: defaultValue,\n })\n\n useEffect(() => {\n const sub = watch(() => handleSubmit(onSubmit)())\n return () => sub.unsubscribe()\n }, [onSubmit, watch])\n\n return <form onSubmit={handleSubmit(onSubmit)}>\n <Stack spacing=\"1rem\">\n <FormControl>\n <FormLabel htmlFor='sort' color='blue.300'>Sort by</FormLabel>\n <SelectSeriesUserSort {...register('sort')} />\n </FormControl>\n\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='user-can-watch' alignItems='center' mb='0' color='blue.300'>\n On play servers\n </FormLabel>\n <Switch id='user-can-watch' {...register('user_can_watch')} size='lg' />\n </FormControl> \n\n <SwitchRadioGroup control={control} name='user_has_watched' options={[\n { name: 'Have watched', value: 'true' },\n { name: 'Have NOT watched', value: 'false' },\n ]} />\n \n <Stack spacing=\"0.25rem\">\n <FormControl display='flex' alignItems='center' justifyContent='space-between' mb='0'>\n <FormLabel alignItems='center' mb='0' color='blue.300'>\n Premiered\n </FormLabel>\n </FormControl>\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='premiered_gt' alignItems='center' mb='0' fontWeight='normal'>\n From:\n </FormLabel>\n <Input id='premiered_gt' type='date' {...register('premiered_gt')} width='auto'/>\n </FormControl>\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='premiered_lt' alignItems='center' mb='0' fontWeight='normal'>\n To:\n </FormLabel>\n <Input id='premiered_lt' type='date' {...register('premiered_lt')} width='auto' />\n </FormControl>\n </Stack>\n\n <Stack spacing=\"0.25rem\">\n <FormControl display='flex' alignItems='center' justifyContent='space-between' mb='0'>\n <FormLabel alignItems='center' mb='0' color='blue.300'>\n Rating\n </FormLabel>\n </FormControl>\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='rating_gt' alignItems='center' mb='0' fontWeight='normal'>\n From:\n </FormLabel>\n <Select id='rating_gt' {...register('rating_gt')} width='auto'>\n {[...Array(11).keys()].map((i) => (\n <option key={i} value={i}>{i}</option>\n ))}\n </Select>\n <FormLabel htmlFor='rating_lt' alignItems='center' mb='0' fontWeight='normal'>\n To:\n </FormLabel>\n <Select id='rating_lt' {...register('rating_lt')} width='auto' defaultValue={10}>\n {[...Array(10).keys()].map((i) => (\n <option key={i+1} value={i+1}>{i+1}</option>\n ))}\n </Select>\n </FormControl>\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='rating_gt' alignItems='center' mb='0' fontWeight='normal'>\n Minumum votes:\n </FormLabel>\n <Select id='rating_lt' {...register('rating_votes_gt')} width='auto'>\n {[...Array(31).keys()].map((i) => (\n <option key={i} value={i*100}>{i*100}</option>\n ))}\n </Select>\n </FormControl>\n </Stack>\n\n <FormControl>\n <FormLabel htmlFor='Language' color='blue.300'>Language</FormLabel>\n <SelectLanguage name='language' {...register('language')} />\n </FormControl>\n\n <FormControl>\n <FormLabel htmlFor='genres' color='blue.300'>Genres</FormLabel>\n <SelectGenre control={control} name='genre_id' type='series' />\n </FormControl>\n\n </Stack>\n </form>\n}","import { Box } from '@chakra-ui/react'\nimport { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport ImageList from '@seplis/components/list'\nimport { ISeries } from '@seplis/interfaces/series'\nimport { ISliderItem } from '@seplis/interfaces/slider'\nimport { useEffect } from 'react'\nimport { useLocation, useNavigate } from 'react-router-dom'\nimport { BooleanParam, NumberParam, NumericArrayParam, StringParam, useQueryParams, withDefault } from 'use-query-params'\nimport { IUserFilterData, SeriesUserFilter } from '../../components/series/user-filter'\nimport { searchStringToObject } from 'serialize-query-params'\n\ninterface IProps<S = ISeries>{\n title: string\n url: string\n defaultSort?: string | null\n emptyMessage?: string | null,\n showFilterButton?: boolean,\n onItemSelected?: (item: S) => void\n parseItem?: (item: S) => ISliderItem\n}\n\nexport default function UserSeriesList<S = ISeries>({ \n title, \n url, \n defaultSort, \n emptyMessage,\n showFilterButton=true,\n parseItem, \n onItemSelected\n}: IProps<S>) {\n const { ref, focusKey, focusSelf } = useFocusable()\n const navigate = useNavigate()\n const location = useLocation()\n\n const [query, setQuery] = useQueryParams({\n sort: withDefault(StringParam, defaultSort),\n genre_id: withDefault(NumericArrayParam, []),\n user_can_watch: withDefault(BooleanParam, localStorage.getItem('filter-user-can-watch') === 'true'),\n premiered_gt: StringParam,\n premiered_lt: StringParam,\n rating_gt: NumberParam,\n rating_lt: withDefault(NumberParam, 10),\n rating_votes_gt: NumberParam,\n language: StringParam,\n user_has_watched: StringParam,\n }, {\n searchStringToObject: () => {\n // Prevent using the the actual location.search string when the series modal is open\n // so the background update when the actual location.search changes\n return searchStringToObject(location.search)\n }\n })\n\n useEffect(() => {\n focusSelf()\n }, [focusSelf])\n\n return <>\n <FocusContext.Provider value={focusKey}>\n <Box ref={ref}>\n <ImageList<S>\n title={title}\n url={url}\n emptyMessage={emptyMessage}\n filtersActive={isFilterActive(query)}\n showFilterButton={showFilterButton}\n urlParams={{\n ...query,\n 'per_page': 50,\n }}\n parseItem={parseItem || ((series) => (\n {\n key: `series-${series.id}`,\n title: series.title,\n img: series.poster_image?.url,\n }\n ))}\n onItemSelected={onItemSelected || ((series: ISeries) => {\n navigate(`/series/${series.id}`, {state: {\n background: location\n }})\n })}\n \n renderFilter={(options) => {\n return <SeriesUserFilter defaultValue={query} onSubmit={(data) => {\n setQuery(data)\n if (data.user_can_watch === true) \n localStorage.setItem('filter-user-can-watch', 'true')\n else\n localStorage.removeItem('filter-user-can-watch')\n }} />\n }}\n />\n </Box>\n </FocusContext.Provider>\n </>\n}\n\n\nfunction isFilterActive(query: IUserFilterData) {\n return query.genre_id?.length > 0\n || query.user_can_watch === true \n || query.premiered_gt != null\n || query.premiered_lt != null\n || (query.rating_gt != null && query.rating_gt !== 0)\n || (query.rating_lt != null && query.rating_lt !== 10)\n || query.rating_votes_gt != null\n || query.language != null\n || query.user_has_watched != null\n}","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport SeriesUserList from '@seplis/components/series/user-list'\nimport { setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\n\nexport default function Browse() {\n useEffect(() => {\n setTitle('Series')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"series\" />\n <Box margin=\"1rem\">\n <SeriesUserList\n title=\"Series\"\n url=\"/2/series\"\n defaultSort='popularity_desc'\n emptyMessage={`No series to show.`}\n />\n </Box>\n </>\n}\n","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport SeriesUserList from '@seplis/components/series/user-list'\nimport { setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\n\nexport default function SeriesWatchlist() {\n useEffect(() => {\n setTitle('Series Watchlist')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"series\" />\n <Box margin=\"1rem\">\n <SeriesUserList\n title=\"Series watchlist\"\n url=\"/2/series?user_watchlist=true\"\n defaultSort='user_watchlist_added_at_desc'\n emptyMessage={`You have no series in your watchlist.`}\n />\n </Box>\n </>\n}\n","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport SeriesUserList from '@seplis/components/series/user-list'\nimport { setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\n\nexport default function SeriesFavorites() {\n useEffect(() => {\n setTitle('Series favorites')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"series\" />\n <Box margin=\"1rem\">\n <SeriesUserList\n title=\"Series favorites\"\n url=\"/2/series?user_favorites=true\"\n defaultSort='user_favorite_added_at_desc'\n emptyMessage={`You have no series in your favorites.`}\n />\n </Box>\n </>\n}\n","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport UserSeriesList from '@seplis/components/series/user-list'\nimport { setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\n\nexport default function SeriesWatched() {\n useEffect(() => {\n setTitle('Series watched')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"series\" />\n <Box margin=\"1rem\">\n <UserSeriesList\n title=\"Series watched\"\n url=\"/2/series?user_has_watched=true\"\n defaultSort='user_last_episode_watched_at_desc'\n emptyMessage={`You have not watched any series.`}\n />\n </Box>\n </>\n}\n","import { Select, SelectProps } from '@chakra-ui/react'\nimport { forwardRef } from 'react'\n\n\nexport const SelectMovieUserSort = forwardRef<any, SelectProps>((props, ref) => {\n return <Select ref={ref} {...props}>\n <option value=\"popularity_desc\">Popularity</option>\n <option value=\"rating_desc\">IMDb Rating</option>\n <option value=\"release_date_desc\">Release Date DESC</option>\n <option value=\"release_date_asc\">Release Date ASC</option>\n <option value=\"user_watchlist_added_at_desc\">Added to watchlist at DESC</option>\n <option value=\"user_watchlist_added_at_asc\">Added to watchlist at ASC</option>\n <option value=\"user_favorite_added_at_desc\">Added to favorites at DESC</option>\n <option value=\"user_favorite_added_at_asc\">Added to favorites at ASC</option>\n <option value=\"user_last_watched_at_desc\">Watched at DESC</option>\n <option value=\"user_last_watched_at_asc\">Watched at ASC</option>\n </Select>\n})","import { FormControl, FormLabel, Heading, Input, Select, Stack, Switch } from '@chakra-ui/react'\nimport { SelectGenre } from '@seplis/components/select-genre'\nimport { useForm } from 'react-hook-form'\nimport { SelectMovieUserSort } from './user-sort-select'\nimport { useEffect } from 'react'\nimport { SelectLanguage } from '../select-language'\nimport { SwitchRadioGroup } from '../switch-radio-group'\n\nexport interface IUserFilterData {\n genre_id?: number[]\n sort?: string | null\n user_can_watch?: boolean | null\n release_date_gt?: string | null\n release_date_lt?: string | null\n rating_gt?: number | null\n rating_lt?: number | null\n rating_votes_gt?: number | null\n language?: string | null\n user_has_watched?: string | null\n}\n\nexport function MovieUserFilter({ defaultValue, onSubmit }: { defaultValue?: IUserFilterData, onSubmit?: (data: IUserFilterData) => void }) {\n const { register, handleSubmit, control, watch } = useForm<IUserFilterData>({\n defaultValues: defaultValue,\n })\n \n useEffect(() => {\n const sub = watch(() => handleSubmit(onSubmit)())\n return () => sub.unsubscribe()\n }, [onSubmit, watch])\n\n return <form onSubmit={handleSubmit(onSubmit)}>\n <Stack spacing=\"1rem\">\n \n <FormControl>\n <FormLabel htmlFor='sort' color='blue.300'>Sort by</FormLabel>\n <SelectMovieUserSort {...register('sort')} />\n </FormControl>\n\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='user-can-watch' alignItems='center' mb='0' color='blue.300'>\n On play servers\n </FormLabel>\n <Switch id='user-can-watch' {...register('user_can_watch')} size='lg' />\n </FormControl>\n\n <SwitchRadioGroup control={control} name='user_has_watched' options={[\n { name: 'Have watched', value: 'true' },\n { name: 'Have NOT watched', value: 'false' },\n ]} />\n \n <Stack spacing=\"0.25rem\">\n <FormControl display='flex' alignItems='center' justifyContent='space-between' mb='0'>\n <FormLabel alignItems='center' mb='0' color='blue.300'>\n Release date\n </FormLabel> \n </FormControl>\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='release_date_gt' alignItems='center' mb='0' fontWeight='normal'>\n From:\n </FormLabel>\n <Input id='release_date_gt' type='date' {...register('release_date_gt')} width='auto' />\n </FormControl>\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='release_date_lt' alignItems='center' mb='0' fontWeight='normal'>\n To:\n </FormLabel>\n <Input id='release_date_lt' type='date' {...register('release_date_lt')} width='auto' />\n </FormControl>\n </Stack>\n \n <Stack spacing=\"0.25rem\">\n <FormControl display='flex' alignItems='center' justifyContent='space-between' mb='0'>\n <FormLabel alignItems='center' mb='0' color='blue.300'>\n Rating\n </FormLabel>\n </FormControl>\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='rating_gt' alignItems='center' mb='0' fontWeight='normal'>\n From:\n </FormLabel>\n <Select id='rating_gt' {...register('rating_gt')} width='auto'>\n {[...Array(11).keys()].map((i) => (\n <option key={i} value={i}>{i}</option>\n ))}\n </Select>\n <FormLabel htmlFor='rating_lt' alignItems='center' mb='0' fontWeight='normal'>\n To:\n </FormLabel>\n <Select id='rating_lt' {...register('rating_lt')} width='auto' defaultValue={10}>\n {[...Array(10).keys()].map((i) => (\n <option key={i+1} value={i+1}>{i+1}</option>\n ))}\n </Select>\n </FormControl>\n <FormControl display='flex' alignItems='center' justifyContent='space-between'>\n <FormLabel htmlFor='rating_gt' alignItems='center' mb='0' fontWeight='normal'>\n Minumum votes:\n </FormLabel>\n <Select id='rating_lt' {...register('rating_votes_gt')} width='auto'>\n {[...Array(31).keys()].map((i) => (\n <option key={i} value={i*100}>{i*100}</option>\n ))}\n </Select>\n </FormControl>\n </Stack>\n \n <FormControl>\n <FormLabel htmlFor='Language' color='blue.300'>Language</FormLabel>\n <SelectLanguage name='language' {...register('language')} />\n </FormControl>\n \n <FormControl>\n <FormLabel htmlFor='genres' color='blue.300'>Genres</FormLabel>\n <SelectGenre control={control} name='genre_id' type='movie' />\n </FormControl>\n\n </Stack>\n </form>\n}","import { Box } from '@chakra-ui/react'\nimport { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport ImageList from '@seplis/components/list'\nimport { IMovie } from '@seplis/interfaces/movie'\nimport { useEffect } from 'react'\nimport { useLocation, useNavigate } from 'react-router-dom'\nimport { BooleanParam, NumberParam, NumericArrayParam, StringParam, searchStringToObject, useQueryParams, withDefault } from 'use-query-params'\nimport { IUserFilterData, MovieUserFilter } from './user-filter'\nimport { ISliderItem } from '@seplis/interfaces/slider'\n\n\ninterface IProps<S = IMovie>{\n title: string\n url: string\n defaultSort?: string | null\n emptyMessage?: string | null,\n onItemSelected?: (item: S) => void\n parseItem?: (item: S) => ISliderItem\n}\n\n\nexport default function MovieUserList<S = IMovie>({ \n title, \n url, \n emptyMessage, \n defaultSort,\n onItemSelected,\n parseItem,\n}: IProps<S>) {\n const { ref, focusKey, focusSelf } = useFocusable()\n const navigate = useNavigate()\n const location = useLocation()\n\n const [query, setQuery] = useQueryParams({\n sort: withDefault(StringParam, defaultSort),\n genre_id: withDefault(NumericArrayParam, []),\n user_can_watch: withDefault(BooleanParam, localStorage.getItem('filter-user-can-watch') === 'true'),\n release_date_gt: StringParam,\n release_date_lt: StringParam,\n rating_gt: NumberParam,\n rating_lt: NumberParam,\n rating_votes_gt: NumberParam,\n language: StringParam,\n user_has_watched: StringParam,\n }, {\n searchStringToObject: () => {\n // Prevent using the the actual location.search string when the movie modal is open\n // so the background update when the actual location.search changes\n return searchStringToObject(location.search)\n }\n })\n\n useEffect(() => {\n focusSelf()\n }, [focusSelf])\n\n return <>\n <FocusContext.Provider value={focusKey}>\n <Box ref={ref}>\n <ImageList<IMovie>\n title={title}\n url={url}\n emptyMessage={emptyMessage}\n filtersActive={isFilterActive(query)}\n urlParams={{\n ...query,\n 'per_page': 50,\n }}\n parseItem={parseItem || ((movie) => (\n {\n key: `movie-${movie.id}`,\n title: movie.title,\n img: movie.poster_image?.url,\n }\n ))}\n onItemSelected={onItemSelected || ((movie: IMovie) => {\n navigate(`/movies/${movie.id}`, {state: {\n background: location\n }})\n })}\n renderFilter={(options) => {\n return <MovieUserFilter defaultValue={query} onSubmit={(data) => {\n setQuery(data)\n if (data.user_can_watch === true) \n localStorage.setItem('filter-user-can-watch', 'true')\n else\n localStorage.removeItem('filter-user-can-watch')\n }} />\n }}\n />\n </Box>\n </FocusContext.Provider>\n </>\n}\n\n\nfunction isFilterActive(query: IUserFilterData) {\n return query.genre_id?.length > 0\n || query.user_can_watch === true \n || query.release_date_gt != null\n || query.release_date_lt != null\n || query.rating_gt != null\n || query.rating_lt != null\n || query.rating_votes_gt != null\n || query.language != null\n || query.user_has_watched != null\n}","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport MovieUserList from '@seplis/components/movie/user-list'\nimport { setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\n\nexport default function MoviesBrowse() {\n useEffect(() => {\n setTitle('Movies')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"movies\" />\n <Box margin=\"1rem\">\n <MovieUserList\n title=\"Movies\"\n url=\"/2/movies\"\n defaultSort='popularity_desc'\n emptyMessage={`No movies to show.`}\n />\n </Box>\n </>\n}\n","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport MovieUserList from '@seplis/components/movie/user-list'\nimport { setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\n\nexport default function MovieWatchlist() {\n useEffect(() => {\n setTitle('Movie watchlist')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"movies\" />\n <Box margin=\"1rem\">\n <MovieUserList\n title=\"Movie watchlist\"\n url=\"/2/movies?user_watchlist=true\"\n defaultSort='user_watchlist_added_at_desc'\n emptyMessage={`You have no movies in your watchlist.`}\n />\n </Box>\n </>\n}","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport MovieUserList from '@seplis/components/movie/user-list'\nimport { setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\n\nexport default function MovieFavorites() {\n useEffect(() => {\n setTitle('Movie favorites')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"movies\" />\n <Box margin=\"1rem\">\n <MovieUserList\n title=\"Movie favorites\"\n url=\"/2/movies?user_favorites=true\"\n defaultSort='user_favorite_added_at_desc'\n emptyMessage={`You have no movies in your favorites.`}\n />\n </Box>\n </>\n}","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport MovieUserList from '@seplis/components/movie/user-list'\nimport { setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\n\nexport default function MoviesWatched() {\n useEffect(() => {\n setTitle('Movies watched')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"movies\" />\n <Box margin=\"1rem\">\n <MovieUserList\n title=\"Movies watched\"\n url=\"/2/movies?user_has_watched=true\"\n defaultSort='user_last_watched_at_desc'\n emptyMessage={`You have not watched any movies.`}\n />\n </Box>\n </>\n}\n","import api from '@seplis/api'\nimport Player, { IPlayNextProps } from '@seplis/components/player/player'\nimport { IEpisode } from '@seplis/interfaces/episode'\nimport { IPlaySourceStream } from '@seplis/interfaces/play-server'\nimport { ISeries, ISeriesUserSettings } from '@seplis/interfaces/series'\nimport { episodeTitle } from '@seplis/utils'\nimport { useQuery } from '@tanstack/react-query'\nimport { useRef } from 'react'\nimport { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'\n\n\nexport default function PlayEpisode() {\n const { seriesId, episodeNumber } = useParams()\n const navigate = useNavigate()\n const [searchParams] = useSearchParams()\n const location = useLocation()\n\n const episode = useQuery(['episode-title-watched', seriesId, episodeNumber], async () => {\n const result = await Promise.all([\n api.get<ISeries>(`/2/series/${seriesId}`),\n api.get<IEpisode>(`/2/series/${seriesId}/episodes/${episodeNumber}`, {\n params: {\n expand: 'user_watched',\n }\n }),\n api.get<ISeriesUserSettings>(`/2/series/${seriesId}/user-settings`),\n ])\n return {\n title: `${result[0].data.title} ${episodeTitle(result[1].data)}`,\n startTime: result[1].data.user_watched?.position ?? 0,\n audioLang: result[2].data?.audio_lang,\n subtitleLang: result[2].data?.subtitle_lang,\n }\n })\n\n const playNext = useQuery<IPlayNextProps>(['episode-play-next', seriesId, episodeNumber], async () => {\n const result = await api.get<IEpisode>(`/2/series/${seriesId}/episodes/${parseInt(episodeNumber) + 1}`, {\n params: {\n 'expand': 'user_can_watch',\n }\n })\n if (result.data && result.data.user_can_watch.on_play_server)\n return {\n title: episodeTitle(result.data),\n url: `/series/${seriesId}/episodes/${result.data.number}/play?start_time=0`\n }\n return null\n })\n\n const markedAsWatched = useRef(false)\n const prevSavedPosition = useRef(0)\n const onTimeUpdate = (time: number, duration: number) => {\n time = Math.round(time)\n if ((time === episode.data.startTime) || (time === prevSavedPosition.current) || (time < 10) || ((time % 10) != 0))\n return\n const watched = (((time / 100) * 10) > (duration - time))\n prevSavedPosition.current = time\n if (watched) {\n if (!markedAsWatched.current) {\n markedAsWatched.current = true\n api.post(`/2/series/${seriesId}/episodes/${episodeNumber}/watched`).catch(() => {\n markedAsWatched.current = false\n })\n }\n } else {\n markedAsWatched.current = false\n api.put(`/2/series/${seriesId}/episodes/${episodeNumber}/watched-position`, {\n position: time\n })\n }\n }\n\n const onAudioChange = (source: IPlaySourceStream) => {\n api.put(`/2/series/${seriesId}/user-settings`, {\n 'audio_lang': source ? `${source.language || source.title}:${source.index}` : null,\n })\n }\n const onSubtitleChange = (source: IPlaySourceStream) => {\n api.put(`/2/series/${seriesId}/user-settings`, {\n 'subtitle_lang': source ? `${source.language || source.title}:${source.index}` : 'off',\n })\n }\n \n let startTime = 0\n if (searchParams.has('start_time'))\n startTime = parseInt(searchParams.get('start_time'))\n else if (episode.data)\n startTime = episode.data.startTime\n const playServerUrl = `/2/series/${seriesId}/episodes/${episodeNumber}/play-servers`\n return <Player\n key={playServerUrl}\n getPlayServersUrl={playServerUrl}\n title={episode.data?.title}\n startTime={startTime}\n playNext={playNext?.data}\n onTimeUpdate={onTimeUpdate}\n loading={episode.isLoading}\n defaultAudio={episode.data?.audioLang}\n defaultSubtitle={episode.data?.subtitleLang}\n onAudioChange={onAudioChange}\n onSubtitleChange={onSubtitleChange}\n onClose={() => {\n if (location.key && location.key != 'default')\n navigate(-1)\n else\n navigate(`/series/${seriesId}`)\n }}\n />\n}","import api from '@seplis/api'\nimport Player from '@seplis/components/player/player'\nimport { IMovie, IMovieWatched } from '@seplis/interfaces/movie'\nimport { useQuery } from '@tanstack/react-query'\nimport { useRef } from 'react'\nimport { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'\n\n\nexport default function PlayMovie() {\n const { movieId } = useParams()\n const navigate = useNavigate()\n const [searchParams] = useSearchParams()\n const location = useLocation()\n\n const movie = useQuery(['movie-title-watched', movieId], async () => {\n const result = await Promise.all([\n api.get<IMovie>(`/2/movies/${movieId}`),\n api.get<IMovieWatched>(`/2/movies/${movieId}/watched`),\n ])\n return {\n title: `${result[0].data.title}`,\n startTime: result[1].data?.position ?? 0,\n }\n })\n\n const markedAsWatched = useRef(false)\n const prevSavedPosition = useRef(0)\n const onTimeUpdate = (time: number, duration: number) => {\n time = Math.round(time)\n if ((time === movie.data.startTime) || (time === prevSavedPosition.current) || (time < 10) || ((time % 10) != 0))\n return\n const watched = (((time / 100) * 10) > (duration - time))\n prevSavedPosition.current = time\n if (watched) {\n if (!markedAsWatched.current) {\n markedAsWatched.current = true\n api.post(`/2/movies/${movieId}/watched`).catch(() => {\n markedAsWatched.current = false\n })\n }\n } else {\n markedAsWatched.current = false\n api.put(`/2/movies/${movieId}/watched-position`, {\n position: time\n })\n }\n }\n\n let startTime = 0\n if (searchParams.has('start_time'))\n startTime = parseInt(searchParams.get('start_time'))\n else if (movie.data)\n startTime = movie.data.startTime\n const playServerUrl = `/2/movies/${movieId}/play-servers`\n return <Player\n key={playServerUrl}\n getPlayServersUrl={playServerUrl}\n title={movie.data?.title}\n startTime={startTime}\n onTimeUpdate={onTimeUpdate}\n loading={movie.isLoading}\n onClose={() => {\n if (location.key && location.key != 'default')\n navigate(-1)\n else\n navigate(`/movies/${movieId}`)\n }}\n />\n}","import { Flex, Heading, Input, Button, InputGroup, Stack, InputLeftElement, Box, Avatar, FormControl, FormErrorMessage, Alert, AlertIcon, AlertTitle } from '@chakra-ui/react'\nimport { FaUserAlt, FaLock, FaEnvelope } from 'react-icons/fa'\nimport { useForm } from 'react-hook-form'\nimport axios from 'axios'\nimport { useEffect, useState } from 'react'\nimport { Link, useNavigate } from 'react-router-dom'\nimport { IToken } from '@seplis/interfaces/token'\nimport { setAuthorizationHeader } from '@seplis/api'\nimport { setTitle } from '@seplis/utils'\nimport { IError, IValidationError } from '@seplis/interfaces/error'\n\n\ninterface ISignUp {\n [key: string]: string\n username: string\n password: string\n email: string\n}\n\nexport default function Login() {\n const { handleSubmit, register, formState: { isSubmitting, errors }, setFocus, setError } = useForm<ISignUp>()\n const [rootError, setRootError] = useState<string>()\n const navigate = useNavigate()\n\n useEffect(() => {\n setTitle('Sign up')\n setFocus('username')\n }, [location.pathname])\n\n const submit = async (data: ISignUp) => {\n try {\n setRootError(null)\n const r = await axios.post<IToken>('/api/signup', data)\n localStorage.setItem('accessToken', r.data.access_token)\n setAuthorizationHeader()\n navigate('/')\n } catch (e) {\n const data = e.response.data as IError<IValidationError>\n\n if (data?.errors) {\n for (const e of data?.errors) {\n setError(e.field[1], { message: e.message })\n }\n } else {\n if (data.code == 1501)\n setError('email', {message: data.message})\n else if (data.code == 1502)\n setError('username', {message: data.message})\n else\n setRootError(data.message)\n }\n }\n }\n return <Flex\n flexDirection=\"column\"\n width=\"100wh\"\n justifyContent=\"center\"\n alignItems=\"center\"\n marginTop=\"4rem\"\n >\n <Stack\n flexDir=\"column\"\n mb=\"2\"\n justifyContent=\"center\"\n alignItems=\"center\"\n spacing=\"1rem\"\n >\n <Avatar src=\"/static/img/apple-touch-icon.png\" />\n <Box minW={{ base: \"90%\", md: \"468px\" }} p=\"2rem\" backgroundColor=\"blackAlpha.400\" rounded=\"md\">\n <form\n onSubmit={handleSubmit(submit)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\")\n handleSubmit(submit)()\n }}\n >\n <Stack spacing=\"1rem\">\n <Heading>Sign up to SEPLIS</Heading>\n\n {rootError && <Alert status=\"error\" rounded=\"md\">\n <AlertIcon />\n {rootError}\n </Alert>}\n\n <FormControl isInvalid={errors?.username !== undefined}>\n <InputGroup>\n <InputLeftElement pointerEvents=\"none\" children={<FaUserAlt />} />\n <Input id=\"username\" {...register('username')} type=\"input\" placeholder=\"Username\" />\n </InputGroup>\n <FormErrorMessage>\n {errors.username?.message}\n </FormErrorMessage>\n </FormControl>\n\n <FormControl isInvalid={errors?.email !== undefined}>\n <InputGroup>\n <InputLeftElement pointerEvents=\"none\" children={<FaEnvelope />} />\n <Input id=\"email\" {...register('email')} type=\"input\" placeholder=\"Email\" />\n </InputGroup>\n <FormErrorMessage>\n {errors.email?.message}\n </FormErrorMessage>\n </FormControl>\n\n <FormControl isInvalid={errors?.password !== undefined}>\n <InputGroup>\n <InputLeftElement pointerEvents=\"none\" children={<FaLock />} />\n <Input id=\"password\" {...register('password')} type=\"password\" placeholder=\"Password\" />\n </InputGroup>\n <FormErrorMessage>\n {errors.password?.message}\n </FormErrorMessage>\n </FormControl>\n\n <Flex>\n <Button\n marginLeft=\"auto\"\n type=\"submit\"\n colorScheme=\"blue\"\n isLoading={isSubmitting}\n loadingText='Creating user'\n paddingLeft=\"2rem\"\n paddingRight=\"2rem\">\n Sign up\n </Button>\n </Flex>\n </Stack>\n </form>\n </Box>\n <Box>\n <Link to=\"/login\">\n Login\n </Link>\n </Box>\n </Stack>\n </Flex>\n}","import { setAuthorizationHeader } from '@seplis/api'\nimport { IUser, IUsersLoggedIn } from '@seplis/interfaces/user'\nimport { useEffect } from 'react'\nimport { useNavigate } from 'react-router-dom'\n\nexport function Logout() {\n const navigate = useNavigate()\n \n useEffect(() => {\n localStorage.removeItem('accessToken')\n setAuthorizationHeader() \n const users: IUsersLoggedIn = JSON.parse(localStorage.getItem('users')) || {}\n const activeUser: IUser = JSON.parse(localStorage.getItem('activeUser'))\n if (activeUser)\n delete users[activeUser.username]\n localStorage.setItem('users', JSON.stringify(users))\n navigate('/')\n })\n return <></>\n}","import { Flex, Heading, Input, Button, InputGroup, Stack, InputLeftElement, Box, Avatar, FormControl, FormErrorMessage, Alert, AlertIcon, AlertTitle } from '@chakra-ui/react'\nimport { FaEnvelope } from 'react-icons/fa'\nimport { useForm } from 'react-hook-form'\nimport axios from 'axios'\nimport { useEffect, useState } from 'react'\nimport { Link } from 'react-router-dom'\nimport { setTitle } from '@seplis/utils'\nimport { IError, IValidationError } from '@seplis/interfaces/error'\n\n\ninterface IResetPassword {\n [key: string]: string\n email: string\n}\n\nexport default function SendResetPassword() {\n const { handleSubmit, register, formState: { isSubmitting, errors }, setFocus, setError } = useForm<IResetPassword>()\n const [rootError, setRootError] = useState<string>()\n const [success, setSuccess] = useState<string>()\n\n useEffect(() => {\n setTitle('Reset password')\n setFocus('email')\n }, [location.pathname])\n\n const submit = async (data: IResetPassword) => {\n try {\n setRootError(null)\n await axios.post('/api/users/send-reset-password', data)\n setSuccess('A password reset link has been sent to your email.')\n } catch (e) {\n const data = e.response.data as IError<IValidationError>\n\n if (data?.errors) {\n for (const e of data?.errors) {\n setError(e.field[1], { message: e.message })\n }\n } else {\n setRootError('Failed to send password reset link, please try again')\n }\n }\n }\n return <Flex\n flexDirection=\"column\"\n width=\"100wh\"\n justifyContent=\"center\"\n alignItems=\"center\"\n marginTop=\"4rem\"\n >\n <Stack\n flexDir=\"column\"\n mb=\"2\"\n justifyContent=\"center\"\n alignItems=\"center\"\n spacing=\"1rem\"\n >\n <Avatar src=\"/static/img/apple-touch-icon.png\" />\n <Box minW={{ base: \"90%\", md: \"468px\" }} p=\"2rem\" backgroundColor=\"blackAlpha.400\" rounded=\"md\">\n <form\n onSubmit={handleSubmit(submit)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\")\n handleSubmit(submit)()\n }}\n >\n <Stack spacing=\"1rem\">\n <Heading>Reset password to SEPLIS</Heading>\n\n {rootError && <Alert status=\"error\" rounded=\"md\">\n <AlertIcon />\n {rootError}\n </Alert>}\n\n <FormControl isInvalid={errors?.email !== undefined}>\n <InputGroup>\n <InputLeftElement pointerEvents=\"none\" children={<FaEnvelope />} />\n <Input {...register('email', { disabled: !!success, required: true })} type=\"input\" placeholder=\"Email\" />\n </InputGroup>\n <FormErrorMessage>\n {errors.email?.message}\n </FormErrorMessage>\n </FormControl>\n\n {success && <Alert status=\"success\" rounded=\"md\">\n <AlertIcon />\n {success}\n </Alert>}\n\n {!success && <Flex>\n <Button\n marginLeft=\"auto\"\n type=\"submit\"\n colorScheme=\"blue\"\n isLoading={isSubmitting}\n loadingText='Sending reset password link'\n paddingLeft=\"2rem\"\n paddingRight=\"2rem\">\n Reset password\n </Button>\n </Flex>}\n </Stack>\n </form>\n </Box>\n <Flex gap=\"1rem\">\n <Link to=\"/login\">Login</Link>\n <Link to=\"/signup\">Sign up</Link>\n </Flex>\n </Stack>\n </Flex>\n}","import { Flex, Heading, Input, Button, InputGroup, Stack, InputLeftElement, Box, Avatar, FormControl, FormErrorMessage, Alert, AlertIcon, AlertTitle } from '@chakra-ui/react'\nimport { FaEnvelope, FaLock } from 'react-icons/fa'\nimport { useForm } from 'react-hook-form'\nimport axios from 'axios'\nimport { useEffect, useState } from 'react'\nimport { Link, useNavigate, useParams } from 'react-router-dom'\nimport { IToken } from '@seplis/interfaces/token'\nimport { setTitle } from '@seplis/utils'\nimport { IError, IValidationError } from '@seplis/interfaces/error'\nimport { ErrorMessageFromResponse } from '@seplis/components/error'\n\n\ninterface INewPassword {\n [key: string]: string\n new_password: string\n key: string\n}\n\nexport default function ResetPassword() {\n const { handleSubmit, register, formState: { isSubmitting, errors }, setFocus, setError } = useForm<INewPassword>()\n const [rootError, setRootError] = useState<JSX.Element>()\n const navigate = useNavigate()\n const { key } = useParams()\n\n useEffect(() => {\n setTitle('Reset password')\n setFocus('new_password')\n }, [location.pathname])\n\n const submit = async (data: INewPassword) => {\n try {\n setRootError(null)\n await axios.post<IToken>('/api/users/reset-password', data)\n navigate('/login')\n } catch (e) {\n const data = e.response.data as IError<IValidationError>\n if (data?.errors) {\n for (const e of data?.errors) {\n setError(e.field[1], { message: e.message })\n }\n } else {\n setRootError(ErrorMessageFromResponse(e))\n }\n }\n }\n return <Flex\n flexDirection=\"column\"\n width=\"100wh\"\n justifyContent=\"center\"\n alignItems=\"center\"\n marginTop=\"4rem\"\n >\n <Stack\n flexDir=\"column\"\n mb=\"2\"\n justifyContent=\"center\"\n alignItems=\"center\"\n spacing=\"1rem\"\n >\n <Avatar src=\"/static/img/apple-touch-icon.png\" />\n <Box minW={{ base: \"90%\", md: \"468px\" }} p=\"2rem\" backgroundColor=\"blackAlpha.400\" rounded=\"md\">\n <form\n onSubmit={handleSubmit(submit)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\")\n handleSubmit(submit)()\n }}\n >\n <Stack spacing=\"1rem\">\n <Heading>New password to SEPLIS</Heading>\n\n {rootError && <Alert status=\"error\" rounded=\"md\">\n <AlertIcon />\n {rootError}\n </Alert>}\n\n <FormControl isInvalid={!!errors?.new_password}>\n <InputGroup>\n <InputLeftElement pointerEvents=\"none\" children={<FaLock />} />\n <Input {...register('new_password', { required: true })} type=\"password\" placeholder=\"New password\" />\n </InputGroup>\n <FormErrorMessage>\n {errors.new_password?.message}\n </FormErrorMessage>\n </FormControl>\n <input {...register('key')} value={key} type=\"hidden\" />\n\n <Flex>\n <Button\n marginLeft=\"auto\"\n type=\"submit\"\n colorScheme=\"blue\"\n isLoading={isSubmitting}\n loadingText='Changing password'\n paddingLeft=\"2rem\"\n paddingRight=\"2rem\">\n Change password\n </Button>\n </Flex>\n </Stack>\n </form>\n </Box>\n <Flex gap=\"1rem\">\n <Link to=\"/login\">Login</Link>\n <Link to=\"/signup\">Sign up</Link>\n </Flex>\n </Stack>\n </Flex>\n}","import { Stack } from '@chakra-ui/react'\nimport { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation'\nimport MainMenu from '@seplis/components/main-menu'\nimport Slider from '@seplis/components/slider'\nimport { IMovie } from '@seplis/interfaces/movie'\nimport { ISeries, ISeriesAndEpisode } from '@seplis/interfaces/series'\nimport { IUserWatched } from '@seplis/interfaces/user_watched'\nimport { episodeNumber, setTitle } from '@seplis/utils'\nimport { useCallback, useEffect } from 'react'\nimport { useLocation, useNavigate } from 'react-router-dom'\n\n\nexport default function WatchHome() {\n const { ref, focusKey, focusSelf } = useFocusable()\n const navigate = useNavigate()\n const location = useLocation()\n\n useEffect(() => {\n setTitle('Watch')\n }, [location.pathname])\n\n useEffect(() => {\n focusSelf()\n }, [focusSelf])\n\n const onRowFocus = useCallback(({ y }: { y: number }) => {\n window.scrollTo({\n top: y,\n behavior: 'smooth'\n });\n }, [ref])\n\n const itemSelected = useCallback((item: ISeriesAndEpisode) => {\n navigate(`/series/${item.series.id}`, { state: { background: location } })\n }, [])\n\n const seriesSelected = useCallback((series: ISeries) => {\n navigate(`/series/${series.id}`, { state: { background: location } })\n }, [])\n\n const movieSelected = useCallback((movie: IMovie) => {\n navigate(`/movies/${movie.id}`, { state: { background: location } })\n }, [])\n\n const userWatchedSelected = useCallback((item: IUserWatched) => {\n if (item.type == 'series')\n seriesSelected(item.data as ISeries)\n else if (item.type == 'movie')\n movieSelected(item.data as IMovie)\n }, [])\n\n return <>\n <MainMenu active=\"watch\" />\n\n <FocusContext.Provider value={focusKey}>\n\n <Stack ref={ref} marginTop=\"0.5rem\" marginBottom=\"0.5rem\">\n\n <Slider<IUserWatched>\n title=\"Watched\"\n url=\"/2/users/me/watched?user_can_watch=true\"\n parseItem={(item) => (\n {\n key: `${item.type}-${item.data.id}`,\n title: item.data.title,\n img: item.data.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={userWatchedSelected}\n hideIfEmpty={false}\n emptyMessage={`You haven't watched anything that's available on a play server.`}\n />\n\n\n <Slider<ISeriesAndEpisode>\n title=\"Series to Watch\"\n url=\"/2/series/to-watch?user_can_watch=true\"\n parseItem={(item) => (\n {\n key: `series-${item.series.id}`,\n title: item.series.title,\n img: item.series.poster_image?.url,\n bottomText: episodeNumber(item.episode),\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={itemSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<IMovie>\n title=\"Movie watchlist\"\n url=\"/2/movies?user_watchlist=true&user_can_watch=true&sort=user_watchlist_added_at_desc\"\n parseItem={(movie) => (\n {\n key: `movie-${movie.id}`,\n title: movie.title,\n img: movie.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={movieSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<ISeries>\n title=\"Series recently added\"\n url=\"/2/series?user_can_watch=true&sort=user_play_server_series_added_desc\"\n parseItem={(series) => (\n {\n key: `series-${series.id}`,\n title: series.title,\n img: series.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={seriesSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<IMovie>\n title=\"Movies recently added\"\n url=\"/2/movies?user_can_watch=true&sort=user_play_server_movie_added_desc\"\n parseItem={(movie) => (\n {\n key: `movie-${movie.id}`,\n title: movie.title,\n img: movie.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={movieSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<ISeries>\n title=\"Popular series\"\n url=\"/2/series?user_can_watch=true&sort=popularity_desc\"\n parseItem={(series) => (\n {\n key: `series-${series.id}`,\n title: series.title,\n img: series.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={seriesSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<IMovie>\n title=\"Popular movies\"\n url=\"/2/movies?user_can_watch=true&sort=popularity_desc\"\n parseItem={(movie) => (\n {\n key: `movie-${movie.id}`,\n title: movie.title,\n img: movie.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={movieSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<ISeriesAndEpisode>\n title=\"Episodes recently aired\"\n url=\"/2/series/recently-aired?user_can_watch=true&days_ahead=7\"\n parseItem={(item) => (\n {\n key: `series-${item.series.id}`,\n title: item.series.title,\n img: item.series.poster_image?.url,\n bottomText: episodeNumber(item.episode),\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={itemSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<ISeries>\n title=\"Series watchlist\"\n url=\"/2/series?user_watchlist=true&user_can_watch=true&sort=user_watchlist_added_at_desc\"\n parseItem={(series) => (\n {\n key: `series-${series.id}`,\n title: series.title,\n img: series.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={seriesSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<ISeries>\n title=\"Series you haven't watched\"\n url=\"/2/series?user_has_watched=false&user_can_watch=true\"\n parseItem={(series) => (\n {\n key: `series-${series.id}`,\n title: series.title,\n img: series.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={seriesSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<IMovie>\n title=\"Movies you haven't watched\"\n url=\"/2/movies?user_has_watched=false&user_can_watch=true\"\n parseItem={(movie) => (\n {\n key: `movie-${movie.id}`,\n title: movie.title,\n img: movie.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={movieSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<ISeries>\n title=\"Series favorites\"\n url=\"/2/series?user_favorites=true&user_can_watch=true&sort=user_favorite_added_at_desc\"\n parseItem={(series) => (\n {\n key: `series-${series.id}`,\n title: series.title,\n img: series.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={seriesSelected}\n hideIfEmpty={true}\n />\n\n\n <Slider<IMovie>\n title=\"Movie favorites\"\n url=\"/2/movies?user_favorites=true&user_can_watch=true&sort=user_favorite_added_at_desc\"\n parseItem={(series) => (\n {\n key: `series-${series.id}`,\n title: series.title,\n img: series.poster_image?.url,\n }\n )}\n onFocus={onRowFocus}\n onItemSelected={movieSelected}\n hideIfEmpty={true}\n />\n\n\n </Stack>\n </FocusContext.Provider>\n </>\n}","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport SeriesUserList from '@seplis/components/series/user-list'\nimport { ISeriesAndEpisode } from '@seplis/interfaces/series'\nimport { dateCountdown, episodeNumber, setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\nimport { useLocation, useNavigate } from 'react-router-dom'\n\nexport default function SeriesCountdown() {\n const navigate = useNavigate()\n const location = useLocation()\n useEffect(() => {\n setTitle('Series countdown')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"series\" />\n <Box margin=\"1rem\">\n <SeriesUserList<ISeriesAndEpisode>\n title=\"Series countdown\"\n url=\"/2/series/countdown\"\n parseItem={(item) => (\n {\n key: `series-${item.series.id}`,\n title: item.series.title,\n img: item.series.poster_image?.url,\n bottomText: episodeNumber(item.episode),\n topText: dateCountdown(item.episode.air_datetime),\n }\n )}\n onItemSelected={(item: ISeriesAndEpisode) => {\n navigate(`/series/${item.series.id}`, {state: {\n background: location\n }})\n }}\n emptyMessage={`No series on your watchlist has episodes airing in the future.`}\n showFilterButton={false}\n />\n </Box>\n </>\n}","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport SeriesUserList from '@seplis/components/series/user-list'\nimport { ISeriesAndEpisode } from '@seplis/interfaces/series'\nimport { episodeNumber, setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\nimport { useLocation, useNavigate } from 'react-router-dom'\n\nexport default function SeriesRecentlyAired() {\n const navigate = useNavigate()\n const location = useLocation()\n useEffect(() => {\n setTitle('Series recently aired')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"series\" />\n <Box margin=\"1rem\">\n <SeriesUserList<ISeriesAndEpisode>\n title=\"Series recently aired\"\n url=\"/2/series/recently-aired?user_watchlist=true\"\n parseItem={(item) => (\n {\n key: `series-${item.series.id}`,\n title: item.series.title,\n img: item.series.poster_image?.url,\n bottomText: episodeNumber(item.episode),\n }\n )}\n onItemSelected={(item: ISeriesAndEpisode) => {\n navigate(`/series/${item.series.id}`, {state: {\n background: location\n }})\n }}\n emptyMessage={`No series on your watchlist has recently aired.`}\n />\n </Box>\n </>\n}","import { Box } from '@chakra-ui/react'\nimport MainMenu from '@seplis/components/main-menu'\nimport SeriesUserList from '@seplis/components/series/user-list'\nimport { ISeriesAndEpisode } from '@seplis/interfaces/series'\nimport { episodeNumber, setTitle } from '@seplis/utils'\nimport { useEffect } from 'react'\nimport { useLocation, useNavigate } from 'react-router-dom'\n\nexport default function SeriesToWatch() {\n const navigate = useNavigate()\n const location = useLocation()\n useEffect(() => {\n setTitle('Series to watch')\n }, [location.pathname])\n\n return <>\n <MainMenu active=\"series\" />\n <Box margin=\"1rem\">\n <SeriesUserList<ISeriesAndEpisode>\n title=\"Series to watch\"\n url=\"/2/series/to-watch\"\n parseItem={(item) => (\n {\n key: `series-${item.series.id}`,\n title: item.series.title,\n img: item.series.poster_image?.url,\n bottomText: episodeNumber(item.episode),\n }\n )}\n onItemSelected={(item: ISeriesAndEpisode) => {\n navigate(`/series/${item.series.id}`, {state: {\n background: location\n }})\n }}\n emptyMessage={`You have no series to watch.`}\n />\n </Box>\n </>\n}","import { BrowserRouter, Route, Routes, useLocation } from 'react-router-dom'\nimport { createRoot } from 'react-dom/client'\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query'\nimport { ChakraProvider, extendTheme, type ThemeConfig } from '@chakra-ui/react'\n\nimport './index.less'\n\nimport Login from './pages/login'\nimport Movie, { MovieModalPage } from './pages/movie'\nimport Series, { SeriesModalPage } from './pages/series'\n\nimport { QueryParamProvider } from 'use-query-params'\nimport { ReactRouter6Adapter } from 'use-query-params/adapters/react-router-6'\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n refetchOnWindowFocus: false,\n keepPreviousData: true,\n },\n },\n})\n\nconst config: ThemeConfig = {\n initialColorMode: 'dark',\n useSystemColorMode: false,\n}\n\nconst theme = extendTheme({\n config: config,\n colors: {\n seplis: {\n 100: '#36c',\n 'modalBackgroundColor': '#1b1b1b',\n },\n },\n components: {\n Popover: {\n variants: {\n responsive: {\n content: { width: \"unset\" },\n },\n },\n },\n Button: {\n variants: {\n playButton: {\n backgroundColor: '#000',\n fontSize: '42px',\n }\n }\n }\n },\n layerStyles: {\n episodeCard: {\n backgroundColor: 'blackAlpha.500',\n padding: '0.5rem',\n borderRadius: 'md',\n },\n baseModal: {\n maxWidth: '1100px',\n backgroundColor: 'seplis.modalBackgroundColor',\n padding: '1rem 0',\n }\n },\n textStyles: {\n h2: {\n fontSize: '1.25rem',\n fontWeight: '600',\n },\n selectedText: {\n fontWeight: 'bolder',\n },\n },\n\n})\n\nimport { init as spatialInit } from '@noriginmedia/norigin-spatial-navigation'\nimport SeriesHome from './pages/series/home'\nimport SeriesBrowse from './pages/series/browse'\nimport SeriesWatchlist from './pages/series/watchlist'\nimport SeriesFavorites from './pages/series/favorites'\nimport SeriesWatched from './pages/series/watched'\nimport MoviesBrowse from './pages/movies/browse'\nimport MovieWatchlist from './pages/movies/watchlist'\nimport MovieFavorites from './pages/movies/favorites'\nimport MoviesWatched from './pages/movies/watched'\nimport PlayEpisode from './pages/series/play-episode'\nimport PlayMovie from './pages/movies/play'\nimport Signup from './pages/signup'\nimport { Logout } from './pages/logout'\nimport SendResetPassword from './pages/send-reset-password'\nimport ResetPassword from './pages/reset-password'\nimport WatchHome from './pages/watch/home'\nimport { CastProvider } from './components/player/react-cast-sender'\nimport SeriesCountdown from './pages/series/countdown'\nimport SeriesRecentlyAired from './pages/series/recently-aired'\nimport SeriesToWatch from './pages/series/series-to-watch'\nimport { StrictMode } from 'react'\n\nspatialInit({})\n\ncreateRoot(document.getElementById(\"root\")).render(\n <StrictMode>\n <ChakraProvider theme={theme}>\n <BrowserRouter >\n <QueryParamProvider adapter={ReactRouter6Adapter}>\n <QueryClientProvider client={queryClient}>\n <CastProvider receiverApplicationId={(window as any).seplisChromecastAppId}>\n <App />\n </CastProvider>\n </QueryClientProvider>\n </QueryParamProvider>\n </BrowserRouter>\n </ChakraProvider>\n </StrictMode>\n)\n\nfunction App() {\n const location = useLocation()\n const background = location.state?.background\n return <>\n <Routes location={background || location}>\n <Route path=\"/\" element={<WatchHome />} />\n <Route path=\"/login\" element={<Login />} />\n <Route path=\"/logout\" element={<Logout />} />\n <Route path=\"/signup\" element={<Signup />} />\n <Route path=\"/users/reset-password\" element={<SendResetPassword />} />\n <Route path=\"/users/reset-password/:key\" element={<ResetPassword />} />\n <Route path=\"/movies\" element={<MoviesBrowse />} />\n <Route path=\"/movies/watchlist\" element={<MovieWatchlist />} />\n <Route path=\"/movies/favorites\" element={<MovieFavorites />} />\n <Route path=\"/movies/watched\" element={<MoviesWatched />} />\n <Route path=\"/movies/:movieId\" element={<Movie />} />\n <Route path=\"/movies/:movieId/play\" element={<PlayMovie />} />\n <Route path=\"/series\" element={<SeriesBrowse />} />\n <Route path=\"/series/home\" element={<SeriesHome />} />\n <Route path=\"/series/watchlist\" element={<SeriesWatchlist />} />\n <Route path=\"/series/favorites\" element={<SeriesFavorites />} />\n <Route path=\"/series/watched\" element={<SeriesWatched />} />\n <Route path=\"/series/countdown\" element={<SeriesCountdown />} />\n <Route path=\"/series/recently-aired\" element={<SeriesRecentlyAired />} />\n <Route path=\"/series/to-watch\" element={<SeriesToWatch />} />\n <Route path=\"/series/:seriesId\" element={<Series />} />\n <Route path=\"/series/:seriesId/episodes/:episodeNumber/play\" element={<PlayEpisode />} />\n <Route path=\"/watch\" element={<WatchHome />} />\n </Routes>\n {background && <Routes>\n <Route path=\"/series/:seriesId\" element={<SeriesModalPage />} />\n <Route path=\"/movies/:movieId\" element={<MovieModalPage />} />\n </Routes>}\n </>\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","var scriptUrl;\nif (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \"\";\nvar document = __webpack_require__.g.document;\nif (!scriptUrl && document) {\n\tif (document.currentScript)\n\t\tscriptUrl = document.currentScript.src;\n\tif (!scriptUrl) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tif(scripts.length) {\n\t\t\tvar i = scripts.length - 1;\n\t\t\twhile (i > -1 && !scriptUrl) scriptUrl = scripts[i--].src;\n\t\t}\n\t}\n}\n// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration\n// or pass an empty string (\"\") and set the __webpack_public_path__ variable from your code to use your own logic.\nif (!scriptUrl) throw new Error(\"Automatic publicPath is not supported in this browser\");\nscriptUrl = scriptUrl.replace(/#.*$/, \"\").replace(/\\?.*$/, \"\").replace(/\\/[^\\/]+$/, \"/\");\n__webpack_require__.p = scriptUrl;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t179: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkseplis\"] = self[\"webpackChunkseplis\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [573], () => (__webpack_require__(2259)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","leafPrototypes","getProto","___CSS_LOADER_EXPORT___","push","module","id","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","locals","ErrorMessageFromResponse","errorObj","isAxiosError","e","data","response","code","errors","length","map","error","index","join","detail","message","api","create","baseURL","window","seplisAPI","paramsSerializer","indexes","setAuthorizationHeader","localStorage","getItem","defaults","headers","interceptors","use","status","location","href","encodeURIComponent","pathname","search","Login","handleSubmit","register","formState","isSubmitting","resetField","setFocus","setValue","setError","useState","next","useQueryParam","StringParam","navigate","useEffect","document","title","submit","async","r","axios","post","login","password","setItem","access_token","user","get","users","JSON","parse","token","stringify","flexDirection","width","justifyContent","alignItems","marginTop","flexDir","mb","spacing","src","minW","base","md","p","backgroundColor","rounded","onSubmit","onKeyDown","event","key","pointerEvents","children","I","required","type","placeholder","textAlign","to","marginLeft","colorScheme","isLoading","loadingText","paddingLeft","paddingRight","isAuthed","pad","str","max","toString","episodeNumber","episode","season","number","episodeTitle","EpisodeAirdate","air_datetime","format","air_date","secondsToTime","secs","hours","Math","floor","minutes","seconds","dateInDays","dt","Date","days","abs","getTime","l","divmod","pluralize","dateCountdown","num","word","a","b","setTitle","secondsToHourMin","minutesLeft","s","trim","langCodeToLang","Intl","DisplayNames","of","browser","isMobile","Poster","url","onClick","fallback","height","PosterAspectRatio","ratio","cursor","objectFit","focusedBorder","borderColor","borderWidth","EVENT_EPISODE_WATCHED","TriggerEpisodeWatched","seriesId","watched","CustomEvent","dispatchEvent","EVENT_MOVIE_WATCHED","TriggerMovieWatched","movieId","useEventListener","eventName","handler","deps","handleEvent","addEventListener","removeEventListener","WatchlistButton","toast","queryClient","toggleWatchlist","useMutation","onWatchlist","cancelQueries","delete","put","setQueryData","on_watchlist","onError","isClosable","position","isInitialLoading","useQuery","enabled","handleClick","mutate","ref","focused","useFocusable","onEnterPress","leftIcon","style","MovieNew","onDone","SettingsForm","externals","onSave","result","MovieUpdate","movie","patch","defaultValues","fontSize","align","gap","basis","DeleteConfirm","isOpen","onOpen","onClose","cancelRef","useRef","leastDestructiveRef","isCentered","fontWeight","reload","duration","description","ml","useGetPlayServers","getPlayServers","sourcePromises","request","getPlayServerSources","Promise","all","filter","item","playRequest","sources","play_url","params","play_id","timeout","console","log","PickQuality","source","selectedWidth","onChange","direction","Object","entries","resolutionNames","sort","parseInt","value","w","textStyle","resolutionToText","getDefaultResolutionWidth","getResolutionWidth","PickSource","playServers","selected","server","isSelected","renderPlaySource","resolution","codec","toUpperCase","video_color_range","video_color_range_type","pickStartSource","defaultResolutionWidth","playServer","reverse","createContext","initialized","connected","deviceName","player","playerController","getDefaultTrackStyling","chrome","cast","media","TextTrackStyle","fontGenericFamily","TextTrackFontGenericFamily","SANS_SERIF","CastLoader","static","resolve","reject","isAvailable","onGCastApiAvailable","loadCastSDK","then","catch","warn","t","getElementsByTagName","createElement","onload","onreadystatechange","this","readyState","onerror","onabort","parentNode","insertBefore","CastButton","props","propTypes","useContext","tracks","setTracks","currentTime","setCurrentTime","setDuration","isMediaLoaded","setIsMediaLoaded","isPaused","setIsPaused","isMuted","setIsMuted","onCurrentTimeChange","framework","RemotePlayerEventType","CURRENT_TIME_CHANGED","onDurationChange","DURATION_CHANGED","onMediaLoadedChange","IS_MEDIA_LOADED_CHANGED","onIsPausedChange","IS_PAUSED_CHANGED","onIsMutedChange","IS_MUTED_CHANGED","onMediaInfoChanged","newTitle","newTracks","MEDIA_INFO_CHANGED","loadMedia","useCallback","castSession","CastContext","getInstance","getCurrentSession","togglePlay","playOrPause","toggleMute","muteOrUnmute","seek","time","setVolume","volume","volumeLevel","setVolumeLevel","editTracks","activeTrackIds","textTrackStyle","trackStyle","tracksInfoRequest","EditTracksInfoRequest","getMediaSession","editTracksInfo","sendMessage","namespace","useMemo","PickSubtitleSource","subtitleSources","subtitle","subtitleSourceToName","language","pickStartSubtitle","sourceStreams","defaultSubtitle","stringToSourceStream","sub","default","forced","streams","lang","toLowerCase","split","undefined","stream","PickAudioSource","audioSources","audio","audioSourceToName","pickStartAudio","defaultAudio","PlayButtonMenu","playServersUrl","isLazy","as","icon","variant","PlayButtonMenuItems","isFetching","target","size","PlayButton","onPlayClick","isAttached","MoviePlayButton","castMovieRequest","startTime","requestSource","audioLang","subtitleLang","subtitleOffset","resolutionWidth","session","user_watched","subtitles","requestMedia","hls_url","direct_play_url","mediaInfo","MediaInfo","hlsVideoSegmentFormat","HlsSegmentFormat","FMP4","streamType","StreamType","OTHER","metadata","MovieMediaMetadata","releaseDate","release_date","images","poster_image","customData","selectedRequestSource","requestSources","apiUrl","track","Track","TrackType","TEXT","name","subtype","TextTrackType","CAPTIONS","trackContentType","trackContentId","LoadRequest","WatchedButton","onIncrement","onDecrement","times","isUpdating","placement","closeOnBlur","BaseButton","padding","forwardRef","background","color","MovieWatchedButtonData","watched_at","setWatched","setUpdating","MovieWatchedButton","MovieSkeleton","maxWidth","className","borderRadius","flex","EpisodePlayButton","canPlay","castEpisodeRequest","audio_lang","subtitle_lang","TvShowMediaMetadata","seriesTitle","originalAirdate","metadataType","MetadataType","TV_SHOW","series","episode_type","FullErrorPage","h","py","px","maxW","mx","PickSubtitleOffset","labelStyles","mt","labelStylesMinus","min","step","onChangeEnd","v","boxSize","SubtitleOffsetToText","offset","SettingsMenu","audioSource","subtitleSource","forceTranscode","onRequestSourceChange","onResolutionWidthChange","onAudioSourceChange","onSubtitleSourceChange","onSubtitleOffsetChange","onForceTranscodeChange","containerRef","nested","setNested","showModal","setShowModal","autoSelect","isDisabled","command","maxHeight","overflow","portalProps","Slider","onTimeChange","hoverTime","setHoverTime","userSelect","onMouseMove","eventToTime","onTouchMove","onMouseLeave","onTouchCancel","onTouchEnd","SliderHoverTime","percentage","SliderTrack","SliderTrackProgress","progress","top","display","bottom","transform","left","match","originalEvent","touches","changedTouches","getBoundingClientRect","x","clientX","norm","right","trunc","Video","subtitleLinePosition","onAutoPlayFailed","onTimeUpdate","onPause","onPlay","onLoadingState","onAirplayAvailabilityChange","videoElement","hls","useImperativeHandle","current","play","getCurrentTime","skipSeconds","video","paused","pause","getVolume","toggleFullscreen","fullscreenElement","cancelFullScreen","webkitCancelFullScreen","requestFullscreen","webkitEnterFullscreen","showAirplayPicker","webkitShowPlaybackTargetPicker","videoCodecs","types","codecs","canPlayType","Set","getSupportedVideoCodecs","Error","String","getSupportedAudioCodecs","getSupportedVideoContainers","startsWith","keep_alive_url","close_session_url","getPlayRequestMedia","can_direct_play","load","startPosition","manifestLoadingTimeOut","enableWorker","lowLatencyMode","backBufferLength","loadSource","attachMedia","airPlayHlsSource","appendChild","disableRemotePlayback","on","MANIFEST_PARSED","ERROR","NETWORK_ERROR","fatal","MEDIA_ERROR","start","setInterval","destroy","removeAttribute","childNodes","HTMLSourceElement","removeChild","clearInterval","onWaiting","onLoadStart","onPlaying","onCanPlayThrough","onLoadedData","currentTarget","MEDIA_ERR_DECODE","recoverMediaError","controls","preload","crossOrigin","playsInline","SetSubtitle","firstTrackLoad","useJASSUB","includes","textTracks","mode","cue","cues","line","close","subUrl","workerUrl","URL","wasmUrl","legacyWasmUrl","availableFonts","timeOffset","offscreenRender","os","kind","label","srcLang","VolumeBar","defaultVolume","defaultValue","orientation","minH","Player","getPlayServersUrl","playNext","loading","onAudioChange","onSubtitleChange","Loading","VideoPlayer","setRequestSource","setResolutionWidth","setAudioSource","setSubtitleSource","setForceTranscode","navigator","userAgent","setSubtitleOffset","setTime","setPaused","setLoading","showBigPlay","setShowBigPlay","controlsVisible","setControlsVisible","hideControlsTimer","videoControls","boxRef","airplayAvailable","setAirplayAvailable","showControls","clearTimeout","setTimeout","requestSourceChange","newRequestSource","parseFloat","keyDown","preventDefault","available","BigPlay","ControlsTop","ControlsBottom","grow","VolumeButton","PlayNext","FullscreenButton","fullscreen","setFullscreen","fullscreenToggle","getElementById","returnFocusOnClose","replace","stopPropagation","element","mozCancelFullScreen","enterFullscreen","requestFullScreen","mozRequestFullScreen","webkitRequestFullScreen","Element","ALLOW_KEYBOARD_INPUT","ChromecastControls","info","setInfo","addMessageListener","infoReceived","removeMessageListener","MovieCollection","collection","state","collection_id","per_page","items","substring","favorite","CastCard","castPerson","layerStyle","person","profile_image","lineHeight","character","CastCardSkeleton","CastFeatured","order_le","minChildWidth","Array","_","i","member","MovieLoad","onLoaded","Movie","SeriesWaitingForData","focusKey","FocusContext","Provider","MoviePoster","Title","BaseInfo","Genres","genres","ListButtons","Plot","ExternalLinks","WatchButtons","DisplaySettings","wrap","genre","Genre","spacingX","runtime","rating","mr","expand","setExpand","plot","noOfLines","original_title","tagline","imdb","themoviedb","isExternal","marginBottom","ChangePasswordForm","isSubmitSuccessful","rootError","setRootError","field","isInvalid","current_password","new_password","ChromecastIcon","SearchButtonDialog","paddingBottom","Search","afterSelected","query","signal","keepPreviousData","SearchInput","RenderItemSkeleton","RenderItems","onSelected","RenderItem","pt","ShowType","SeriesNew","SeriesForm","importers","episodes","SeriesUpdate","onDelete","Externals","Importers","EpisodeType","MainMenu","active","marginRight","MenuItems","MobileMenu","UserAvatar","ChangePasswordMenuItem","rightIcon","SeriesNewMenuItem","MovieNewMenuItem","setUser","username","MoviePage","margin","MovieModalPage","autoFocus","EpisodeWatchedButton","episode_number","EpisodeCard","EpisodeCardWrapper","user_can_watch","on_play_server","EpisodeSkeleton","EpisodeLastWatched","refetch","refetchOnWindowFocus","EpisodeNextToAir","toISOString","EpisodeToWatch","SeasonSelect","seasons","onSelect","Episodes","defaultSeason","setSeason","RenderEpisodes","config","GetAllCursor","LoadingEpisodes","watchlist","SeriesSkeleton","flexShrink","FavoriteButton","toggleFavorite","roles","slice","role","SeriesLoad","Series","SeriesPoster","Buttons","UserEpisodes","SeasonEpisodes","premiered","SeasonsText","EpisodesText","total","SeriesPage","SeriesModalPage","hideIfEmpty","emptyMessage","parseItem","onFocus","onItemSelected","setItems","setIndex","displayItemCount","setDisplayItemCount","rowWidthItems","fetchNextPage","useInfiniteQuery","pageParam","loadPerPage","getNextPageParam","lastPage","handleResize","pages","flatMap","page","Cards","layout","details","node","getAttribute","PeekCard","SkeletonCards","Card","viewItemIndex","keys","EmptyCard","topText","TextBox","img","bottomText","displayCount","itemIndex","innerWidth","SeriesHome","focusSelf","onRowFocus","y","scrollTo","behavior","itemSelected","user_last_episode_watched","SplitWidths","List","urlParams","filtersActive","showFilterButton","renderFilter","isFetchingNextPage","hasNextPage","obj","reduce","acc","k","FilterButton","amount","BlankCards","SelectGenre","control","htmlFor","flexGrow","isChecked","checked","SelectSeriesUserSort","SelectLanguage","languages","SwitchRadioGroup","option","SeriesUserFilter","watch","unsubscribe","UserSeriesList","defaultSort","setQuery","useQueryParams","withDefault","genre_id","NumericArrayParam","BooleanParam","premiered_gt","premiered_lt","rating_gt","NumberParam","rating_lt","rating_votes_gt","user_has_watched","searchStringToObject","isFilterActive","removeItem","Browse","SeriesWatchlist","SeriesFavorites","SeriesWatched","SelectMovieUserSort","MovieUserFilter","MovieUserList","release_date_gt","release_date_lt","MoviesBrowse","MovieWatchlist","MovieFavorites","MoviesWatched","PlayEpisode","searchParams","markedAsWatched","prevSavedPosition","has","playServerUrl","round","PlayMovie","email","Logout","activeUser","SendResetPassword","success","setSuccess","disabled","ResetPassword","WatchHome","seriesSelected","movieSelected","userWatchedSelected","SeriesCountdown","SeriesRecentlyAired","SeriesToWatch","defaultOptions","queries","retry","theme","initialColorMode","useSystemColorMode","colors","seplis","components","Popover","variants","responsive","content","Button","playButton","layerStyles","episodeCard","baseModal","textStyles","h2","selectedText","render","StrictMode","QueryParamProvider","adapter","QueryClientProvider","client","receiverApplicationId","autoJoinPolicy","resumeSavedSession","setConnected","setDeviceName","castInitialized","setCastInititalized","setPlayer","setPlayerController","resetCast","onSessionStateChange","sessionState","SessionState","SESSION_RESUMED","SESSION_STARTED","SESSION_ENDED","setOptions","RemotePlayer","RemotePlayerController","CastContextEventType","SESSION_STATE_CHANGED","onConnectedChange","_data","getSessionObj","receiver","friendlyName","IS_CONNECTED_CHANGED","seplisChromecastAppId","path","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","loaded","__webpack_modules__","call","m","O","chunkIds","fn","priority","notFulfilled","Infinity","fulfilled","j","every","splice","n","getter","__esModule","d","getPrototypeOf","ns","def","indexOf","getOwnPropertyNames","forEach","definition","o","defineProperty","enumerable","g","globalThis","Function","prop","prototype","hasOwnProperty","Symbol","toStringTag","nmd","paths","scriptUrl","importScripts","currentScript","scripts","baseURI","self","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","some","chunkLoadingGlobal","bind","nc","__webpack_exports__"],"sourceRoot":""}