diff --git a/.github/workflows/build-analyze-linux.yml b/.github/workflows/build-analyze-linux.yml index 29582016..8f1b0635 100644 --- a/.github/workflows/build-analyze-linux.yml +++ b/.github/workflows/build-analyze-linux.yml @@ -27,6 +27,21 @@ on: - cron: '44 20 * * 1' jobs: + + flatpak: + name: "Flatpak Builder" + runs-on: ubuntu-latest + container: + image: bilelmoussaoui/flatpak-github-actions:gnome-40 + options: --privileged + steps: + - uses: actions/checkout@v2 + - uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v4 + with: + bundle: Cider.flatpak + manifest-path: ./flatpak/org.cidercollective.cider.yml + cache-key: flatpak-builder-${{ github.sha }} + analyze: name: Analyze runs-on: ubuntu-latest diff --git a/.github/workflows/release-all.yml b/.github/workflows/release-all.yml new file mode 100644 index 00000000..f18367a5 --- /dev/null +++ b/.github/workflows/release-all.yml @@ -0,0 +1,31 @@ +name: Build/release + +on: push + +jobs: + release: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + + steps: + + - name: Check out Git repository + uses: actions/checkout@v1 + + - name: Install Node.js, NPM and Yarn + uses: actions/setup-node@v1 + with: + node-version: 16 + + - name: Build/release Electron app + uses: samuelmeuli/action-electron-builder@v1 + with: + # GitHub token, automatically provided to the action + # (No need to define this secret in the repo settings) + github_token: ${{ secrets.github_token }} + + # release the app after building + release: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index e1bcb518..e2efe76a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ dist yarn* package-lock.json .yarnclean +build # Misc .idea @@ -307,4 +308,10 @@ GitHub.sublime-settings #Service Worker mappings src/renderer/sw.js.map -src/renderer/workbox-962786f2.js.map \ No newline at end of file +src/renderer/workbox-962786f2.js.map +/src/renderer/musickit-dev.js + +#Mac certs +*.p12 +keys.sh + diff --git a/Assets/Cider with text.svg b/Assets/Cider with text.svg new file mode 100644 index 00000000..81052080 --- /dev/null +++ b/Assets/Cider with text.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + Cider + + + diff --git a/Assets/Release.svg b/Assets/Release.svg new file mode 100644 index 00000000..f27dc45d --- /dev/null +++ b/Assets/Release.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Assets/Sources/Cider with text.afdesign b/Assets/Sources/Cider with text.afdesign new file mode 100644 index 00000000..ff9e4ee5 Binary files /dev/null and b/Assets/Sources/Cider with text.afdesign differ diff --git a/Assets/Sources/Release.afdesign b/Assets/Sources/Release.afdesign new file mode 100644 index 00000000..b6484806 Binary files /dev/null and b/Assets/Sources/Release.afdesign differ diff --git a/Assets/Sources/cider-vinyl no raster.afdesign b/Assets/Sources/cider-vinyl no raster.afdesign new file mode 100644 index 00000000..64d895bd Binary files /dev/null and b/Assets/Sources/cider-vinyl no raster.afdesign differ diff --git a/Assets/Sources/cider-vinyl-no raster 2.afdesign b/Assets/Sources/cider-vinyl-no raster 2.afdesign new file mode 100644 index 00000000..dbc8db8f Binary files /dev/null and b/Assets/Sources/cider-vinyl-no raster 2.afdesign differ diff --git a/Assets/Sources/cider-vinyl.afdesign b/Assets/Sources/cider-vinyl.afdesign new file mode 100644 index 00000000..ba1f0da0 Binary files /dev/null and b/Assets/Sources/cider-vinyl.afdesign differ diff --git a/Assets/Vinyl Logo/cider-vinyl no raster.svg b/Assets/Vinyl Logo/cider-vinyl no raster.svg new file mode 100644 index 00000000..5077ad35 --- /dev/null +++ b/Assets/Vinyl Logo/cider-vinyl no raster.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Assets/Vinyl Logo/cider-vinyl textured.svg b/Assets/Vinyl Logo/cider-vinyl textured.svg new file mode 100644 index 00000000..f115c926 --- /dev/null +++ b/Assets/Vinyl Logo/cider-vinyl textured.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index defd9101..00316da3 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Open Collective
Discord - Twitter + Twitter Reddit

Windows Build Status diff --git a/appx/Square150x150Logo.PNG b/appx/Square150x150Logo.PNG index 7556b01a..7ec9fb93 100644 Binary files a/appx/Square150x150Logo.PNG and b/appx/Square150x150Logo.PNG differ diff --git a/appx/Square44x44Logo.PNG b/appx/Square44x44Logo.PNG index 5e4e3099..7374d271 100644 Binary files a/appx/Square44x44Logo.PNG and b/appx/Square44x44Logo.PNG differ diff --git a/appx/StoreLogo.PNG b/appx/StoreLogo.PNG index d711fc40..c9ff7a22 100644 Binary files a/appx/StoreLogo.PNG and b/appx/StoreLogo.PNG differ diff --git a/flatpak/flatpak-node-generator.py b/flatpak/flatpak-node-generator.py new file mode 100644 index 00000000..2a7c1f21 --- /dev/null +++ b/flatpak/flatpak-node-generator.py @@ -0,0 +1,1839 @@ +#!/usr/bin/env python3 + +# pyright: strict + +__license__ = 'MIT' + +from typing import * # pyright: reportWildcardImportFromLibrary=false +# Explictly import these. +from typing import cast, IO + +from pathlib import Path +from distutils.version import StrictVersion + +import argparse +import asyncio +import base64 +import binascii +import collections +import contextlib +import hashlib +import json +import os +import re +import shlex +import shutil +import sys +import tempfile +import textwrap +import types +import urllib.parse +import urllib.request + +DEFAULT_PART_SIZE = 4096 + +GIT_SCHEMES: Dict[str, Dict[str, str]] = { + 'github': { + 'scheme': 'https', + 'netloc': 'github.com' + }, + 'gitlab': { + 'scheme': 'https', + 'netloc': 'gitlab.com' + }, + 'bitbucket': { + 'scheme': 'https', + 'netloc': 'bitbucket.com' + }, + 'git': {}, + 'git+http': { + 'scheme': 'http' + }, + 'git+https': { + 'scheme': 'https' + }, +} + +GIT_URL_PATTERNS = [ + re.compile(r'^git:'), + re.compile(r'^git\+.+:'), + re.compile(r'^ssh:'), + re.compile(r'^https?:.+\.git$'), + re.compile(r'^https?:.+\.git#.+'), +] + +GIT_URL_HOSTS = ['github.com', 'gitlab.com', 'bitbucket.com', 'bitbucket.org'] + +NPM_MIRROR = 'https://unpkg.com/' + + +class Cache: + instance: 'Cache' + + @classmethod + def get_working_instance_if(cls, condition: bool) -> 'Cache': + return cls.instance if condition else NullCache() + + class BucketReader: + def read_parts(self, size: int = DEFAULT_PART_SIZE) -> Iterator[bytes]: + raise NotImplementedError + + def read_all(self) -> bytes: + raise NotImplementedError + + def close(self) -> None: + raise NotImplementedError + + def __enter__(self) -> 'Cache.BucketReader': + return self + + def __exit__(self, exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[types.TracebackType]) -> None: + self.close() + + class BucketWriter: + def write(self, data: bytes) -> None: + raise NotImplementedError + + def cancel(self) -> None: + raise NotImplementedError + + def seal(self) -> None: + raise NotImplementedError + + def __enter__(self) -> 'Cache.BucketWriter': + return self + + def __exit__(self, exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[types.TracebackType]) -> None: + if traceback is None: + self.seal() + else: + self.cancel() + + class BucketRef: + def __init__(self, key: str) -> None: + self.key = key + + def open_read(self) -> Optional['Cache.BucketReader']: + raise NotImplementedError + + def open_write(self) -> 'Cache.BucketWriter': + raise NotImplementedError + + def get(self, key: str) -> BucketRef: + raise NotImplementedError + + +class NullCache(Cache): + class NullBucketWriter(Cache.BucketWriter): + def write(self, data: bytes) -> None: + pass + + def cancel(self) -> None: + pass + + def seal(self) -> None: + pass + + class NullBucketRef(Cache.BucketRef): + def __init__(self, key: str) -> None: + super().__init__(key) + + def open_read(self) -> Optional[Cache.BucketReader]: + return None + + def open_write(self) -> Cache.BucketWriter: + return NullCache.NullBucketWriter() + + def get(self, key: str) -> Cache.BucketRef: + return NullCache.NullBucketRef(key) + + +class FilesystemBasedCache(Cache): + _SUBDIR = 'flatpak-node-generator' + _KEY_CHAR_ESCAPE_RE = re.compile(r'[^A-Za-z0-9._\-]') + + @staticmethod + def _escape_key(key: str) -> str: + return FilesystemBasedCache._KEY_CHAR_ESCAPE_RE.sub( + lambda m: f'_{ord(m.group()):02X}', key) + + class FilesystemBucketReader(Cache.BucketReader): + def __init__(self, file: IO[bytes]) -> None: + self.file = file + + def close(self) -> None: + self.file.close() + + def read_parts(self, size: int = DEFAULT_PART_SIZE) -> Iterator[bytes]: + while True: + data = self.file.read(size) + if not data: + break + + yield data + + def read_all(self) -> bytes: + return self.file.read() + + class FilesystemBucketWriter(Cache.BucketWriter): + def __init__(self, file: IO[bytes], temp: Path, target: Path) -> None: + self.file = file + self.temp = temp + self.target = target + + def write(self, data: bytes) -> None: + self.file.write(data) + + def cancel(self) -> None: + self.file.close() + self.temp.unlink() + + def seal(self) -> None: + self.file.close() + self.temp.rename(self.target) + + class FilesystemBucketRef(Cache.BucketRef): + def __init__(self, key: str, cache_root: Path) -> None: + super().__init__(key) + self._cache_root = cache_root + + self._cache_path = self._cache_root / FilesystemBasedCache._escape_key(key) + + def open_read(self) -> Optional[Cache.BucketReader]: + try: + fp = self._cache_path.open('rb') + except FileNotFoundError: + return None + else: + return FilesystemBasedCache.FilesystemBucketReader(fp) + + def open_write(self) -> Cache.BucketWriter: + target = self._cache_path + if not target.parent.exists(): + target.parent.mkdir(exist_ok=True, parents=True) + + fd, temp = tempfile.mkstemp(dir=self._cache_root, prefix='__temp__') + return FilesystemBasedCache.FilesystemBucketWriter(os.fdopen(fd, 'wb'), + Path(temp), target) + + @property + def _cache_root(self) -> Path: + xdg_cache_home = os.environ.get('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) + return Path(xdg_cache_home) / self._SUBDIR + + def get(self, key: str) -> Cache.BucketRef: + return FilesystemBasedCache.FilesystemBucketRef(key, self._cache_root) + + +Cache.instance = NullCache() + + +class Requests: + instance: 'Requests' + + DEFAULT_RETRIES = 5 + retries: ClassVar[int] = DEFAULT_RETRIES + + @property + def is_async(self) -> bool: + raise NotImplementedError + + def __get_cache_bucket(self, cachable: bool, url: str) -> Cache.BucketRef: + return Cache.get_working_instance_if(cachable).get(f'requests:{url}') + + async def _read_parts(self, + url: str, + size: int = DEFAULT_PART_SIZE) -> AsyncIterator[bytes]: + raise NotImplementedError + yield b'' # Silence mypy. + + async def _read_all(self, url: str) -> bytes: + raise NotImplementedError + + async def read_parts(self, + url: str, + *, + cachable: bool, + size: int = DEFAULT_PART_SIZE) -> AsyncIterator[bytes]: + bucket = self.__get_cache_bucket(cachable, url) + + bucket_reader = bucket.open_read() + if bucket_reader is not None: + for part in bucket_reader.read_parts(size): + yield part + + return + + for i in range(1, Requests.retries + 1): + try: + with bucket.open_write() as bucket_writer: + async for part in self._read_parts(url, size): + bucket_writer.write(part) + yield part + + return + except Exception: + if i == Requests.retries: + raise + + async def read_all(self, url: str, *, cachable: bool = False) -> bytes: + bucket = self.__get_cache_bucket(cachable, url) + + bucket_reader = bucket.open_read() + if bucket_reader is not None: + return bucket_reader.read_all() + + for i in range(1, Requests.retries + 1): + try: + with bucket.open_write() as bucket_writer: + data = await self._read_all(url) + bucket_writer.write(data) + return data + except Exception: + if i == Requests.retries: + raise + + assert False + + +class UrllibRequests(Requests): + @property + def is_async(self) -> bool: + return False + + async def _read_parts(self, + url: str, + size: int = DEFAULT_PART_SIZE) -> AsyncIterator[bytes]: + with urllib.request.urlopen(url) as response: + while True: + data = response.read(size) + if not data: + return + + yield data + + async def _read_all(self, url: str) -> bytes: + with urllib.request.urlopen(url) as response: + return cast(bytes, response.read()) + + +class StubRequests(Requests): + @property + def is_async(self) -> bool: + return True + + async def _read_parts(self, + url: str, + size: int = DEFAULT_PART_SIZE) -> AsyncIterator[bytes]: + yield b'' + + async def _read_all(self, url: str) -> bytes: + return b'' + + +Requests.instance = UrllibRequests() + +try: + import aiohttp + + class AsyncRequests(Requests): + @property + def is_async(self) -> bool: + return True + + @contextlib.asynccontextmanager + async def _open_stream(self, url: str) -> AsyncIterator[aiohttp.StreamReader]: + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + yield response.content + + async def _read_parts(self, + url: str, + size: int = DEFAULT_PART_SIZE) -> AsyncIterator[bytes]: + async with self._open_stream(url) as stream: + while True: + data = await stream.read(size) + if not data: + return + + yield data + + async def _read_all(self, url: str) -> bytes: + async with self._open_stream(url) as stream: + return await stream.read() + + Requests.instance = AsyncRequests() + +except ImportError: + pass + + +class CachedRequests(Requests): + pass + + +class Integrity(NamedTuple): + algorithm: str + digest: str + + @staticmethod + def parse(value: str) -> 'Integrity': + algorithm, encoded_digest = value.split('-', 1) + assert algorithm.startswith('sha'), algorithm + digest = binascii.hexlify(base64.b64decode(encoded_digest)).decode() + + return Integrity(algorithm, digest) + + @staticmethod + def from_sha1(sha1: str) -> 'Integrity': + assert len(sha1) == 40, f'Invalid length of sha1: {sha1}' + return Integrity('sha1', sha1) + + @staticmethod + def generate(data: Union[str, bytes], *, algorithm: str = 'sha256') -> 'Integrity': + builder = IntegrityBuilder(algorithm) + builder.update(data) + return builder.build() + + @staticmethod + def from_json_object(data: Any) -> 'Integrity': + return Integrity(algorithm=data['algorithm'], digest=data['digest']) + + def to_json_object(self) -> Any: + return {'algorithm': self.algorithm, 'digest': self.digest} + + def to_base64(self) -> str: + return base64.b64encode(binascii.unhexlify(self.digest)).decode() + + +class IntegrityBuilder: + def __init__(self, algorithm: str = 'sha256') -> None: + self.algorithm = algorithm + self._hasher = hashlib.new(algorithm) + + def update(self, data: Union[str, bytes]) -> None: + data_bytes: bytes + if isinstance(data, str): + data_bytes = data.encode() + else: + data_bytes = data + self._hasher.update(data_bytes) + + def build(self) -> Integrity: + return Integrity(algorithm=self.algorithm, digest=self._hasher.hexdigest()) + + +class RemoteUrlMetadata(NamedTuple): + integrity: Integrity + size: int + + @staticmethod + def __get_cache_bucket(cachable: bool, kind: str, url: str) -> Cache.BucketRef: + return Cache.get_working_instance_if(cachable).get( + f'remote-url-metadata:{kind}:{url}') + + @staticmethod + def from_json_object(data: Any) -> 'RemoteUrlMetadata': + return RemoteUrlMetadata(integrity=Integrity.from_json_object(data['integrity']), + size=data['size']) + + @classmethod + async def get(cls, + url: str, + *, + cachable: bool, + integrity_algorithm: str = 'sha256') -> 'RemoteUrlMetadata': + bucket = cls.__get_cache_bucket(cachable, 'full', url) + + bucket_reader = bucket.open_read() + if bucket_reader is not None: + data = json.loads(bucket_reader.read_all()) + return RemoteUrlMetadata.from_json_object(data) + + builder = IntegrityBuilder(integrity_algorithm) + size = 0 + + async for part in Requests.instance.read_parts(url, cachable=False): + builder.update(part) + size += len(part) + + metadata = RemoteUrlMetadata(integrity=builder.build(), size=size) + + with bucket.open_write() as bucket_writer: + bucket_writer.write(json.dumps(metadata.to_json_object()).encode('ascii')) + + return metadata + + @classmethod + async def get_size(cls, url: str, *, cachable: bool) -> int: + bucket = cls.__get_cache_bucket(cachable, 'size', url) + + bucket_reader = bucket.open_read() + if bucket_reader is not None: + return int(bucket_reader.read_all()) + + size = 0 + async for part in Requests.instance.read_parts(url, cachable=False): + size += len(part) + + with bucket.open_write() as bucket_writer: + bucket_writer.write(str(size).encode('ascii')) + + return size + + def to_json_object(self) -> Any: + return {'integrity': self.integrity.to_json_object(), 'size': self.size} + + +class ResolvedSource(NamedTuple): + resolved: str + integrity: Optional[Integrity] + + async def retrieve_integrity(self) -> Integrity: + if self.integrity is not None: + return self.integrity + else: + url = self.resolved + assert url is not None, 'registry source has no resolved URL' + metadata = await RemoteUrlMetadata.get(url, cachable=True) + return metadata.integrity + + +class UnresolvedRegistrySource: + pass + + +class GitSource(NamedTuple): + original: str + url: str + commit: str + from_: Optional[str] + + +PackageSource = Union[ResolvedSource, UnresolvedRegistrySource, GitSource] + + +class Package(NamedTuple): + name: str + version: str + source: PackageSource + lockfile: Path + + +class ManifestGenerator(contextlib.AbstractContextManager): + MAX_GITHUB_SIZE = 49 * 1000 * 1000 + JSON_INDENT = 4 + + def __init__(self) -> None: + # Store the dicts as a set of tuples, then rebuild the dict when returning it. + # That way, we ensure uniqueness. + self._sources: Set[Tuple[Tuple[str, Any], ...]] = set() + self._commands: List[str] = [] + + def __exit__(self, exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + tb: Optional[types.TracebackType]) -> None: + self._finalize() + + @property + def data_root(self) -> Path: + return Path('flatpak-node') + + @property + def tmp_root(self) -> Path: + return self.data_root / 'tmp' + + @property + def source_count(self) -> int: + return len(self._sources) + + def ordered_sources(self) -> Iterator[Dict[Any, Any]]: + return map(dict, sorted(self._sources)) # type: ignore + + def split_sources(self) -> Iterator[List[Dict[Any, Any]]]: + BASE_CURRENT_SIZE = len('[\n]') + current_size = BASE_CURRENT_SIZE + current: List[Dict[Any, Any]] = [] + + for source in self.ordered_sources(): + # Generate one source by itself, then check the length without the closing and + # opening brackets. + source_json = json.dumps([source], indent=ManifestGenerator.JSON_INDENT) + source_json_len = len('\n'.join(source_json.splitlines()[1:-1])) + if current_size + source_json_len >= ManifestGenerator.MAX_GITHUB_SIZE: + yield current + current = [] + current_size = BASE_CURRENT_SIZE + current.append(source) + current_size += source_json_len + + if current: + yield current + + def _add_source(self, source: Dict[str, Any]) -> None: + self._sources.add(tuple(source.items())) + + def _add_source_with_destination(self, + source: Dict[str, Any], + destination: Optional[Path], + *, + is_dir: bool, + only_arches: Optional[List[str]] = None) -> None: + if destination is not None: + if is_dir: + source['dest'] = str(destination) + else: + source['dest-filename'] = destination.name + if len(destination.parts) > 1: + source['dest'] = str(destination.parent) + + if only_arches: + source['only-arches'] = tuple(only_arches) + + self._add_source(source) + + def add_url_source(self, + url: str, + integrity: Integrity, + destination: Optional[Path] = None, + *, + only_arches: Optional[List[str]] = None) -> None: + source: Dict[str, Any] = { + 'type': 'file', + 'url': url, + integrity.algorithm: integrity.digest + } + self._add_source_with_destination(source, + destination, + is_dir=False, + only_arches=only_arches) + + def add_archive_source(self, + url: str, + integrity: Integrity, + destination: Optional[Path] = None, + only_arches: Optional[List[str]] = None, + strip_components: int = 1) -> None: + source: Dict[str, Any] = { + 'type': 'archive', + 'url': url, + 'strip-components': strip_components, + integrity.algorithm: integrity.digest + } + self._add_source_with_destination(source, + destination, + is_dir=True, + only_arches=only_arches) + + def add_data_source(self, data: Union[str, bytes], destination: Path) -> None: + if isinstance(data, bytes): + source = { + 'type': 'inline', + 'contents': base64.b64encode(data).decode('ascii'), + 'base64': True, + } + else: + assert isinstance(data, str) + source = { + 'type': 'inline', + 'contents': data, + } + self._add_source_with_destination(source, destination, is_dir=False) + + def add_git_source(self, + url: str, + commit: str, + destination: Optional[Path] = None) -> None: + source = {'type': 'git', 'url': url, 'commit': commit} + self._add_source_with_destination(source, destination, is_dir=True) + + def add_script_source(self, commands: List[str], destination: Path) -> None: + source = {'type': 'script', 'commands': tuple(commands)} + self._add_source_with_destination(source, destination, is_dir=False) + + def add_shell_source(self, + commands: List[str], + destination: Optional[Path] = None, + only_arches: Optional[List[str]] = None) -> None: + """This might be slow for multiple instances. Use `add_command()` instead.""" + source = {'type': 'shell', 'commands': tuple(commands)} + self._add_source_with_destination(source, + destination=destination, + only_arches=only_arches, + is_dir=True) + + def add_command(self, command: str) -> None: + self._commands.append(command) + + def _finalize(self) -> None: + if self._commands: + self._add_source({'type': 'shell', 'commands': tuple(self._commands)}) + + +class LockfileProvider: + def parse_git_source(self, version: str, from_: Optional[str] = None) -> GitSource: + # https://github.com/microsoft/pyright/issues/1589 + # pyright: reportPrivateUsage=false + + original_url = urllib.parse.urlparse(version) + assert original_url.scheme and original_url.path and original_url.fragment + + replacements = GIT_SCHEMES.get(original_url.scheme, {}) + new_url = original_url._replace(fragment='', **replacements) + # Replace e.g. git:github.com/owner/repo with git://github.com/owner/repo + if not new_url.netloc: + path = new_url.path.split('/') + new_url = new_url._replace(netloc=path[0], path='/'.join(path[1:])) + + return GitSource(original=original_url.geturl(), + url=new_url.geturl(), + commit=original_url.fragment, + from_=from_) + + def process_lockfile(self, lockfile: Path) -> Iterator[Package]: + raise NotImplementedError() + + +class ModuleProvider(contextlib.AbstractContextManager): + async def generate_package(self, package: Package) -> None: + raise NotImplementedError() + + +class ElectronBinaryManager: + class Arch(NamedTuple): + electron: str + flatpak: str + + class Binary(NamedTuple): + filename: str + url: str + integrity: Integrity + + arch: Optional['ElectronBinaryManager.Arch'] = None + + ELECTRON_ARCHES_TO_FLATPAK = { + 'ia32': 'i386', + 'x64': 'x86_64', + 'armv7l': 'arm', + 'arm64': 'aarch64', + } + + INTEGRITY_BASE_FILENAME = 'SHASUMS256.txt' + + def __init__(self, version: str, base_url: str, integrities: Dict[str, + Integrity]) -> None: + self.version = version + self.base_url = base_url + self.integrities = integrities + + def child_url(self, child: str) -> str: + return f'{self.base_url}/{child}' + + def find_binaries(self, binary: str) -> Iterator['ElectronBinaryManager.Binary']: + for electron_arch, flatpak_arch in self.ELECTRON_ARCHES_TO_FLATPAK.items(): + binary_filename = f'{binary}-v{self.version}-linux-{electron_arch}.zip' + binary_url = self.child_url(binary_filename) + + arch = ElectronBinaryManager.Arch(electron=electron_arch, + flatpak=flatpak_arch) + yield ElectronBinaryManager.Binary( + filename=binary_filename, + url=binary_url, + integrity=self.integrities[binary_filename], + arch=arch) + + @property + def integrity_file(self) -> 'ElectronBinaryManager.Binary': + return ElectronBinaryManager.Binary( + filename=f'SHASUMS256.txt-{self.version}', + url=self.child_url(self.INTEGRITY_BASE_FILENAME), + integrity=self.integrities[self.INTEGRITY_BASE_FILENAME]) + + @staticmethod + async def for_version(version: str) -> 'ElectronBinaryManager': + base_url = f'https://github.com/electron/electron/releases/download/v{version}' + integrity_url = f'{base_url}/{ElectronBinaryManager.INTEGRITY_BASE_FILENAME}' + integrity_data = (await Requests.instance.read_all(integrity_url, + cachable=True)).decode() + + integrities: Dict[str, Integrity] = {} + for line in integrity_data.splitlines(): + digest, star_filename = line.split() + filename = star_filename.strip('*') + integrities[filename] = Integrity(algorithm='sha256', digest=digest) + + integrities[ElectronBinaryManager.INTEGRITY_BASE_FILENAME] = ( + Integrity.generate(integrity_data)) + + return ElectronBinaryManager(version=version, + base_url=base_url, + integrities=integrities) + + +class SpecialSourceProvider: + class Options(NamedTuple): + node_chromedriver_from_electron: str + electron_ffmpeg: str + electron_node_headers: bool + nwjs_version: str + nwjs_node_headers: bool + nwjs_ffmpeg: bool + xdg_layout: bool + + def __init__(self, gen: ManifestGenerator, options: Options): + self.gen = gen + self.node_chromedriver_from_electron = options.node_chromedriver_from_electron + self.electron_ffmpeg = options.electron_ffmpeg + self.electron_node_headers = options.electron_node_headers + self.nwjs_version = options.nwjs_version + self.nwjs_node_headers = options.nwjs_node_headers + self.nwjs_ffmpeg = options.nwjs_ffmpeg + self.xdg_layout = options.xdg_layout + + @property + def electron_cache_dir(self) -> Path: + if self.xdg_layout: + return self.gen.data_root / 'cache' / 'electron' + return self.gen.data_root / 'electron-cache' + + def _add_electron_cache_downloads(self, + manager: ElectronBinaryManager, + binary_name: str, + *, + add_integrities: bool = True) -> None: + electron_cache_dir = self.electron_cache_dir + + for binary in manager.find_binaries(binary_name): + assert binary.arch is not None + self.gen.add_url_source(binary.url, + binary.integrity, + electron_cache_dir / binary.filename, + only_arches=[binary.arch.flatpak]) + #Symlinks for @electron/get, which stores electron zips in a subdir + if self.xdg_layout: + sanitized_url = ''.join(c for c in binary.url if c not in '/:') + + #And for @electron/get >= 1.12.4 its sha256 hash of url dirname + url = urllib.parse.urlparse(binary.url) + url_dir = urllib.parse.urlunparse( + url._replace(path=os.path.dirname(url.path))) + url_hash = hashlib.sha256(url_dir.encode()).hexdigest() + + self.gen.add_shell_source([ + f'mkdir -p "{sanitized_url}"', + f'ln -s "../{binary.filename}" "{sanitized_url}/{binary.filename}"', + f'mkdir -p "{url_hash}"', + f'ln -s "../{binary.filename}" "{url_hash}/{binary.filename}"' + ], + destination=electron_cache_dir, + only_arches=[binary.arch.flatpak]) + + if add_integrities: + integrity_file = manager.integrity_file + self.gen.add_url_source(integrity_file.url, integrity_file.integrity, + electron_cache_dir / integrity_file.filename) + + async def _handle_electron(self, package: Package) -> None: + manager = await ElectronBinaryManager.for_version(package.version) + self._add_electron_cache_downloads(manager, 'electron') + + if self.electron_ffmpeg is not None: + if self.electron_ffmpeg == 'archive': + self._add_electron_cache_downloads(manager, + 'ffmpeg', + add_integrities=False) + elif self.electron_ffmpeg == 'lib': + for binary in manager.find_binaries('ffmpeg'): + assert binary.arch is not None + self.gen.add_archive_source(binary.url, + binary.integrity, + destination=self.gen.data_root, + only_arches=[binary.arch.flatpak]) + else: + assert False, self.electron_ffmpeg + + def _handle_gulp_atom_electron(self, package: Package) -> None: + # Versions after 1.22.0 use @electron/get and don't need this + if StrictVersion(package.version) <= StrictVersion('1.22.0'): + cache_path = self.gen.data_root / 'tmp' / 'gulp-electron-cache' / 'atom' / 'electron' + self.gen.add_command(f'mkdir -p "{cache_path.parent}"') + self.gen.add_command(f'ln -sfTr "{self.electron_cache_dir}" "{cache_path}"') + + async def _handle_electron_headers(self, package: Package) -> None: + if self.xdg_layout: + node_gyp_headers_dir = self.gen.data_root / 'cache' / 'node-gyp' / package.version + else: + node_gyp_headers_dir = self.gen.data_root / 'node-gyp' / 'electron-current' + url = f'https://www.electronjs.org/headers/v{package.version}/node-v{package.version}-headers.tar.gz' + metadata = await RemoteUrlMetadata.get(url, cachable=True) + self.gen.add_archive_source(url, + metadata.integrity, + destination=node_gyp_headers_dir) + if self.xdg_layout: + install_version_data = "9" + self.gen.add_data_source(install_version_data, + destination=node_gyp_headers_dir / 'installVersion') + + async def _get_chromedriver_binary_version(self, package: Package) -> str: + # Note: node-chromedriver seems to not have tagged all releases on GitHub, so + # just use unpkg instead. + url = urllib.parse.urljoin(NPM_MIRROR, f'chromedriver@{package.version}/lib/chromedriver') + js = await Requests.instance.read_all(url, cachable=True) + # XXX: a tad ugly + match = re.search(r"exports\.version = '([^']+)'", js.decode()) + assert match is not None, f'Failed to get ChromeDriver binary version from {url}' + return match.group(1) + + async def _handle_electron_chromedriver(self, package: Package) -> None: + manager = await ElectronBinaryManager.for_version(package.version) + self._add_electron_cache_downloads(manager, 'chromedriver') + + async def _handle_node_chromedriver(self, package: Package) -> None: + version = await self._get_chromedriver_binary_version(package) + destination = self.gen.data_root / 'chromedriver' + + if self.node_chromedriver_from_electron is not None: + manager = await ElectronBinaryManager.for_version( + self.node_chromedriver_from_electron) + + for binary in manager.find_binaries('chromedriver'): + assert binary.arch is not None + self.gen.add_archive_source(binary.url, + binary.integrity, + destination=destination, + only_arches=[binary.arch.flatpak]) + else: + url = (f'https://chromedriver.storage.googleapis.com/{version}/' + 'chromedriver_linux64.zip') + metadata = await RemoteUrlMetadata.get(url, cachable=True) + + self.gen.add_archive_source(url, + metadata.integrity, + destination=destination, + only_arches=['x86_64']) + + async def _add_nwjs_cache_downloads(self, version: str, flavor: str = 'normal'): + assert not version.startswith('v') + nwjs_mirror = 'https://dl.nwjs.io' + ffmpeg_dl_base = 'https://github.com/iteufel/nwjs-ffmpeg-prebuilt/releases/download' + + if self.nwjs_node_headers: + headers_dl_url = f'{nwjs_mirror}/v{version}/nw-headers-v{version}.tar.gz' + headers_dest = self.gen.data_root / 'node-gyp' / 'nwjs-current' + headers_metadata = await RemoteUrlMetadata.get(headers_dl_url, cachable=True) + self.gen.add_archive_source(headers_dl_url, + headers_metadata.integrity, + destination=headers_dest) + + if flavor == 'normal': + filename_base = 'nwjs' + else: + filename_base = f'nwjs-{flavor}' + + destdir = self.gen.data_root / 'nwjs-cache' + nwjs_arch_map = [ + ('x86_64', 'linux-x64', 'linux64'), + ('i386', 'linux-ia32', 'linux32'), + ] + for flatpak_arch, nwjs_arch, platform in nwjs_arch_map: + filename = f'{filename_base}-v{version}-{nwjs_arch}.tar.gz' + dl_url = f'{nwjs_mirror}/v{version}/{filename}' + metadata = await RemoteUrlMetadata.get(dl_url, cachable=True) + dest = destdir / f'{version}-{flavor}' / platform + + self.gen.add_archive_source(dl_url, + metadata.integrity, + destination=dest, + only_arches=[flatpak_arch]) + + if self.nwjs_ffmpeg: + ffmpeg_dl_url = f'{ffmpeg_dl_base}/{version}/{version}-{nwjs_arch}.zip' + ffmpeg_metadata = await RemoteUrlMetadata.get(ffmpeg_dl_url, cachable=True) + self.gen.add_archive_source(ffmpeg_dl_url, + ffmpeg_metadata.integrity, + destination=dest, + strip_components=0, + only_arches=[flatpak_arch]) + + async def _handle_nw_builder(self, package: Package) -> None: + if self.nwjs_version: + version = self.nwjs_version + else: + versions_json = json.loads(await Requests.instance.read_all( + 'https://nwjs.io/versions.json', cachable=False)) + version = versions_json['latest'].lstrip('v') + await self._add_nwjs_cache_downloads(version) + self.gen.add_data_source(version, destination=self.gen.data_root / 'nwjs-version') + + async def _handle_dugite_native(self, package: Package) -> None: + dl_json_url = urllib.parse.urljoin( + NPM_MIRROR, f'{package.name}@{package.version}/script/embedded-git.json') + dl_json = json.loads(await Requests.instance.read_all(dl_json_url, cachable=True)) + dugite_arch_map = { + 'x86_64': 'linux-x64', + } + destdir = self.gen.data_root / 'tmp' + for arch, dugite_arch in dugite_arch_map.items(): + url = dl_json[dugite_arch]['url'] + filename = dl_json[dugite_arch]['name'] + integrity = Integrity(algorithm='sha256', + digest=dl_json[dugite_arch]['checksum']) + + self.gen.add_url_source(url, + integrity, + destination=destdir / filename, + only_arches=[arch]) + + async def _handle_ripgrep_prebuilt(self, package: Package) -> None: + async def get_ripgrep_tag(version: str) -> str: + url = f'https://github.com/microsoft/vscode-ripgrep/raw/v{version}/lib/postinstall.js' + tag_re = re.compile(r"VERSION\s+=\s+'(v[\d.-]+)';") + resp = await Requests.instance.read_all(url, cachable=True) + match = tag_re.search(resp.decode()) + assert match is not None + return match.group(1) + + tag = await get_ripgrep_tag(package.version) + ripgrep_arch_map = { + 'x86_64': 'x86_64-unknown-linux-musl', + 'i386': 'i686-unknown-linux-musl', + 'arm': 'arm-unknown-linux-gnueabihf', + 'aarch64': 'aarch64-unknown-linux-gnu' + } + destdir = self.gen.data_root / 'tmp' / f'vscode-ripgrep-cache-{package.version}' + for arch, ripgrep_arch in ripgrep_arch_map.items(): + filename = f'ripgrep-{tag}-{ripgrep_arch}.tar.gz' + url = f'https://github.com/microsoft/ripgrep-prebuilt/releases/download/{tag}/{filename}' + metadata = await RemoteUrlMetadata.get(url, cachable=True) + self.gen.add_url_source(url, + metadata.integrity, + destination=destdir / filename, + only_arches=[arch]) + + async def _handle_playwright(self, package: Package) -> None: + base_url = f'https://github.com/microsoft/playwright/raw/v{package.version}/' + if StrictVersion(package.version) >= StrictVersion('1.16.0'): + browsers_json_url = base_url + 'packages/playwright-core/browsers.json' + else: + browsers_json_url = base_url + 'browsers.json' + browsers_json = json.loads(await Requests.instance.read_all(browsers_json_url, + cachable=True)) + for browser in browsers_json['browsers']: + if not browser.get('installByDefault', True): + continue + name = browser['name'] + revision = int(browser['revision']) + + if name == 'chromium': + if revision < 792639: + url_tp = 'https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/%d/%s' + dl_file = 'chrome-linux.zip' + else: + url_tp = 'https://playwright.azureedge.net/builds/chromium/%d/%s' + dl_file = 'chromium-linux.zip' + elif name == 'firefox': + url_tp = 'https://playwright.azureedge.net/builds/firefox/%d/%s' + if revision < 1140: + dl_file = 'firefox-linux.zip' + else: + dl_file = 'firefox-ubuntu-18.04.zip' + elif name == 'webkit': + url_tp = 'https://playwright.azureedge.net/builds/webkit/%d/%s' + if revision < 1317: + dl_file = 'minibrowser-gtk-wpe.zip' + else: + dl_file = 'webkit-ubuntu-20.04.zip' + elif name == 'ffmpeg': + url_tp = 'https://playwright.azureedge.net/builds/ffmpeg/%d/%s' + dl_file = 'ffmpeg-linux.zip' + else: + raise ValueError(f'Unknown playwright browser {name}') + + dl_url = url_tp % (revision, dl_file) + metadata = await RemoteUrlMetadata.get(dl_url, cachable=True) + destdir = self.gen.data_root / 'cache' / 'ms-playwright' / f'{name}-{revision}' + self.gen.add_archive_source(dl_url, + metadata.integrity, + destination=destdir, + strip_components=0) + # Arbitrary string here; flatpak-builder segfaults on empty data: url + self.gen.add_data_source("flatpak-node-cache", + destination=destdir / 'INSTALLATION_COMPLETE') + + async def _handle_esbuild(self, package: Package) -> None: + pkg_names = { + 'x86_64': 'esbuild-linux-64', + 'i386': 'esbuild-linux-32', + 'arm': 'esbuild-linux-arm', + 'aarch64': 'esbuild-linux-arm64' + } + + for flatpak_arch, pkg_name in pkg_names.items(): + dl_url = f'https://registry.npmjs.org/{pkg_name}/-/{pkg_name}-{package.version}.tgz' + metadata = await RemoteUrlMetadata.get(dl_url, cachable=True) + + cache_dst = self.gen.data_root / 'cache' / 'esbuild' + archive_dst = cache_dst / '.package' / f'{pkg_name}@{package.version}' + bin_src = archive_dst / 'bin' / 'esbuild' + bin_dst = cache_dst / 'bin' / f'{pkg_name}@{package.version}' + + self.gen.add_archive_source(dl_url, + metadata.integrity, + destination=archive_dst, + only_arches=[flatpak_arch], + strip_components=1) + + cmd = [ + f'mkdir -p "{bin_dst.parent.relative_to(cache_dst)}"', + f'cp "{bin_src.relative_to(cache_dst)}" "{bin_dst.relative_to(cache_dst)}"', + f'ln -sf "{bin_dst.name}" "bin/esbuild-current"' + ] + self.gen.add_shell_source(cmd, + only_arches=[flatpak_arch], + destination=cache_dst) + + def _handle_electron_builder(self, package: Package) -> None: + destination = self.gen.data_root / 'electron-builder-arch-args.sh' + + script: List[str] = [] + script.append('case "$FLATPAK_ARCH" in') + + for electron_arch, flatpak_arch in ( + ElectronBinaryManager.ELECTRON_ARCHES_TO_FLATPAK.items()): + script.append(f'"{flatpak_arch}")') + script.append(f' export ELECTRON_BUILDER_ARCH_ARGS="--{electron_arch}"') + script.append(' ;;') + + script.append('esac') + + self.gen.add_script_source(script, destination) + + async def generate_special_sources(self, package: Package) -> None: + if isinstance(Requests.instance, StubRequests): + # This is going to crash and burn. + return + + if package.name == 'electron': + await self._handle_electron(package) + if self.electron_node_headers or self.xdg_layout: + await self._handle_electron_headers(package) + elif package.name == 'electron-chromedriver': + await self._handle_electron_chromedriver(package) + elif package.name == 'chromedriver': + await self._handle_node_chromedriver(package) + elif package.name == 'electron-builder': + self._handle_electron_builder(package) + elif package.name == 'gulp-atom-electron': + self._handle_gulp_atom_electron(package) + elif package.name == 'nw-builder': + await self._handle_nw_builder(package) + elif package.name in {'dugite', '@shiftkey/dugite'}: + await self._handle_dugite_native(package) + elif package.name == 'vscode-ripgrep': + await self._handle_ripgrep_prebuilt(package) + elif package.name == 'playwright': + await self._handle_playwright(package) + elif package.name == 'esbuild': + await self._handle_esbuild(package) + + +class NpmLockfileProvider(LockfileProvider): + class Options(NamedTuple): + no_devel: bool + + def __init__(self, options: Options): + self.no_devel = options.no_devel + + def process_dependencies( + self, lockfile: Path, + dependencies: Dict[str, Dict[Any, Any]]) -> Iterator[Package]: + for name, info in dependencies.items(): + if info.get('dev') and self.no_devel: + continue + elif info.get('bundled'): + continue + + version: str = info['version'] + + source: PackageSource + if info.get('from'): + git_source = self.parse_git_source(version, info['from']) + source = git_source + else: + # NOTE: npm ignores the resolved field and just uses the provided + # registry instead. We follow the same behavior here. + source = UnresolvedRegistrySource() + + yield Package(name=name, version=version, source=source, lockfile=lockfile) + + if 'dependencies' in info: + yield from self.process_dependencies(lockfile, info['dependencies']) + + def process_lockfile(self, lockfile: Path) -> Iterator[Package]: + with open(lockfile) as fp: + data = json.load(fp) + + assert data['lockfileVersion'] <= 2, data['lockfileVersion'] + + yield from self.process_dependencies(lockfile, data.get('dependencies', {})) + + +class NpmModuleProvider(ModuleProvider): + class Options(NamedTuple): + registry: str + no_autopatch: bool + no_trim_index: bool + + class RegistryPackageIndex(NamedTuple): + url: str + data: Dict[Any, Any] + used_versions: Set[str] + + def __init__(self, gen: ManifestGenerator, special: SpecialSourceProvider, + lockfile_root: Path, options: Options) -> None: + self.gen = gen + self.special_source_provider = special + self.lockfile_root = lockfile_root + self.registry = options.registry + self.no_autopatch = options.no_autopatch + self.no_trim_index = options.no_trim_index + self.npm_cache_dir = self.gen.data_root / 'npm-cache' + self.cacache_dir = self.npm_cache_dir / '_cacache' + # Awaitable so multiple tasks can be waiting on the same package info. + self.registry_packages: Dict[ + str, asyncio.Future[NpmModuleProvider.RegistryPackageIndex]] = {} + self.index_entries: Dict[Path, str] = {} + self.all_lockfiles: Set[Path] = set() + # Mapping of lockfiles to a dict of the Git source target paths and GitSource objects. + self.git_sources: DefaultDict[Path, Dict[ + Path, GitSource]] = collections.defaultdict(lambda: {}) + + def __exit__(self, exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + tb: Optional[types.TracebackType]) -> None: + self._finalize() + + def get_cacache_integrity_path(self, integrity: Integrity) -> Path: + digest = integrity.digest + return Path(digest[0:2]) / digest[2:4] / digest[4:] + + def get_cacache_index_path(self, integrity: Integrity) -> Path: + return self.cacache_dir / Path('index-v5') / self.get_cacache_integrity_path( + integrity) + + def get_cacache_content_path(self, integrity: Integrity) -> Path: + return (self.cacache_dir / Path('content-v2') / integrity.algorithm / + self.get_cacache_integrity_path(integrity)) + + def add_index_entry(self, url: str, metadata: RemoteUrlMetadata) -> None: + key = f'make-fetch-happen:request-cache:{url}' + index_json = json.dumps({ + 'key': + key, + 'integrity': + f'{metadata.integrity.algorithm}-{metadata.integrity.to_base64()}', + 'time': + 0, + 'size': + metadata.size, + 'metadata': { + 'url': url, + 'reqHeaders': {}, + 'resHeaders': {}, + }, + }) + + content_integrity = Integrity.generate(index_json, algorithm='sha1') + index = '\t'.join((content_integrity.digest, index_json)) + + key_integrity = Integrity.generate(key) + index_path = self.get_cacache_index_path(key_integrity) + self.index_entries[index_path] = index + + async def resolve_source(self, package: Package) -> ResolvedSource: + # These results are going to be the same each time. + if package.name not in self.registry_packages: + cache_future = asyncio.get_event_loop().create_future() + self.registry_packages[package.name] = cache_future + + data_url = f'{self.registry}/{package.name.replace("/", "%2f")}' + # NOTE: Not cachable, because this is an API call. + raw_data = await Requests.instance.read_all(data_url, cachable=False) + data = json.loads(raw_data) + + assert 'versions' in data, f'{data_url} returned an invalid package index' + cache_future.set_result( + NpmModuleProvider.RegistryPackageIndex(url=data_url, + data=data, + used_versions=set())) + + if not self.no_trim_index: + for key in list(data): + if key != 'versions': + del data[key] + + index = await self.registry_packages[package.name] + + versions = index.data['versions'] + assert package.version in versions, \ + f'{package.name} versions available are {", ".join(versions)}, not {package.version}' + + dist = versions[package.version]['dist'] + assert 'tarball' in dist, f'{package.name}@{package.version} has no tarball in dist' + + index.used_versions.add(package.version) + + integrity: Integrity + if 'integrity' in dist: + integrity = Integrity.parse(dist['integrity']) + elif 'shasum' in dist: + integrity = Integrity.from_sha1(dist['shasum']) + else: + assert False, f'{package.name}@{package.version} has no integrity in dist' + + return ResolvedSource(resolved=dist['tarball'], integrity=integrity) + + async def generate_package(self, package: Package) -> None: + self.all_lockfiles.add(package.lockfile) + source = package.source + + assert not isinstance(source, ResolvedSource) + + if isinstance(source, UnresolvedRegistrySource): + source = await self.resolve_source(package) + assert source.resolved is not None + assert source.integrity is not None + + integrity = await source.retrieve_integrity() + size = await RemoteUrlMetadata.get_size(source.resolved, cachable=True) + metadata = RemoteUrlMetadata(integrity=integrity, size=size) + content_path = self.get_cacache_content_path(integrity) + self.gen.add_url_source(source.resolved, integrity, content_path) + self.add_index_entry(source.resolved, metadata) + + await self.special_source_provider.generate_special_sources(package) + + # pyright: reportUnnecessaryIsInstance=false + elif isinstance(source, GitSource): + # Get a unique name to use for the Git repository folder. + name = f'{package.name}-{source.commit}' + path = self.gen.data_root / 'git-packages' / name + self.git_sources[package.lockfile][path] = source + self.gen.add_git_source(source.url, source.commit, path) + + def relative_lockfile_dir(self, lockfile: Path) -> Path: + return lockfile.parent.relative_to(self.lockfile_root) + + def _finalize(self) -> None: + for _, async_index in self.registry_packages.items(): + index = async_index.result() + + if not self.no_trim_index: + for version in list(index.data['versions'].keys()): + if version not in index.used_versions: + del index.data['versions'][version] + + raw_data = json.dumps(index.data).encode() + + metadata = RemoteUrlMetadata(integrity=Integrity.generate(raw_data), + size=len(raw_data)) + content_path = self.get_cacache_content_path(metadata.integrity) + self.gen.add_data_source(raw_data, content_path) + self.add_index_entry(index.url, metadata) + + patch_commands: DefaultDict[Path, List[str]] = collections.defaultdict(lambda: []) + + if self.git_sources: + # Generate jq scripts to patch the package*.json files. + scripts = { + 'package.json': + r''' + walk( + if type == "object" + then + to_entries | map( + if (.value | type == "string") and $data[.value] + then .value = "git+file:\($buildroot)/\($data[.value])" + else . + end + ) | from_entries + else . + end + ) + ''', + 'package-lock.json': + r''' + walk( + if type == "object" and (.version | type == "string") and $data[.version] + then + .version = "git+file:\($buildroot)/\($data[.version])" + else . + end + ) + ''', + } + + for lockfile, sources in self.git_sources.items(): + prefix = self.relative_lockfile_dir(lockfile) + data: Dict[str, Dict[str, str]] = { + 'package.json': {}, + 'package-lock.json': {}, + } + + for path, source in sources.items(): + original_version = f'{source.original}' + new_version = f'{path}#{source.commit}' + assert source.from_ is not None + data['package.json'][source.from_] = new_version + data['package-lock.json'][original_version] = new_version + + for filename, script in scripts.items(): + target = Path('$FLATPAK_BUILDER_BUILDDIR') / prefix / filename + script = textwrap.dedent(script.lstrip('\n')).strip().replace( + '\n', '') + json_data = json.dumps(data[filename]) + patch_commands[lockfile].append( + 'jq' + ' --arg buildroot "$FLATPAK_BUILDER_BUILDDIR"' + f' --argjson data {shlex.quote(json_data)}' + f' {shlex.quote(script)} {target}' + f' > {target}.new') + patch_commands[lockfile].append(f'mv {target}{{.new,}}') + + patch_all_commands: List[str] = [] + for lockfile in self.all_lockfiles: + patch_dest = self.gen.data_root / 'patch' / self.relative_lockfile_dir( + lockfile) + # Don't use with_extension to avoid problems if the package has a . in its name. + patch_dest = patch_dest.with_name(patch_dest.name + '.sh') + + self.gen.add_script_source(patch_commands[lockfile], patch_dest) + patch_all_commands.append(f'$FLATPAK_BUILDER_BUILDDIR/{patch_dest}') + + patch_all_dest = self.gen.data_root / 'patch-all.sh' + self.gen.add_script_source(patch_all_commands, patch_all_dest) + + if not self.no_autopatch: + # FLATPAK_BUILDER_BUILDDIR isn't defined yet for script sources. + self.gen.add_command(f'FLATPAK_BUILDER_BUILDDIR=$PWD {patch_all_dest}') + + if self.index_entries: + for path, entry in self.index_entries.items(): + self.gen.add_data_source(entry, path) + + +class YarnLockfileProvider(LockfileProvider): + @staticmethod + def is_git_version(version: str) -> bool: + for pattern in GIT_URL_PATTERNS: + if pattern.match(version): + return True + url = urllib.parse.urlparse(version) + if url.netloc in GIT_URL_HOSTS: + return len([p for p in url.path.split("/") if p]) == 2 + return False + + def unquote(self, string: str) -> str: + if string.startswith('"'): + assert string.endswith('"') + return string[1:-1] + else: + return string + + def parse_package_section(self, lockfile: Path, section: List[str]) -> Package: + assert section + name_line = section[0] + assert name_line.endswith(':'), name_line + name_line = name_line[:-1] + + name = self.unquote(name_line.split(',', 1)[0]) + name, _ = name.rsplit('@', 1) + + version: Optional[str] = None + resolved: Optional[str] = None + integrity: Optional[Integrity] = None + + section_indent = 0 + + line = None + for line in section[1:]: + indent = 0 + while line[indent].isspace(): + indent += 1 + + assert indent, line + if not section_indent: + section_indent = indent + elif indent > section_indent: + # Inside some nested section. + continue + + line = line.strip() + if line.startswith('version'): + version = self.unquote(line.split(' ', 1)[1]) + elif line.startswith('resolved'): + resolved = self.unquote(line.split(' ', 1)[1]) + elif line.startswith('integrity'): + _, values_str = line.split(' ', 1) + values = self.unquote(values_str).split(' ') + integrity = Integrity.parse(values[0]) + + assert version and resolved, line + + source: PackageSource + if self.is_git_version(resolved): + source = self.parse_git_source(version=resolved) + else: + source = ResolvedSource(resolved=resolved, integrity=integrity) + + return Package(name=name, version=version, source=source, lockfile=lockfile) + + def process_lockfile(self, lockfile: Path) -> Iterator[Package]: + section: List[str] = [] + + with open(lockfile) as fp: + for line in map(str.rstrip, fp): + if not line.strip() or line.strip().startswith('#'): + continue + + if not line[0].isspace(): + if section: + yield self.parse_package_section(lockfile, section) + section = [] + + section.append(line) + + if section: + yield self.parse_package_section(lockfile, section) + + +class YarnModuleProvider(ModuleProvider): + # From https://github.com/yarnpkg/yarn/blob/v1.22.4/src/fetchers/tarball-fetcher.js + _PACKAGE_TARBALL_URL_RE = re.compile( + r'(?:(@[^/]+)(?:/|%2f))?[^/]+/(?:-|_attachments)/(?:@[^/]+/)?([^/]+)$') + + def __init__(self, gen: ManifestGenerator, special: SpecialSourceProvider) -> None: + self.gen = gen + self.special_source_provider = special + self.mirror_dir = self.gen.data_root / 'yarn-mirror' + + def __exit__(self, exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + tb: Optional[types.TracebackType]) -> None: + pass + + async def generate_package(self, package: Package) -> None: + source = package.source + + if isinstance(source, ResolvedSource): + integrity = await source.retrieve_integrity() + url_parts = urllib.parse.urlparse(source.resolved) + match = self._PACKAGE_TARBALL_URL_RE.search(url_parts.path) + if match is not None: + scope, filename = match.groups() + if scope: + filename = f'{scope}-{filename}' + else: + filename = os.path.basename(url_parts.path) + + self.gen.add_url_source(source.resolved, integrity, + self.mirror_dir / filename) + + elif isinstance(source, GitSource): + repo_name = urllib.parse.urlparse(source.url).path.split('/')[-1] + name = f'{repo_name}-{source.commit}' + repo_dir = self.gen.tmp_root / name + target_tar = os.path.relpath(self.mirror_dir / name, repo_dir) + + self.gen.add_git_source(source.url, source.commit, repo_dir) + self.gen.add_command( + f'cd {repo_dir}; git archive --format tar -o {target_tar} HEAD') + + await self.special_source_provider.generate_special_sources(package) + + +class ProviderFactory: + def create_lockfile_provider(self) -> LockfileProvider: + raise NotImplementedError() + + def create_module_provider(self, gen: ManifestGenerator, + special: SpecialSourceProvider) -> ModuleProvider: + raise NotImplementedError() + + +class NpmProviderFactory(ProviderFactory): + class Options(NamedTuple): + lockfile: NpmLockfileProvider.Options + module: NpmModuleProvider.Options + + def __init__(self, lockfile_root: Path, options: Options) -> None: + self.lockfile_root = lockfile_root + self.options = options + + def create_lockfile_provider(self) -> NpmLockfileProvider: + return NpmLockfileProvider(self.options.lockfile) + + def create_module_provider(self, gen: ManifestGenerator, + special: SpecialSourceProvider) -> NpmModuleProvider: + return NpmModuleProvider(gen, special, self.lockfile_root, self.options.module) + + +class YarnProviderFactory(ProviderFactory): + def __init__(self) -> None: + pass + + def create_lockfile_provider(self) -> YarnLockfileProvider: + return YarnLockfileProvider() + + def create_module_provider(self, gen: ManifestGenerator, + special: SpecialSourceProvider) -> YarnModuleProvider: + return YarnModuleProvider(gen, special) + + +class GeneratorProgress(contextlib.AbstractContextManager): + def __init__(self, packages: Collection[Package], + module_provider: ModuleProvider) -> None: + self.finished = 0 + self.packages = packages + self.module_provider = module_provider + self.previous_package: Optional[Package] = None + self.current_package: Optional[Package] = None + + def __exit__(self, exc_type: Optional[Type[BaseException]], + exc_value: Optional[BaseException], + tb: Optional[types.TracebackType]) -> None: + print() + + def _format_package(self, package: Package, max_width: int) -> str: + result = f'{package.name} @ {package.version}' + + if len(result) > max_width: + result = result[:max_width - 3] + '...' + + return result + + def _update(self) -> None: + columns, _ = shutil.get_terminal_size() + + sys.stdout.write('\r' + ' ' * columns) + + prefix_string = f'\rGenerating packages [{self.finished}/{len(self.packages)}] ' + sys.stdout.write(prefix_string) + max_package_width = columns - len(prefix_string) + + if self.current_package is not None: + sys.stdout.write(self._format_package(self.current_package, + max_package_width)) + + sys.stdout.flush() + + def _update_with_package(self, package: Package) -> None: + self.previous_package, self.current_package = self.current_package, package + self._update() + + async def _generate(self, package: Package) -> None: + self._update_with_package(package) + await self.module_provider.generate_package(package) + self.finished += 1 + self._update_with_package(package) + + async def run(self) -> None: + self._update() + await asyncio.wait( + [asyncio.create_task(self._generate(pkg)) for pkg in self.packages]) + + +def scan_for_lockfiles(base: Path, patterns: List[str]) -> Iterator[Path]: + for root, _, files in os.walk(base.parent): + if base.name in files: + lockfile = Path(root) / base.name + if not patterns or any(map(lockfile.match, patterns)): + yield lockfile + + +async def main() -> None: + parser = argparse.ArgumentParser(description='Flatpak Node generator') + parser.add_argument('type', choices=['npm', 'yarn']) + parser.add_argument('lockfile', + help='The lockfile path (package-lock.json or yarn.lock)') + parser.add_argument('-o', + '--output', + help='The output sources file', + default='generated-sources.json') + parser.add_argument( + '-r', + '--recursive', + action='store_true', + help='Recursively process all files under the lockfile directory with ' + 'the lockfile basename') + parser.add_argument( + '-R', + '--recursive-pattern', + action='append', + help='Given -r, restrict files to those matching the given pattern.') + parser.add_argument('--registry', + help='The registry to use (npm only)', + default='https://registry.npmjs.org') + parser.add_argument('--no-trim-index', + action='store_true', + help="Don't trim npm package metadata (npm only)") + parser.add_argument('--no-devel', + action='store_true', + help="Don't include devel dependencies (npm only)") + parser.add_argument('--no-aiohttp', + action='store_true', + help="Don't use aiohttp, and silence any warnings related to it") + parser.add_argument('--no-requests-cache', + action='store_true', + help='Disable the requests cache') + parser.add_argument('--retries', + type=int, + help='Number of retries of failed requests', + default=Requests.DEFAULT_RETRIES) + parser.add_argument('-P', + '--no-autopatch', + action='store_true', + help="Don't automatically patch Git sources from package*.json") + parser.add_argument('-s', + '--split', + action='store_true', + help='Split the sources file to fit onto GitHub.') + parser.add_argument('--node-chromedriver-from-electron', + help='Use the ChromeDriver version associated with the given ' + 'Electron version for node-chromedriver') + # Deprecated alternative to --node-chromedriver-from-electron + parser.add_argument('--electron-chromedriver', help=argparse.SUPPRESS) + parser.add_argument('--electron-ffmpeg', + choices=['archive', 'lib'], + help='Download prebuilt ffmpeg for matching electron version') + parser.add_argument('--electron-node-headers', + action='store_true', + help='Download the electron node headers') + parser.add_argument('--nwjs-version', + help='Specify NW.js version (will use latest otherwise)') + parser.add_argument('--nwjs-node-headers', + action='store_true', + help='Download the NW.js node headers') + parser.add_argument('--nwjs-ffmpeg', action='store_true', + help='Download prebuilt ffmpeg for current NW.js version') + parser.add_argument('--xdg-layout', + action='store_true', + help='Use XDG layout for caches') + # Internal option, useful for testing. + parser.add_argument('--stub-requests', action='store_true', help=argparse.SUPPRESS) + + args = parser.parse_args() + + Requests.retries = args.retries + + if args.type == 'yarn' and (args.no_devel or args.no_autopatch): + sys.exit('--no-devel and --no-autopatch do not apply to Yarn.') + + if args.electron_chromedriver: + print('WARNING: --electron-chromedriver is deprecated', file=sys.stderr) + print(' (Use --node-chromedriver-from-electron instead.)', file=sys.stderr) + + if args.stub_requests: + Requests.instance = StubRequests() + elif args.no_aiohttp: + if Requests.instance.is_async: + Requests.instance = UrllibRequests() + elif not Requests.instance.is_async: + print('WARNING: aiohttp is not found, performance will suffer.', file=sys.stderr) + print(' (Pass --no-aiohttp to silence this warning.)', file=sys.stderr) + + if not args.no_requests_cache: + Cache.instance = FilesystemBasedCache() + + lockfiles: List[Path] + if args.recursive or args.recursive_pattern: + lockfiles = list(scan_for_lockfiles(Path(args.lockfile), args.recursive_pattern)) + if not lockfiles: + sys.exit('No lockfiles found.') + print(f'Found {len(lockfiles)} lockfiles.') + else: + lockfiles = [Path(args.lockfile)] + + lockfile_root = Path(args.lockfile).parent + + provider_factory: ProviderFactory + if args.type == 'npm': + npm_options = NpmProviderFactory.Options( + NpmLockfileProvider.Options(no_devel=args.no_devel), + NpmModuleProvider.Options(registry=args.registry, + no_autopatch=args.no_autopatch, + no_trim_index=args.no_trim_index)) + provider_factory = NpmProviderFactory(lockfile_root, npm_options) + elif args.type == 'yarn': + provider_factory = YarnProviderFactory() + else: + assert False, args.type + + print('Reading packages from lockfiles...') + packages: Set[Package] = set() + + for lockfile in lockfiles: + lockfile_provider = provider_factory.create_lockfile_provider() + packages.update(lockfile_provider.process_lockfile(lockfile)) + + print(f'{len(packages)} packages read.') + + gen = ManifestGenerator() + with gen: + options = SpecialSourceProvider.Options( + node_chromedriver_from_electron=args.node_chromedriver_from_electron + or args.electron_chromedriver, + nwjs_version=args.nwjs_version, + nwjs_node_headers=args.nwjs_node_headers, + nwjs_ffmpeg=args.nwjs_ffmpeg, + xdg_layout=args.xdg_layout, + electron_ffmpeg=args.electron_ffmpeg, + electron_node_headers=args.electron_node_headers) + special = SpecialSourceProvider(gen, options) + + with provider_factory.create_module_provider(gen, special) as module_provider: + with GeneratorProgress(packages, module_provider) as progress: + await progress.run() + + if args.xdg_layout: + script_name = "setup_sdk_node_headers.sh" + node_gyp_dir = gen.data_root / "cache" / "node-gyp" + gen.add_script_source([ + 'version=$(node --version | sed "s/^v//")', + 'nodedir=$(dirname "$(dirname "$(which node)")")', + f'mkdir -p "{node_gyp_dir}/$version"', + f'ln -s "$nodedir/include" "{node_gyp_dir}/$version/include"', + f'echo 9 > "{node_gyp_dir}/$version/installVersion"', + ], + destination=gen.data_root / script_name) + gen.add_command(f"bash {gen.data_root / script_name}") + + if args.split: + i = 0 + for i, part in enumerate(gen.split_sources()): + output = Path(args.output) + output = output.with_suffix(f'.{i}{output.suffix}') + with open(output, 'w') as fp: + json.dump(part, fp, indent=ManifestGenerator.JSON_INDENT) + + print(f'Wrote {gen.source_count} to {i + 1} file(s).') + else: + with open(args.output, 'w') as fp: + json.dump(list(gen.ordered_sources()), + fp, + indent=ManifestGenerator.JSON_INDENT) + + if fp.tell() >= ManifestGenerator.MAX_GITHUB_SIZE: + print('WARNING: generated-sources.json is too large for GitHub.', + file=sys.stderr) + print(' (Pass -s to enable splitting.)') + + print(f'Wrote {gen.source_count} source(s).') + + +if __name__ == '__main__': + asyncio.run(main()) diff --git a/flatpak/generated-sources.json b/flatpak/generated-sources.json new file mode 100644 index 00000000..a629990e --- /dev/null +++ b/flatpak/generated-sources.json @@ -0,0 +1,7600 @@ +[ + { + "type": "file", + "url": "https://codeload.github.com/bitfocus/node-dns-js/tar.gz/e5f0c3da63653398005bf36f66ad0b77770dcad6", + "sha256": "bf7bfb00f51ea158aa1f6a76814fbc5f6123bc089c7861caca96202a3c679389", + "dest-filename": "e5f0c3da63653398005bf36f66ad0b77770dcad6", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://codeload.github.com/bitfocus/node-mdns-js/tar.gz/1af6b83ce91e5538012f977e1dcadbda5dc0d3b5", + "sha256": "0f4ffd7064e01fff4455f14413d20f6c6a3e1119aa9a4de40d268bbf914a785c", + "dest-filename": "1af6b83ce91e5538012f977e1dcadbda5dc0d3b5", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://codeload.github.com/devsnek/node-register-scheme/tar.gz/e7cc9a63a1f512565da44cb57316d9fb10750e17", + "sha256": "ab95956c7df0d1252400d97a9b62c7c2e807f41c38629471dc0f41723aa7ff17", + "dest-filename": "e7cc9a63a1f512565da44cb57316d9fb10750e17", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://github.com/electron/electron/releases/download/v17.0.0-beta.8/SHASUMS256.txt", + "sha256": "3272f07d071093b3fae5ba6f11fd7b1889edc77fb5a5876ad9bb40b95ea4feda", + "dest-filename": "SHASUMS256.txt-17.0.0-beta.8", + "dest": "flatpak-node/electron-cache" + }, + { + "type": "file", + "url": "https://github.com/electron/electron/releases/download/v17.0.0-beta.8/electron-v17.0.0-beta.8-linux-arm64.zip", + "sha256": "fd116b98d965f435b1ac6696308297fd995e91c040c24f02081b1eb3705eb114", + "dest-filename": "electron-v17.0.0-beta.8-linux-arm64.zip", + "dest": "flatpak-node/electron-cache", + "only-arches": [ + "aarch64" + ] + }, + { + "type": "file", + "url": "https://github.com/electron/electron/releases/download/v17.0.0-beta.8/electron-v17.0.0-beta.8-linux-armv7l.zip", + "sha256": "f6d7bc963b27930a4f9c367a9dfea26214bb309bad9cc6e7594adbcb90ac5cc6", + "dest-filename": "electron-v17.0.0-beta.8-linux-armv7l.zip", + "dest": "flatpak-node/electron-cache", + "only-arches": [ + "arm" + ] + }, + { + "type": "file", + "url": "https://github.com/electron/electron/releases/download/v17.0.0-beta.8/electron-v17.0.0-beta.8-linux-ia32.zip", + "sha256": "96e99d642835a98332f320e8ffb94180632c5c37023acaed26c775b2c5712035", + "dest-filename": "electron-v17.0.0-beta.8-linux-ia32.zip", + "dest": "flatpak-node/electron-cache", + "only-arches": [ + "i386" + ] + }, + { + "type": "file", + "url": "https://github.com/electron/electron/releases/download/v17.0.0-beta.8/electron-v17.0.0-beta.8-linux-x64.zip", + "sha256": "d346cdb4b333caa6078b4c2196d45e9a3a631cf46fef109ce78e423089e82e85", + "dest-filename": "electron-v17.0.0-beta.8-linux-x64.zip", + "dest": "flatpak-node/electron-cache", + "only-arches": [ + "x86_64" + ] + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.1.1.tgz#9274ec7460652f9c632c59addf24efb1684ef876", + "sha512": "b003f82e575e58dcf494dce64e2adddee59f1435964de83a57f32c9b2c8b47d5f589dc0a056220b7f66f8a7a9095d266dcb79c284b357a691baae3ba3c288b55", + "dest-filename": "7zip-bin-5.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/7zip/-/7zip-0.0.6.tgz#9cafb171af82329490353b4816f03347aa150a30", + "sha1": "9cafb171af82329490353b4816f03347aa150a30", + "dest-filename": "7zip-0.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789", + "sha512": "8805ea527f0821e05335def6c6c16581a5c790c04cb7acb81c9a75b4868ae3ae4258b4ff7c6d5aa81ef292bf798071e69417466c579659fc81e0d249d2799e22", + "dest-filename": "@babel-code-frame-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60", + "sha512": "9bb3a45f421d28b28fa41949b45e7ad5825a979cbf8f22397cd7d66cfc61d83fe76f3cc6238a91cab0fcc4eda3076e2eee5fb92366b8dec7021b622b7e30b9d1", + "dest-filename": "@babel-compat-data-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784", + "sha512": "74ae4fb46d6e88dda2924fbee4ecd262c8ad64a9f2e303820f49eb3b84ea9d6e015414d0d8d192dcd82296f4ff4c4cb14d24fb2cdc9657f4f8b570e80f77ce82", + "dest-filename": "@babel-core-7.16.12.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe", + "sha512": "d688d9c04f7e94e5f371675698ee936d4cc37ea2c3dfd0a612137cfb6717f57903a39c96d4ea607de8df962cac4760162e931a99388e880a7f9adae86b29a1a7", + "dest-filename": "@babel-generator-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862", + "sha512": "b3ab76c3f20f4154c0113d478ada28c11197a285fc98282db8fe75f79c03fd024f57ac188e9ba308617b26e30e0d55f664024e7f5193e834fd307119bcb3854b", + "dest-filename": "@babel-helper-annotate-as-pure-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b", + "sha512": "0ba15d6d16b1623c15bbf81e296e19790d10df501fb6045c7529d9e7f8ec1fa0730896edbd7be1a5f91b9138584aebad640ee7097a4f47a003f73775769acc90", + "dest-filename": "@babel-helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b", + "sha512": "986a23070216730183eab7ea8115d59556263c0bfb78ea487a6506ddd1a70dd098e0f69eef444e8a3dd799fac7e856b58756a20f29698256d9ca4b5fcf2a3f84", + "dest-filename": "@babel-helper-compilation-targets-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz#8a6959b9cc818a88815ba3c5474619e9c0f2c21c", + "sha512": "c0379e8f4a6edd637f7df4f130d08f5b950288e6aff0870b471488ca9ffdf88176c4950cf61fce6238342092c768be85f2853c92a333f67735bebc9784cb205e", + "dest-filename": "@babel-helper-create-class-features-plugin-7.16.10.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz#0cb82b9bac358eb73bfbd73985a776bfa6b14d48", + "sha512": "7e4e40eb299fa7e3b9fa9db20a45c0bb92b28fabf4c61d1105e35c024614303bef000a31bd22979fe25bdfbb7fc961624150c52b510ba544c3f3f68b8423eefa", + "dest-filename": "@babel-helper-create-regexp-features-plugin-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665", + "sha512": "27d8463292509ad5a68f8e81de404798bdfc5212468585fb7aa91cabeda0b2cb7262ddf8d4798f796b298a15f8df2551034992fbc18693619c91cedb63f1c298", + "dest-filename": "@babel-helper-define-polyfill-provider-0.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7", + "sha512": "48b2dbd00027e8f9147807ca24208e97d7b5479de94251807dce32e17b8c4597ea78c60b13474cd4b321a9b180946418d257f0e7fa21a185807bd575ca26d16a", + "dest-filename": "@babel-helper-environment-visitor-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a", + "sha512": "2b251e9e158c0bc56bc739063f4262ce3a38fd9c7ed67359860a1cb3e80bcf267207c48789d868abd28affc02da386a7870b22bdf9012dfb64cbb82fcdb64cb5", + "dest-filename": "@babel-helper-explode-assignable-expression-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f", + "sha512": "41f0df127214cb20524771edaed1840ae67a0c0c82918169ec61e5ef9bc5b539e7ea98ca78ad13d4307994b905bc179af0c75a894001c77a2c6e02f2227a1e8c", + "dest-filename": "@babel-helper-function-name-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419", + "sha512": "7e573e44b48e057ccdcd585c2eeeae8de1d4ac3ead00d00e539a23ad1c7f6acfad6f37fcfacb540a3efe21f451a006c466a8ff6a15c432c8e13a181e66cae74f", + "dest-filename": "@babel-helper-get-function-arity-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246", + "sha512": "9b4e1dff43a9df81f9bfba5b670ea948a3fbc1e03a96c32f7e220031e22f918fd1e3142d05230512282ef504d9daa07ff65db6becc6d33c6be43c0b30f6e797e", + "dest-filename": "@babel-helper-hoist-variables-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0", + "sha512": "56d27feb9b58894ffa01b3130f0ca85c63ca1e04ec7d16ab8af9be61b079b80cca532b8f8e065280015e1bcec50a281ceca347bb63de821d57213de55e3bf3dd", + "dest-filename": "@babel-helper-member-expression-to-functions-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.35.tgz#308e350e731752cdb4d0f058df1d704925c64e0a", + "sha512": "bda0b52b22194aec966f72e3dbbedf5f4a718afc87c2e0d4e3166ca1faa06006e40f136278c836bee8733f902033078c63b7c24143138be0603ea4cb8e4c5716", + "dest-filename": "@babel-helper-module-imports-7.0.0-beta.35.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437", + "sha512": "2d5b52e93aa324715cfa761e213468e952d7bdeef4c66abbc0f8564ea0c9bac2448069a4000096c0c89336bbdfa10a3a844845c00222c4d92f0748cf5c32fc5a", + "dest-filename": "@babel-helper-module-imports-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41", + "sha512": "81aaad2c3c4910509e41b629f5a2c079f8e190a76329c761e8307b8e7888194dcfcf9d960263f6ebcccad1580fcfd85436431261e1fdefa2b6fd8eb23da7699e", + "dest-filename": "@babel-helper-module-transforms-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2", + "sha512": "12d801860eeb77f25c9e96455e9072d337b56117dd9bb067057e2e28c05dde2c5add1180134d3625907ae85272347ee0d05dfc534e695e60393fc70187bcfed7", + "dest-filename": "@babel-helper-optimise-call-expression-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5", + "sha512": "420dcd93b671a6032bb28c7a1eb798d5934a741abb2bbdad0d296203a7429797f4d3b8d1e277bc883e54cee3670891f6c417f60441151abfbf38be86769ed1c4", + "dest-filename": "@babel-helper-plugin-utils-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3", + "sha512": "7e6d201fb1656fc1f9d4ba891f2dc7277c27135faab5847603df4ad3a6a1c2b6b02dd385b021168d93ab62b89c5c91e83d2b9d34ac6b30150f1083f188822f07", + "dest-filename": "@babel-helper-remap-async-to-generator-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1", + "sha512": "cbdbec5a295335a567561eb18897c0073b0da600cf29ebfd1e7020cfa19bd69e945307fd35ea5d96c57b5571827ed24cfa3a83e5fec9204b9b7292e3663e5d07", + "dest-filename": "@babel-helper-replace-supers-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7", + "sha512": "648cc7572a1e2ccbd730dfefa24fdae0b591cbc1b6bf6d3998d3f45ceb9ff5744bc97e7fbbd0a756e954b438144da99ade54fe6dffd4aae72e663aa21ae4d2d6", + "dest-filename": "@babel-helper-simple-access-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09", + "sha512": "fa2975813cb4a07c14b01419c89bee91b078bcf31d71806b1476b451ce008b32f16eae813980b9d51bf8b56a1c5fd04b0432d9e2473aa9416943a1d180bfb7cf", + "dest-filename": "@babel-helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b", + "sha512": "c5b5a8cbf3c5a314966b3213a13f5289ffa325396b31c9dd22c68e2af4c0eaeed0128ee2964459a637b0d7cfd6ddcee79bc7d77540d7874d955d36d9d2918337", + "dest-filename": "@babel-helper-split-export-declaration-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad", + "sha512": "86c12715e99e896e03d3c039814019c4b0535e9677f4ff9af83183b07c35cb1ab243f8f31449f17f9b93106a7eddbcc06cd3b1535a5a4e0612e04094fc881f0f", + "dest-filename": "@babel-helper-validator-identifier-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23", + "sha512": "4d1b5e9ceb91515a3da084063c2e46f4380ae3be3771dc6fb4ec34c1e40da595da4b5e920818b930d8d917cbdb6b71135118d9a536d59fb56f71fd9e030168cd", + "dest-filename": "@babel-helper-validator-option-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200", + "sha512": "f11a724552005b545c0c319303e1a93c0c15db6c1709f28ea0cf5b7ade932e4188153911412907d67310e587ade0ca685ded59c073d5b4d6ac736c34b9932a9f", + "dest-filename": "@babel-helper-wrap-function-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc", + "sha512": "f590e8aad7d8ec0b843adddcc5c85f8a2e82ec60f2c8c05f7e4b51e41da3bd6bfcbb6f9e7f0be99d5297316ccd7a1ab2ebcb4a8007d2c1f770fe55a9b614b66f", + "dest-filename": "@babel-helpers-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88", + "sha512": "e459d340b48bb30123e88920570e4abac35450563d646a9efd34459cffc12981d881f87bb5cf82ee6c22cbde7fc8d3fb0e1f71e7cd15bfcafbbbb65f4c117177", + "dest-filename": "@babel-highlight-7.16.10.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6", + "sha512": "55f695d79a68f11899b2cae43f07b2bdb19549ee31db2f9a722142827d27d3f489311db6730a1f455d66b6725061c481d70513680fd7d4b9c0ddeb3ae8c08ee4", + "dest-filename": "@babel-parser-7.16.12.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050", + "sha512": "6a7bff0ce6e5ef06a21849c2db83bdcea2f4a52b88f619638a1aa20ee1470bc77bfdb8ebff844b18f5ae73cad839f7ff40fcdb10f4a4cc6f30186f5a0ee84746", + "dest-filename": "@babel-plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9", + "sha512": "762f2f50745d7fee1a27b96d5e16836cfa2ccdd921e7d010b49339b282ecb87a5025d15064e038b868f4576bbf099f1b27fbbc50b0cbe72aba14efdb0979ca1f", + "dest-filename": "@babel-plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8", + "sha512": "ef560722f32e8aea9625091e6d626d7614137dde10e2617beaad885f7eee64f906f7ea25071b17fab1f5be4845b68e1478967d74f636b3e983be10e6d6ed8119", + "dest-filename": "@babel-plugin-proposal-async-generator-functions-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0", + "sha512": "2286d4d1799edf57b08d839285222a77f64633faff72e3b3db3d0c0db36b845e455be655822d1fda5c9ea23f4a14f0ce02ab18c662d666d7b558ec25bd8f5ac3", + "dest-filename": "@babel-plugin-proposal-class-properties-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a", + "sha512": "760a8926b719a06ff80a4328a7384f2631b1b087bd03c4659102e72ff561871f0003d66e691c064a5b1c4a1e3685acdced64abc9afc82bb9937a81740cff6d13", + "dest-filename": "@babel-plugin-proposal-class-static-block-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2", + "sha512": "23c496f47a37ffc0d149d983747de039177252e6279359b870cc5401dbb9a32e27dce7cdf1f943107f9deb4886edd51f8b42a46304afa1a947cf3751ce95874e", + "dest-filename": "@babel-plugin-proposal-dynamic-import-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163", + "sha512": "67176da835cb44604beb8a1c65cb3ba2fb7bd4bde3842d51192c91f7deacbeb0a2dcf62a1cd91bdd2c0f242b3c448cc3f3ab3e58fa6dd92ef7f841c218ef8d50", + "dest-filename": "@babel-plugin-proposal-export-namespace-from-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8", + "sha512": "94d677104820b0663bf096af81b1ec2bdbb93f7a50696ee4e1ac658052d890c77b501b2235a8422134a12e3350b1c84fca3b4ee9d003acbdb8ef9ec876106bb1", + "dest-filename": "@babel-plugin-proposal-json-strings-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea", + "sha512": "2b75f3c99246402af4d3e12d62dac38e6c17ee8ecf2cae94f5b8b59c2c24422a1115552fe9d268c5b423b5656d3fe6c23f2f366ce341286f0d3f2438fa2eb28e", + "dest-filename": "@babel-plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99", + "sha512": "6943ab614dc456d8dfeb68d0ac28fade9619ee4eaf9ecda1fc342f1cf5869ac25163359767afc0b1f829891cba5e2b880c00e12733f643d33048c29ab8143e51", + "dest-filename": "@babel-plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9", + "sha512": "bd080f3249ce2208ae56a6e8913a325db918fce9a68c0cebff49614886c6fca9a7cd73c6c16fc076174aa62f8ee17fd59168968e790a3818aa26b4da0bdf152b", + "dest-filename": "@babel-plugin-proposal-numeric-separator-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz#94593ef1ddf37021a25bdcb5754c4a8d534b01d8", + "sha512": "dced18e3e770f781c0f3aa9283d2077f23e4b6047bab782935501e88a41dfbc8c1285694e4d412d586ad828e3063e50536e2e3bf17129b372c1eaae1813c8150", + "dest-filename": "@babel-plugin-proposal-object-rest-spread-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf", + "sha512": "78c387fcbe0ebd6499004d559076ebd6f7242c6d5651c1c62522eaa90c25d86694a86e908dd76face69350c3588afefb1f920a3cc67d53d3fb11a1f0bc04a17c", + "dest-filename": "@babel-plugin-proposal-optional-catch-binding-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a", + "sha512": "782df1cbe66b51c06d3fbc7eb2aeb643f1d877aef8a4f4dbffbed764c6f9c1b0cf19621d51b4abe0082bd39dbecda50f49bfa01919e3c577ca16fc7988c27e0c", + "dest-filename": "@babel-plugin-proposal-optional-chaining-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50", + "sha512": "17fdae0243e55c3afcf811e966fa35f70de12c52a07be93be57529ac4ea36aa2b18c691261c2bee1cf9bba9e4f756ffb5bf4698f0aa5ec54d51035be7d1010b3", + "dest-filename": "@babel-plugin-proposal-private-methods-7.16.11.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce", + "sha512": "acc4248dc3856e6fae7deddb4d92f239fb0e50ec72bcb5d92424c046126bfbc50c4a8666a937b52b506090572b5b7eeb01c856839ef223af4e471896bd420db9", + "dest-filename": "@babel-plugin-proposal-private-property-in-object-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2", + "sha512": "4112b4608ff8d152e13551888d13400109041f0b3472cc12745163a45cadf78dd8989214d5d6bdb96eb722ee8d155e82c53656e5e4c30abc1952cb415a0a7f46", + "dest-filename": "@babel-plugin-proposal-unicode-property-regex-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d", + "sha512": "b727266719067d96b184c45b5e53d7b95169756957a62af65b800c85226044ace4fde0e52173a16f62c75a82e90c5ed3107ca5579ccd872917e8a0201c999337", + "dest-filename": "@babel-plugin-syntax-async-generators-7.8.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10", + "sha512": "7e6e227632a56b461a85436014d2c2074ab249db283e264fde2404deb932d26054b4c676df20c9f5225d83a7574d20e7ba5395aa21771e0afd9db5ef5d341960", + "dest-filename": "@babel-plugin-syntax-class-properties-7.12.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406", + "sha512": "6fe6323e6afa95dc8d9cceaca9878c584f9b809709a4eeb24b8403ef29b1807df81813cd0ccfd31c187c8ae9f2bca219ced8b02c7e02259d11c5393d7a68298f", + "dest-filename": "@babel-plugin-syntax-class-static-block-7.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3", + "sha512": "e607466c5a27f8fb33633aacf374b71399a98bbff2ffc33d782f743114d97ddb903985bbea283a48e48f35ee35206e4ba0fdc51819f6374463543490892f7891", + "dest-filename": "@babel-plugin-syntax-dynamic-import-7.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a", + "sha512": "3177f995a5e8e9cd486c46de8039b318fc06353b07666132e901b39eee528765025afb9ecb06f679ef82084e3342266cb7153d04ca103bd8bacd41526342a3d1", + "dest-filename": "@babel-plugin-syntax-export-namespace-from-7.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a", + "sha512": "958ea4746a561ef8e87b6be4e16ac06a912e051ebd10cc5997e46819186b14635854af2638f016f157db4ff660ac56d794336289ac509c0b6054267a8efdf410", + "dest-filename": "@babel-plugin-syntax-json-strings-7.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699", + "sha512": "77cc1a4a19691438a743932dbc653dc4300ecca1f8efe145a277b2d9b68522832bf79da128e2e9d4747b56cce866f3ac57fe3e451b33358ec3d7b6dad2d7b48a", + "dest-filename": "@babel-plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9", + "sha512": "6927dfe333c8235bb6403ef2f85f280eccf5f5ec3820610983d4955be6eac29c2d7c595e8900cc77303f47e525583cdf9c7142c7195e153d0f308ad1dfa5cb35", + "dest-filename": "@babel-plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97", + "sha512": "f47e9875f91c2bfb8e9d8fcaeff680db1a73680824427dfbcb35943112bb39a3cea8ea464b5fa7d07e61c53f40530f44b128cf5bc495c8c270611b56b375f7ba", + "dest-filename": "@babel-plugin-syntax-numeric-separator-7.10.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871", + "sha512": "5e8a8c8a31996fdcb7cb65ec90df8fd70506895c16679266a03470c79fb71a612994dc95336b360e0f082c5426f2b58ce3ca2b1b2e58a48e4197c535cbbc9d94", + "dest-filename": "@babel-plugin-syntax-object-rest-spread-7.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1", + "sha512": "e953c3d0f7359694eac3468aa1e45332207e916840a13db83c0fa4b16481ac5b65e52211569665c0ddcd34f4237a103613ff75155dd18cb5a855382559c495dd", + "dest-filename": "@babel-plugin-syntax-optional-catch-binding-7.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a", + "sha512": "2a82bd12b1f53019423f15745403645d6dbf770e2f95b183ac5833f1b994b0119890545c6d1c0c87a70826e6dd3eb931470b8676d0a4d2fff03d329b42006392", + "dest-filename": "@babel-plugin-syntax-optional-chaining-7.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad", + "sha512": "d30567a7d77127bd995090d5dbb65f6d28fa8872e8cad6199a1deb15cc4d9efb0917792d9332c364fcbf980d7b1c6b1a413dff0d0b16617d5fd50196902a1552", + "dest-filename": "@babel-plugin-syntax-private-property-in-object-7.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c", + "sha512": "871fbeba92efe54d6b8187f07b5c41414851994e35344be952fae9f2392b48276f1929cce7fa9d44cb72949e8f1b938590168791b4c02939dddff63211244717", + "dest-filename": "@babel-plugin-syntax-top-level-await-7.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154", + "sha512": "f5f7e414531bbf34efbfeedd4e9ffaeb1bd9016012b8f0f94e5f4b2b767dbe13a600da3a8fde2b8a4fb960c06de02c0754c58b5a932cae221cdb3b1add65b7c5", + "dest-filename": "@babel-plugin-transform-arrow-functions-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808", + "sha512": "32d9949932501c29f2255ad270dccd9687d027774b16ea1b627de6c0e4ca1e748232d6cdb2abc5ef51909897c58ddad74ac000ee2cac166616c386d7676d213a", + "dest-filename": "@babel-plugin-transform-async-to-generator-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620", + "sha512": "254bb3973985e3467d717cb2b5c6d911929c920ad0cc285b409c3fe4fb841d87aacc2b2f79b0f1d0ad235a720855c9a60ce01572d0a09d8b34a4c72b623db326", + "dest-filename": "@babel-plugin-transform-block-scoped-functions-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87", + "sha512": "39b65ebf69f1540600e1b872bac10b768f616f71fe039e9bc47dc564c6c42266458840d85475d0489d6140a1650e796df06f5b06b099e59a5445952b5781b9a9", + "dest-filename": "@babel-plugin-transform-block-scoping-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00", + "sha512": "598ee8837f1214019845eeb806b8ca7fc3ab13aba5107b6be63118699330a31f4a79b82a3e2ebb66acfc2b9dc42a4d5f1442609bdeabdf6ae4299dea0369c259", + "dest-filename": "@babel-plugin-transform-classes-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470", + "sha512": "80def61bd6dc99e9d520b8fffecbf5ccb35a3f261c3b3521a36948241321fe26a427dca00a8fe1105f5ca466fad5208c103c5b6f2068550c6bb7e6d62aee4a1b", + "dest-filename": "@babel-plugin-transform-computed-properties-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz#ca9588ae2d63978a4c29d3f33282d8603f618e23", + "sha512": "56a0308531c19eee710550c2bebbea25bb4b51afbea996960b4160af69aaa24065ba5640446c88bd90e8a9b3e53da288990f5d280702cdbbfeba5fffbaabbbd0", + "dest-filename": "@babel-plugin-transform-destructuring-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241", + "sha512": "2f2b6d69aa364a3645e8f7f8be4d5d54abfc632a4ca689806f2816fa65397183f74b97164df0898c6f3157a08577318595f58af352232fdbe2893be96fa1bb81", + "dest-filename": "@babel-plugin-transform-dotall-regex-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9", + "sha512": "d370efa5b45fbd6217c8ad3fe90891d4a31359e4fa39c43bb5b863ad7c854b4da48ee5ff9aee41be78794834961f1c9ac22b7683969684ac08f3a104ec65274f", + "dest-filename": "@babel-plugin-transform-duplicate-keys-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b", + "sha512": "f1460b4a5c8b8118b142f9581f72767a45c51c314b42eb5dcbb15f140326dc23d9eaaf701c2c27532897a5009ede05559d09477399ecba2115ce2b5e44d4d710", + "dest-filename": "@babel-plugin-transform-exponentiation-operator-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c", + "sha512": "fd0666f56f763eda70eec8c8f4dc7599b72c5b3df7fa5f24b8c2109c3c204011b9b377c07d0be446343b36a5e1b4d70a3a73e47480a6507c826965b4e870acaa", + "dest-filename": "@babel-plugin-transform-for-of-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf", + "sha512": "494fc2ebc615c13471a968f9920b1b28835a9066a0d0a4e0abd7f6899117752b6801b3b32c7101458cc89a603ac85a3c61984955f96f5e620750eec65879b1c4", + "dest-filename": "@babel-plugin-transform-function-name-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1", + "sha512": "ead1fc453a53588d2cdac57abaaddefc2f703e8e0f4eaa99a6ce2e17493343dff13cb150b62a729ef993d60fdd39f109fb4110b0786443fcf244877c2766fccd", + "dest-filename": "@babel-plugin-transform-literals-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384", + "sha512": "981aee44c6e4b4a4306f1689a1fdf62d3f4a2f2d9fde01fedbb6b95d2b97a3a87b477bea96d9743e067cd02f1930ac3df017fc6eab7a044562decbce8763f333", + "dest-filename": "@babel-plugin-transform-member-expression-literals-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186", + "sha512": "29a684b6004bec5298c2327fb5e1fade802613794fdf837792c873f269b854c030ed4dcfc63570c149b110592c6e0b0d51a3b7c0877d4760154184841916b6fa", + "dest-filename": "@babel-plugin-transform-modules-amd-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe", + "sha512": "a1f94a3efb0b4f6fae290a297ac26ddc0a626884b61d6fa1cc715cc1136dc831a2780782fdd207657f1bb894362765f5af118fcb87917148a39b7a9c48f8d870", + "dest-filename": "@babel-plugin-transform-modules-commonjs-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7", + "sha512": "0ee2b913793e4109a73aa051f5492eb01cb2e56656191c5fcd5e76f6cf673eb6b5184ee8966c5fa8ed851e86c439848f2233c14ebe29eba603723427b7c7019b", + "dest-filename": "@babel-plugin-transform-modules-systemjs-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618", + "sha512": "10c87bba896c0bc3b8c61b9d17617ac1e75b4879b51c76740ba689ecaebbcdc0cd89d33355cc56746afe86d5bd9f6d64966f9b3a7f91c78081b009ed65ddeb11", + "dest-filename": "@babel-plugin-transform-modules-umd-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252", + "sha512": "8f7270fa7e4fbe99a1451fa6ae0221d38a6e48034293f4ff500de6dcfd4c8c992194af74ebe0291e10c8a8140374e80bfebd54629cf818d7254d7c7266b6064b", + "dest-filename": "@babel-plugin-transform-named-capturing-groups-regex-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244", + "sha512": "c622c3cd634c7caa063a973ab7753e7ad084db24679f748cd3d057a963c864e0692f682f56b05650a9ec271d0afc00e2e45e580b97fc00f15f5abcf6e537651a", + "dest-filename": "@babel-plugin-transform-new-target-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94", + "sha512": "d782757de890556686bd1c63d968f232e5d2da3b0192007731d48de47b82d86e6746ca5ae512bd08e72cf363f0cb906e19c8dbf9f61a523f7899870e8fbac2bf", + "dest-filename": "@babel-plugin-transform-object-super-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f", + "sha512": "013dccb9f43bcd9121536870380d756b10671315b42ecceee112ffb40954241b8da116a4fb07a1416f21e8a71739c823638d9f1ed0f1b30b8c84c8c512ebff6b", + "dest-filename": "@babel-plugin-transform-parameters-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55", + "sha512": "cf8146afd34c19da0897546a6af0aa186f99b988df67f8640887ae1fa0e8eed5e64a6d25b35d67615489a8511439225b0da6f9c02ea5444ff0e988d572be87ab", + "dest-filename": "@babel-plugin-transform-property-literals-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb", + "sha512": "985ee33a01980a44896a027a5c2ba349083eeb10b533beffd372b6a01995256a0518d52d9d524ee161ca264ddd9cf0bc1c2723e310503f51209bc0d68773dbdd", + "dest-filename": "@babel-plugin-transform-regenerator-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586", + "sha512": "290cf30e767d8564018f08b9969639bfdb219a6e88546d14f69075f33bccbb68b81fdd31a53e209aac0f62c9fcace6e269d61ed8cd209a0b2238817903fdabb6", + "dest-filename": "@babel-plugin-transform-reserved-words-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a", + "sha512": "85a876f85127a11a004dd21bd3920e5dffb81b35d84eaef94d58489f53dec2285ba72acd594b7625bb9d2903844d6c3a4292def80214a49e4c54b61341b79e52", + "dest-filename": "@babel-plugin-transform-shorthand-properties-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44", + "sha512": "fa98c9a6002781be772f489a039814ff530b5c921f5dc61ea4b8170777ac5517f87ea9a3f1fd9cc4cdff14a687b199acd3c84540990571c116b88a66e36f535e", + "dest-filename": "@babel-plugin-transform-spread-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660", + "sha512": "3496b405dffced05793596734ee646e413c98cb61a75e499f5f3baa0e5282f8890c7ef4412ec3f78433dd92aec4f5f587368e0075bb586c8ea0ed1f4d9cdc3af", + "dest-filename": "@babel-plugin-transform-sticky-regex-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab", + "sha512": "5706e40c351e7a79488e67cd7835ff574696ad01f642257226dc32995412cc8b450d3a717f2261dc455a4224b4ac837f0aa6cb1abd157069aec324dd66d748b0", + "dest-filename": "@babel-plugin-transform-template-literals-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e", + "sha512": "a76ace8b108a449ce983d241e208e71b88235a459af3d6686149e5f6c9c9d5c5887131ff86fc59a9f3be5a31ba4fc0d106972d1289798f0d4ee6b03c8240a891", + "dest-filename": "@babel-plugin-transform-typeof-symbol-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3", + "sha512": "4c05792066a1233df267dfc77efdf94d5db1126fa46810da6500a7d92fe11bdfc26740e4b7126ff5e29f3dcef2602bce611e091b1d61f02fa37123af81a688fd", + "dest-filename": "@babel-plugin-transform-unicode-escapes-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2", + "sha512": "a02e6d6182b0e7a1ceef929954b43e47f365dc7ae8f647fc886d215e86873fbb630320a9bea06248d7babc6ad99e2d59e8c820994382e80ed53fb0159b0db6e5", + "dest-filename": "@babel-plugin-transform-unicode-regex-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982", + "sha512": "a9c9961bc47b656e960513d92bfff2f84dc2962d79d41db45b546fee59f6eefb8f69753ff132a6b3a8c576226d17b5034f172b6fb99977cf2d01e2bd2e3753f2", + "dest-filename": "@babel-preset-env-7.16.11.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9", + "sha512": "039eed87a6111bba11ddcabfcadfd8f3832f1a01347891b617524b84abb21be8c5c4482b77f1c03096ad885b663a266eaf3fb40e4aef6e17822da5797f625f8c", + "dest-filename": "@babel-preset-modules-0.1.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa", + "sha512": "f44f45268c2a02ccadc8e63a2c6fb52aeb9e72444bf9a416fa62af5d15e7b851b2440c9ea493e6128f6f80c7d7500e8ef6edc878476ff4c024a6915c690c2881", + "dest-filename": "@babel-runtime-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155", + "sha512": "23c8ffc7c90752b6d84535315ebacc6df09aee3c6413bb59adedfdc77923afd86f23cd9c2b515fa8bca0a2d71637991d3c659c2dd58c1e94816afb1ee6d5b0df", + "dest-filename": "@babel-template-7.16.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f", + "sha512": "cb3b9a617a1124118c94186c309a145bb1b552649bfde5ebfc91d833f32c38981abc989b2f00128a35bba1705dc37350e93d1b5bb4f2e4ffd56ab3acf5c1e6ab", + "dest-filename": "@babel-traverse-7.16.10.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.35.tgz#cf933a9a9a38484ca724b335b88d83726d5ab960", + "sha512": "cbd5d3d750a8cc70e08d67137719a14a3d77ac9557a5ae595f08e33a24de76368cd1b6b922da9d4b4daddf51213e5ec7b4e5b1b1991808250dad27eb3a2b00eb", + "dest-filename": "@babel-types-7.0.0-beta.35.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1", + "sha512": "b263760d0739b3833b7e7b728c6b7220f6d126feb05b8ad4ffde1f99827b3ca42e6640b4a863075c96e0eac346b75d89995af893961aa6d23f5ed88b2419e622", + "dest-filename": "@babel-types-7.16.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@develar/schema-utils/-/schema-utils-2.6.5.tgz#3ece22c5838402419a6e0425f85742b961d9b6c6", + "sha512": "d1ca783ec590ffd6afa9354c0ad67e1a2ae2908037ea292f8ed1f0794e3f8fcc8bb6039b234f8950f858152720c25b5ebde181d6bb770a6f1484dd385dac838a", + "dest-filename": "@develar-schema-utils-2.6.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@electron/get/-/get-1.13.1.tgz#42a0aa62fd1189638bd966e23effaebb16108368", + "sha512": "539be45c367d0f05ed90faa5078e6d7d89e760137c3de3e9d73fd70c2ba99d2a5daf14fcfd3842bfd582c0f2dff68aa2486653907e9dc768c350fba85e98e470", + "dest-filename": "@electron-get-1.13.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@electron/universal/-/universal-1.0.5.tgz#b812340e4ef21da2b3ee77b2b4d35c9b86defe37", + "sha512": "cd7f4eebe8ebd8d33201d4a4c04525ca5b62238fc404bbb62ecfd50f7a5441d8b770061e61f7509d3d80249dfc1c4e10c4b71c6d4d772d2a5c730d485a59326a", + "dest-filename": "@electron-universal-1.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d", + "sha512": "45304658be45590720f68ac3382729e0bbc8b4dcd43dcc8453d6f069e257d2b275210c73b9c0b8f18d3fb102e9fe0eadf7d21080094621a7ac252fa04e7eed55", + "dest-filename": "@malept-cross-spawn-promise-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz#e8a32c30a95d20c2b1bb635cc580981a06389858", + "sha512": "f503ad35f7dc385fdcd6c78c0839e37246f747d587706df8b64cbe147a4d28a096d3073fb1c60bc0cb4efa9b721947cc5b4fdbfe7e2a46200b95a14773d3a3ed", + "dest-filename": "@malept-flatpak-bundler-0.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@nornagon/put/-/put-0.0.8.tgz#9d497ec46c9364acc3f8b59aa3cf8ee4134ae337", + "sha512": "ba0bd7263c05e6576d5296bb0fde64aee349e35c8540310ac85e425b84e02899e1f96ff39a50735d778a4f2a88830305ae478f37626a381a9c174334a0eba7a3", + "dest-filename": "@nornagon-put-0.0.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.7.1.tgz#e01144a08984a486ecc91d7922cc457e9c9bd6b7", + "sha512": "4793d8c784d3be27dc53bf745e42ba2551b06af29a5f0c9c0d4d0c680c1f73855fec12e6e4a08d242b03c92bb544f01aa7fd35ecc5587f9e29e9d5af2a246f88", + "dest-filename": "@sentry-browser-6.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/core/-/core-6.7.1.tgz#c3aaa6415d06bec65ac446b13b84f073805633e3", + "sha512": "540bfc391ffb20d9f625f88b72ea29e217c37320bb99f2fd7dd3e775012195a7239b0f2046b8178d1eeaca19c24e0cc52e41c8ed5e5b71d23303cdd344f610a4", + "dest-filename": "@sentry-core-6.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/electron/-/electron-2.5.4.tgz#337b2f7e228e805a3e4eb3611c7b12c6cf87c618", + "sha512": "b4208af8fe7cd5399d8ec0e91c1433eea61c95dcc675493515de853f13f2d49286cde638b9ffee48b2b347cd0bcece644e911914ec22307480f328f0169e6aa0", + "dest-filename": "@sentry-electron-2.5.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.7.1.tgz#d46d24deec67f0731a808ca16796e6765b371bc1", + "sha512": "7950935afbdca7ac5ad00e4618d1cc4045ac96628f962b04e6b1a6b15fe48ef494bf7cd2ac8d1e2037dbe758a47670a20631e92b634158ff15cbc71938425e82", + "dest-filename": "@sentry-hub-6.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.7.1.tgz#babf85ee2f167e9dcf150d750d7a0b250c98449c", + "sha512": "1c30cf1274110fa842d2a68776aa8a0d2b5c744d4a864161d110ad24d3020e7d33a5abfc0e3f40b5e17bd31ea42d296588027f245c22e80990acbcfe1713dec7", + "dest-filename": "@sentry-minimal-6.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/node/-/node-6.7.1.tgz#b09e2eca8e187168feba7bd865a23935bf0f5cc0", + "sha512": "aed668d4ef113afe25670ba58d0cf7885656f3da174a5817086d95aa4c50c91b293d6bbcf5a6d13a9c4b8d8cec5b043c7639eeaf55e316fe7590e2c35134ba43", + "dest-filename": "@sentry-node-6.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.7.1.tgz#b11f0c17a6c5dc14ef44733e5436afb686683268", + "sha512": "c324b79d6365e66cda0b5a99d80229d618d79df3bd1044633082630a286cd8b581cf5af779fc6b1f1247b3cc1794d5afad3dca2e1abfeefbc5e42754f36b8f79", + "dest-filename": "@sentry-tracing-6.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/types/-/types-6.7.1.tgz#c8263e1886df5e815570c4668eb40a1cfaa1c88b", + "sha512": "f403bb1caa22a7630130d40911debe00ab638f6faaf597b8a28594744bdd3954ade5dae0ec11a92b6db5fe9f4910ec89019c043c45dd70c77754020c88e6f830", + "dest-filename": "@sentry-types-6.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.7.1.tgz#909184ad580f0f6375e1e4d4a6ffd33dfe64a4d1", + "sha512": "4eada8b5d6d694702472d0fe1164d82a4131e812f5427dd9fe29a43b4ebf3efce95af561256439a87033cf95e7c30a8d1f2574dca573601eb39ead4179af47b8", + "dest-filename": "@sentry-utils-6.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea", + "sha512": "f4d113f75d0335a20f9e06272cb3de83e3a0ceab22f6e3389926e8539cbaa7c4b90f3313544b0966b6b08be0680cd51505ad83849a9061416f3037e0534eb62d", + "dest-filename": "@sindresorhus-is-0.14.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.4.0.tgz#e277e5bdbdf7cb1e20d320f02f5e2ed113cd3185", + "sha512": "429a4f33ff25dcc6b0be1e2b9fd08d118214f5bc695d409131a5fdc94a6f064d6730abac2caa5f5c60c4284c4a68f84bcdc9f79738a5ee947aae7275d4781e45", + "dest-filename": "@sindresorhus-is-4.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421", + "sha512": "5c80765dbcc74cdea27888df20c57d86555c7cf536eacdaf69f61641c6475971cec62691658103284c1d975dbd672839d3e7e8615da30a0b6ba9203aa8db8d48", + "dest-filename": "@szmarczak-http-timer-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807", + "sha512": "e0101f7f29183a03bee67cc1598c04dd6f74b0180b26850f45659c2fcc25ca233c201f22a49cf750c27d29741dd512905e92a9f13bad9fcd0766d5acbb6bbbeb", + "dest-filename": "@szmarczak-http-timer-4.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276", + "sha512": "3af8c5fb3e752f7a2fd0ec8053476ecec62ebced353c7ef1e2de83271fa0b9a8604e704792125d1bbb2841e4d214b58ddde7e71f289b67867c97612e5b024ddc", + "dest-filename": "@tokenizer-token-0.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0", + "sha512": "00b6289deea99ba426c19a0081ec8d92c71c4fd438016650e8fbdfc11dfb193eabe855943e0baaeac52634648c5765abefad68428071c0619ae83479a350c2f6", + "dest-filename": "@types-body-parser-1.19.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9", + "sha512": "077c55a3e76528cea79ca4dc9a6e59b58fce2fc6ce00e7763a579ef4cd737edeb9a31e743b38c41d6f75b03894f63e9cbd6f048e0d7f4247f8c5dda4ba002950", + "dest-filename": "@types-cacheable-request-6.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1", + "sha512": "71d798cafe0a5a8120a412124f15afa98b15cb8e380cea9e8621777ccde77b5d00989eb6452c8d9149f13095c7416450417d9e47de26e72d486720f006357d15", + "dest-filename": "@types-connect-3.4.35.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82", + "sha512": "f40a27533c938d75e110e6b40e7aa9cd98ba54796a28cb3081af445e3a579e7ab1c0bb5dbcf3ed94ef1ebeb2390fd4ba6ac151090eaffb0a6250a6f0faf2aaca", + "dest-filename": "@types-debug-4.1.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/discord-rpc/-/discord-rpc-4.0.0.tgz#29080812b9092996046af1a21138fb488d180f87", + "sha512": "6b91e228e701901e3783f94de9f058c3c17219ce947bd098b9cc711f15e510b5e96f50b109ad8d036a462b651bf3ca62e2e639f8741e4856d8b47e8326d57743", + "dest-filename": "@types-discord-rpc-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224", + "sha512": "3c1de5772adc9c089c4f7e5358fb3921cc0a0fc4b7df71cc69ad9556fe3ec1dbde6c99235ae5bfc444a807c23045ca20f0761561a99bd60fd1df542fe41c74de", + "dest-filename": "@types-eslint-scope-3.7.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304", + "sha512": "184e38f83344cb1c61d8a73aae8fd59088fef666b4a4ed1bc2ff7eb874b206b8a460e1ebf3361c74fbe704ea756b0f2cf828d1bee4b1ec2c96a91acd150e7d98", + "dest-filename": "@types-eslint-8.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83", + "sha512": "0ba379b36645b6e6518f9e24dbfcf24613438c9c3071588033735b9bcce30696ea01d674d26af4085c6f48a78ef18fded3759514ba5031d1d855f51de9207e1f", + "dest-filename": "@types-estree-0.0.50.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8", + "sha512": "3f5049004016dc4d8325496482ae2d38bdd1c8cba7a165ea6d20b2816a396485938d480dd589da5d65b855697fa1cf2fb3f5e86226c418128fd2e6721780078a", + "dest-filename": "@types-express-serve-static-core-4.17.28.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034", + "sha512": "e9b4994cf6932000b19f8f25e74491f9ac60aea9baa97148c6b74029a1ba3da264dfecee52bdf98419604fbbce98972e9be38468804bb4757faa5a0400521378", + "dest-filename": "@types-express-4.17.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45", + "sha512": "9c49f007efb5bb99550ccd94238735fb947e15868a7da0334b83a87287229a3566de7430dd3bb31f950db2872b71305b8677ab6e5c878f8038f6a5db22265da4", + "dest-filename": "@types-fs-extra-9.0.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb", + "sha512": "654c5bcca97421f2482d34bab7b8a9e5f41033f2774c962e6c39b79cc6e0b9b34d612eb6797794a682d40bcffb7c93621581d3ac63d09fb86ca435332075f750", + "dest-filename": "@types-glob-7.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57", + "sha512": "87895332030972d2726c3a7c090af14d48a262679d8a11d69239c5ffc3f1b1ebb64ba3657dccbc9306e843cc9e8e1e39eab3f6c96a04566d6c4bf155b1f338f3", + "dest-filename": "@types-html-minifier-terser-5.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812", + "sha512": "499b3b7a46cff02374b71546db15511fa1202a6126df504ec40d3bbe415a113cd9cf5c61f9c6edf01708d2c969ca6bf0871e5d9459d01b6ad394f5509fe8913d", + "dest-filename": "@types-http-cache-semantics-4.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d", + "sha512": "a9c517b9e9ad12ef84e7065224737151778266101f5ca438d43f9db97f9560f75eef1c84559722fbfa172892f5ded9d1b3d951da9af87e8779f464fafd7d7fc9", + "dest-filename": "@types-json-schema-7.0.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.3.tgz#1c9aae32872ec1f20dcdaee89a9f3ba88f465e41", + "sha512": "157089832c8dde2bd5811a2697887de06fe9de463ebbf07ce8b6be429b5ca89696b415ad99ce93b6435f4b8d27f5b22fc8bb5e1e1ef35ceb606e86ce44a3db0e", + "dest-filename": "@types-keyv-3.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a", + "sha512": "6004f1571811a8d1fa9c7108b2f83a93606873524723d65b1f9896145bff31391c873ddbd627860dae53d1af51ce735d2342a155b75b59237e2965ab4194714f", + "dest-filename": "@types-mime-1.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40", + "sha512": "2a5cfde3d874d86cf6b9908c1b00d44834b56019537430e06d61e2fbcd65dbdb5000b52dbf3e2b0188b9ba85611392da828aba0dea805256eb1ef5bf9970e075", + "dest-filename": "@types-minimatch-3.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197", + "sha512": "8a25202b357d02e684919aa438b0c8be54222fa96db9977db46716de0c299d7f096ee8ae8459441a69855c45e4379d02beaeceb3cf08636bf47640ea5d859580", + "dest-filename": "@types-ms-0.7.31.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/node/-/node-14.18.9.tgz#0e5944eefe2b287391279a19b407aa98bd14436d", + "sha512": "8f5d574ae46e0257edeaf2c3117e11be1a82d0ac4dc71e9023231735bd2f1c748d3d74cf7a2cb76a580449698e388cc4b6210bd2a8a8c0f5377b05bd84755aed", + "dest-filename": "@types-node-14.18.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/node/-/node-17.0.13.tgz#5ed7ed7c662948335fcad6c412bb42d99ea754e3", + "sha512": "63ce8c0310127b6e613739436ecbe25e5f234076f4443bcab78738d19250d43a27d0000bd124cb652b3837eea02c43b9e6979dcbbaf670bc12f990f13e6ff607", + "dest-filename": "@types-node-17.0.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/plist/-/plist-3.0.2.tgz#61b3727bba0f5c462fe333542534a0c3e19ccb01", + "sha512": "50baaf64d18cbf4cd116faa7f3fe0b48fb6798de0c7e194f36d2424e92ae208c46546676ad85b3157aef101a21f42572a9213b0fa605449d61c9d2c723a91b5b", + "dest-filename": "@types-plist-3.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb", + "sha512": "1466b517ad854f4f6a72bb9e040eaa613ac93d50f36a1f5afb8f77fa8d8f097b1eb161c89f6ec6f7c4ec48cb3758f35b648123e3e5497fab1a485a6f0fedd9b3", + "dest-filename": "@types-qs-6.9.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc", + "sha512": "10486c2ec0fa52c0ccd7216102fcb40a3afa5709a9316a850426fdc34ef056e805ef0f677da8f12ee5669e04c8a604bab2f0a79ba55ac3e3198680c22a739fb3", + "dest-filename": "@types-range-parser-1.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29", + "sha512": "f396360638ae7c5cda30896f243bd34c1f05c65db17cba381e0987cd5073d3cc38c0378f0938d8c3ae8f76ba253b4933962df26a6fd80a046e7f2a350dd4154c", + "dest-filename": "@types-responselike-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc", + "sha512": "2ff4cca725117c191ffa8ff9dba65bea477fb5c8543f78810c43e3aa36fe536300261551c71ae6af67f0a5ed3c13b42c57b60b729ab4b54690f4ef71f7b648c5", + "dest-filename": "@types-semver-7.3.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9", + "sha512": "9c2907188e30ed980074d92b12ed1bbfee31355fd70ea5be0f27649de6cc390c24a431b1f06f874e58fb47b00123c8bc9cac55c34c2d28f8b50fe94f3a487861", + "dest-filename": "@types-serve-static-1.13.10.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9", + "sha512": "2b92beca697c2d3a3d6d6248feb1027c83eb1a0c5da5e35b8fe779de5c0de108d6d4c0b09648549acfa0b5dce2813794c81af4f7ebbc070388637317bc775cb0", + "dest-filename": "@types-source-list-map-0.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310", + "sha512": "8a98b1b95ae1d8e74d99abafb53e75a3777ccf5da9e8bb455bd8a7ed4efd75eaff9307a38dd35c8500b950c9f9bbf2b136833b5471ceb3f97c292f2e1f184e0d", + "dest-filename": "@types-tapable-1.0.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.1.tgz#5e889e9e81e94245c75b6450600e1c5ea2878aea", + "sha512": "3b732644093a66e00a6bd087820d0faf4fa550eaa830ba5cf404b847c6a7a366aebec83b204f2cc85dd787f34faf6e935a497161caa810415dccb2ecd5f57d3d", + "dest-filename": "@types-uglify-js-3.13.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.5.tgz#2a1413aded46e67a1fe2386800e291123ed75eb1", + "sha512": "f548cc0872b918f81046835ba9d2c802f032d04227ba2a9b5b43c132d54fe81e41d8740996fa091ccf8aa1d3d93048ce6b956449cfb92c7ef1cbe714cd07661f", + "dest-filename": "@types-verror-1.10.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.3.tgz#b776327a73e561b71e7881d0cd6d34a1424db86a", + "sha512": "f60b4e3cf91fc8da04a82420c78a892a4b8d9bfc7447684a47b7dd97bcef4c9c879c88acb84fcb7ef5ceb1858bd28deaababa206729934d3738b7974cbf5fec7", + "dest-filename": "@types-webpack-env-1.16.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-3.2.0.tgz#16d759ba096c289034b26553d2df1bf45248d38b", + "sha512": "16ded81f794455143a96cf24e057f5a01e2337aa32fd7994ead40848a7617e1fb5991faf899169852e962f422bb433b3bde7e6260e5ad2ced9428457c2a4c416", + "dest-filename": "@types-webpack-sources-3.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.32.tgz#a7bab03b72904070162b2f169415492209e94212", + "sha512": "71bfb48a88a5ffba33e7fffbb59512c1bad200dfcd587ad0ca5cf9716f06d1d593705fe0fbf75274c94a559b29058b8c00dd7e5a7c07ae4c6246b2dcc1dd077a", + "dest-filename": "@types-webpack-4.41.32.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21", + "sha512": "34e9f978872058b3a8eaa5bc01cb8b67b1bc3f2717bb4c53c71912e90d7c55617180f5123b0574a418f66bfe2f88d655bb6e62ed1201ec6b6d7640085145ce3a", + "dest-filename": "@types-ws-8.2.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129", + "sha512": "eed1489a080d78d05532c9f4bcbae99f51f5b8fad405d9c044f4e96688ad637ed9add2511337fb235ead32b94ade17a7df8f60af535887c0a66506bb0931ba03", + "dest-filename": "@types-yargs-parser-20.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.8.tgz#d23a3476fd3da8a0ea44b5494ca7fa677b9dad4c", + "sha512": "c03794c225267a6f45ceccb2b04c11ba468474335cc1b44ebd0f5019129a2c8eadf8896d3736e7e3f8b86ac981d746aebd91900b3490eadd0649ccc44e19545f", + "dest-filename": "@types-yargs-17.0.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.2.tgz#c48e5d56aff1444409e39fa164b0b4d4552a7b7a", + "sha512": "f2e00b6392d3bd2b87825a03554bd63f7a486ae20b9bef3fd290cca24b83608a0db0e912c1de408870534842632930dc66be73f14a60396664c411788897eda0", + "dest-filename": "@types-yauzl-2.9.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7", + "sha512": "ba4061d78a852e3c5340d4d7a1c77292c37941d336f12d42c47b76addb241722fec4557b56b7a6b812d56e609e3e3f9445a957044371ffd2e6ee59e18a1b424b", + "dest-filename": "@webassemblyjs-ast-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f", + "sha512": "88645fc9ce41abe36736e5fc6f987006b463cdfd2872b24f23a1961687411739859f2beb43cdd21ca8668a5094ffc26febb8b818964132113396dc7370d6a0b5", + "dest-filename": "@webassemblyjs-floating-point-hex-parser-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16", + "sha512": "465852f020425df45447f730a36868f5b9217925c6d3e370a285dc7373c020b00b7f640b745ca3eca1ac2916d573de61667867111a27e245bf0f7499a69e9372", + "dest-filename": "@webassemblyjs-helper-api-error-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5", + "sha512": "8308a417ae5a0cd79e5daf09c576b604093e4448d2ca1acd0bd670753d1ff2373875041e0d0ec6e26d1fd9008b3c988c4d33bac1f0e64668ffa56d0fb14bc870", + "dest-filename": "@webassemblyjs-helper-buffer-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae", + "sha512": "bc391bc6207ccdf9cf74d2bd45a8dc7b2e42d30f9026e804825374a1ffa498ef25ee50dbefb02794a61017b69aad9b82aeffa5d14bea2feebc8120ebde4f4b3d", + "dest-filename": "@webassemblyjs-helper-numbers-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1", + "sha512": "3efa68386889c17793ad27ffa9fb9d261c25bc34311607a56ccaadab9d965a25c2e97820d484447678263cdddbb384683bcdcf9cbfe716bc6e7178f5f815fad9", + "dest-filename": "@webassemblyjs-helper-wasm-bytecode-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a", + "sha512": "d743fd368dbdad85f58fb1771153d7dc9bc63d03da7be0289ae4933e217d78141e0a11c8ea2aa3308c11f4998e257c299e7fe85460e4ec8e4896c92e33053fa6", + "dest-filename": "@webassemblyjs-helper-wasm-section-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614", + "sha512": "849f3b4083ed00c29b16ae821939196098af1306436d052061ddea29269d4cd3a1558ee9fa07cfe92af494b4554da1b5263163fabdd8721a2a458c4d1f733419", + "dest-filename": "@webassemblyjs-ieee754-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5", + "sha512": "049d8fd21359d2ef938756195c9a735ba9a2c2a41419c2074f51bfb1fef680b543f4367901d613a8f35b1d987a2b53395662af157c064966400f3faa056c5e47", + "dest-filename": "@webassemblyjs-leb128-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff", + "sha512": "f64a9cc4011d3218b04241e990d8a8ad9ceaa46ae8750436206ac71f10b2f8ece7834a1fc8c034953aa22e456cd6ecd345e8d7fbf3b410e4fb2b1a953ee5e8b1", + "dest-filename": "@webassemblyjs-utf8-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6", + "sha512": "83e46cba9502d5a4c77d1f020e09ec551559149a9d9051e9b0731f26e590cd6537b6f9cb0b4ed4a872027cffb85f22f6b67af56a6be5d52769d3a4e760299590", + "dest-filename": "@webassemblyjs-wasm-edit-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76", + "sha512": "17b42a297c30365326b2e963ebe3bbaf89a6b4094259f3bfd077603b14a49597d0703bb44e92e20f5991b7fcc5db9064e7d1488c4b86008ca7e5e8b8c8c7cb84", + "dest-filename": "@webassemblyjs-wasm-gen-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2", + "sha512": "56a9e436a9d9954e4407ae29a7597b85d9b7866430ed582a6b4285fca08d3bdb08a48e8593a6eb0c4897fa208e62bbccb81583c2cd0d9133b16046fce574071f", + "dest-filename": "@webassemblyjs-wasm-opt-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199", + "sha512": "aeb06e8f0f9d26edf681807bfcbba9e9485d90fc7d4bd4a7a1b6734552fb55c047f41b7d6c204b12e5ff61738eb41b0e678350ad1ca42a17df4561ef8a042f38", + "dest-filename": "@webassemblyjs-wasm-parser-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0", + "sha512": "2106e851633878acd65be37f8e28f6b116ad28c87df5011e968dc46f6ab4a9792f3d1212023f10c6d9b0e62b70a8af934e406e508138e40c583d3a2a3ed2f982", + "dest-filename": "@webassemblyjs-wast-printer-1.11.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790", + "sha512": "0d7f272a0a9c1b0b1cd1e252a98b799703f80c7e459479e6b96581472ed7d0d71a191d19b6ec9e11280cc1361512dc66b0d198faa8ade10613fcc2184ce4cf78", + "dest-filename": "@xtuc-ieee754-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d", + "sha512": "36e1ea058d4f07f0fcc54eacfed84180e02200fec73980d0df6f8115920b27c8af9149001d09d67e7e9684befd3b08f5aa6527a0dfd83e192d748a2e722a6401", + "dest-filename": "@xtuc-long-4.2.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/abstract-socket/-/abstract-socket-2.1.1.tgz#243a7e6e6ff65bb9eab16a22fa90699b91e528f7", + "sha512": "619262cecbd2d5a06e6b919dd35c287b8ceec9804681231ea83381ebf0a1c1d4c8f74e0a3fa406b49b305e5e2172a5b16f3f3a85005efbe1d6574845d5a194b4", + "dest-filename": "abstract-socket-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd", + "sha512": "225f3442cd968d89492013733642ba298aa554c4db64b5e01f1da84f4a54fdf8d11f2129f8f11f10f634477582c001953ad6aec61d613b136021fe5bbfb750a4", + "dest-filename": "accepts-1.3.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9", + "sha512": "9bb559de3c33e1e2ba03856db7c130d7f98d6cfdb8bb41617727c0edf4af9c947a2cc75f3989e6b88aeb24082b61f609d7417fa2d6874edaedaed98774c37313", + "dest-filename": "acorn-import-assertions-1.8.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf", + "sha512": "57f2c6af500fcbe3d723029e6c45ab9193f0a1ea05fb0d6388e0549aec6e89421a387b686fc41cf414eb628ed5b88e5f47cb6ab32f9bb80d96168a11e6896abd", + "dest-filename": "acorn-8.7.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77", + "sha512": "45937035c945efe312ffc6c383bd1a9a0df6772799199c620ee42667128b025423af78c6c8bc7ee0a924e7c50eec3d90760148402a2fb92b991129dee911ba5d", + "dest-filename": "agent-base-6.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a", + "sha512": "e08ed3774d6ab96fd1a6871f35ac85745564d6a4aea21d04ec9adb449d7a9c7d351e128543cf0836af5277e9ddef6cea4724a5afd0660c0f3194427abc932b60", + "dest-filename": "aggregate-error-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d", + "sha512": "0c245f3bfe2743ef3da7f44ae378bc133778d44a9d18853895dee7185f0e435e2873fc1ee6b127b4b0946bbfa3ae7de79fcdc1a2c7f0640d306f8a689f6a3c89", + "dest-filename": "ajv-errors-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520", + "sha512": "5b1d0ac79da1c44ec2d7c8643048206251227ea599b58691828b89a2bf9631d3e743210ad77be0116c9536ea7b4a879ea0b32caf891fe61e9d396d75235e4c50", + "dest-filename": "ajv-formats-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d", + "sha512": "e69e964cdd03753195424e958dc123bb5f4881a1ee75a95c7da6c3ef284319e03a6dc42798bf82a6f78b26aff786f7f07756a87fa2f7f3a3ae824c7a45fc8c21", + "dest-filename": "ajv-keywords-3.5.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4", + "sha512": "8f77d52e0bd3a39dbb6a7c98c893864d825b1bebe79d062f1349b99a691cd532be9f1029a6408b3082f4699e1d6e55423681928619be933138654ca4068320e2", + "dest-filename": "ajv-6.12.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18", + "sha512": "a8e289c8d8ff87e396c7bb390de3cbe99bb529e33d8cf661c01aacfbb0f33fa6c63afab354249fd31b9e62656e682fe843f56d4b6ccb30b1dd4056e491af970d", + "dest-filename": "ajv-8.9.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59", + "sha512": "20e7f0c0117989ccce8e9fd6798e18c728ea005310a19b9f750583775f52104c5b54b357aafa73489fcced96b8fec08f990d3e191aaea00edb19c20d7317b0eb", + "dest-filename": "ansi-align-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf", + "sha512": "84751719a81e7e3376891ac80fadf172422fa2d3973a88e140a5883d467898d519f672d95beec530da04d653a412135662cc7fef2b0622e2580a230003d167ac", + "dest-filename": "ansi-colors-3.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41", + "sha512": "d403c7032af7f8f09a9b0370ddb5c23e9e0714b38d66dff2207d2c669d3fe3af4a58d4c4cbea8de634371955fa0cc675517022df8c95c2d4de686fc7a41baecf", + "dest-filename": "ansi-html-community-0.0.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df", + "sha1": "c3b33ab5ee360d86e0e628f0468ae7ef27d654df", + "dest-filename": "ansi-regex-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997", + "sha512": "d5aa5e3df5ccd54392ab0d28f48885028bd5cfd3394b50e0fb84eb0f07cc7b043aa7fae632e79beed5998d0d6bc782e8cb502b060828a86a5faaa748e2ba2776", + "dest-filename": "ansi-regex-4.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304", + "sha512": "aae2505e54d25062f62c7f52517a3c570b18e2ca1a9e1828e8b3529bce04d4b05c13cb373b4c29762473c91f73fd9649325316bf7eea38e6fda5d26531410a15", + "dest-filename": "ansi-regex-5.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d", + "sha512": "553d1923a91945d4e1f18c89c3748c6d89bfbbe36a7ec03112958ed0f7fdb2af3f7bde16c713a93cac7d151d459720ad3950cd390fbc9ed96a17189173eaf9a8", + "dest-filename": "ansi-styles-3.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937", + "sha512": "cdb07dac22404f5adb8e25436f686a2851cd60bc60b64f0d511c59dc86700f717a36dc5b5d94029e74a2d4b931f880e885d3e5169db6db05402c885e64941212", + "dest-filename": "ansi-styles-4.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb", + "sha512": "e6d78eb105800571c70453fdcb7b244b93f777f59f597a6fdc5529cbe2e8accacd61a4fda48e282cc417ee3cd0d8a9253691a9587cdd0974c34f66375c695907", + "dest-filename": "anymatch-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716", + "sha512": "3f8dde3df38022ea6482e1d4c9cadce2a27d933f198ae3948a36844f05fb4c7b7463f18d2bbbf469af2b63cd7ac568d9eeb25d0395dd31ca5515328cabe46f5a", + "dest-filename": "anymatch-3.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.7.1.tgz#cb0825c5e12efc85b196ac3ed9c89f076c61040e", + "sha512": "aa5f77bc452ae96b2cb465c3f9204b488430e9236785b0c4334b30ce0ba0cad3312e9deb4f6e0083f8dc0bcd191f188f45375ec359e2b91ecfdff142ac3a888f", + "dest-filename": "app-builder-bin-3.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/app-builder-lib/-/app-builder-lib-22.14.5.tgz#a61a50b132b858e98fdc70b6b88994ae99b4f96d", + "sha512": "93757028fe24a6c9d4697a14926d6ce336921cf1c83059cde243cc53dc9768a984d4b7c71ea05a11a8796d7793017e55fc10b8d7015d83c085e6f3a3be0cbc46", + "dest-filename": "app-builder-lib-22.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a", + "sha512": "63d27a6635eda1887c4675d508c394fedb439a4d5a063ba7abdbced2d6b9c7ce560d08907d417db083c121375b8a2215701a34dc78b78ccc62801b6c75d95747", + "dest-filename": "aproba-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911", + "sha512": "a39468cbab4d1b848bfc53a408037a4738e26a4652db944b605adc32db49a9b75df015ab9c0f9f1b3e7b88de4f6f4ea9bc11af979810d01e3c74996c957be84e", + "dest-filename": "argparse-1.0.10.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38", + "sha512": "f3ef56a9e6db173a57f4e47e59ae8edbd6ac22881e44ccdc1ad00835da4c1c7c80835d1fd3969215505b704a867ff3d7c35123019faadbf6c4060dc3beeacadd", + "dest-filename": "argparse-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520", + "sha1": "d6461074febfec71e7e15235761a329a5dc7c520", + "dest-filename": "arr-diff-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1", + "sha512": "2f784a57947fa79a3cd51eced362069f0a439a4a7a13df365e1b5bbb049edcee2a3ad30c32da1d89c0120350a7cb653e6825dc3699a5fa6e1d3ecbec2778dab6", + "dest-filename": "arr-flatten-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4", + "sha1": "e39b09aea9def866a8f206e288af63919bae39c4", + "dest-filename": "arr-union-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2", + "sha1": "9a5f699051b1e7073328f2a008968b64ea2955d2", + "dest-filename": "array-flatten-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099", + "sha512": "84d7f370e57c5b835db9a96da8114fc953bee780d226e64663da93e2946ba01e92f5ede28a2768d884880b987d476b0f27c1f71470888849ecbf594f5cedcab5", + "dest-filename": "array-flatten-2.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39", + "sha1": "9a34410e4f4e3da23dea375be5be70f24778ec39", + "dest-filename": "array-union-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6", + "sha1": "af6ac877a25cc7f74e058894753858dfdb24fdb6", + "dest-filename": "array-uniq-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428", + "sha1": "a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428", + "dest-filename": "array-unique-0.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/asar/-/asar-3.1.0.tgz#70b0509449fe3daccc63beb4d3c7d2e24d3c6473", + "sha512": "bf2c4fc4fe5aadc02a37817f79b1ddfc78709c0899b7086096f76673b051d9fd32c1b54d4cea527b284b0db197b44ff2e7c86fd680bbe5368d217bad9ec399b1", + "dest-filename": "asar-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525", + "sha1": "f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525", + "dest-filename": "assert-plus-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367", + "sha1": "59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367", + "dest-filename": "assign-symbols-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31", + "sha512": "67bb4cc35cad4d7b798ea31c38ff8e42d794d55b8d2bd634daeb89b4a4354afebd8d740a2a0e5c89b2f0189a30f32cd93fe780735f0498b18f6a5d1ba77eabbd", + "dest-filename": "astral-regex-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf", + "sha512": "cff5a143914fc922ddbd1101c88daf6624d6c029c5d26a0c27584af584300d31ca87a23bfee49c90c7ada1119be540593c2d73d23970fa7fd70a08de1fbcb501", + "dest-filename": "async-each-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3", + "sha512": "356d9c5fc9b543b28f03b6b933650b41e676c11e6a2393c06f0e4bd1438cc5d8a8564f4f319d21d539b264490f62b0af6230e51480aeb0ebb576510a00079707", + "dest-filename": "async-exit-hook-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd", + "sha512": "72c3a558601c44525a23a9be17658a76730aaf81e1761155064d07fd06c914c0abfae3b6930a21c1740fc70ffd382c69d39af9821541152ca2a22c71de07e435", + "dest-filename": "async-limiter-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d", + "sha1": "aea74d5e61c1f899613bf64bda66d4c78f2fd17d", + "dest-filename": "async-0.9.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff", + "sha512": "cdf96f96cd750c2cbe7505b34d6d9dcee8a5bfc6795ffa637e664e59b6ba4cd2150e6fb650368999748e5e56ac1ca7cd06cf28a37334693e747c31167ca6635e", + "dest-filename": "async-2.6.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79", + "sha1": "c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79", + "dest-filename": "asynckit-0.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2", + "sha512": "faafedec492fd440d8da5e8675ae8b2e25f5e2b53d4d5db459ade87de426c0f1596ce328f435eb2db3a315a69c9645ca5a27486a8a7000e6d00eac16b46523aa", + "dest-filename": "at-least-node-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9", + "sha512": "5a6eae92868e1898bfef7a7f725d86bcb8d323924cd64fced788ac0fbdd830bf12b6b1ffeff9511609a0f272026600f76d966f8f0086c6d30e0f7c16340bbc72", + "dest-filename": "atob-2.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe", + "sha512": "5dccfd974cfbcbdc90f6b7436b1966688e2e2477ff4fc83d84e13325cb04a97d928c28f8276d2e2bbfa57640c731ba490caefac05ef110883173fbd296c7f0e7", + "dest-filename": "atomically-1.7.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450", + "sha1": "d08885be6b9bbf9439fe087c76287245f0a81450", + "dest-filename": "author-regex-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d", + "sha512": "9f865eb5af0d0b7400b2eca28b3bb41a4991710e9c96457d58552751fd625cffff21e48a6d68e87d6dd41f2655c25381e32d37f5840a79f6b0c939fae19c1bbb", + "dest-filename": "babel-loader-8.2.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/babel-plugin-component/-/babel-plugin-component-1.1.1.tgz#9b023a23ff5c9aae0fd56c5a18b9cab8c4d45eea", + "sha512": "594c3cf3b9097f6187f34360fd931cb4a679d7589a98736a3e177db8aa35e32ce2b2f57b5add4472422b6fca2afee0b3dc1dcfa405bb5df97b0244cb0d84fa6a", + "dest-filename": "babel-plugin-component-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3", + "sha512": "8d9548facf5983722a03f91d8b48ba5030b26d423769204b9e096161b4928ca955ef217517fe4b5aff0c6a4426bd8a676c90d2e9f7012f62b31d2c4d08cb5649", + "dest-filename": "babel-plugin-dynamic-import-node-2.3.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5", + "sha512": "bfbfd3e8441c35f54b7dc3765fc2ee95bec38e9ae27b22d624aff33961f90d461c0207b1f6c3f7876e50f832ec5fd4e5a177b7cb53bc976ab626ff6af14541f7", + "dest-filename": "babel-plugin-polyfill-corejs2-0.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.1.tgz#d66183bf10976ea677f4149a7fcc4d8df43d4060", + "sha512": "4e286a11ee2c41c6ff41c3c9bf17bde3ff5166e2d0b85d7e4e8e16a90711bdcfb727780b08f20f8032b318b1bace640b7c7de79f6e61791b833644b6291e08f0", + "dest-filename": "babel-plugin-polyfill-corejs3-0.5.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990", + "sha512": "636074eadbe01d8b75c74cb3d7b8c690679e32be4578a52ef80489f8dea7079950f036a97e0e368b4395adff0f346277cca2f8036dec9cc8b5211c2baaa343ec", + "dest-filename": "babel-plugin-polyfill-regenerator-0.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee", + "sha512": "de849e50ed13315ebb84dd4099b5ec2b8c9aa94eed8e21e56f144364ea47d0a5bdf82797e1b440697d009f1b74b71d8cae94695b041a3f02252121098585393f", + "dest-filename": "balanced-match-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f", + "sha512": "e53e8fe313e0a69d180c5bd25b0119e0da04dda3384014170f39956eb6829058fccc733e99b6bc4b2a81e436d95b247b9981e8e98ec1750a373280389b44de42", + "dest-filename": "base-0.11.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a", + "sha512": "00aa5a6251e7f2de1255b3870b2f9be7e28a82f478bebb03f2f6efadb890269b3b7ca0d3923903af2ea38b4ad42630b49336cd78f2f0cf1abc8b2a68e35a9e58", + "dest-filename": "base64-js-1.5.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16", + "sha1": "dc34314f4e679318093fc760272525f94bf25c16", + "dest-filename": "batch-0.6.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328", + "sha512": "bf22f63b2989c666ab3bc83132bd2684286c3bd406c21ca77eebb8f8c1d3016e9ccdfabd86e98207bacaa548c377d6148833d4e26ce9caea454af382940c1b99", + "dest-filename": "big.js-5.2.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65", + "sha512": "527ecc2040dd502e603697060d5f7ba29d58c24ef8f0ca477054c7a18b3aaa78f56778fb239dd51b79f06612b3a016666dd44d9dbe9645d165c25eed483b991b", + "dest-filename": "binary-extensions-1.13.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df", + "sha512": "a76abfb7f9a1bee3a3fd478b955eb9eba183fe0ba8c25af4847c42948d16f66ecc59890bd45d212e8fb401ec6cf4748f0ad4754974344c3dcc30aad765a8db89", + "dest-filename": "bindings-1.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.9.tgz#a64a0e4365658b9ab5fe875eb9dfb694189bb41c", + "sha512": "ec1d51b71f368639d20f83c62c08d559e607ded1c07155260a187ce5ade596d2909ba16b7ac5e1f44ad0a3aa00bfa0aac6db5ccc2dff90483c498e4d96e3ee53", + "dest-filename": "bluebird-lst-1.0.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f", + "sha512": "5e9363e860d0cdd7d6fabd969e7ef189201ded33378f39311970464ed58ab925efd71515f9acf1026f2375664dd3a413424fb63765c1f6344392f6e6426711b6", + "dest-filename": "bluebird-3.7.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4", + "sha512": "f258df422e5e064f0425f10232b82a34658f118e6358ffb5233933906745144c05419672699db552a75a1e4b6088c947d312c7a8816d13fbb639813974eb5588", + "dest-filename": "body-parser-1.19.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5", + "sha1": "8e890a183d8ee9a2393b3844c691a42bcf7bc9f5", + "dest-filename": "bonjour-3.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e", + "sha1": "68dff5fbe60c51eb37725ea9e3ed310dcc1e776e", + "dest-filename": "boolbase-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/boolean/-/boolean-3.1.4.tgz#f51a2fb5838a99e06f9b6ec1edb674de67026435", + "sha512": "de1c74930537bb31ba45e437a6768540f4a4b69070e911cddff8af0ca12e53c8355d27da7e8c32bc39da763bf5c69f0866a86d4ae931970bfd6c5e85857f26d3", + "dest-filename": "boolean-3.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50", + "sha512": "f6062040a5f1fb59cff263fb0b3172694011860ec3de7d5d17f16712b5a6bbd97a26f1a9354376efc8746926fe423a22292586fa2677b87adcaa4d2aad8f5141", + "dest-filename": "boxen-5.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd", + "sha512": "882b8f1c3160ac75fb1f6bc423fe71a73d3bcd21c1d344e9ba0aa1998b5598c3bae75f260ae44ca0e60595d101974835f3bb9fa3375a1e058a71815beb5a8688", + "dest-filename": "brace-expansion-1.1.11.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729", + "sha512": "68d75b9e3f4ff0f8dd5d4e326da58b2b6205de373f1280d86c2ec06b35bab68dd346c7d7c6c702f545ce07988388442b93221b5a9d922d075ae3e4006bb9dcdf", + "dest-filename": "braces-2.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3", + "sha512": "bb6b5b6c6e4f74a45352872d3b73410fc150e4774f8756573c7ce9d6bc1a6b98d373e455f7ff9195688020a9a344f405fb16c633d2a4963e5b65015adacff7f0", + "dest-filename": "browserslist-4.19.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0", + "sha512": "4c433688c20441d276ca33c9a1222c95d9e5795680935a16dc305553293238bb04b0598473d927f921453f3fa0979e0a40dc650e7030097a2c392f4e931db102", + "dest-filename": "buffer-alloc-unsafe-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec", + "sha512": "085b074208ed5b550285d5e06f2246b679be3bfb8b41e65db5b0e8f267d48185c21d2335c20ad5c579ba6d2cab52e12b11bfb8b185460b3012051a2def3caba3", + "dest-filename": "buffer-alloc-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242", + "sha1": "0d333e3f00eac50aa1454abd30ef8c2a5d9a7242", + "dest-filename": "buffer-crc32-0.2.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe", + "sha1": "59616b498304d556abd466966b22eeda3eca5fbe", + "dest-filename": "buffer-equal-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c", + "sha1": "f8f78b76789888ef39f205cd637f68e702122b2c", + "dest-filename": "buffer-fill-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5", + "sha512": "13e5d0091c126da6a20a1b6fea4e83c2073e6f1f81b3abee2891c7979928c7f05a29b8625f3a903b02b870edb6c84946a763829a3c15853dc79b18323c69c97d", + "dest-filename": "buffer-from-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c", + "sha512": "e3face120f3a8e2bed3d378e5144fad6324ed586b54eb47f3a4a824990f2abce16261dcbbae8a984160937e7e6e71b9f224e17005704c2d7bff16cc2f087ffd6", + "dest-filename": "buffer-indexof-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0", + "sha512": "10773220f050e0148696f8c1d7a9392a0009dbb088b0763fd8906609145ea38f32f6b43731a533597dca56505ae14eccc97d361dd563d0aec2dd6681de3bbb15", + "dest-filename": "buffer-5.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.1.tgz#25f066b3fbc20b3e6236a9b956b1ebb0e33ff66a", + "sha512": "73c6bc277c0ae812152d6ee5b3eed344af6282ca536f35a652ac456e02b49b8d06826e9e7d46f1b565421888dcf9db5c872af9a8030050bea210645d4bfeafc2", + "dest-filename": "builder-util-runtime-8.9.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/builder-util/-/builder-util-22.14.5.tgz#42a18608d2a566c0846e91266464776c8bfb0cc9", + "sha512": "cea2070c5270980ee357b482f5a23edf7316c13da65a88a31fe3a5f489ed340c2eb915e84beed7789c2784b0573a17030735d3e240f31e7464e0929e6b280460", + "dest-filename": "builder-util-22.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048", + "sha1": "d32815404d689699f85a4ea4fa8755dd13a96048", + "dest-filename": "bytes-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a", + "sha512": "7567b89d63bfaee10e63b1e4509e6016dd4308557dccf46826bf29574fc04907ab98e663b6af233233a9ac2d0a775d062cdfa5ef16943efc732455adc46bbc16", + "dest-filename": "bytes-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c", + "sha512": "e59bc0c5dd391c30d4fb2f4156f72a62ed8b2d798f9d0d215bada1df6838c414e02ff329a51e3fd383477e3ff270cdb2ea59939dbc3a1d58bed5e3743ec6daeb", + "dest-filename": "cacache-13.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2", + "sha512": "00a71d4e71525804dde7f1823d1c6bd82870209f3909ecab1328d11e52b1439e9de1724c1b29b4b8088a9f4c5b2ce18e977fb24693938b8f38755084739014cd", + "dest-filename": "cache-base-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005", + "sha512": "dbf90db1c3e1a5cc6b3a280c6736e2585eddcfc8a585bfe72075371326625d65e97aafdabbca89f1585d7ed324b72de7ec68fa1c819a9501bca2204d07700980", + "dest-filename": "cacheable-lookup-5.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912", + "sha512": "3a3ddc0063c2a8e657ed1cfae149f2d8660064d962412a9f6de3eb800435c0a022858982527ada06d26d29c191e31cfbc05f8ba090beb2c159befe41805f4882", + "dest-filename": "cacheable-request-6.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27", + "sha512": "a68b96f3f16688f41bb86a645d0f4100fbff328e710c600d812357cd3cc9f03aca1ae5ceb2c338c084118df6a735187762ee5c7d83ef728aea6e183628826d7b", + "dest-filename": "cacheable-request-7.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c", + "sha512": "ecef856c28a1ac1e5619b1587ac72dc264ca69eeab3a22339b3d6272b79627ed1a03b2c97eeaa112ca364fd9dca5c16dccc42dcd77f64061ae7962464d8b2aac", + "dest-filename": "call-bind-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a", + "sha512": "83119606b4d3d49b8cc7a47ea393d35cc9949e19d5ccb43d48dbad0f862a2ad23a6a9f3deedded28409895aea0096124a655e794dc9b124660f46106c4a14283", + "dest-filename": "camel-case-4.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320", + "sha512": "2f6f124c1d7bd27c164badd48ed944384ddd95d400a5a257664388d6e3057f37f7ad1b8f7a01da1deb3279ef98c50f96e92bd10d057a52b74e751891d79df026", + "dest-filename": "camelcase-5.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a", + "sha512": "1a6cba161625098eee3849595126f1a365020c7f28c0493df7a8246eba6c806b6b24b33727b8c6c65f4873b430c23e22bce13901665644c79c0dd17b86a1a314", + "dest-filename": "camelcase-6.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001303.tgz#9b168e4f43ccfc372b86f4bc5a551d9b909c95c9", + "sha512": "fcca9cd681129dd50db3324fd24c7451a414f6412ff6736d27b2a7f00740d263671fc791d5c8f4906f8d6cdb82d56abf6f6d5e03ca6b84a440ddb6e48ce35e81", + "dest-filename": "caniuse-lite-1.0.30001303.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424", + "sha512": "32d8be7fd96924d730178b5657cfcead34ed1758198be7fc16a97201da2eada95c156150585dbe3600874a18e409bf881412eaf5bb99c04d71724414e29792b9", + "dest-filename": "chalk-2.4.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01", + "sha512": "a0a9db845c91217a54b9ecfc881326c846b89db8f820e432ba173fc32f6463bfd654f73020ef5503aebc3eef1190eefed06efa48b44e7b2c3d0a9434eb58b898", + "dest-filename": "chalk-4.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917", + "sha512": "6666546b37cecdfd0dbdeeddba208a0f6dcf1520ace093e863271c8d4145dda42441a76a0617f3863930047da634e1bd71307085a98cdfb108b08919c379d182", + "dest-filename": "chokidar-2.1.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b", + "sha512": "8c9d1bab36b296626d567360cd37923acf033dabe96d8804aff6f460bf3fd863b7c4912122716684a3149c42508d9ba62bb297185854cbcf4faec25695a90156", + "dest-filename": "chownr-1.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac", + "sha512": "a772942f2420e12ecd2078b17706c65fe9c51e4a01880e18426c96b636fc5e7812295d76e27266472b2001eba36d455bd79be1f91bc551f08fa94eeb5e4fa166", + "dest-filename": "chrome-trace-event-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205", + "sha1": "04a106672c18b085ab774d983dfa3ea138f22205", + "dest-filename": "chromium-pickle-js-0.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46", + "sha512": "e6d2bb12dad9d0df8e2c532d86da8e8f87c8d8979bf3c0b808064fbb6e4b0d55205c9d00dc9b383cc1aaae7d095355b4321d7f67cc19cd83f1a94ad77816e809", + "dest-filename": "ci-info-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2", + "sha512": "ae24ffdef239629547ebfaa89a50e7268c3a4c179ed8f04a484a71dcedf61063d86d618846c2251919acdd29bbe30604d49328f119ced381dbd76fafd49e480b", + "dest-filename": "ci-info-3.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463", + "sha512": "a8e84f6bf163eece9363c1fc7ac1aee5036930c431cfbf61faeaf3acd60dea69fef419f194319fe5067e5de083b314a33eab12479e973993899a97aeae72cc7a", + "dest-filename": "class-utils-0.3.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178", + "sha512": "1095034fb9c35450ef690800a361bf3c9bf19a9d68fdcea25cb6ecc2c05b5055e2d4dafe02303670a99f6ca0cc8ccbf311eef98373fa2646830c02a4f7a03ce4", + "dest-filename": "clean-css-4.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b", + "sha512": "e1d882f4769313e29100c5a10e1ac63840a0599c687af31ce5396439b32a352b1553ad8f6335d9fd23138f3c8600517562eb20c46712593117061a7408fc10d4", + "dest-filename": "clean-stack-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f", + "sha512": "cb872831cca581209d5629e388306e47c3c20b66cb8f2193c0498f6fd34747f41a354e8450e5dc4d8fece958c6303e8435211a790607098d063464b98df3303f", + "dest-filename": "cli-boxes-2.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7", + "sha512": "9fc7ce8b1c030fa6ff39b8a7cd3ae9d59285cdb82f299beecff4ef7a39cb9f56907c2eabe765c4c7ce459ae0bedc723e24cedca0145752f36a114d8f1d5ac7a6", + "dest-filename": "cli-truncate-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5", + "sha512": "3d87864849a61cceb3be879fdb0f133f396b9cda572234e2a582bbf3462cc2620ff6f8f199de98d9adc20762acebf014f0d1e366e817be8f30de858cdaa9f05c", + "dest-filename": "cliui-5.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1", + "sha512": "b7ac1b82da025ef033b2ded0817c4962a3edd2eb047db81075fb443db2cbfdcbefe873c4e5582fa82b80203474360539d9db3aac5c2aae06a434bac712309bad", + "dest-filename": "cliui-6.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f", + "sha512": "39c444ebc70eb15317a7562fa2797f7f39103b28cb4aeffc6e13c37d0b747b4fc46f6f374ca3f6d05b3632aa0fb2bf52c00e7de6b44203e40ccd873d9c13fe25", + "dest-filename": "cliui-7.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b", + "sha1": "d1dc973920314df67fbeb94223b4ee350239e96b", + "dest-filename": "clone-response-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0", + "sha1": "4bc0373c164bc3291b4d368c829cf1a80a59dca0", + "dest-filename": "collection-visit-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8", + "sha512": "41f014b5dfaf15d02d150702f020b262dd5f616c52a8088ad9c483eb30c1f0dddca6c10102f471a7dcce1a0e86fd21c7258013f3cfdacff22e0c600bb0d55b1a", + "dest-filename": "color-convert-1.9.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3", + "sha512": "4511023ec8fb8aeff16f9a0a61cb051d2a6914d9ec8ffe763954d129be333f9a275f0545df3566993a0d70e7c60be0910e97cafd4e7ce1f320dfc64709a12529", + "dest-filename": "color-convert-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25", + "sha1": "a7d0558bd89c42f795dd42328f740831ca53bc25", + "dest-filename": "color-name-1.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2", + "sha512": "74ecbedc0b96ddadb035b64722e319a537208c6b8b53fb812ffb9b71917d3976c3a3c7dfe0ef32569e417f479f4bcb84a18a39ab8171edd63d3a04065e002c40", + "dest-filename": "color-name-1.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b", + "sha1": "0433f44d809680fdeb60ed260f1b0c262e82a40b", + "dest-filename": "colors-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f", + "sha512": "1503783117ee25e1dfedc05b04c2455e12920eafb690002b06599106f72f144e410751d9297b5214048385d973f73398c3187c943767be630e7bffb971da0476", + "dest-filename": "combined-stream-1.0.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33", + "sha512": "1a956498cf2f176bd05248f62ef6660f7e49c5e24e2c2c09f5c524ba0ca4da7ba16efdfe989be92d862dfb4f9448cc44fa88fe7b2fe52449e1670ef9c7f38c71", + "dest-filename": "commander-2.20.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4", + "sha1": "9c99094176e12240cb22d6c5146098400fe0f7d4", + "dest-filename": "commander-2.9.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068", + "sha512": "34e2a6f31864cc08f3171f01dafe4e0074febb9a5141cd9409ad95abd8d82ffdf5a36c22f66c4103b2c816cdec5795520b8f73ea91217db3142ef4a12a3dba58", + "dest-filename": "commander-4.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae", + "sha512": "3f40b2b0d0d0eebb55c3840842d9be311c55ebabca152be5b10bc6617656477a855348e530a1d9659830f1efbc0d26a1e140ca32a9e49d10d0cfec6e41743f66", + "dest-filename": "commander-5.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b", + "sha1": "ddd800da0c66127393cca5950ea968a3aaf1253b", + "dest-filename": "commondir-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/compare-version/-/compare-version-0.1.2.tgz#0162ec2d9351f5ddd59a9202cba935366a725080", + "sha1": "0162ec2d9351f5ddd59a9202cba935366a725080", + "dest-filename": "compare-version-0.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0", + "sha512": "45ddec7ba401fac3b54f0a998ec710aeeae910f21f3b4ff26274a29fa43fac3de63aeb47bd4ac202126e6f7afdd2e35bf9211206e134418a01f7461d7dab6c46", + "dest-filename": "component-emitter-1.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba", + "sha512": "005debecfe5d5b12fc331c884d132539140d68e036224005693af893b054ba68cfb51a460d36699743dbd5708ee89783081769d76e8282cf6c331a928e063246", + "dest-filename": "compressible-2.0.18.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f", + "sha512": "8da4880f33fda59552e197d0f93cefb625a17691611364431f3f10264a57f522292eaf3c56e785e63270eadfba09441c02803ab7ec7cf4c2eb580aa97c313c89", + "dest-filename": "compression-1.7.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b", + "sha1": "d8a96bd77fd68df7793a73036a3ba0d5405d477b", + "dest-filename": "concat-map-0.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34", + "sha512": "dbb1c18212718e266d224dd872f9ffe246c993fd6e66e2457ee3c49ece8b684be9bc6d5fd214de6bc96296ba2eca8f6655cd8659d70467c38ba0699200396b0b", + "dest-filename": "concat-stream-1.6.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/conf/-/conf-10.1.1.tgz#ff08046d5aeeee0eaff55d57f5b4319193c3dfda", + "sha512": "cf6722bf0abf93c4cc62d727dd254fd0f7aca38a2d2169c7b5c4ee1e1434cc364374fe0d4f1a8473ca307e4cf8cc1b1d318767fcb15c13e6616c27aa921b6add", + "dest-filename": "conf-10.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4", + "sha512": "aa3f9ff003c04571eb33486b6aa5d86f6fdb395495e0fbc9425359fc3563d10ae634cdaad9eba2ce47ae55c910e7b27e5b49911fa1ef8be939d0ce09ba5d9545", + "dest-filename": "config-chain-1.1.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96", + "sha512": "68c2a9ae093962104dc87db9863f301addbe0f9d92c350d1448cea0702e9d986bd985998f0a3efbedbe69daf12c5547d24c678933303ebc376daf95a46991e14", + "dest-filename": "configstore-5.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc", + "sha512": "7b9e01f7dabf394a07eb8cd86117f71c13f9cf6e06dfc8790f7a97bb6dc9191a228295f94ace2bf599c393783467cb900b6c7694f689f9495605cd5958159d2e", + "dest-filename": "connect-history-api-fallback-1.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe", + "sha512": "16f7994cdb86c34e1cc6502259bce2eb34c02ff9617a16966d3b6096e261e3f13de43a8cc139a16b7299375680580f1c148847ccc654bcb7af930e51aa4fad49", + "dest-filename": "content-disposition-0.5.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b", + "sha512": "8483f71043ecf2d07d013d4bf8d52ab70380a6ce269366686fcf4c5973078c75a0f668a517f8f8a2c9e740b5c108114193fb6f206fed51cf663942623c184f5c", + "dest-filename": "content-type-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369", + "sha512": "f8e41d8cfe3dcd5888ffa8bb9c826903cac0978b15fc974f7d4f6766cdd5a8ec062208b3202bee376aeee9f31dfb89652f4b5aaf5f146095df67f4d6b668548c", + "dest-filename": "convert-source-map-1.8.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c", + "sha1": "e303a882b342cc3ee8ca513a79999734dab3ae2c", + "dest-filename": "cookie-signature-1.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1", + "sha512": "670ac5906271511dc42285ed3bec9513af446fb2a58b16da78059f05007dbd5b0d9ffa3e630ebd8015924832bcdb985035d37ec05f3310b7f7745365fe4c6450", + "dest-filename": "cookie-0.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0", + "sha512": "7f676899df5fb150c5b5a15c6da459b985f0b5d9a7cea6c00d2c21496631601fd0f33b1d51414c5d54705c60cc5a66c4cc09f591d46bb48d53fca4c538be17d8", + "dest-filename": "copy-concurrently-1.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d", + "sha1": "676f6eb3c39997c2ee1ac3a924fd6124748f578d", + "dest-filename": "copy-descriptor-0.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.20.3.tgz#d71f85f94eb5e4bea3407412e549daa083d23bd6", + "sha512": "73c339874224359f88f76421229b928a33b1180723de5829b167640aa9944d937089dba3178af7a62eb1d4308df9572ce6a4d2d9759631f592b82ab2ba95fc83", + "dest-filename": "core-js-compat-3.20.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7", + "sha1": "b5fd54220aa2bc5ab57aab7140c940754503c1a7", + "dest-filename": "core-util-is-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85", + "sha512": "65006f8b50dca49e060ea6a78ee719d878f7c043b9a590d2f3d0566e472bbddc64b09a2bc140c365a997f65745929f5ac369660432e090e6c40380d6349f4561", + "dest-filename": "core-util-is-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6", + "sha512": "897de67e0713308ab764a2c8b151406efefe31cd7493169b00641bf07be3035a374f53c8629adb6a443ae5ddc8fb61c61edea748a90cf4f62382824ed8a70505", + "dest-filename": "crc-3.8.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/crocket/-/crocket-0.9.11.tgz#288fca11ef0d3dd239b62c488265f30c8edfb0c5", + "sha1": "288fca11ef0d3dd239b62c488265f30c8edfb0c5", + "dest-filename": "crocket-0.9.11.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cross-spawn-windows-exe/-/cross-spawn-windows-exe-1.2.0.tgz#46253b0f497676e766faf4a7061004618b5ac5ec", + "sha512": "9a42ed2497186c30b1106ec9b3a7949d43677568f2519c09dc7edb12b9a6b4e614fd96fdf43c949296a6b88644d1bddb86627267b0fdd2e4ba7fe086c514633b", + "dest-filename": "cross-spawn-windows-exe-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4", + "sha512": "79354bac14adedf8db0f2833f34e69327b2d22cd954c1364466d2ac5977e33b0395c377155158ee4cc460576618d8e1ca8b60b76dac6a917fc9813e6cf04a959", + "dest-filename": "cross-spawn-6.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6", + "sha512": "8910cf24a50f544343edd1cf3bcae46ce9cfa720f281c0c5b568e9796342832f163f6ad77315cbf13b2445e425e8eac1d86efe509ada82cd6ad7916e75cec6eb", + "dest-filename": "cross-spawn-7.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cross-unzip/-/cross-unzip-0.0.2.tgz#5183bc47a09559befcf98cc4657964999359372f", + "sha1": "5183bc47a09559befcf98cc4657964999359372f", + "dest-filename": "cross-unzip-0.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5", + "sha512": "bf5a65203df2f6bfe53e1be2275c2b5e92dec94206019d921cd61311aa66efff00f672cfa32bd5a7744afc43c5aa7e641339f25a061936c46d6182166ee1bc28", + "dest-filename": "crypto-random-string-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/css-hot-loader/-/css-hot-loader-1.4.4.tgz#ae784932cd8b7d092f7f15702af08b3ec9436052", + "sha512": "27fa971f3fabec5393f76a8c2097f1524d0b0bd7de71035956bd0cb3043814ea4a2f2382063a1f54c7dce91dbaf1b87fe64b644d286bc1e32bd305aa7ab0bdda", + "dest-filename": "css-hot-loader-1.4.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645", + "sha512": "339952ba4a168b521ff1d8500140af8f81fcbd4b77bce9f06d0047f437539bfb38626d81ff774f32d6197899aaed0dd2dcf6be23de03719ee973d6cfd7871621", + "dest-filename": "css-loader-3.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd", + "sha512": "fda52c94a873913342414076a935fce255667e26bd3728cfdd6a431ad8ff5b18700735816145770e0529bab1d399ef144cf70f9400f50c9f9bd2737fb79d330d", + "dest-filename": "css-select-4.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe", + "sha512": "6ab48c456208158d2157ca48c593047e6308e3b5a3dd1fda5a96430f159808f12238cbfab5f3ab9e90ed8310583c4403e15d18ffde7cfb54dd0b78964c57143f", + "dest-filename": "css-what-5.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee", + "sha512": "fd36ff25c8cad75d67352706a1be4c36db27b4d3356823540e2a41fd39306458720ebac4e3b48ec7fd7cc05d9b6e381cdd9cc248a5b54f99ede446c5a00cff56", + "dest-filename": "cssesc-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dbus-next/-/dbus-next-0.9.2.tgz#d69a24ea5b54d90ab6bd543c7b81bcb965a99f93", + "sha512": "b7342affec2b4d9db253e5393e879773deca001857dafe790bf4f47e29c7ded48a62e23c1ff4aaa69205ca6041ad41dc2b5dcbbc4198def763de290f3de9cbe6", + "dest-filename": "dbus-next-0.9.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/debounce-fn/-/debounce-fn-4.0.0.tgz#ed76d206d8a50e60de0dd66d494d82835ffe61c7", + "sha512": "f296024222fd5dd720d143d20f777ed0a3253a3a7e28653910fc1875d83343b0c04ec8387ee5038d0b6c60b9968e7936a1b9cd1e0577bc4d98e237a348e25505", + "dest-filename": "debounce-fn-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f", + "sha512": "6c2ec496b7496899cf6c03fed44a2d62fa99b1bdde725e708ba05f8ba0494d470da30a7a72fb298348d7ce74532838e6fc4ec076014155e00f54c35c286b0730", + "dest-filename": "debug-2.6.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a", + "sha512": "0858f3618022e1385f890be2ceb1507af4d35c7b670aa59f7bbc75021804b1c4f3e996cb6dfa0b44b3ee81343206d87a7fc644455512c961c50ffed6bb8b755d", + "dest-filename": "debug-3.2.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664", + "sha512": "ff3c70e7ebe1d537effb8427edae67b1b70928f692bc20e1a239fa14497dbeea702b6542483b44884b6aafc0c5b7360539dcfadcb064c5e73b0d8b9cda3a27e9", + "dest-filename": "debug-4.3.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290", + "sha1": "f6534d15148269b20352e7bee26f501f9a191290", + "dest-filename": "decamelize-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545", + "sha1": "eb3913333458775cb84cd1a1fae062106bb87545", + "dest-filename": "decode-uri-component-0.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3", + "sha1": "80a4dd323748384bfa248083622aedec982adff3", + "dest-filename": "decompress-response-3.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc", + "sha512": "696df9c9933a05bff8a099599dc307d8b0a866d2574d1c444b5eef137868462a305369161da24a1644810e70d1f9c9bd27ef5085799113221fbf4a638bd7a309", + "dest-filename": "decompress-response-6.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a", + "sha512": "c9df5ce40762a95711f898dcc1441bf4392125cf2780daf431a844046bc3889c3ca6e59a6f6c99961fa791ab0e9d93fe1064c03faad1a76273261259cef345f2", + "dest-filename": "deep-equal-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac", + "sha512": "2ce1f120e68f61d1e5251b4241f0c8559b5fc3fb9f33cfab563eb8f51207cdc9bfbc6c1045716de8e3ea2055ac9b65c432b34812d591eb8b18d4b10a0f6bc038", + "dest-filename": "deep-extend-0.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b", + "sha512": "87ab0cad507554c595ad6d7799273a89afc3c18630e4c37af9ec4dbb539a25e15a73969202fc0cee56743557d3001b929107a5af8879a1e6e0dca0755cf76380", + "dest-filename": "default-gateway-4.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591", + "sha512": "d0849d368bac1ef653d84885959799007054bd2c662acc150847fc856eca5a01b86bc31512eff755beae598a33923ca5c82c5ed090488910758d5e394bbd1655", + "dest-filename": "defer-to-connect-1.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587", + "sha512": "e2dbedb5ea571b555a606ad189b93913025dd6de2e76e9d239531d2d200bea621dd62c78dfca0fc0f64c00b638d450a28ee90ed4bd2dc0d706b1dcd2edd1e00e", + "dest-filename": "defer-to-connect-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1", + "sha512": "dcca9f60a8f694bcdd3127fc648644fd5f99bb2f81803e9fd7ae1ef0adb0edd827a4a02b0437ab198a4ce3a21861c8e791d3cd3233e4f40e95141f3edd22a55d", + "dest-filename": "define-properties-1.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116", + "sha1": "c35b1ef918ec3c990f9a5bc57be04aacec5c8116", + "dest-filename": "define-property-0.2.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6", + "sha1": "769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6", + "dest-filename": "define-property-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d", + "sha512": "8f02b6515e1c9cfa5b706efe55101129364f516a30c1703c6f31f934feae774a1e031c983ee1995000bb84cba0a42773e01792665d8397d93ae821c9ff8e9961", + "dest-filename": "define-property-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4", + "sha512": "4301ae114a2e3f6915c107a702c3a87f916ff0af6ddc3f026bc3717172ab2291078d35cae49da75cb74ff802c8d5c82ff308fb2aec01853c0190e65224a3395d", + "dest-filename": "del-4.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619", + "sha1": "df3ae199acadfb7d440aaae0b29e2272b24ec619", + "dest-filename": "delayed-stream-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9", + "sha1": "9bcd52e14c097763e749b274c4346ed2e560b5a9", + "dest-filename": "depd-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80", + "sha1": "978857442c44749e4206613e37946205826abd80", + "dest-filename": "destroy-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7", + "sha1": "f0d66d03672a825cb1b73bdb3fe62310c8e552b7", + "dest-filename": "detect-file-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1", + "sha512": "4f4348b90a674ef14301336e1cde6ba0fc12046f37ac5b2e3be3175c7f7fdcdd5e15b9f8c1c3e3b6dbe330b10f589d11194620404edc1a04b7b4dc5ba8218cee", + "dest-filename": "detect-node-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.2.tgz#2e48c0d3b825462afe75ab4ad5e829c8ece36257", + "sha512": "415e8f31a1d308d98a49e3fa4285e1553c3db2773d543f0cba54d3d0177df4f69ca78492d5c8dcad83e004f9a26ea295b4c2497ea0ba5ef39780f30410f1ff7e", + "dest-filename": "dijkstrajs-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dir-compare/-/dir-compare-2.4.0.tgz#785c41dc5f645b34343a4eafc50b79bac7f11631", + "sha512": "97d866bbcc7fae3542f59db3986ce484e128c19bd6ee9998c2ce42587bad83cbb5260bec296331ed0fd43837aee1d8cb6781605b96deb30e72bcc427047cee08", + "dest-filename": "dir-compare-2.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/discord-rpc/-/discord-rpc-4.0.1.tgz#a89aa04a048aa83ad4f347d53fa0162501eae0d8", + "sha512": "1cebc7a5bab9493459263408073c282a74348c7a656c45855a53c3c175ca9bf6c82e1e27ce3720ee636a965d1463b46c8c5a1a5c0edefe861bff896fa5d6b6cc", + "dest-filename": "discord-rpc-4.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dmg-builder/-/dmg-builder-22.14.5.tgz#137c0b55e639badcc0b119eb060e6fa4ed61d948", + "sha512": "d46bc5190137df66ef3da99c330643a96a9f59f253cb20cb3ac1cc7068b4cecf8987b24e9faff3b8190724858776c8f64096e1ccb572776fd9aadb4e2afec8f3", + "dest-filename": "dmg-builder-22.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dmg-license/-/dmg-license-1.0.10.tgz#89f52afae25d827fce8d818c13aff30af1c16bcc", + "sha512": "49579eca239e8a75792423c75cc74a3a02b56156da93fe3ef162f6ac19dfa9162903915a7856909d059bdb9c7adbc6a6d70ef409b8a9183bfd4b9d5b8a987adc", + "dest-filename": "dmg-license-1.0.10.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d", + "sha1": "b39e7f1da6eb0a75ba9c17324b34753c47e0654d", + "dest-filename": "dns-equal-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f", + "sha512": "050e85e2fc9c2d706f76b259e92de065ec2deab72b92cf4a06033dbeb856fa49c646a73cb84753edfb82c25a1cee79f2e71368309d7b1c61f447fe9fa68f0408", + "dest-filename": "dns-packet-1.3.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6", + "sha1": "b91d806f5d27188e4ab3e7d107d881a1cc4642b6", + "dest-filename": "dns-txt-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768", + "sha512": "81ddf2a483df38cafd8798c82aaf04dec1ce4c28de8ab9e5d162b965d4b5016d0e76dd1bd4f696687749e10938925bfe601f5a2414bb9844978c5a0340fbba0c", + "dest-filename": "dom-converter-0.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91", + "sha512": "e5ce78064e43c38a80c4d388d691448b33d28d5b31e7e6e924a98bda43e7f0984152adaad3db5309ade68e28ee9f635f2bbf0d328b8360d30190eacf6624be8a", + "dest-filename": "dom-serializer-1.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57", + "sha512": "0ed04ca3cda9bf5745b54987cabe3c6de8aeabbf764b1a21afef079bdce8c649583df6ba9f46770728e3d8857b6e6af6232a82967a844217e01c9279405d11e4", + "dest-filename": "domelementtype-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a", + "sha512": "2750b9ac800d51bb982be16e14bf7ceb9d2b8a1ca750e13344bc56fbdd1b29945607a0355f54dff361b1475a8058bc9f34f46f8ea7e2a77439b5d6259806bd94", + "dest-filename": "domhandler-3.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626", + "sha512": "7c2d1a5cd417a8a4854ebdb00cd64386c1188c2898b035a5dc3d35930b76e619b56083f20c61efbe2debc3e3cba87025fe6ef531a885edde73bc1af4a79501da", + "dest-filename": "domhandler-4.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135", + "sha512": "c3de828e87e9ef63392088698e0a1b06299811fa0f8f1d55c740525fd3f7d1605d656d9620a5344f505dd24cf678d67d8a48ca8076c4c8ac7c041e87d4bde1dc", + "dest-filename": "domutils-2.8.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751", + "sha512": "2afe672a587ac91addac6bf1789d9ee72d9e454a64528b085b8036012dfccf04b3dbbceeeee7c3c103e2e4986cdd702518d7ad9776e69c6850b0cb642899e3df", + "dest-filename": "dot-case-3.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88", + "sha512": "40cf2adf30dee7c86a52a8eb6903a6cd9d4b207f525902539442821f8909da842f2d993b45b417bed0ccd9712addfc2457d082bef1f82c0d0057ea2016c04cd9", + "dest-filename": "dot-prop-5.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083", + "sha512": "b44ef3b58cd71c87b2bdcecdfa1477a22ec521b7ff3488d53fd86602ddf2317ceb434ef6fdfa6318bc761b13711b1525e55ef7304a98ce2a0e32856118c27970", + "dest-filename": "dot-prop-6.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0", + "sha512": "617425d4349ae3f3d0c917e0aefe9aa0d8e16aca7fa78aacf458c9e2ae1c424fbc9b8afa938652884cb2b4a1bc7fc5bd822f16b10b4839b36629dfad33335398", + "dest-filename": "dotenv-expand-5.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b", + "sha512": "22b3dd5d0b24d816f3bc204604e4e69921f94a8766a9936de04440643996e024feb4bf15b6f8a7ab2c2e00d685bb86ce316922d7a9ea7f47b8a02d1021a0ebfe", + "dest-filename": "dotenv-8.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05", + "sha512": "23d3afbeb1e9e2920046fe3ec7d8ae7b0ad6c9c5fa09c66da00bb55ebccfc5ce54ca03095c9658981b329e4bbc224ac9c20ca91390c63630cf98f4610c2a6d52", + "dest-filename": "dotenv-9.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6", + "sha512": "8ed0fa606dfbd190888bff464da24a431593643d38e7ee11e214e4ff1d54ca8a9a77227dc7d0a04a2d519550d017c536b312cb4a716409a32286a9631c85a032", + "dest-filename": "duplexer-0.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2", + "sha1": "ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2", + "dest-filename": "duplexer3-0.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d", + "sha1": "590c61156b0ae2f4f0255732a158b266bc56b21d", + "dest-filename": "ee-first-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a", + "sha512": "f65b7d66c7b884fb9c3e4a0fec51c31742d00251b217d255a670a514b147dda4926f19b2a2a20d469a7ff7078f5894d497828e43044bef6230dc89c73c39281b", + "dest-filename": "ejs-3.1.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-builder/-/electron-builder-22.14.5.tgz#3a25547bd4fe3728d4704da80956a794c5c31496", + "sha512": "37bde149b5c5cfa333e59ea1e82e65cba081f9d50dea4d4bb820c98c8f15178edb317bff404d0713e2a46f418f2aa4ea33b1ec93fc88617fa41c27d2911e451a", + "dest-filename": "electron-builder-22.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-devtools-installer/-/electron-devtools-installer-2.2.4.tgz#261a50337e37121d338b966f07922eb4939a8763", + "sha512": "6f991c33786652a9fae3e4547078e3afc64ca474b6589e583b4a671bdf8ffd14ddc78ea87ff26b123b9c8875aec7aa44f8e9faca75a11c9179de3fc40c93743c", + "dest-filename": "electron-devtools-installer-2.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-fetch/-/electron-fetch-1.7.4.tgz#af975ab92a14798bfaa025f88dcd2e54a7b0b769", + "sha512": "f9f04b5c4cb8089590e5bcfc77269e486d610fa249d799016728f77a1db8a4856b77784b338ec7fee99f7eb7507d2e866747da945d20f494fd7f746ce8055487", + "dest-filename": "electron-fetch-1.7.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-log/-/electron-log-4.4.5.tgz#5fcfd0c2dc5fbda915ee0a9d802705dc57930786", + "sha512": "09f6b608a9f00619547c897faabd86179482a9fa00f723c1a9327aff03ecf8f127dfa336f8467746919268e858435059a6894bd425b27aede0306f1ea4b97736", + "dest-filename": "electron-log-4.4.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-notarize/-/electron-notarize-1.1.1.tgz#3ed274b36158c1beb1dbef14e7faf5927e028629", + "sha512": "92e7ec9ea87ce824d7f3d018346dcd08fa1ba2a9e4bbffb7d91c5e276fbb03845b9b86db3b1d0d73b5d3cb7fe002505fa63f713c0c477e164b38781f8ba70957", + "dest-filename": "electron-notarize-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-osx-sign/-/electron-osx-sign-0.5.0.tgz#fc258c5e896859904bbe3d01da06902c04b51c3a", + "sha512": "89ca112c7cc5cffab1cc387f3783e2db3e32547bab96c080610bec0921bb7c279d2785095c14ba3e8432187ef521f72a2aea5c29e2bb1d7fcd9327c6fafeaf95", + "dest-filename": "electron-osx-sign-0.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-packager/-/electron-packager-15.4.0.tgz#07ea036b70cde2062d4c8dce4d907d793b303998", + "sha512": "26bacb7013f5e4a1ab3e3d1c67f00b28699a438809927de6a1c7f41376d129d47793129661c0d1a42bdd864b180d7c3faf723ab4c11c67b5f3c80a56157755a7", + "dest-filename": "electron-packager-15.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-publish/-/electron-publish-22.14.5.tgz#34bcdce671f0e651330db20040d6919c77c94bd6", + "sha512": "87e34035175a0343ea185d7918abe8aec7963f38753d76bfcf1e08dfbfff3c8a245bc78a228bfc932db77e85126f9e591565071a9c5026ec7bcb63427c1b507a", + "dest-filename": "electron-publish-22.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-store/-/electron-store-8.0.1.tgz#9b598c1d2edeffebee9d8c1cd957ad368c528925", + "sha512": "6722ef372c22a92a5bc02fe9a7cf4efc0c9c55663f5092249adcb317605dd0d9bfacb99c15cd0d4c6b8b760ebe2c4f264bcaac88ae493287b83e7ade70b1c7e7", + "dest-filename": "electron-store-8.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.57.tgz#2b2766df76ac8dbc0a1d41249bc5684a31849892", + "sha512": "14d0be3f92b59faa45f8cd3320afa0142a17709861cc35622f70d1206cb616fe4fa21b92112d491d1ed3f86970c52c65cf1e3261bb2ecc266f1f17014910883b", + "dest-filename": "electron-to-chromium-1.4.57.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.1.tgz#80ca805c4f51b2e682aac29d18fed75d6a533d32", + "sha512": "62c535987a972eb5d798132cc61c72db83eb6da07cae7a590cf9856b680e913624fc2875dfe4747e3b114a93d8beab6c915558d2ec7c7eef879d491592a73ba2", + "dest-filename": "electron-updater-4.6.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-webpack-js/-/electron-webpack-js-2.4.1.tgz#5389cc22f34c71f6416d5ba1e043f9b0fd6130af", + "sha512": "34f6dc2389e7b9c9642c42a6c1123cb2e8b618d7b7ecd2a6d2909047a29903b612577290747e08ef03a0219d8091e0a9c9e507ac148c19063e56a84f0fb3ad30", + "dest-filename": "electron-webpack-js-2.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-webpack/-/electron-webpack-2.8.2.tgz#5a0357ce8f7d147e5f559294a08bb072d1092b0a", + "sha512": "ad1ee1c683a56487097fa474f26565ff84c1b4563e1d6eacbf8676f1374c5844ef70ce1904805d18d1b297117480dc01f20913828f149240db5c65f8f0ae15a3", + "dest-filename": "electron-webpack-2.8.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/electron-window-state/-/electron-window-state-5.0.3.tgz#4f36d09e3f953d87aff103bf010f460056050aa8", + "sha512": "d66353c027e4a255e5de431fe74c96def1369598f4cbdd8ffc7616141adbfafd92fe90a46b999dc0dddc6a02a6e39f00ecd8e7752c228f29d781c2d646876c56", + "dest-filename": "electron-window-state-5.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156", + "sha512": "0b004b444210ecbbd8141d16c91bf086ae4de6a3e173a3cc8c3e9b620805948e58c83825fb4bf1ab95476cc385a8b83b85f5b39aef13e59d50a1f8664c8848b4", + "dest-filename": "emoji-regex-7.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37", + "sha512": "3128d8cdc58d380d1ec001e9cf4331a5816fc20eb28f2d4d1b7c6d7a8ab3eb8e150a8fd13e09ebd7f186b7e89cde2253cd0f04bb74dd335e126b09d5526184e8", + "dest-filename": "emoji-regex-8.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78", + "sha512": "fe4c8cd7c11f8a7c1765b9e8f45c9419e161f3b282f074500501a295d1d96c4b91c9614e9afd54d74a3d041a7c5d564354d36e40ac88188bb96580005c9d15d9", + "dest-filename": "emojis-list-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda", + "sha512": "b9c027b8112150ae1ba07d878d5606e50da64323e8aefbf4bbfa1c4bece1770d12f00947618f8638584fd468a8e73e227293f68af152be1b458d08bcf93f69a7", + "dest-filename": "encode-utf8-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59", + "sha1": "ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59", + "dest-filename": "encodeurl-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9", + "sha512": "11305aba8c354f7e58fd664c922a3d8e2334679c631c7989e179a364eab597f757cf796bdac467f3b9c9cb6d11ba9a928751769b71c73d2a7c4a120f409ac9dc", + "dest-filename": "encoding-0.1.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0", + "sha512": "faec358a720754f428695b87cd1c97776d6270cf9c9ede02cc3e6b5be342d708ce5124ceb3e4deec53afec084deef4bdc7fa08ca12cfe4f4751fea614001eee5", + "dest-filename": "end-of-stream-1.4.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec", + "sha512": "36ff66dfa4bfbf1a6c23e1dce3f64646cd27f665ea496186ab8f73c5bfdc25f3c040c6d4b6db4902534f4b8010cda05dc3fa4ab24c396cc6de913fd8ed6fd696", + "dest-filename": "enhanced-resolve-4.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0", + "sha512": "10601b1af1fb8fb5edda773413b0fdf4b6b53a212cf0b9f28a6911830131a5431270de8efb7c7db485acecf2d0655371e180fed34b241d73d78b5c901e902664", + "dest-filename": "enhanced-resolve-5.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55", + "sha512": "a7dda27f9373eb5f48d30f9a909acb647d0c5f43dbe435f7f573b0413b5749d41039a607d374b5b88429e2684e66d017af1ab85623baed84e22c1a36eb7f28f4", + "dest-filename": "entities-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2", + "sha512": "fa1d6590b2a164c4d88e8835544a49346ecd64959cb9cd830e4feab2a49345108e5e22e3790d5dd7fb9dad41a1a8cc5480097028d67471fdaea9a9f918bb92d8", + "dest-filename": "env-paths-2.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f", + "sha512": "749ea806be5243555277daa493b0724606ffd521f82598c21d25bf9abeb7fd07173bdccb571bc9e8ecb5de78a8d37af1a529d50c38c5a2bef94a355e6563d6fc", + "dest-filename": "errno-0.1.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf", + "sha512": "edd147366a9e15212dd9906c0ab8a8aca9e7dd9da98fe7ddf64988e90a16c38fff0cbfa270405f73453ba890a2b2aad3b0a4e3c387cd172da95bd3aa4ad0fce2", + "dest-filename": "error-ex-1.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3", + "sha512": "daf27ab6303f51fa8b9b630fb3b8f15726cba01f22d6dd4977d4779084a5776d2c2313dc4db2ee82040e531796780bc852476ebff09f323ba1e169a25ebdaff7", + "dest-filename": "es-abstract-1.19.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19", + "sha512": "d47436336b0fb71c27bcebd3d590a51f24038a081d3635115a9636c1ee9a30a0908945714e656cd9460f2c8ac3f38b12fa431d5307c14b295b24fc0d9c1ae71d", + "dest-filename": "es-module-lexer-0.9.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a", + "sha512": "4023a5960649b5a528f6689805c2c285351a1cd8c91773d8b35562743ec0c22123d6463129e41372d2c07b300e1f964a447d20d8880f9fa2b0078213f22469bc", + "dest-filename": "es-to-primitive-1.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d", + "sha512": "526ffe17132bf422125a1d1b8b966fd22383fb8705879a8b7a4b35aa1028a4a540270dddae029b2b24a2929ef01a10cbd073de6a36b43f950b66bc4b92789456", + "dest-filename": "es6-error-4.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40", + "sha512": "9347abda05242dff0ed332898808669139c9953bc8346bfbca00cd3db788b17fd3263189647ba1f41d94c5bb1a1249a5128f4c7e1ad2ce68489614652361979f", + "dest-filename": "escalade-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675", + "sha512": "f3fb8885b1b5d82b23cb62445bb0fda476eb79a55a4bf3a9377c9c9f2bc49537703399fa198e96e9ed883de99fbc665e50ca99f40ff71aa2193202a7061030fd", + "dest-filename": "escape-goat-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988", + "sha1": "0258eae4d3d0c0974de1c169188ef0051d1d1988", + "dest-filename": "escape-html-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4", + "sha1": "1b61c0562190a8dff6ae3bb2cf0200ca130b86d4", + "dest-filename": "escape-string-regexp-1.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34", + "sha512": "4eda5c349dd7033c771aaf2c591cc96956a346cd2e57103660091d6f58e6d9890fcf81ba7a05050320379f9bed10865e7cf93959ae145db2ae4b97ca90959d80", + "dest-filename": "escape-string-regexp-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c", + "sha512": "d8dc706c5fe16742a97a960dd1c35ba3e14de97a0aec6687950860c7f848665e956b46c5e3945038ec212c8cbc9500dbb8289a7522c20671f608562aba2b796f", + "dest-filename": "eslint-scope-5.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71", + "sha512": "786b85170ed4a5d6be838a7e407be75b44724d7fd255e2410ccfe00ad30044ed1c2ee4f61dc10a9d33ef86357a6867aaac207fb1b368a742acce6d23b1a594e0", + "dest-filename": "esprima-4.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921", + "sha512": "2a67ca2f76fa1be457bcff0dd6faf74ead642ffa021609f63585c4b6a3fcfcbde929aa540381bc70555aa05dd2537db7083e17ca947f7df8a81e692d8bafd36a", + "dest-filename": "esrecurse-4.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d", + "sha512": "dfd9e729f7d6cfcc4dd4153fd9cefd9fd9c1f470f3a349e2614ab1eb1caa527ca8027432c96a4e4dd6447a209c87c041bb9d79b78c29f599a055f5619fd101a7", + "dest-filename": "estraverse-4.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123", + "sha512": "30c74046e54443388d4de243f0380caa6870475d41450fdc04ffa92ed61d4939dfdcc20ef1f15e8883446d7dfa65d3657d4ffb03d7f7814c38f41de842cbf004", + "dest-filename": "estraverse-5.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64", + "sha512": "915b1ca97938382a7af126747648042958baffc8a3df4d0a0564c9ab7d8ffdd61e5934b02b8d56c93c5a94dd5e46603967d514fcb5fd0fb1564a657d480631ea", + "dest-filename": "esutils-2.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887", + "sha1": "41ae2eeb65efa62268aebfea83ac7d79299b0887", + "dest-filename": "etag-1.8.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571", + "sha1": "4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571", + "dest-filename": "event-stream-3.3.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f", + "sha512": "f20b870590b02a716161d1ebdb2b2e45612b4f08683765fc5c42d196b470a667de6368e3b94378b5a40cb142ca515a352b80ef665fb4a607f2a32b07c6f9af13", + "dest-filename": "eventemitter3-4.0.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400", + "sha512": "990c3ed9f9106c02f343b574318d08a9d9d734e793b4fe2bd2537dcfb0006b009782a79aedb0e28b6d0062b201ac577f1f1d0cd8e733e92d75d4268591471bd1", + "dest-filename": "events-3.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.0.tgz#00e8ca7c92109e94b0ddf32dac677d841028cfaf", + "sha512": "5522634f9a0236b16f092ea2823ccf02de61073436a8f04521b274df32c8f521349b1c19a4cc3a05f26b6c51e6d5ad78d406af30407c24798185601deba3df0a", + "dest-filename": "eventsource-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8", + "sha512": "69d6f1732595e3aaa21f2bd2a79d132add39b41e2d2b71dc985eff9f17c07619e8c7cdec7930dbc276aa28ee2c5d1cbbae81c0205a893ff470fc0b846d7eb52c", + "dest-filename": "execa-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622", + "sha1": "b77735e315ce30f6b6eff0f83b04151a22449622", + "dest-filename": "expand-brackets-2.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502", + "sha1": "97e801aa052df02454de46b02bf621642cdc8502", + "dest-filename": "expand-tilde-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3", + "sha512": "a31971271710958c2a3d6295249b6f422c07828b07fcbacb48f03e1f8531a72bd24ba8c2e5a1fee4ca0714cf8a0018133add003ee7b8c3ae876bc8c2528f501a", + "dest-filename": "express-4.17.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f", + "sha1": "51af7d614ad9a9f610ea1bafbb989d6b1c56890f", + "dest-filename": "extend-shallow-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8", + "sha1": "26a71aaf073b39fb2127172746131c2704028db8", + "dest-filename": "extend-shallow-3.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543", + "sha512": "3666fa4179042ecb81af6e02252922968e941c781b7a42b95226607c4e941c3dc46f6ed80baa03f9b85c4feb49e9c97c766b20750c675a572bcbc92c04804ba7", + "dest-filename": "extglob-2.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927", + "sha512": "c688791b55bf3c1d3fdbb95780c4322213f90d263f2e1a02b0ec9981bfba88c991b42c15068e79b8a68ca0462b0c2290856bea122a7964f28073a7853727ff30", + "dest-filename": "extract-zip-1.7.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a", + "sha512": "183854f67b70b8ac865dd6415204c87bebd79d68f47e9a5412d3032f4fa275de52b5af131a91ecb27fdebac03d9ab3ebf6a343ca6e92c406198cdbc29fff5106", + "dest-filename": "extract-zip-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07", + "sha512": "5ab937e5ef327422838ff02b0a5a3556b3d598df33a61e55e00b47c08b8786f317b0a7fbdd44f704e0fe6b30485bedf0389e058441fbcf2689085bc286362f30", + "dest-filename": "extsprintf-1.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525", + "sha512": "7f7a90f68432f63d808417bf1fd542f75c0b98a042094fe00ce9ca340606e61b303bb04b2a3d3d1dce4760dcfd70623efb19690c22200da8ad56cd3701347ce1", + "dest-filename": "fast-deep-equal-3.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633", + "sha512": "96177fc05f8b93df076684c2b6556b687b5f8795d88a32236a55dc93bb1a52db9a9d20f22ccc671e149710326a1f10fb9ac47c0f4b829aa964c23095f31bf01f", + "dest-filename": "fast-json-stable-stringify-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884", + "sha512": "5be28973676620b94fa650ff1f82bd97d2dc00701f3ed3fa058f38b952d743a12f733f4b720df7636cf52156e54fac5d639e0f5d854712ffb45a9abc228eb390", + "dest-filename": "fast-safe-stringify-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da", + "sha512": "0b36c297095702e891400954c9fa8f82f3e834a4dc9133c67f0655e1974085570fda587d294c498366f91a413b5db8ca4376099d0f73e83f67b4b02507eb4ff2", + "dest-filename": "faye-websocket-0.11.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e", + "sha1": "25c7c89cb1f9077f8891bbe61d8f390eae256f1e", + "dest-filename": "fd-slicer-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e", + "sha512": "d1bb6723f1fc7f6a5abc630df30e349a548a39f4cad925499817c1795223de4370d2cc30833c91ab47794c954ec287459adbe93de58f37f30271fb961741336f", + "dest-filename": "figgy-pudding-3.5.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d", + "sha512": "aa8de096ac936bad58b60e2eef71ae96d8c71a3751ca2837b46ea53edc97fe338426f1e27fdb81d3f3822362a27fa72d17771a4135b61b98329b6d6802c238a7", + "dest-filename": "file-loader-6.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/file-type/-/file-type-16.5.3.tgz#474b7e88c74724046abb505e9b8ed4db30c4fc06", + "sha512": "b95b25ee21611d2398e1b10e34b9532b8ee2007b4db051d63f9604e3125f678ae75fb4b5437c1c7b4f5782a482ec4ff187c35cbff6ded65368ca9ae5507ff1e8", + "dest-filename": "file-type-16.5.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd", + "sha512": "d19b7eb372fb55fd5b8b0599dbd6804625582f1ee23069c4525f71df77db07f8f78d1f35bbf3b62dba8af819b508348d0ca56d27f623c18ed351de5291e2d02f", + "dest-filename": "file-uri-to-path-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b", + "sha512": "cfb3b4212f0f95cdfdad30aaea2ea21f1938dddb983a7f2e14989649ec08ab4070c3544dc9b5474828da866702f3b66a026e0e4ef173973786bb75c0cc6d5cb5", + "dest-filename": "filelist-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229", + "sha1": "abf73dfab735d045440abfea2d91f389ebbfa229", + "dest-filename": "filename-reserved-regex-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/filenamify/-/filenamify-4.3.0.tgz#62391cb58f02b09971c9d4f9d63b3cf9aba03106", + "sha512": "85c14ac941b9ef2586033bb508cb7f74fcd866ebfe8c02544fce5b2fc9ab5ef35eea15a3eb210711ce0475c82203a677a22d7ff705c97593d7176759360c203a", + "dest-filename": "filenamify-4.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7", + "sha1": "d544811d428f98eb06a63dc402d2403c328c38f7", + "dest-filename": "fill-range-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d", + "sha512": "68059c5b9eeec5536b419a855e3213a56dec2144261c61b7a926fd9946a1f4c80c0b835e5a134e94d8d7118ab71e3440bcbe9aad4be2646189b0183acf4cec58", + "dest-filename": "finalhandler-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b", + "sha512": "c17655e5e985123aeb89d220103d753a850a2f18988c072aa2dfcd25d0243a1949faf1b3c213807dc1b9397d633fe4b43dc8c49fc6dd309bfe8368f04373a78a", + "dest-filename": "find-cache-dir-3.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7", + "sha1": "45d1b7e506c717ddd482775a2b77920a3c0c57a7", + "dest-filename": "find-up-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73", + "sha512": "d720fa4662c8d5705fc6e82f391c25724e9fef9b582fe891d23ab0b0eacec4c672198a94b83849d25e005dd3b5897fc54ecf5c040304935816484c759126f296", + "dest-filename": "find-up-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19", + "sha512": "3e93b001d43f6255d0daf8fc6b787c222a43b98462df071e550406616c4d20d71cab8d009f0ec196c11708c6edd59b7e38b03a16af6cb88a48583d0eb2721297", + "dest-filename": "find-up-4.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1", + "sha512": "61b7df6ab85c89c1213ab9b80adaf074a05d0aecf9efa44b761243b087ef36dc54ba17517add6a65cb0c8ea6de3ed02c78a7409c3c8cfc8c976eeecf44f44b62", + "dest-filename": "findup-sync-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/flora-colossus/-/flora-colossus-1.0.1.tgz#aba198425a8185341e64f9d2a6a96fd9a3cbdb93", + "sha512": "77ef676bbb7d1721fc8012683434a2dbc984e0d8105461afc50e1a1ed1517ad8f28794978eebacf95e4465ac4598575755e9923abc7496c80497f64c8e739624", + "dest-filename": "flora-colossus-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685", + "sha512": "fa16f1a0b6c531b44a0f0a215fc1a44dab5a1aa3ba25bee31b0a40970832d9b233db95ed466eca13324cefa4755a2353e52c19917e18ef94b0068964a6613b89", + "dest-filename": "follow-redirects-1.14.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80", + "sha1": "81068d295a8142ec0ac726c6e2200c30fb6d5e80", + "dest-filename": "for-in-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452", + "sha512": "1131249521a2e6dd10319ba25e803f43abdc9f170b40fe6f76e812a6e0328ba4951a2d9c94f3e9fb180486e31a1c2fb31a09f7d4a776df95b7e5fec7ca491ac3", + "dest-filename": "form-data-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811", + "sha512": "6ee446d1fa41b511d24c238049eea10f6e7cb44b9b16844b6f864d03a3713151cdc3680e7301e8f70c9a6e5ccccce039cfdc40f4bd4a36393f36de8c4fd698a3", + "dest-filename": "forwarded-0.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19", + "sha1": "4290fad27f13e89be7f33799c6bc5a0abfff0d19", + "dest-filename": "fragment-cache-0.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7", + "sha1": "3d8cadd90d976569fa835ab1f8e4b23a105605a7", + "dest-filename": "fresh-0.5.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe", + "sha1": "83c60afc58b9c56997007ed1a768b3ab303a44fe", + "dest-filename": "from-0.1.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1", + "sha512": "0b9a306f5e2ef5e2708b328675c85c0d441e16d9521c7b61064f296d7f557353c566b2e899bb9d8c39cd9ecf3c698b250b217a218e52530dd1a33eb14a170421", + "dest-filename": "fs-extra-10.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94", + "sha512": "abaadb743775a369809d0ade3bb6000c8c5ffd6871e001c18917fa77efdc553f21e38b2cfa51e0c5fd457a672a0e742df57ddcb7831c1ebf893069584ac2bb0a", + "dest-filename": "fs-extra-4.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9", + "sha512": "6090da0896449c199c6f0d777ef74033d03034e2703b3ac4e29a8ca81ab99c5884a9752a1f094ae01fb7a54c3a24dbdf48fb57d39c451ed632ff59e2d357860b", + "dest-filename": "fs-extra-7.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0", + "sha512": "ca1950800ea69ce25428eb11505b2025d402be42a1733f2d9591b91c141f45e619cb8e8ec0b718f9989ad26b5d1ec3a8f72fe13fe0b130dd1353d431a0eb46e2", + "dest-filename": "fs-extra-8.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d", + "sha512": "85c8376667a94b7d3fec1485a91be8a370ce310bbb223ab13b99c20edfb333d5d68dbdf75a0ef388d4fe42fa9bb9cdfe816a733b4d89b9b5729361b866fa3539", + "dest-filename": "fs-extra-9.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb", + "sha512": "57f26038b1424be47a55cab4b250ae69e58474d0b7a2e0e524c348b1a707d95b402e2bbd995e0b3eb1dce5c0e5f24e5ac3a27c8f08165a9893a39458866233be", + "dest-filename": "fs-minipass-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9", + "sha1": "b47df53493ef911df75731e70a9ded0189db40c9", + "dest-filename": "fs-write-stream-atomic-1.0.10.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f", + "sha1": "1504ad2523158caa40db4a2787cb01411994ea4f", + "dest-filename": "fs.realpath-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38", + "sha512": "a166f567a9a41c8b242f3109fd7597d2cae4a644d0eef6a8a4c424c9a108a2ad1f9ad155c4eb616fc702c5e4fea77ca74dd924fd16706e01b86eb47905e5840b", + "dest-filename": "fsevents-1.2.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d", + "sha512": "c88a2f033317e3db05f18979f1f482589e6cbd22ee6a26cfc5740914b98139b4ee0abd0c7f52a23e8a4633d3621638980426df69ad8587a6eb790e803554c8d0", + "dest-filename": "function-bind-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/galactus/-/galactus-0.2.1.tgz#cbed2d20a40c1f5679a35908e2b9415733e78db9", + "sha1": "cbed2d20a40c1f5679a35908e2b9415733e78db9", + "dest-filename": "galactus-0.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0", + "sha512": "de137b35ab2462f3032d0639e609d6dcd43e99eb0401ea53aa583e5446e3ef3cea10c055361cdc19861ea85a3f4e5633e9e42215ca751dcb0264efa71a04bcce", + "dest-filename": "gensync-1.0.0-beta.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e", + "sha512": "0f214fdc133fdd81d340e0942ffc343991d1d25a4a786af1a2d70759ca8d11d9e5b6a1705d57e110143de1e228df801f429a34ac6922e1cc8889fb58d3a87616", + "dest-filename": "get-caller-file-2.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6", + "sha512": "91666b9d5338d900a2100d888356c6f338e820c3a0c56c1808478d77063a4effdc392786a5ca17e295c77ca53134a56802b9eb12bd9ef6cae7031c4622b692f5", + "dest-filename": "get-intrinsic-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/get-package-info/-/get-package-info-1.0.0.tgz#6432796563e28113cd9474dbbd00052985a4999c", + "sha1": "6432796563e28113cd9474dbbd00052985a4999c", + "dest-filename": "get-package-info-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193", + "sha512": "83f4356934833b11697215c2e22f195afc40d659cfab1fc91ea729230d3f2d7f53f31fc605b8ba62794de6785a2881644fca05b2c7142a00c96317f07d2e90b1", + "dest-filename": "get-port-5.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5", + "sha512": "18c6ade04279d7ad64232d877af2e5af896e363060be68f8d7729a400ee3b7857c078443b1fa4793b590f4656a7d8cb2c7c392fcbeba2a8c7eac944d9252caef", + "dest-filename": "get-stream-4.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3", + "sha512": "9c117e175ac06550aefe9eeb8f3800f986f895f617ae997b6ba56626b53cc05f48d422af3ff4303cd6479ce9706d3918e9dbed148cc5312c905db2e84d03d1a4", + "dest-filename": "get-stream-5.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6", + "sha512": "d8499d1f562f210899a65b4236092e8949f2ba4cf133f47a343257df529edc11b536ae5bd12d8f857e7d50a8bdbd9a4f0d055daa7fb521c680c27cd34f9bc28f", + "dest-filename": "get-symbol-description-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28", + "sha1": "dc15ca1c672387ca76bd37ac0a395ba2042a2c28", + "dest-filename": "get-value-2.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae", + "sha1": "9e6af6299d8d3bd2bd40430832bd113df906c5ae", + "dest-filename": "glob-parent-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e", + "sha512": "9645f51c95f0c8c729af0ff961465cdacec3ae90221c1db5fd5f84d6b1d4ad5368924bc1e9ba8ccd3d157d5ebff3a64d69bb75935e18388693ee70ef397dc88b", + "dest-filename": "glob-to-regexp-0.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023", + "sha512": "9662dfea0b72acfabcb538d29ab3bde3005e41b151dc76cb1dbbb20faf70bb2424226a76856a8c181e3b397eb914190f7df3bae3520ff6359ad73e22bea1b6e9", + "dest-filename": "glob-7.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/global-agent/-/global-agent-3.0.0.tgz#ae7cd31bd3583b93c5a16437a1afe27cc33a1ab6", + "sha512": "3d3e9745e27e0f4ec9bc6a3140c913eaa8e2fe354d7d7fe1dfae171d9396791cf2eb8b1216bfb1279397ecb2376f830f43374be07f18f0cd31ccfa6c54cc00f1", + "dest-filename": "global-agent-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686", + "sha512": "bfc868d834b94620a37ed8f59c3f4d9a77da3b34ddb9ded146755df6414d3a3a996c84a5c790d0f8ead3932c20774748b7ba050af29eb59487a0770fdec0dd88", + "dest-filename": "global-dirs-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea", + "sha512": "b0ace91247f5d46a4e16ec346738f39ade01e146708ce706ef9ecf3efadf87170b15bab4c29b20a4eab1a71b71162086e03b46f7733a5d155b176a0675ebfb6e", + "dest-filename": "global-modules-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780", + "sha512": "3466df989069f71f08c722527753fea2d60af2fa27a0969cb4ea20ad57c5448004635ba48a5f1148a0f3d98a3bc21d688a1979d65febe96e1ea6478a247a8bf0", + "dest-filename": "global-modules-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe", + "sha1": "dbf743c6c14992593c655568cb66ed32c0122ebe", + "dest-filename": "global-prefix-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97", + "sha512": "6b00a89c9495087546343eb1ded98c68a710bf05cb8637649a89b2d96f86a1aba2f183e06205c965ec218377d60be0e57eaa90b9683c030aa31930f69c03d55a", + "dest-filename": "global-prefix-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f", + "sha512": "e2cf83c9c896055d1e2b5e3cc2a5f17265406c554faad737b04b5413f19341fb94f34af248b70c8549872921c8eff2c38fcab4803608d6522145107b89e440aa", + "dest-filename": "global-tunnel-ng-2.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e", + "sha512": "58e069fc410652222c252a7bc1cbffcba30efa557d5289dc5aac6e15f9bc781c3358d8327c177a1b3f8878a43d8c29b28681fdf60d793374fe41a5471638b354", + "dest-filename": "globals-11.12.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.2.tgz#2a235d34f4d8036219f7e34929b5de9e18166b8b", + "sha512": "6509d214ed656bc3fb6ae20e4040a79b4b12ba831e692ab4104757301145d9024ee2e35cc1bca14a01b732bb9635b153a822e6c55c063a5ecb67d9004af1dd79", + "dest-filename": "globalthis-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c", + "sha1": "f5a6d70e8395e21c858fb0489d64df02424d506c", + "dest-filename": "globby-6.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/got/-/got-11.8.3.tgz#f496c8fdda5d729a90b4905d2b07dbd148170770", + "sha512": "ee0b50e4a88f87546d192f7f25bbf5a1f0e9045baae368327c489bf9e8da44126e8ffded405791e7e830e7b7b88a9694f1cfeb0a3bd7e9f910cf69720e51803a", + "dest-filename": "got-11.8.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85", + "sha512": "47b796a6d5ee198c708a3b34795fafde8ebe5c7d48a952bc74938479c41f4e6927730f4057875cc3f0e1c62f0c765a8fb61c71a59ca2ccccf283c453984b06f9", + "dest-filename": "got-9.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96", + "sha512": "36d371a947178295b688cadfa927d1ef71a5b77f4af812f05ac3ecf78c91eb7bf8e53d166de8fb79198be5c59fc0482a5e79a3429df36894ec85d456fea0b665", + "dest-filename": "graceful-fs-4.2.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725", + "sha1": "4cafad76bc62f02fa039b2f94e9a3dd3a391a725", + "dest-filename": "graceful-readlink-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e", + "sha512": "f509f8c81c5e971a21d8ec3ada73fe29afe4327397462f015e745a5307b32cd86a7a59cde3dc4acf817f74f3fc3982f12f1aba243b596f68bd5f39d441b34f4e", + "dest-filename": "handle-thing-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113", + "sha512": "2d2052d8b8db3414dfeb6f3b2446c4cef2607ed905e6a164982a3d8434690332a150e949fa1c7c75de144acd344a0b14370738eb5ec9f648b962d10294cd9f7c", + "dest-filename": "has-bigints-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd", + "sha1": "b5d454dc2199ae225699f3467e5a07f3b955bafd", + "dest-filename": "has-flag-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b", + "sha512": "1329094ff4352a34d672da698080207d23b4b4a56e6548e180caf5ee4a93ba6325e807efdc421295e53ba99533a170c54c01d30c2e0d3a81bf67153712f94c3d", + "dest-filename": "has-flag-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423", + "sha512": "7215daefdacbfd40b62a55f5ee3a37bd11b3d1acda584c79b46a99839a4edcd532109541d7b74caee425cc208e7d4bc496084a726e75f78f81091be2d91bff1b", + "dest-filename": "has-symbols-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25", + "sha512": "9058dc48d867946575932a0693b3972926b01f924e6ff2f351ce70f41d3684e4ced1d7c54636c740abe0d5de9c7f71db7949ad53d55b6d5deacd9d937a1f7b59", + "dest-filename": "has-tostringtag-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f", + "sha1": "7b1f58bada62ca827ec0a2078025654845995e1f", + "dest-filename": "has-value-0.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177", + "sha1": "18b281da585b1c5c51def24c930ed29a0be6b177", + "dest-filename": "has-value-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771", + "sha1": "6d61de95d91dfca9b9a02089ad384bff8f62b771", + "dest-filename": "has-values-0.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f", + "sha1": "95b0b63fec2146619a6fe57fe75628d5a39efe4f", + "dest-filename": "has-values-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77", + "sha512": "52a051aa2e23bbb4fe4ea18d76a00ed0f692546b0318950142f93d79458d191635085183cd884b5a833b25011e9a796f55cbff60499cdb0356f010b6e049d4b3", + "dest-filename": "has-yarn-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796", + "sha512": "7f676f3b4554e8e7a3ed1916246ade8636f33008c5a79fd528fa79b53a56215e091c764ad7f0716c546d7ffb220364964ded3d71a0e656d618cd61086c14b8cf", + "dest-filename": "has-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f", + "sha512": "17fd439d418fa29391662d278be0afac28074391721001d12d2029b9858c9ab6d2c28376327ffb93e1a5dfc8099d1ef2c83664e962d7c221a877524e58d0ca1b", + "dest-filename": "he-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/hexy/-/hexy-0.2.11.tgz#9939c25cb6f86a91302f22b8a8a72573518e25b4", + "sha512": "722aba845b121bf069b760e6ad926dbfee7ace93dd9eaf8d4388a3105aef78a374646d66865fcb753d4d419f6c7bab72d5f002708e1de2f62a0bdbfc118a47d8", + "dest-filename": "hexy-0.2.11.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8", + "sha512": "7929a6584e5b6532b6368bb8834008df367daecc29ec644aa0a5d2d412d492f3ef88eaace184cdd5d8d022aad7cbd939804b5d2cfcbce898d1c2c34cf6d9c370", + "dest-filename": "homedir-polyfill-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9", + "sha512": "9b120301bf4bb26e83a0e27bc47fb9f97e32d4b53fe078b9d0bf42e6c22cc0adc9cd42d2e1bc24d45be374182f611e1bcd3e2db944220b5e451367f91db2ef63", + "dest-filename": "hosted-git-info-2.8.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224", + "sha512": "9320ae10e5a326a66e0db447ccbf15f77373421c0807bd681564b2cd5a3e28f648fa99d03cfc6e71d92b399be42d19eb7f9511b1033e209d3d0f0dbd71100b20", + "dest-filename": "hosted-git-info-4.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2", + "sha1": "87774c0949e513f42e84575b3c45681fade2a0b2", + "dest-filename": "hpack.js-2.1.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc", + "sha512": "f27c6370171df30a2f6de2b1ee1df04e38b87bafab85a56e3cda4cab05a09c787e37d4e8aac0ace97ced59104f43e52dceca0c01d299b5410da15cd4fc432d64", + "dest-filename": "html-entities-1.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/html-loader/-/html-loader-1.3.2.tgz#5a72ebba420d337083497c9aba7866c9e1aee340", + "sha512": "0c4914c12774b228cae4f1779115aca588b9e973fb6d3364ca0e58592cc17636920e6bc2b9f7a9e5ce15a5bdcf05fea550bd183ed2f005fcbd7cbd2de6104018", + "dest-filename": "html-loader-1.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054", + "sha512": "64faf930d39baa757f4fd6a4b213ca6d58323aa2e6cbe071a3b8ee2827d37e78cd9e24c031dcb8873db5610aa8a1f301243da475111aa8f3dd4e1a11efc4e0c6", + "dest-filename": "html-minifier-terser-5.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz#76fc83fa1a0f12dd5f7da0404a54e2699666bc12", + "sha512": "ab9a187738ca5083d05633a8b2382f08740ebfd12db7d098607960bc97971b4a90bdd4a88e706ae2f01d401c27d7ec86bde0301c2a1efeb311f3aa335f7f9cd8", + "dest-filename": "html-webpack-plugin-4.5.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78", + "sha512": "e330ead5ad73844e2042ca3f7392cfd4eb6b8584e7717352a6f258b56241b570044cf94c7e2dc814d8c6b906d82ee558e1947440ca9156fa383ddcbd28bc8ff1", + "dest-filename": "htmlparser2-4.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7", + "sha512": "832c8f93aae0a272c51031a879181035a114bdd27892d4e699487f876b7bb3e33ca0fa483f180d00259afba112479ee45ecb70a8f882badd15f0d469730814ec", + "dest-filename": "htmlparser2-6.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390", + "sha512": "71aacf92571487b44e5912bb0afdbb44fb5d858854b1e95afee7b9fe32b38de815bd70ea33620b13d4360469fd259261d60f3b729e7ab2efc58104b37164bc71", + "dest-filename": "http-cache-semantics-4.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87", + "sha1": "fa7168944ab9a519d337cb0bec7284dc3e723d87", + "dest-filename": "http-deceiver-1.2.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d", + "sha1": "8b55680bb4be283a0b5bf4ea2e38580be1d9320d", + "dest-filename": "http-errors-1.6.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c", + "sha512": "2a993d4a6ecd988f911e19e3e8e2160c8d5de9f228140b45b7d44b693311960ffcc38f63b804adb2b060a740e9e0e7717556d121e2a1b4252fa22fd1b8084ee2", + "dest-filename": "http-errors-1.8.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5", + "sha512": "c7e2551243b63e833caaaa5b3db38bddca873f07ab7a9ecec332bb032fac3108cacda282a96be3a179b9b6a30ff6d5d65939d3cc08c885783e27df5762e3e13c", + "dest-filename": "http-parser-js-0.5.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a", + "sha512": "c876138163103bc56fc0d4b6d9e2cb968024bee9e0b0a74a4cb3bc00995fb5820a35f26bdc62b7ccad1909fcc30c6501b6d74673cc45cb59828adbcd290b42dd", + "dest-filename": "http-proxy-middleware-0.19.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549", + "sha512": "ee6cffef6d406e72702156e7692bf50b3dc09b464b4ff501c240bdd95971857bff93f04141f3367d712540d0b6ec1546af4bb0529a6560f40cf4b9da04c47935", + "dest-filename": "http-proxy-1.18.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d", + "sha512": "57edb7b0332bd765a7cfb893703789af73ba008c659ef4ff6e66800003ff5dd6b7e42f74a7de7df69d05d5e1d1fcdd4a20b592a1654088e3058c105769748cc6", + "dest-filename": "http2-wrapper-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2", + "sha512": "124626e4170a50689dbb1cd2b77129a64a3e3e2356344a5ae324a4f6f4c2eb00ec4095bdac749af94846349a11629edbcfa1edd5e69121ae90689a8ee6b0856c", + "dest-filename": "https-proxy-agent-5.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz#31065e6ab2c9272154c8b0821151e2c88f1b002a", + "sha512": "4f5d2abe4c34cf3e309e6e7ad253848343e8bd5a945ee3858611c0922c70f3fb32732ed326deeffd1ae410a1109c0c36be23d226eea202412bc67cd1d20f0fa5", + "dest-filename": "iconv-corefoundation-1.1.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b", + "sha512": "bf73179d901cbe7cb091350466898801cb657bb4575de79d391df5c3097b565ca85cee108bd6abbd27a73505a77b54dc4708422f51f02c8db56c4a9da63f3fac", + "dest-filename": "iconv-lite-0.4.24.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501", + "sha512": "e1f0a4efdc2c84c773329dab1f4eaa5ab244e22a25a8b842507f8e8ae22053ef91074fbde0d9432fcd5ab4eec65f9e6e50ab9ea34b711cdb6f13223a0fb59d33", + "dest-filename": "iconv-lite-0.6.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467", + "sha512": "e1a16aef0bd6c8c1ca831b07f1042d1a9bdb01209ff9e337c0f44b23a47e3200274c267a49362c46fb6d2ef4562b435f89fe69885dfde12b771de2436a58c63c", + "dest-filename": "icss-utils-4.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352", + "sha512": "75ccaa843bd7d42e3a95765c56a0a92be16d31141574830debf0dfe63b36ce8b94b2a1bb23ab05c62b480beeca60adbd29d5ce2c776ef732f8b059e85509ea68", + "dest-filename": "ieee754-1.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501", + "sha1": "c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501", + "dest-filename": "iferr-0.1.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43", + "sha1": "05698e3d45c88e8d7e9d92cb0584e77f096f3e43", + "dest-filename": "import-lazy-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d", + "sha512": "6fab34e26dcefacdc21926ea0c8c8fe11e9a03001e62556af7e59459ea7a8876bc11345ff727a2d54e3c0b93267c9995f4088b61804a3ccabf5befd646942609", + "dest-filename": "import-local-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea", + "sha1": "9218b9b2b928a238b13dc4fb6b6d576f231453ea", + "dest-filename": "imurmurhash-0.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251", + "sha512": "11d0c366ee00d8ec882bb2ebff6cc6fb0e6399bba4d435419c4c11110bc1ceca412640846d16bc1b153596085871a1890a745689b8c35e5abbefd5f5ff2e71c2", + "dest-filename": "indent-string-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467", + "sha512": "202963f97cfde3e77b8ab1f9a91c9f2689ce75f4f3b836a27c4e993d67f1d0dd3efc04d909bb933eada9ac5979dbabab91077dd16c942888750df050da1333f4", + "dest-filename": "infer-owner-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9", + "sha1": "49bd6331d7d02d0c09bc910a1075ba8165b56df9", + "dest-filename": "inflight-1.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de", + "sha1": "633c2c83e3da42a502f52466022480f4208261de", + "dest-filename": "inherits-2.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c", + "sha512": "93fbc6697e3f6256b75b3c8c0af4d039761e207bea38ab67a8176ecd31e9ce9419cc0b2428c859d8af849c189233dcc64a820578ca572b16b8758799210a9ec1", + "dest-filename": "inherits-2.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c", + "sha512": "255ff2ba0576bb35b988c4528990320ed41dfa7c6d5278de2edd1a70d770f7c90a2ebbee455c81f34b6c444384ef2bc65606a5859e913570a61079142812b17b", + "dest-filename": "ini-1.3.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5", + "sha512": "ecf9c5e283770af645db7003840e7045a60442927cab281291bb535d605e5d65e61154572bed484dc8875b01e1b23bf54e65b432069c22fea1122e695f935074", + "dest-filename": "ini-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907", + "sha512": "4b5cc1a350facdcb32b82e8f326639fb9e583082d0f5abfc968b4cc78e3b06ae92020a3fb032bacbab942a6b98856ede69c9c88457ec3e608d61d0f3b279c30a", + "dest-filename": "internal-ip-4.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c", + "sha512": "3b40c1d490bfb0fc9997b708a3bf27e5d47b7944b0c2960f8974614f337165500c52e07cbe59d11722f176b553a24b3a5cf2d59c57dbcda55de562e386083ebc", + "dest-filename": "internal-slot-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e", + "sha512": "6a013841f0762e4a7db880a7ec102aa2c730e1264ff644c4da1c62148de304f99725f76a89a8536d4b8a1ac3283761ada8bf40c61622a00715be0b1bd47bd16c", + "dest-filename": "interpret-1.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9", + "sha1": "fa78bf5d2e6913c911ce9f819ee5146bb6d844e9", + "dest-filename": "ip-regex-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a", + "sha1": "bdded70114290828c0a039e72ef25f5aaec4354a", + "dest-filename": "ip-1.1.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3", + "sha512": "d0a23feb4ef1a31493a07ec68cdd457d26cba14d3e6ed4e2723b1049642587f859ca437c2a998c7fbb98c0f5b747e6a467a47fc35f199574870585e26143cede", + "dest-filename": "ipaddr.js-1.9.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698", + "sha512": "a2998d217eee1674bde8db4f9a1590810c7afcd60582c51760c96571fcf058a50cc1fa3c924bb54ef13a86435c1fe435b6ce5c315aec63b8f46f15d00dc8aef5", + "dest-filename": "is-absolute-url-3.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6", + "sha1": "a9e12cb3ae8d876727eeef3843f8a0897b5c98d6", + "dest-filename": "is-accessor-descriptor-0.1.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656", + "sha512": "9b98671d391c56c3dfab1dc02a5cadb483dbec9f97ca41ef24fd81f5b6438e584b22812ae17a0aeb8560edba199555982ba2d463de1d60f104ecb87466464a71", + "dest-filename": "is-accessor-descriptor-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b", + "sha512": "f10ec40118f31272a9b7f3c20fb7b5720512d1ae97f2ee6d75288ca978688ce76857d4ec32c88efbd54b0b9bc098ef0deff1a65e7ef28d1f2a9c0e9b5401337c", + "dest-filename": "is-arguments-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d", + "sha1": "77c99840527aa8ecb1a8ba697b80645a7a926a9d", + "dest-filename": "is-arrayish-0.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3", + "sha512": "cc1f42aee31a9a3ca6f358b6259dd4327e783ca1ac433b097a8eb1bcddc7249e0202c40d07a891bada764e8efb39f08dba8c6ca6c221cda3e83b5cf20848453a", + "dest-filename": "is-bigint-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898", + "sha1": "75f16642b480f187a711c814161fd3a4a7655898", + "dest-filename": "is-binary-path-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719", + "sha512": "80361a2872669e3e1a5b1ca3e981f25d5a5d41ac2d54b1d4e5c6fe7b3b4f19ccdfe9c8ee4ddc2f7b964811f817a87e1ee7b027d43d4029ff02677918ad046a60", + "dest-filename": "is-boolean-object-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be", + "sha512": "35c7402f0a579139b966fbdb93ba303944af56f04a0e028fe7f7b07d71339e64057ece194666a739e2814e34558e46b7405a0de9727ef45dd44aa7c7a93694e7", + "dest-filename": "is-buffer-1.1.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945", + "sha512": "9ecbb0b7165f317ebb3abca5f4b090faea670b4674060a709eda52f3d9b51ff4cb174ccd7f37cb315ffd59affa319b23d1a72912300ed0a175c53e9974b97de7", + "dest-filename": "is-callable-1.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c", + "sha512": "61f253eeb929401d2ea5db1d1cb196aef84125f71fccd35ac180cd232417273d0856219fef93bc1013ca49dbf0dab17e2c60ac5f8159f2d72bddbd7d2dc66ae3", + "dest-filename": "is-ci-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867", + "sha512": "658bc282b79fc2aa10eb24f26146d0bbae07b084d9dcd7ca5f597368461d9130dc7cacf3088ff0b6145160a91d8c72855603625ca00a9bae59a35a64d9ab3f41", + "dest-filename": "is-ci-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211", + "sha512": "49d34252cdbce21af8d2115314fea5d087d9fd14ab317177aa0a111dddffefdba7513beb14efc9a17c241a6fb927f39edc4fdbe46b271b7df4b94360469bb53c", + "dest-filename": "is-core-module-2.8.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56", + "sha1": "0b5ee648388e2c860282e793f1856fec3f301b56", + "dest-filename": "is-data-descriptor-0.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7", + "sha512": "8db457cb5166b40a028d0915988558c2ebaa0c551b68e7838e679dd6d3863ebb0c86d240e2b0fdb64800d05d6a2778111515dc1d856475e68fe74439ac4fe32d", + "dest-filename": "is-data-descriptor-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f", + "sha512": "f5841a4b1b00892c1cbd2df7301937c130959d62be1e117c5594768d1c5e84cd7a41c54e747a8f9f854f1e644ae254abdfc9fd26b8aeac89cb70ff74c6c60d7d", + "dest-filename": "is-date-object-1.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca", + "sha512": "6af0d8af4481dc3c0ef73b0ca2fd20282112158a829c4e21abfe33dd375496e904cb9b7d0b4611abb1cbaec379d8d01ca9729a7a97820f49fe0746ab9d51b71e", + "dest-filename": "is-descriptor-0.1.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec", + "sha512": "d9e8ace56a90195ee97a8a03c8b98d10f52ba6cf7e4975f973da4bdf1101fb87bd1e71ae0daee607b907c47c3809ba92f64d53da1387de688bf27f16b62615b6", + "dest-filename": "is-descriptor-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa", + "sha512": "17e8b604ab05ac7eba89a505734c280fcb0bcbc81eb64c13c2d3818efb39e82c780a024378a41ea9fcfcc0062249bf093a9ad68471f9a7becf6e6602bef52e5d", + "dest-filename": "is-docker-2.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89", + "sha1": "62b110e289a471418e3ec36a617d472e301dfc89", + "dest-filename": "is-extendable-0.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4", + "sha512": "6ab9d73314f5861a0aa3d9352d976694dc897430dfcb6bf47d78c5966a24e3e8bcba5ffa5a56d581ef5b84cef83a934f40f306513a03b73f8a5dad4f9de27138", + "dest-filename": "is-extendable-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2", + "sha1": "a88c02535791f02ed37c76a1b9ea9773c833f8c2", + "dest-filename": "is-extglob-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f", + "sha1": "a3b30a5c4f199183167aaab93beefae3ddfb654f", + "dest-filename": "is-fullwidth-code-point-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d", + "sha512": "cf29a6e7ebbeb02b125b20fda8d69e8d5dc316f84229c94a762cd868952e1c0f3744b8dbee74ae1a775d0871afd2193e298ec130096c59e2b851e83a115e9742", + "dest-filename": "is-fullwidth-code-point-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a", + "sha1": "7ba5ae24217804ac70707b96922567486cc3e84a", + "dest-filename": "is-glob-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084", + "sha512": "c5e9526b21c7dfa66013b6568658bba56df884d6cd97c3a3bf92959a4243e2105d0f7b61f137e4f6f61ab0b33e99758e6611648197f184b4a7af046be1e9524a", + "dest-filename": "is-glob-4.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520", + "sha512": "8b01aa3b7276d5a692902ee35a71cffdd89f6b3c12ed215e22ac6feb012d2d4f18e4a9731538f2a9c4884f477cb38f9d0e12b2b6c93d3c96760644b9799c1045", + "dest-filename": "is-installed-globally-0.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150", + "sha512": "76a26f6ab2dac17b056cd0de256ef3033f08b49f5c776f18b9fbae1738741bca4d1e324c9d8d3c0efeec617dae17952940ec2278078e13111801659fbbb65950", + "dest-filename": "is-negative-zero-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8", + "sha512": "596feb40b39acd4abe493fdb080541a7fda83044562ec47b3ab2b2b74e7674d0e4e031dc0c4d3fed04972139668be541715d770df21bcac1b7b59266e517dd04", + "dest-filename": "is-npm-5.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0", + "sha512": "6c454eaa245cbe8df33b5f86da554ccbe8249049bd621edc0cc46eb0a2aee5924a3d46122702024ca66b34a1c0d846d23f44eed3ee81fde9ac60d1d9ca7e8af2", + "dest-filename": "is-number-object-1.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195", + "sha1": "24fd6201a4782cf50561c810276afc7d12d71195", + "dest-filename": "is-number-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982", + "sha512": "76ba831b771b733c7110946839770e8ed769d49fe5ca9d66367d316b39d1b3cfa6b8186041cae76eca68c795f97cec341e73276df0f3be710c12da83109128f3", + "dest-filename": "is-obj-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb", + "sha512": "c3de366d372287c7dd24f266407173912efa3443fc2b3cef9b0f76717b1acdbf229edc0ba8f89b3cf7577f800d74a577ad832eb90606216b6fcfd262941dcd15", + "dest-filename": "is-path-cwd-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb", + "sha512": "acda1c5c7822a4efabbe73fa764df3236d11a4eb6b00cfe4cdb076e7c530e415abdd3a578bceb5cb38e8d7a0e7e21528c74ee2c3903278c2c75acba3923cef45", + "dest-filename": "is-path-in-cwd-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2", + "sha512": "c22ca14f37c35acbf0016e77381585e73baf68e1a567a3f063101b3d50e1a66fa0334f712901a306affcb98375d9a0ef3319c09eadddc53ca84a844d9a0e5816", + "dest-filename": "is-path-inside-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283", + "sha512": "15de200016fec9c18098aa2ef1e31fb42ba94a2af9951c6a7f8683fef774703daa7381cbd3b3a309eb8732bf11a380a831a782283074fc40813955a34f052f3d", + "dest-filename": "is-path-inside-3.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e", + "sha1": "71a50c8429dfca773c92a390a4a03b39fcd51d3e", + "dest-filename": "is-plain-obj-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677", + "sha512": "8793e98179168ad737f0104c61ac1360c5891c564956706ab85139ef11698c1f29245885ea067e6d4f96c88ff2a9788547999d2ec81835a3def2e6a8e94bfd3a", + "dest-filename": "is-plain-object-2.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958", + "sha512": "92f45dc43b31663873517d3b6672f27734b54d4fd32654d41c763860b2fcededfba14038f437e42ea832f958c5a1ca30cb6f5c2af7128aefa422fef6f234d356", + "dest-filename": "is-regex-1.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6", + "sha512": "214d0d9b2927619374ac285c2a144ed57f0b633e48b23fc5b2a87c3493927fe37f842393c32dbd177d8893b6be42ccc4eb721dbe6c1d4cf0dde9c679a60e1cc0", + "dest-filename": "is-shared-array-buffer-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44", + "sha1": "12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44", + "dest-filename": "is-stream-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd", + "sha512": "b44d945f38af8deea87cf5bb976ddc8c338c6b4f606fbc6502a1ba8c6e5e8fab8f577d939563f734a3e282d68678736ef5fa2171c458bc889931f38e9ce614b6", + "dest-filename": "is-string-1.0.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c", + "sha512": "0bf08f06a2969ef75cc6a200471c8e878bf551410e087a600dad16620a4a0c532ccdcacf71f7e0e6e8704a03c22c3d965b19aaea2b22b33f3bb734f4d6db8686", + "dest-filename": "is-symbol-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a", + "sha1": "e479c80858df0c1b11ddda6940f96011fcda4a9a", + "dest-filename": "is-typedarray-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2", + "sha512": "a9cb6cb8b666210d3ebd248c7e856fc857b6f86484be7999d9ecd3ba9d5206c7bdfadc0209e89a97a1048b735cd8a15c7fafaacf61413e78d7b24f3184a49a3d", + "dest-filename": "is-weakref-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d", + "sha512": "7972b55089ead9b3e68f25fa7b754723330ba1b73827de22e005a7f87a6adce5392a4ad10bde8e01c4773d127fa46bba9bc4d19c11cff5d917415b13fc239520", + "dest-filename": "is-windows-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d", + "sha1": "1f16e4aa22b04d1336b66188a66af3c600c3a66d", + "dest-filename": "is-wsl-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271", + "sha512": "7cacc0adad2b18951407018180d90766e4e865c9fe4ed5c7a5e0a09a430930c631d6c40361a092ca32414826b69c7d431a6eecde7d68067a21a154c168decbc3", + "dest-filename": "is-wsl-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232", + "sha512": "56349e6ff9479a4a3277caf23d520abce0a7e03d64a0ca98fafab28e351f737c722ad3f87583b1338e2c66b9ea412cd276cdf1c8ead44cb4c2f4b5425602e783", + "dest-filename": "is-yarn-global-0.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11", + "sha1": "bb935d48582cba168c06834957a54a3e07124f11", + "dest-filename": "isarray-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.3.tgz#5d6def3edebf6e8ca8cae9c30183a804b5f8be80", + "sha512": "f1c2412f9b53776392d1d3388f3d3bc107798347420aa2215313c81ad65f6b92fa85696f5793074c84f2fc3040b05f8e7b62d2d57de4ac1521370686516a56c7", + "dest-filename": "isbinaryfile-3.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.8.tgz#5d34b94865bd4946633ecc78a026fc76c5b11fcf", + "sha512": "e7787a5c59e2abbed8756faca6846b79b8749a7993c513d395cb8802b3b9ee598c76ae2e04a14a69e4e39dbf76a185ab4a7fcb54bf8b4fe1daa76b45423f15fb", + "dest-filename": "isbinaryfile-4.0.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10", + "sha1": "e8fbf374dc556ff8947a10dcb0572d633f2cfa10", + "dest-filename": "isexe-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89", + "sha1": "f065561096a3f1da2ef46272f815c840d87e0c89", + "dest-filename": "isobject-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df", + "sha1": "4e431e92b11a9731636aa1f9c8d1ccbcfdab78df", + "dest-filename": "isobject-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b", + "sha512": "78ba4acab7c6de6cef184d83bbc5683db792911af2d3ddfeb723637586816c94bdbf5ee49c899818d5d009457480bc50b45f369b713c8916ffc1d49064ba2aec", + "dest-filename": "jake-10.8.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.5.0.tgz#2611d071b79cea0f43ee57a3d118593ac1547db1", + "sha512": "fddb12994908cb910119fbff2238ea985c6b34052904445f1acd681d13b20fbcb18c6ff0fadd063890d7f0ed64df6c9299defe6b92219c9536a9015c2789f5bf", + "dest-filename": "jest-worker-25.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e", + "sha512": "80758917fe978b90931b9402bd13abe86726a48a8d6290c9c9cf00d61fc3c97a87d6d0fa4a74423347775399ac577d43d8b07f53e13433e5b8a32bca578e2837", + "dest-filename": "jest-worker-27.4.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499", + "sha512": "45d2547e5704ddc5332a232a420b02bb4e853eef5474824ed1b7986cf84737893a6a9809b627dca02b53f5b7313a9601b690f690233a49bce0e026aeb16fcf29", + "dest-filename": "js-tokens-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537", + "sha512": "a24307ece5d727b62b37d3a4dff497ae7bb8897f723a4fb6e67a97e22992da7a6ebd36039a8fd0119a2ac199186880e4de356f04e4ce20480485a2ceca7052f6", + "dest-filename": "js-yaml-3.14.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602", + "sha512": "c29c59b3d368c596891122462194f20c4698a65d0529203e141f5a262c9e98a84cc24c5083ade1e13d4a2605061e94ea3c33517269982ee82b46326506d5af44", + "dest-filename": "js-yaml-4.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jsbi/-/jsbi-2.0.5.tgz#82589011da87dc59b4b549d94dcef51a9155f6fe", + "sha512": "4f33bfeb61f179bdba40c6f8206948ff95fe40bafd52aa7514f930a76f8a388096f90faf4ae163eb573ca644fac009ece1670ae7a5fb0a64878497831963aac5", + "dest-filename": "jsbi-2.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d", + "sha1": "e7dee66e35d6fc16f710fe91d5cf69f70f08911d", + "dest-filename": "jsesc-0.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4", + "sha512": "398bbb5c4ce39024370b93ecdd0219b107cda6aa09c99640f7dc1df5a59dd39342b42e6958e91284ada690be875d047afc2cb695b35d3e5641a6e4075c4eb780", + "dest-filename": "jsesc-2.5.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898", + "sha1": "5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898", + "dest-filename": "json-buffer-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13", + "sha512": "e1b57905f4769aa7d04c99be579b4f3dd7fe669ba1888bd3b8007983c91cad7399a534ff430c15456072c17d68cebea512e3dd6c7c70689966f46ea6236b1f49", + "dest-filename": "json-buffer-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9", + "sha512": "9abab264a7d7e4484bee1bea715e961b5c988e78deb980f30e185c00052babc3e8f3934140124ff990d44fbe6a650f7c22452806a76413192e90e53b4ecdb0af", + "dest-filename": "json-parse-better-errors-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660", + "sha512": "c5b6c21f9742614e53f0b704861ba1ec727cf075ee5b7aac237634cce64529f6441dca5688753f271ce4eb6f41aec69bfe63221d0b62f7030ffbce3944f7b756", + "dest-filename": "json-schema-traverse-0.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2", + "sha512": "34cf3f3fd9f75e35e12199f594b86415a0024ce5114178d6855e0103f4673aff31be0aadaa9017f483b89914314b1d51968e2dab37aa6f4b0e96bb9a3b2dddba", + "dest-filename": "json-schema-traverse-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz#23ff481b8b4eebcd2ca123b4fa0409e66469a2d9", + "sha512": "ec313c9a91befdf570f9d4e98dbc67c78ed368c9c37ce2358f07edf60d55c9b96d64276ec9140f24fbdcfb3cca63d58f1f184f59ccf216e61ae88f0cc38894e4", + "dest-filename": "json-schema-typed-7.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb", + "sha1": "1296a2d58fd45f19a0f6ce01d65701e2c735b6eb", + "dest-filename": "json-stringify-safe-5.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81", + "sha512": "73bffc99b52c2a28006cb903e41d35d012b80fd2d99bb035a4d22d904c2251946920deba7b1bbf7bb6105b2b06ba7f9344a689a7c3217a633e5647d6bf8d9a08", + "dest-filename": "json3-3.3.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe", + "sha512": "68a4b85908cf7a7471890b02f7730d7e3c7e9db1783c0758ce677fd49223f07633a9f6eef3a6de4ee3605c3ccf9275a4d27d2e0119727b0668e2cfbe112dfa3b", + "dest-filename": "json5-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3", + "sha512": "7fef1c95dbbb5ffcbb44026eacc10999da0a5c607f5f9e74c3636bded4db7b32fa470104fe231c9beb599d77a866d2ae3aae9fb7cf82ab3124ac8831d5f3e840", + "dest-filename": "json5-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jsonc/-/jsonc-2.0.0.tgz#9e2a25100d164a9bb864c57517563717fa882551", + "sha512": "076f356cb093d9344c41af80414418e4019ca9239704e29a6063f8c03ce803ff90b3051f37cb0e0de92d6cf12cf416aaecb18aba7e6341b345a73c06b9560a87", + "dest-filename": "jsonc-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb", + "sha1": "8771aae0799b64076b76640fca058f9c10e33ecb", + "dest-filename": "jsonfile-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae", + "sha512": "e5d8277563ab8984a6e5c9d86893616a52cd0ca3aa170c8307faebd44f59b067221af28fb3c476c5818269cb9fdf3e8ad58283cf5f367ddf9f637727de932a5d", + "dest-filename": "jsonfile-6.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1", + "sha512": "a41c5c0772c573c41581d820bd95b27b2b3e867acd5a0e0e719214ff55f9f64e6341d2c1942b1819141acf6df84aaa112d30a0307d347d8d314491fe17d3044d", + "dest-filename": "junk-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9", + "sha512": "f72909ff8e9237ff4a3ccfec89c87343b3af5f218360a19368394a306080960d942bc291cb88dbd1df2c15cfb44edd186274e1abc5f645980283be113f181c54", + "dest-filename": "keyv-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/keyv/-/keyv-4.0.5.tgz#bb12b467aba372fab2a44d4420c00d3c4ebd484c", + "sha512": "e77d699062ea57704c834783aaa2452344759a42b5366e7120fda633a91e3f93fc59f16d0a483620ec29953526946a1380883dc90619fe4762861cfcf571f7bc", + "dest-filename": "keyv-4.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892", + "sha512": "2f3aad2ca954c22ac453297f9e2722ad598d88fbd8b3b9799fcc0e3cfedfc8956950f92f0a75bfbee8971a9ca51949673c39c1ef7d75ac047302ddcc86cc298e", + "dest-filename": "killable-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64", + "sha1": "31ea21a734bab9bbb0f32466d893aea51e4a3c64", + "dest-filename": "kind-of-3.2.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57", + "sha1": "20813df3d712928b207378691a45066fae72dd57", + "dest-filename": "kind-of-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d", + "sha512": "346104ae71fa176bd4b970e1f8e95b70a5bbff039c7dd447699ed55ada82ced7c7ae2ffef982a63f9d4e7567863eea8239b6ba924d8e4dee5dd365664c1f343f", + "dest-filename": "kind-of-5.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd", + "sha512": "75c4b5ba5fbdb66783f794fec76f3f7a12e077d98435adcbb2f0d3b739b7bf20443bb44fa6dbc00feb78e165576948d305172ba45785942f160abb94478e7a87", + "dest-filename": "kind-of-6.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lastfm/-/lastfm-0.8.4.tgz#4dddf08297a6fa23f84d4827052a0d282fe99688", + "sha1": "4dddf08297a6fa23f84d4827052a0d282fe99688", + "dest-filename": "lastfm-0.8.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lastfmapi/-/lastfmapi-0.1.1.tgz#ce336dcf7cc81820c22dc40247c97b31133486fa", + "sha1": "ce336dcf7cc81820c22dc40247c97b31133486fa", + "dest-filename": "lastfmapi-0.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face", + "sha512": "c1e4feaf491391141d09d60236d90cc165d04cc12cc0aac50649b872440e315861aa120c235513da1323fb58a28088604999b98139ab45704da06520693635c4", + "dest-filename": "latest-version-5.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d", + "sha512": "d3f06718209fc943240697838168a16a720017d2666611c1814844ab3bdff9a7613462e83fa4da888e6817ca326f7238e4ff8f727aea8a149fd353349741b9f9", + "dest-filename": "lazy-val-1.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8", + "sha1": "7947e42149af80d696cbf797bcaabcfe1fe29ca8", + "dest-filename": "load-json-file-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384", + "sha512": "f76fa1bafc4cbd894ccccb748883ae91cc18045a64609769976c6c67b2eb95ac8eec4f123aff8925410ad7b07f74920700e2cc7e1d9d659fd8d7c5a0986b5837", + "dest-filename": "loader-runner-4.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613", + "sha512": "a87d1648c06d9ffa07bb08f2fcdb9c1206f1e5d6f1c67c6ea7db383d55c95031d905063eb3435603dac97f9dd1067419c5f721edeb94ba2ee1a6800fbc02d974", + "dest-filename": "loader-utils-1.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129", + "sha512": "4cce7b55e1e9b6fe7af5dfc62a1e9301877329b9700cd8ae98e7641677a38c3d17c131fcecaf74c373bb022251a9d4285f282f8b55504c94cb1a1265ed6a80ec", + "dest-filename": "loader-utils-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e", + "sha1": "2b568b265eec944c6d9c0de9c3dbbbca0354cd8e", + "dest-filename": "locate-path-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e", + "sha512": "ec03bbe3cc169c884da80b9ab72d995879101d148d7cf548b0f21fc043963b6d8099aa15ad66af94e70c4799f34cb358be9dfa5f6db4fe669a46cade7351bae4", + "dest-filename": "locate-path-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0", + "sha512": "b7b870f6923e5afbb03495f0939cd51e9ca122ace0daa4e592524e7f4995c4649b7b7169d9589e65c76e3588da2c3a32ea9f6e1a94041961bced6a4c2a536af2", + "dest-filename": "locate-path-5.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af", + "sha1": "82d79bff30a67c4005ffd5e2515300ad9ca4d7af", + "dest-filename": "lodash.debounce-4.0.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347", + "sha1": "64762c48618082518ac3df4ccf5d5886dae20347", + "dest-filename": "lodash.escaperegexp-4.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99", + "sha1": "2d177f652fa31e939b4438d5341499dfa3825e99", + "dest-filename": "lodash.get-4.4.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0", + "sha1": "415c4478f2bcc30120c22ce10ed3226f7d3e18e0", + "dest-filename": "lodash.isequal-4.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c", + "sha512": "bf690311ee7b95e713ba568322e3533f2dd1cb880b189e99d4edef13592b81764daec43e2c54c61d5c558dc5cfb35ecb85b65519e74026ff17675b6f8f916f4a", + "dest-filename": "lodash-4.17.21.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.0.tgz#e7ec73a57e1e7b419cb6c6ac06bf050b67356114", + "sha512": "1ba03f9c92d18163aebb074db80ea4a28bdf115d58a6aa801b8a5152515acf78e3d90359f0ce2f06a9d503e1c14e653f00c354b653ac3264a917a3723a3ced6c", + "dest-filename": "loglevel-1.8.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28", + "sha512": "5ec3fe2a14227f86e35f591bb928b248914d01e84dc602dbea13d1189f50b14afc6a31e4b9719dac79855135145e10f0557d91e5b63824d644c1b52232157e30", + "dest-filename": "long-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf", + "sha512": "972bb13c6aff59f86b95e9b608bfd472751cd7372a280226043cee918ed8e45ff242235d928ebe7d12debe5c351e03324b0edfeb5d54218e34f04b71452a0add", + "dest-filename": "loose-envify-1.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28", + "sha512": "edf9b797734017d59f37a5b724e99fe5daf0a55a97efc26da0627703a5b46ba66795d338d70d9f5790f8f74a6c2854e931db3c4c9b1efde1cb145b0d1c78c782", + "dest-filename": "lower-case-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f", + "sha512": "1b62e3eb5b570e754514e8bc55976cf92a108ed402ddd82890a7431b69939b5b71e26e743541c1399481c10407cb2d15d760342531b889c7d9407fb13f287c54", + "dest-filename": "lowercase-keys-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479", + "sha512": "b6a357ad2efca0c384ef734cc4ae0430b42c428c167fc8caa281fd83bc4f6af453ef4e91e9b91027a0d8d937bb42e91a66cba5c5adf4c10edb934a66e1788798", + "dest-filename": "lowercase-keys-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920", + "sha512": "2a9340450037230bfe8d3034bad51555bae1f8996baf516fd1ee7a186cc014e5cdedd93f16f89a0d6f0b1e62b9d8395c1f858fda7ea023cbcdd5a7ac045828f7", + "dest-filename": "lru-cache-5.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94", + "sha512": "268e9d274e029928eece7c09492de951e5a677f1f47df4e59175e0c198be7aad540a6a90c0287e78bb183980b063df758b615a878875044302c78a938466ec88", + "dest-filename": "lru-cache-6.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd", + "sha1": "b5c8351b9464cbd750335a79650a0ec0e56118dd", + "dest-filename": "lru_map-0.3.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f", + "sha512": "83715e3f6d0b3708402dbffa0b3e837781769e0cded23cfbb5bceb0f6c0057ea3d15e3477b8acbfb22b699dd09fdf8927f5b1ad400e15ea8b9fa857038cfde1b", + "dest-filename": "make-dir-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf", + "sha1": "c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf", + "dest-filename": "map-cache-0.2.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194", + "sha1": "e56aa94c4c8055a16404a0674b78f215f7c8e194", + "dest-filename": "map-stream-0.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f", + "sha1": "ecdca8f13144e660f1b5bd41f12f3479d98dfb8f", + "dest-filename": "map-visit-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca", + "sha512": "3a478368067f6d00b1785028ccce793ca70a534c8930f1a27cbc15e108238adbbee4ca007d240de25b0b25e5d9d5bf30d31fbf12675ae8c6605d2d63bec6a99e", + "dest-filename": "matcher-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748", + "sha1": "8710d7af0aa626f8fffa1ce00168545263255748", + "dest-filename": "media-typer-0.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561", + "sha512": "6a2b27ac33f818d7b4e9470a1675796df30d3c1530e23b0b19a5b059f9c7defd361a706e5d7d8c0959f945bad6a348f7a5ccd48a561b96aedf43b370dade572b", + "dest-filename": "media-typer-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552", + "sha1": "3a9a20b8462523e447cfbc7e8bb80ed667bfc552", + "dest-filename": "memory-fs-0.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c", + "sha512": "8c0d2b754e4aa10302d1eea9a68351b69a7abe316aebe358eebf21cb09c2ed5fb55e3fccb47c0621b07541a2bf76e9f28d6b5e2739a4a5dee8a1e5a0d744fb18", + "dest-filename": "memory-fs-0.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61", + "sha1": "b00aaa556dd8b44568150ec9d1b953f3f90cbb61", + "dest-filename": "merge-descriptors-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60", + "sha512": "69bbffa8e72e3df9375113df0f39995352ca9aec3c913fb49c81ef2ab2a016bc227e897f76859c740e19aac590f0436b14a91debb31fa68fcba2f6c852c6eddf", + "dest-filename": "merge-stream-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee", + "sha1": "5529a4d67654134edcc5266656835b0f851afcee", + "dest-filename": "methods-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23", + "sha512": "3168a4825f67f4cdf0f9ba6c6371def0bfb0f5e17ddf7f31465f0800ee6f8838b3c12cf3885132533a36c6bae5a01eb80036d37fcb80f2f46aaadb434ce99c72", + "dest-filename": "micromatch-3.1.10.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c", + "sha512": "e72f00e7a8e0ed7550c7699bbf596ee3d351e1da24467859613b4bf8a19f69adbbbaae294935e4c10905265e29911332345cff12d6034a48a2107c7717b50dea", + "dest-filename": "mime-db-1.51.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24", + "sha512": "e9c3faf765b0188b3d5d774e3b8fbe37eeea8eabf4aeac7156f2775473e1fd273d99565c40ff991a190a893bd631046bdad6c79093ff627ed8d27a5bdd906ce0", + "dest-filename": "mime-types-2.1.34.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1", + "sha512": "c74567f2ca48fb0b89d4ee92ee09db69083c3f187834d1dbeca4883661162a23c4e1128ea65be28e7f8d92662699180febc99cef48f611b793151b2bb306907a", + "dest-filename": "mime-1.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367", + "sha512": "5123e431e113df5ace3226abb013481d928b1a0bca73f2eb8e87c09c194eb6d7f96a346faa2440f10b1e9db728a1cb4ae9de93b3a6aa657040f976e42ad86242", + "dest-filename": "mime-2.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b", + "sha512": "3aa6ce939a0441e019f165d6c9d96ef47263cfd59574422f6a63027179aea946234e49c7fecaac5af850def830285451d47a63bcd04a437ee76c9818cc6a8672", + "dest-filename": "mimic-fn-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74", + "sha512": "62c6e2f6e616f611727eb4e1743110bb290de04cba06ec0f0f6929239112fe71530e7ffdf32c5834b64972050028f4ff99cacb2ca686cc947d615c49ac874049", + "dest-filename": "mimic-fn-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b", + "sha512": "8f911cb67907eda99f57fab91e09a86a5d60d901c5251ada3ad9b1d09a48aa4c6106123f9494a5d67329438e6155aaf03444cea161229a7759e102b4447c6ec5", + "dest-filename": "mimic-response-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9", + "sha512": "cf4c9623ee050ebaf0792f199ade048f91dd266932d79f8bd9ee96827dfe88ae5f5b36fa4f77e1345ab6f8c79345bd3ae1ce96af837fc2fd03cd04e33731cd19", + "dest-filename": "mimic-response-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e", + "sha512": "969dc6798ef281c80099521c44f05584891ff14b3b1598c0f882e96a5e38a8b752bb5d709a3290dddf64d7995f0fba4ee1eb2ef5e508016eea898201a69bf8d0", + "dest-filename": "mini-css-extract-plugin-0.9.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7", + "sha512": "52d25c003e3211a1ad8cf7b35ae3bdc02e27c149d51fff3f226df210740fe1bebb717943fd0afd85d213094d710db4845e0d9728d68ff23b11795eef41dd34fc", + "dest-filename": "minimalistic-assert-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083", + "sha512": "c891d5404872a8f2d44e0b7d07cdcf5eee96debc7832fbc7bd252f4e8a20a70a060ce510fb20eb4741d1a2dfb23827423bbbb8857de959fb7a91604172a87450", + "dest-filename": "minimatch-3.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602", + "sha512": "14cf6735462b4410042d9413df179943b7e630e060ea758d989293720b0979a2ecb4ffd43835691acaf93a15e185783a7feaad27cba267e3d4c640d67202172f", + "dest-filename": "minimist-1.2.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617", + "sha512": "e93ea51f41fc386f642139bf266ead768a086e8806f5ed2d2e0a58ea6a615d29bf03dbbc36ad6bc811be42ca62b9bf4b8d69413ec3d2ded590fc1a2dab815dc4", + "dest-filename": "minipass-collect-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373", + "sha512": "266412618a4f52a5f92729f5997691c0e75ad6e43c1cfe4a013fe80d22c2cedd41611850534fe10edb01d6e7d97c4133319f5a0159ac070f3e156b085e50a55b", + "dest-filename": "minipass-flush-1.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c", + "sha512": "c6e22aedc20eb74f513d1275f60762e1bf9188dbc31587b9247fa080dbc1a86aa941772bbb73dc466399b8704a58ad53c5ff7e710f8731537877acf8e8b64fec", + "dest-filename": "minipass-pipeline-1.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee", + "sha512": "aedcb9929c3dff3f125fd766c5b94503a79d22d526c0980c7980d946bc25215376ee2f20cac19bce7270520830d95fc556a1520dd5b2d38d193d2f35d43600a9", + "dest-filename": "minipass-3.1.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566", + "sha512": "591a039fffe65c1889d47e34aea6b7bc7d2da1e3f04ac19be398889d6953c926be52ee24ded6144b16b6bf52aa0222edbe5ad2cda131a92d60b64f7a03dcef10", + "dest-filename": "mixin-deep-1.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def", + "sha512": "34a98094449fea3306ca6d7ef91d116bbc2f855fb0156eb715a48e14fc116a1bde6b480c51c19485578083fd010b4c22bfd8a1e4d60f0755a7d54108d7f2fec5", + "dest-filename": "mkdirp-0.5.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92", + "sha1": "be2c005fda32e0b29af1f05d7c4b33214c701f92", + "dest-filename": "move-concurrently-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/mpris-service/-/mpris-service-2.1.2.tgz#ed6db2574f48e1fc356413fd3fc8e857d93d2e7b", + "sha512": "002e967a90a7156c0e304f4e5a994767ca6cfc107e83d42b12950a0afef05fcd9f0cfcd1de73ebca938598bfc59b4265a0402ee904d649f0cb2dcea633f8e29f", + "dest-filename": "mpris-service-2.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8", + "sha1": "5608aeadfc00be6c2901df5f9861788de0d597c8", + "dest-filename": "ms-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009", + "sha512": "b0690fc7e56332d980e8c5f6ee80381411442c50996784b85ea7863970afebcb53fa36f7be4fd1c9a2963f43d32b25ad98b48cd1bf9a7544c4bdbb353c4687db", + "dest-filename": "ms-2.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2", + "sha512": "e85973b9b4cb646dc9d9afcd542025784863ceae68c601f268253dc985ef70bb2fa1568726afece715c8ebf5d73fab73ed1f7100eb479d23bfb57b45dd645394", + "dest-filename": "ms-2.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901", + "sha1": "899f11d9686e5e05cb91b35d5f0e63b773cfc901", + "dest-filename": "multicast-dns-service-types-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229", + "sha512": "8e2e89e5e9db3321911c802400ebb759d57c9e082abe228210ab5770ea9fa61659b50ae61cac9c7f29c9d95ede54f500e0d849e95ed67f84e619b4f0284f41ea", + "dest-filename": "multicast-dns-6.2.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/music-metadata/-/music-metadata-7.11.7.tgz#95051a6a62a94390985a20c49e2207f5b1cfd898", + "sha512": "31ad7f79e8664452ce4c2ad4aff0ae380de86fb21b2bd7821039467ada8a02d6868f8c2f32c405bb6605c0ae90c863e225d3dd6c44953b19cf83cb91bf7cd97a", + "dest-filename": "music-metadata-7.11.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/musickit-typescript/-/musickit-typescript-1.2.4.tgz#d055117e2c897c4ebc570f0d969ad31649744837", + "sha512": "dfeff6d0f8b6cce5401df5057fadf52d4d8dc1a0bfa841c1064b0cf9843343f7df7f8b4830f5f9589e967bf5979b04c790090720e122b495b87113e7bd502af8", + "dest-filename": "musickit-typescript-1.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee", + "sha512": "f19b6f12703673969809961dd5cbe076753a72ac22c51a1883bd313cb594c2ce4e4536bf967c3ebb86a68b1452fc0739539990560a7da679525276cd58569665", + "dest-filename": "nan-2.15.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119", + "sha512": "7e9a1ed93d116c7c014c150e7ed01f04f683122d3ab9f6946a2d2613a627d6469c7374a74c4adf6ff87e5fde155f323ae2b2851d82265d2bddc061829b03aa08", + "dest-filename": "nanomatch-1.2.13.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb", + "sha512": "8595dcecad9ef8f81e23578305eff5d00adde1e91b7ebaea1bc129fbc2667f82480f66cd83b36f08f39937e91f179ef8a45408ee6ba6d8052a0e27682aa7133b", + "dest-filename": "negotiator-0.6.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f", + "sha512": "61ddd4112e665824aa47ea8d4fddd2dd4a18524a8067d94b83c6bb83dae29ac5a66062bc7154e8038fec17746bb21772577b0018c5d5526a4c60ec3e74ba4ebb", + "dest-filename": "neo-async-2.6.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366", + "sha512": "d67878e5d79e6f9a25358ede5fcd8190f3bb492c51e524982623d3ad3745515630025f0228c03937d3e34d89078918e2b15731710d475dd2e1c76ab1c49ccb35", + "dest-filename": "nice-try-1.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d", + "sha512": "7e000dde318087e468c541991d348e2c922a51cdb09a8070191e2d6e93402a69a8bc5a16ab439d4646f456495d45e3b66b68814ff384ba51bd5d251cd74af7ce", + "dest-filename": "no-case-3.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d", + "sha512": "89b3cade203ebda6357848c44a442433405b0aa14e6993225d14ed741d2eedbe1d8ed63a267b23bcf7541d5320eb142ddc1f1fa534d61c8f40f800e333d7ebce", + "dest-filename": "node-addon-api-1.7.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad", + "sha512": "66330f1447d5c798fecb6c85df92b3c79b05ee40f3c6e0e3eb3887e0515b3a9f3bcca0d9371f321312486f4e4e185e0d96df481c520c064465e3555dbdc35d6d", + "dest-filename": "node-fetch-2.6.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3", + "sha512": "3cf9aef1e11e1bdb1a114bc8f7b7e6e0e6315d507a6c5bf2353ca250e062721069146f00d4b8f0ddb63adbee683a30c430746777463b1d0fb1eeecf13b30ba24", + "dest-filename": "node-forge-0.10.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/node-loader/-/node-loader-0.6.0.tgz#c797ef51095ed5859902b157f6384f6361e05ae8", + "sha1": "c797ef51095ed5859902b157f6384f6361e05ae8", + "dest-filename": "node-loader-0.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5", + "sha512": "0aacb337acfb43a68c785fe4b5c3154f38401c21297fc48e6abc29ce97fca4d058da4e7fa0cdf850795d530a7c54a23bbb172dd87c5245d26305a65e112cdcc4", + "dest-filename": "node-releases-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8", + "sha512": "ff908c3774f44785d38f80dc19a7b1a3eae8652752156ff400e39344eae3c73086d70ad65c4b066d129ebe39482fe643138b19949af9103e185b4caa9a42be78", + "dest-filename": "normalize-package-data-2.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9", + "sha1": "1ab28b556e198363a8c1a6f7e6fa20137fe6aed9", + "dest-filename": "normalize-path-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65", + "sha512": "e9e66ce4bb375ad0a2b075a9f52d86532f1daa4a468b80554b3dc66aa884e9ecee6f4e75d844b3b57530501e82e8829b4246363e76ff983e166288c24707302c", + "dest-filename": "normalize-path-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c", + "sha1": "2cc0d66b31ea23036458436e3620d85954c66c3c", + "dest-filename": "normalize-url-1.9.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a", + "sha512": "f546421511d074dadf4e91a0f3ed4834883ddc1eb3134697315164c35585c2f3b84a5672c14e9a2e0e4e7f4029fcf81c6d2c382cdc6f3165cc7ae8303025f400", + "dest-filename": "normalize-url-4.5.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a", + "sha512": "0e52fe5f03b2dcdc4043cc6e0b4a243e02b8ea2b953402b4d5837b46e79806aa85786b018d5f5798203301d82dfbaebb6c297990f87d12a28a0f09da3c6d48ec", + "dest-filename": "normalize-url-6.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9", + "sha512": "6227386d91c93adf510856d13f71a0a6a85270e6381c7dd5d8ff32063e82798ab5d7c42bf812d7a93d89be9274d26af22c44a980ec5fe57945bf86635f12d273", + "dest-filename": "npm-conf-1.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f", + "sha1": "35a9232dfa35d7067b4cb2ddf2357b1871536c5f", + "dest-filename": "npm-run-path-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2", + "sha512": "8add6f13de7317a7534fd941b186f1bea8744a8cb848fa307218f45011a3fd5e9c4cf9d75ed40e3d46e167a0a61b3003feb5b6d8b40ae84f7aa5c7495e4e00e3", + "dest-filename": "nth-check-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863", + "sha1": "2109adc7965887cfc05cbbd442cac8bfbb360863", + "dest-filename": "object-assign-4.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c", + "sha1": "7e7d858b781bd7c991a41ba975ed3812754e998c", + "dest-filename": "object-copy-0.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0", + "sha512": "1e8db3f346d522f265a07f98cd19a965541ef3bfaa01298150a6435a0c7d72ef8a0eb5f66431ffded332fa05db6444d51acd8cf1877139b3a1ed702d8a6f58d2", + "dest-filename": "object-inspect-1.12.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac", + "sha512": "ddcc83b321e0b668bb23b0df4922362c3a7a48ada5c2fb5b834a744757b446f4ea17971e1b1f8ad9d7d28e6d5b283315085103010bf2fa8f1ce9aed5ba339d77", + "dest-filename": "object-is-1.1.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e", + "sha512": "36e00449439432b9485ce7c72b30fa6e93eeded62ddf1be335d44843e15e4f494d6f82bc591ef409a0f186e360b92d971be1a39323303b3b0de5992d2267e12c", + "dest-filename": "object-keys-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb", + "sha1": "f79c4493af0c5377b59fe39d395e41042dd045bb", + "dest-filename": "object-visit-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940", + "sha512": "8b14f62f94c75ec029ca250f60a996fb6107a575dee488b733e7f87be6891401daa396a61515ba27438ee9cfcb53c05ee3bbad0b1d862fcf61c4607a5d298ab9", + "dest-filename": "object.assign-4.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e", + "sha512": "55d0e80b0bc923841d0ba9dd8e9a859a82f7ffe1f17df1416dc2732a2e61c0b2eaab1de675b79d4697d90dd2b44ab3926ae8fc5f81b306f9c3665e2f4cdedd3b", + "dest-filename": "object.getownpropertydescriptors-2.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747", + "sha1": "87a10ac4c1694bd2e1cbf53591a66141fb5dd747", + "dest-filename": "object.pick-1.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e", + "sha512": "3d7d70bb402601d3ea38bd665a1aa694e77c90e219430199c3aae1eee6f2f5f4dce6585a39614b5f723a47586b17d937cd4638d1eea282c2c69035caf762c936", + "dest-filename": "obuf-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947", + "sha1": "20f1336481b083cd75337992a16971aa2d906947", + "dest-filename": "on-finished-2.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f", + "sha512": "a59004f8524ba32213cad76a2b4539b3e148a6337424fdcecc58bfbbc471f84579fd6f894d61971bcc45cdebc4ec08c17c3a87bfff2f2fca90b088479ea464ac", + "dest-filename": "on-headers-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1", + "sha1": "583b1aa775961d4b113ac17d9c50baef9dd76bd1", + "dest-filename": "once-1.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e", + "sha512": "91ba5a4921894d674063928f55e30e2974ab3edafc0bc0bbc287496dcb1de758d19e60fe199bbc63456853a0e6e59e2f5abd0883fd4d2ae59129fee3e5a6984a", + "dest-filename": "onetime-5.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc", + "sha512": "3ea1e98200bd6cb57455e59c74a864a7163edc94f37ad2d2a930962ffcffb4521b23a1bc2428e89dd5e4953d498a77332f3d9789beb6b12a744ff80a4f82a4b0", + "dest-filename": "opn-5.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f", + "sha512": "87205597a8aaa94389f05a917be97f812f07fa42988eb12775de4f9b531f06db04280d37f0792475b025ffbd840171b2a270ff3c5b2f9951be12f708a6588c06", + "dest-filename": "original-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc", + "sha512": "b3bdd7c4e678ce9b7579d658673be1a856babaf41cd6fc146b42b405db4866040c0098fd21b79b1fe26480a65cf61f81d393ca1cb3939786a31b506636b55997", + "dest-filename": "p-cancelable-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf", + "sha512": "0593abde74501ce9ed5234eb1fcf8b879e2c98a1e81f2babf167b557c0d2315ae5e40da66a538ec2e2519ca4438d29e4a1e061e1ab7a0701276f923b265df5c2", + "dest-filename": "p-cancelable-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae", + "sha1": "3fbcfb15b899a44123b34b6dcc18b724336a2cae", + "dest-filename": "p-finally-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8", + "sha512": "bef717b0b009f43af9ad038f93bb68650649029065d8ae09e9d00d4ac12e87a408e3525872c4bfaa14c66bd12b2145202b758d428258bf2971be3aa68aa100f5", + "dest-filename": "p-limit-1.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1", + "sha512": "ffff3c985592271f25c42cf07400014c92f6332581d76f9e218ecc0cbd92a8b98091e294f6ac51bd6b92c938e6dc5526a4110cb857dc90022a11a546503c5beb", + "dest-filename": "p-limit-2.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43", + "sha1": "20a0103b222a70c8fd39cc2e580680f3dde5ec43", + "dest-filename": "p-locate-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4", + "sha512": "c7ed76c3f4e8fb81857e0261044a620dc2e8cd12467a063e122effcf4b522e4326c4664dc9b54c49f5a3f5a267f19e4573b74150d24e39580fbf61fb230ba549", + "dest-filename": "p-locate-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07", + "sha512": "47bf5967fd30031286bb7a18325cfc8f2fe46e1b0dad2ed2299ecfc441c1809e7e1769ad156d9f2b670eb4187570762442c6f3155ec8f84a1129ee98b74a0aec", + "dest-filename": "p-locate-4.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175", + "sha512": "cb76fc2a977c380378e388717c16c57e3d4563f463b5377cb73630854a8d617c747d7c76897e2668fe10afaaa120a6d05c8d36c132c075ae1f6146c36a04d417", + "dest-filename": "p-map-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d", + "sha512": "777a9755317fb3e5be09d279036f70cb05769fc0904186a1960cf66c5880fb87953496c726874f67efe05f03c68746cea80fa3f12fbaf9c926bcb18f935429c5", + "dest-filename": "p-map-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328", + "sha512": "5c4e86e3e6134e44f66b45166f692365ef313707fc6c86e7aa973f212fe274e055872bdeb3498ae4e2607a8723c7bab9a6f5ffea6db7c6ecd53d84f5b8633bdf", + "dest-filename": "p-retry-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3", + "sha1": "cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3", + "dest-filename": "p-try-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6", + "sha512": "4789cf0154c053407d0f7e7f1a4dee25fffb5d86d0732a2148a76f03121148d821165e1eef5855a069c1350cfd716697c4ed88d742930bede331dbefa0ac3a75", + "dest-filename": "p-try-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0", + "sha512": "9376dd9b69f6e6d932c5c8d22b3079c7c91f57194c760b1b3ebd069197301ec2e96dae9c063a82b752a570284a12fc4721c4c1d4554cbb0a228d9dbac5ec7931", + "dest-filename": "package-json-6.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5", + "sha512": "457963ef3098a2445ea96a4e3c7f68622bd4ccb619e6f00f21f1260933558a8b02efc17c1741fdcbb4fb806d8cdfdca682eb7117981c144b326504a987d069dc", + "dest-filename": "param-case-3.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/parse-author/-/parse-author-2.0.0.tgz#d3460bf1ddd0dfaeed42da754242e65fb684a81f", + "sha1": "d3460bf1ddd0dfaeed42da754242e65fb684a81f", + "dest-filename": "parse-author-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9", + "sha1": "f480f40434ef80741f8469099f8dea18f55a4dc9", + "dest-filename": "parse-json-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0", + "sha1": "be35f5425be1f7f6c747184f98a788cb99477ee0", + "dest-filename": "parse-json-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6", + "sha1": "6d5b934a456993b23d37f40a382d6f1666a8e5c6", + "dest-filename": "parse-passwd-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4", + "sha512": "0a2c9e3b1153fc96723799b4cfd3df5f0e1208127a4b2833d43a65d30aa39610c418604fd469ec51510bd29eb78681b57dc8f77c7ca75e2f4d60ee2758e2fea9", + "dest-filename": "parseurl-1.3.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb", + "sha512": "b969464f76129caf71dc140968e75c670ae757a84fa5df23147d7fb9ca622d13e1ff6cc2549292d7d1381af607bda09c0029f77e85d9d1c2c1f56af1d4a19ee6", + "dest-filename": "pascal-case-3.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14", + "sha1": "b363e55e8006ca6fe21784d2db22bd15d7917f14", + "dest-filename": "pascalcase-0.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0", + "sha1": "cc33d24d525e099a5388c0336c6e32b9160609e0", + "dest-filename": "path-dirname-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515", + "sha1": "ce0ebeaa5f78cb18925ea7d810d7b59b010fd515", + "dest-filename": "path-exists-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3", + "sha512": "6a4f50cb943b8d86f65b071ecb9169be0d8aa0073f64884b48b392066466ca03ec1b091556dd1f65ad2aaed333fa6ead2530077d943c167981e0c1b82d6cbbff", + "dest-filename": "path-exists-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f", + "sha1": "174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f", + "dest-filename": "path-is-absolute-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53", + "sha1": "365417dede44430d1c11af61027facf074bdfc53", + "dest-filename": "path-is-inside-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40", + "sha1": "411cadb574c5a140d3a4b1910d40d80cc9f40b40", + "dest-filename": "path-key-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375", + "sha512": "a2399e374a9dfb2d23b3312da18e3caf43deab97703049089423aee90e5fe3595f92cc17b8ab58ae18284e92e7c887079b6e1486ac7ee53aa6d889d2c0b844e9", + "dest-filename": "path-key-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735", + "sha512": "2c32733d510410f47ecb8f33f7703411dd325dbf29001c865a8fe4e5861d620a58dbfd84b0eb24b09aeaee5387c6bcab54e9f57a31baa00a7c6a1bce2100fcb3", + "dest-filename": "path-parse-1.0.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c", + "sha1": "df604178005f522f15eb4490e7247a1bfaa67f8c", + "dest-filename": "path-to-regexp-0.1.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73", + "sha1": "f012ccb8415b7096fc2daa1054c3d72389594c73", + "dest-filename": "path-type-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445", + "sha1": "fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445", + "dest-filename": "pause-stream-0.0.11.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.0.2.tgz#a5cb847e347d3eccdc37642c82d2b4155c1ab8af", + "sha512": "f5f31acface8c70f72a4ed4a672e510c9812ba912dbb443e83f3aaaac5475f7aca191f2a7a144b633b050116786d5bddbdf9272a25efb836e43273b583a711a5", + "dest-filename": "peek-readable-4.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50", + "sha1": "7a57eb550a6783f9115331fcf4663d5c8e007a50", + "dest-filename": "pend-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f", + "sha512": "70c943a9a2c4a9f49a5bc67b379270fa5c885bcebd1334fbdff179961b58f5c2c6a15c525f39df81f5cc3b46792b4a344364e44d7abed0a16c76749ede30d588", + "dest-filename": "picocolors-0.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c", + "sha512": "d5fca0ae84cb947bbaeb38b6e95a130eff324609b415c71e72cb2da3e321b19d03fc3196dac9bc13c0235bb354e5555346de46c5b799e6a06e26bf87c8b6248d", + "dest-filename": "picocolors-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42", + "sha512": "254ded7874cd8e6136542185cee63c117cc20d5c04a81d9af1fb08bf0692b4784058911e55dd68d500fcd0253af997445d748b6d2b2e2f0263902056a9141454", + "dest-filename": "picomatch-2.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c", + "sha1": "ed141a6ac043a849ea588498e7dca8b15330e90c", + "dest-filename": "pify-2.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176", + "sha1": "e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176", + "dest-filename": "pify-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231", + "sha512": "b81f3490115bfed7ddebc6d595e1bd4f9186b063e326b2c05294793d922b8419c86914d0463a9d252b082a438fe8e00815b8fb18eadcb9d739a4d8d9fa0795da", + "dest-filename": "pify-4.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa", + "sha1": "2135d6dfa7a358c069ac9b178776288228450ffa", + "dest-filename": "pinkie-promise-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870", + "sha1": "72556b80cfa0d48a974e80e77248e80ed4f7f870", + "dest-filename": "pinkie-2.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3", + "sha512": "fc4e7b018928790db9aa4c4c8f93c1395805f0a8aefe1edc612df4679f91ed66a208205f2eae7c648fdd49e68429bf565495799ffd37430acddc8796205965bf", + "dest-filename": "pkg-dir-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3", + "sha512": "1d10f36da2a30be00e5955f1014ff1e7808e19e22ff5e6fee82903490a0d4ede17c96a0826fb8fb178b3c6efc5af6dc489e91bb59c2687521c206fe5fdad7419", + "dest-filename": "pkg-dir-4.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5", + "sha512": "9c3cb04e1164d62e0140ae2dc0f43a4c0e114fc6c363deb27ae0950562f778f0110a210a0d14ab3466c5220509a4ba7e5de211eb9bfcadaed6b89385501b6430", + "dest-filename": "pkg-up-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/plist/-/plist-3.0.4.tgz#a62df837e3aed2bb3b735899d510c4f186019cbe", + "sha512": "92caebf32f7e9d73b1401da8b1536aae0bd7fd740f397694e0140c2a362af0fbda635535f26a3e7ca8014b0ccafa5b92ca29ceb8f69ef79ea5495701c3194032", + "dest-filename": "plist-3.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb", + "sha512": "e34416e586a504d7d0a39c916268b0ed8cfa4ca295af787af7bd01d9813eddf429b1672b6e3d4fcc9831789d7d0d142384c6ca3c8b8c63cac569773c9a8a2557", + "dest-filename": "pngjs-5.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778", + "sha512": "49efb68ac6a721c12a7f65cc1e3c942ac91ccf16cf1fb7509e53235d7ebe7726dacb21ef01ffd30a0c8c465cdffc1e900e100414e19eb34a73468ddbcb801b30", + "dest-filename": "portfinder-1.0.28.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab", + "sha1": "01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab", + "dest-filename": "posix-character-classes-0.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e", + "sha512": "2da60b0cd4b8486f10e56016a882607473c9ac30ebfcbbfbef9acc04551b8234f3ea3df8954ce70021dc7515aba0fbd700d3f6563ef234ae7bbe9f5e16accb59", + "dest-filename": "postcss-modules-extract-imports-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0", + "sha512": "7b7c43abe2e8b6219eb329a946528d81a2743c2ce85087691f4763e3b89602e8bf9324e08770a202bd6a3f9e2ea1d989865ea9f6b37a06835c7440d5271f510f", + "dest-filename": "postcss-modules-local-by-default-3.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee", + "sha512": "632120b13311a4d77e1e6c82ec7fe6877cbe31e1567afcbb5757af5612567b098c6e30c721b65b3972020b6cbe9b5c48d5455f213d47316fced381f1caef685d", + "dest-filename": "postcss-modules-scope-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10", + "sha512": "d7ffc4e63081ad9f439915fecc2b6642d45257a3d5e36231ec1ce3f466f025c79dbae7fb22a3fc3207935ee4431ce5a3da6d15cd90f9faba05583b94f1142372", + "dest-filename": "postcss-modules-values-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f", + "sha512": "50edd282764e553c2ee24c8b476d94435c59874f3a472359a696fb94b00a0452bc6b7dadb46e62f3b63f3f7fb66d14a364dc89d41ee17c5368dbbded29ef58c5", + "dest-filename": "postcss-selector-parser-6.0.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514", + "sha512": "d4d342b3abaeadf9156de5c6e12f09153f6dd7d9b8e480a789ff3358b779a0f499e74427c0c7caf87de3bf8d3c7788f0ffb06db6fe5ac52e48887a0b69534779", + "dest-filename": "postcss-value-parser-4.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309", + "sha512": "ca2a1aca335b1e7eb3d7f072c326f6638b37caf0c079718ecb1a83f8b9d53a29eae8c76677ef925b6c14355cdabf2c87c5debe0f1cd6188ba8b20e8fd518fcb8", + "dest-filename": "postcss-7.0.39.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc", + "sha1": "d4f4562b0ce3696e41ac52d0e002e57a635dc6dc", + "dest-filename": "prepend-http-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897", + "sha1": "e92434bfa5ea8c19f41cdfd401d741a3c819d897", + "dest-filename": "prepend-http-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6", + "sha512": "118e680f39ac5f9c2fbb29c0072ae66343f485ca7e4299c029b26783603630f8d52970b1ac3494933821549e1918f22ff890b8817f1f3d45ac702d11b63b161b", + "dest-filename": "pretty-error-2.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2", + "sha512": "de8b943a9421b60adb39ad7b27bfaec4e4e92136166863fbfc0868477f80fbfd5ef6c92bcde9468bf757cc4632bdbc6e6c417a5a7db2a6c7132a22891459f56a", + "dest-filename": "process-nextick-args-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8", + "sha512": "ecf887b4b965e4b767288330d74d08fbcc495d1e605b6430598913ea226f6b46d78ad64a6bf5ccad26dd9a0debd979da89dcfd42e99dd153da32b66517d57db0", + "dest-filename": "progress-2.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3", + "sha1": "98472870bf228132fcbdd868129bad12c3c029e3", + "dest-filename": "promise-inflight-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849", + "sha1": "212d5bfe1318306a420f6402b8e26ff39647a849", + "dest-filename": "proto-list-1.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025", + "sha512": "96542c30b4940d43d3e388ddad4fcedfbaa59e27e2b433fe670ae699972848ac8b2afb59c69c95d27dbf6c3fcde2d040019fe024475953b28cadaa0ad7e5d802", + "dest-filename": "proxy-addr-2.0.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476", + "sha1": "d3fc114ba06995a45ec6893f484ceb1d78f5f476", + "dest-filename": "prr-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64", + "sha512": "2f0672fa9dd216cd4fcad77f8d872de30a6fe3d1e2602a9df5195ce5955d93457ef18cefea34790659374d198f2f57edebd4f13f420c64627e58f154d81161c3", + "dest-filename": "pump-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d", + "sha1": "9653a036fb7c1ee42342f2325cceefea3926c48d", + "dest-filename": "punycode-1.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec", + "sha512": "5d1b118dd7fe8f99a5fb2ffa18a1cf65bac5ffca766206b424fb5da93218d977b9a2124f0fdb1a0c924b3efa7df8d481a6b56f7af7576726e78f672ff0e11dd0", + "dest-filename": "punycode-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62", + "sha512": "9758cd02ca4805216a6d3fb2fb9168b288cda55a45f789e523ec03529a8ff5e9f03937c7c7d7f4821e6707deaf97eeb24e9b09b32a5e36bc1fccfacab87078d4", + "dest-filename": "pupa-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/qap/-/qap-3.3.1.tgz#11f9e8fa8890fe7cb99210c0f44d0613b7372cac", + "sha1": "11f9e8fa8890fe7cb99210c0f44d0613b7372cac", + "dest-filename": "qap-3.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819", + "sha512": "117b73459982f981a61a50c56d72b142231937008b10ee8100d2971b8882b5220cd32a9cfe96a9a52c774482abe2bd2e87926c05c90e5de2ab077233ee6750a5", + "dest-filename": "qrcode-terminal-0.12.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.0.tgz#95abb8a91fdafd86f8190f2836abbfc500c72d1b", + "sha512": "f4c811a6055cfbffb8edd16f41e0fa536b3467dd84b0acdc1e882dba6e1007e50d774db958e2521ef9ff86393dc66ce3ed2b63f790b2500b37d66ae3c65884b1", + "dest-filename": "qrcode-1.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee", + "sha512": "4c8464e1aa982cda0951b77e836944773e642d622e4cc45a8005f197bf10d118958c03ae80799e28d19d777730a3f92da5ff5a2fd7a909f16a58310acac5252d", + "dest-filename": "qs-6.9.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb", + "sha1": "bbb693b9ca915c232515b228b1a02b609043dbeb", + "dest-filename": "query-string-4.3.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620", + "sha1": "b209849203bb25df820da756e747005878521620", + "dest-filename": "querystring-0.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6", + "sha512": "148aa08f6114bd36bb479d2ed2b1acc937edce3626bff6b784edf8e5b64daea69b36a8ed8220cc826a389a452377e9f3539a05ddd0a52aa1483d42b26d4caaa1", + "dest-filename": "querystringify-2.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932", + "sha512": "5aec802d18d63c31adb7fc3326269d3b901763ef2167cd215697ba3328af82b691116ef9d57dd26e146f1b778b28e60dfbc544bea2dc7f7c1d9ede386784b848", + "dest-filename": "quick-lru-5.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a", + "sha512": "bd897788e5fee022945aec468bd5248627ba7eca97a92f4513665a89ce2d3450f637641069738c15bb8a2b84260c70b424ee81d59a78d49d0ba53d2847af1a99", + "dest-filename": "randombytes-2.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031", + "sha512": "1eb82cc7ea2baa8ca09e68456ca68713a736f7a27e1d30105e8c4417a80dba944e9a6189468cb37c6ddc700bdea8206bc2bff6cb143905577f1939796a03b04a", + "dest-filename": "range-parser-1.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32", + "sha512": "44f30015424fd7d5887adffdf67821e88bfc7f301baae9b82e2ec00fa0ed19a5b6469301ff5d710e86a53e224c4dbbba2378646cc564013bd9aea6fd104a9e79", + "dest-filename": "raw-body-2.4.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed", + "sha512": "cb76c682a2a3dd005dc4b6cb9289a5a2192fb00f207408944254812670617e7f813f18386dceb677c4dc056d79c1abc37e07b10a071c72485c66fcb0c9060f3b", + "dest-filename": "rc-1.2.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/rcedit/-/rcedit-3.0.1.tgz#ae21b43e49c075f4d84df1929832a12c302f3c90", + "sha512": "5ccd09bf8d3fcb885502a8ff30eef4a3f216b38b8eb1a4a8a3698bca4de49450d6f924ad2e70adcee42efb53814c830694cf02bda2bd7ed9580a9e8327e70cb3", + "dest-filename": "rcedit-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23", + "sha512": "b3887de8ab4b0d4425b04361327d5aafcb766c46beabf600b63f293cf7488cf0c604321536cac3f5a5cd5aab2951ee80cca0881b40b51d964ba8b57baa938118", + "dest-filename": "react-dom-17.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037", + "sha512": "82784fb7be62fddabfcf7ffaabfd1ab0fefc0f4bb9f760f92f5a5deccf0ff9d724e85bbf8c978bea25552b6ddfa6d494663f158dffbeef05c0f1435c94641c6c", + "dest-filename": "react-17.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/read-config-file/-/read-config-file-4.0.1.tgz#ece5f6b1a5e6a46d0d93fdd0339f2f60ab892776", + "sha512": "e5c6840f7ba8d8801930f71b87ff61c7f3b6f6cdb8df444bc6d9c50ddcf1a47fdea44a5ac0ead09c6047b9ea2d21752b18f3c881d35037e4bf088a765a68927f", + "dest-filename": "read-config-file-4.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/read-config-file/-/read-config-file-6.2.0.tgz#71536072330bcd62ba814f91458b12add9fc7ade", + "sha512": "831ecf82be48e7a26d633f96baa11b4078ffc56a3ee55c2e6b68e16f55703385a27793ea6266788b4d190746041887e4541b02bfd52b8e0caa0a241f4bf3a8b2", + "dest-filename": "read-config-file-6.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be", + "sha1": "6b72a8048984e0c41e79510fd5e9fa99b3b549be", + "dest-filename": "read-pkg-up-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8", + "sha1": "8ef1c0623c6a6db0dc6713c4bfac46332b2368f8", + "dest-filename": "read-pkg-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57", + "sha512": "11b868f0ae2321b1c0c67bb18bba38d8ead9805fd94cd72c663ea744ac949a484b16af021c8b69fdfcba85066e6663ff9f7c99f550546e9e33cff997f219983f", + "dest-filename": "readable-stream-2.3.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198", + "sha512": "055887cbb2ca793cf8a0d9e470b27e95548beafa6215e5fafddde8487f33096ed4c4fda89dc864faf4c6075e37c6e1631d2ddd7938242a85d7ca65eaca688874", + "dest-filename": "readable-stream-3.6.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb", + "sha512": "78f78ae9c73511c28b121245b7f01e6cc08b2fe1a048a86eca0ad9fc62da29960479c22020409fe14694b9a072886b73724c11e1a8a7f55cd487de53d5ec581b", + "dest-filename": "readable-web-to-node-stream-3.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525", + "sha512": "d4953ff2af95805672c70ac9f925483ac87e2b2c161a976cdcd4ea8a488aa43319592726018c8a220aa43be011bcd5897d7797475cf1cfb687178bb80b21fabd", + "dest-filename": "readdirp-2.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326", + "sha512": "dc4d7651e3523df8eb8308e447cd66e49ec0c3f4f9e53bbb9d4c995506022843acfb6764c4463e0e93ed6733b862bbae88f6fb36460b55cc890b8fb309b939a4", + "dest-filename": "regenerate-unicode-properties-9.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a", + "sha512": "ceb71e47f5e119853f77fa29af610a3bb6911d47a2048f2a8ed7c7a800d3c1977a4b37f2d7a95aea4a83d0c214b39cf9871e8068a6be3e2c693eb476f3df88d0", + "dest-filename": "regenerate-1.4.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52", + "sha512": "a77553f9c38483116c45103d5f896423513e936fc2b672ad53881cc7268252b7a294bfefa88e82759df0c55531dd439483e82750e41071123b066488eb9e8c60", + "dest-filename": "regenerator-runtime-0.13.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4", + "sha512": "78e7fabe46b920ed79d497ecc3634ef56a465f9f16eb05a679f2b7235cc41abd25383d2ef2bc0f68da902f5691c546b12de28edc0acd87755883529b683f8517", + "dest-filename": "regenerator-transform-0.14.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c", + "sha512": "27a4838d4803c508f936eb273ad745c43c0dffe1d6ca447c1842f072d27b99daa1732cb5c44738491147517bf14e9ebad586952808df44b67d702a92ead9f7d8", + "dest-filename": "regex-not-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307", + "sha512": "a4c47b84155450623b3cc037ee6da87c87500aca265676acf899f950f1801d0fbf2e5c0a9bf6932c91dd6ac98747395f799c0788039a452a36adb0439b79cd51", + "dest-filename": "regexp.prototype.flags-1.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0", + "sha512": "d45e9b62ca188b3ea2b3ea33ef4356babd95961f4a5adb30b91bb324e7de614adf3d7da8f27ef802751568e1836d4a9518ef5f347bb8f3fa6324ee2c355c2c3a", + "dest-filename": "regexpu-core-4.8.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250", + "sha512": "ea09126f853a696241e1217666f2dbefac8206372fb9f5c1aafbc4c751db98a3e4badb308d6d71355458d3e75a96321845ba2037b3b47ad61295b89a110c8ccb", + "dest-filename": "registry-auth-token-4.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009", + "sha512": "f1a7185d74c8d00910bfa4403a3137bce6885d9913f70a382ce15b04a6101049e730d0692aa754ac8e92e0d4f428f228fd656f279b44fd7e4b17f4d051fd1e93", + "dest-filename": "registry-url-5.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733", + "sha512": "385153dcc7eb1fdd31216f0e392c94ae4e901c3e44f49393786a1d8897814b727a230960cc930d13fd5b664956cf9a1383ef5d08cc847ad725bc255738fa0ddc", + "dest-filename": "regjsgen-0.5.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968", + "sha512": "038a5c68e46a98d3035705235a84f3ba1c0c1a93fe3729297ea02c1202351521ff1330bb96b3794cc77e90df180a8bd7fa3329bbc79aa978173c26b483c15035", + "dest-filename": "regjsparser-0.7.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9", + "sha1": "54dbf377e51440aca90a4cd274600d3ff2d888a9", + "dest-filename": "relateurl-0.2.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef", + "sha1": "c24bce2a283adad5bc3f58e0d48249b92379d8ef", + "dest-filename": "remove-trailing-separator-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.7.tgz#464f276a6bdcee606f4a15993f9b29fc74ca8609", + "sha512": "a02705cb168cacab0a713639f6a9c202d9835522df3dbaefe80ded55b3dd14c32bbf98da2b5d15ea6e3470ab283cd840a8deab9875bdb2cc16e28debb92af051", + "dest-filename": "renderkid-2.0.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9", + "sha512": "2c588d7d1712bbb28addebccc983ae0b3bf72f5d135bbc82d46dbff92b4c8caf18e95a9dd8c1bbaff423c38821b6e08e8c5be59e6b3f88c98baa9bd6fc44bf59", + "dest-filename": "repeat-element-1.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637", + "sha1": "8dcae470e1c88abc2d600fff4a776286da75e637", + "dest-filename": "repeat-string-1.6.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42", + "sha1": "8c64ad5fd30dab1c976e2344ffe7f792a6a6df42", + "dest-filename": "require-directory-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909", + "sha512": "5dfd2759ee91b1ece214cbbe029f5b8a251b9a996ae92f7fa7eef0ed85cffc904786b5030d48706bebc0372b9bbaa7d9593bde53ffc36151ac0c6ed128bfef13", + "dest-filename": "require-from-string-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b", + "sha512": "34a37990c0f294aba577160b4947eb6e8e53bb387885dfb613c34f3d7d36999b67d55b911104e861efd9765272f89dee0a97da886174e5eec1f16d225db4079a", + "dest-filename": "require-main-filename-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff", + "sha1": "925d2601d39ac485e091cf0da5c6e694dc3dcaff", + "dest-filename": "requires-port-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9", + "sha512": "d1ad45e25ef7fd915939a9099d0dc5be4276fa0493416cffaf6284e4e7436344f13e6e61e0692a91659f338ed3ec7b1b9ceb5c255105e1ea42572eaeed0dcafa", + "dest-filename": "resolve-alpn-1.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a", + "sha1": "00a9f7387556e27038eae232caa372a6a59b665a", + "dest-filename": "resolve-cwd-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43", + "sha1": "79a40644c362be82f26effe739c9bb5382046f43", + "dest-filename": "resolve-dir-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748", + "sha1": "b22c7af7d9d6881bc8b6e653335eebcb0a188748", + "dest-filename": "resolve-from-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a", + "sha1": "2c637fe77c893afd2a663fe21aa9080068e2052a", + "dest-filename": "resolve-url-0.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198", + "sha512": "1e1b6bc349cb792ac543ba613e9e0e39c5632cf21e327465af999c9d5b8c7bb33fede067f7c0378661512e8168dc32d9922bd26308515094f23f2580939e962f", + "dest-filename": "resolve-1.22.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7", + "sha1": "918720ef3b631c5642be068f15ade5a46f4ba1e7", + "dest-filename": "responselike-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723", + "sha512": "c47e3cbb715307d56c670ed1fafbe068a78b2b34fa8cea206d08447bf8dec309d98333dc9f25ae8b602fe89a6861917ff75bae782fa5aa15aa794470e7faa10b", + "dest-filename": "responselike-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc", + "sha512": "4d3958a5af8e2febcc30d1b6e314a5406109dc1fd1cc47d494b72dedbe46ff2b5abfec0fae9942a55305bb0cd76e479c26b6fa218a358856f44bdbf7efbe789a", + "dest-filename": "ret-0.1.15.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b", + "sha1": "1b42a6266a21f07421d1b0b54b7dc167b01c013b", + "dest-filename": "retry-0.12.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec", + "sha512": "b968db68a20add3d4e495a6dcd7ecd97a3ef437a801ad284b5546346e6b38df2f7071e5e238d3d5594aa80d0fee143679b32d574f8fd16a14934fa81645bdee3", + "dest-filename": "rimraf-2.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a", + "sha512": "25990931990018514f3f662a5d95cf6cc94c060b31cc4f082ece253085ffda8d0bf54070f4efd8de8eb0170fe2f582daa5c5095b0a9b8b791dc483dd0bad9320", + "dest-filename": "rimraf-3.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd", + "sha512": "08784f87e50d1c3d864d735884f58b9d4f0e347748fb90c8fb811820039a883eb7ac7798959bf287c3fe8a7e7df7d4d348581462e294023cd123899d87fa7ed8", + "dest-filename": "roarr-2.15.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47", + "sha1": "e848396f057d223f24386924618e25694161ec47", + "dest-filename": "run-queue-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/run-script-os/-/run-script-os-1.1.6.tgz#8b0177fb1b54c99a670f95c7fdc54f18b9c72347", + "sha512": "aa5e8fd8bce10534c37f32adb3e428e07f785542a9c4a0c5cfa431c7069464dd26c2f8bb2f7969388ec1a8f0aaee58038775cb974769797c1f715222b65ad8af", + "dest-filename": "run-script-os-1.1.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d", + "sha512": "19dd94641243917958ec66c9c5fb04f3f9ef2a45045351b7f1cd6c88de903fa6bd3d3f4c98707c1a7a6c71298c252a05f0b388aedf2e77fc0fb688f2b381bafa", + "dest-filename": "safe-buffer-5.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6", + "sha512": "ae9dd2a34eca71d9a629b1af81a37141226bedb1954959394bd12ad45fa9a5b468ef4f9879a0f1930e4377c34f37e183e9b8e7626d95b8fb825e6a6e62f9825d", + "dest-filename": "safe-buffer-5.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e", + "sha1": "40a3669f3b077d1e943d44629e157dd48023bf2e", + "dest-filename": "safe-regex-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a", + "sha512": "619a372bcd920fb462ca2d04d4440fa232f3ee4a5ea6749023d2323db1c78355d75debdbe5d248eeda72376003c467106c71bbbdcc911e4d1c6f0a9c42b894b6", + "dest-filename": "safer-buffer-2.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/sanitize-filename/-/sanitize-filename-1.6.3.tgz#755ebd752045931977e30b2025d340d7c9090378", + "sha512": "cbfe7631ccbb6b0de0466ec8adc183171fdb0a4e00851876788f65b8739033cea766cab0891924ab619e9075c1043f9298f89d73c8b63eab58665fa9589f0e7a", + "dest-filename": "sanitize-filename-1.6.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9", + "sha512": "36a543bfd4e900d523166d0df2e3391b12f7e9480a8bdfdab59c3ec7b6059d0f1c9301462ab978c57e325adadecb75099b99cfd6451b9d880ba29a963524615b", + "dest-filename": "sax-1.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91", + "sha512": "d9e59f1a002aa96146aad74c99c2f9cc230ad54f0a957bfc4901468252f7084b5dd1a0d50d681e17f6280a6be59f9e66e734a4dc9ff6d214da48179239bb100d", + "dest-filename": "scheduler-0.20.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770", + "sha512": "8b6ecc89ce0aa2f33f9671accbcc214421e173b5627096a30234eb620d752bdcdf6579d822de24e45fa4664c239eb84accb89cfc72d4e23d759a3b33d86ffbe6", + "dest-filename": "schema-utils-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7", + "sha512": "48788db4c394196050270cc84a25582aef361a257841819e3e9de8765635b6e28eee03eda61013e51fe9cb47c0eb1b5b80b2ff46fb4966753d6fcb34175ab45e", + "dest-filename": "schema-utils-2.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281", + "sha512": "6393d0c52e084e50be11a84bb97698f3a4d77d1ec3739970dbde1a9573aaf3a2401c28a100865faaff273425af68426f682e75b8df616cb19e57470505d1fe17", + "dest-filename": "schema-utils-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca", + "sha1": "625d8658f865af43ec962bfc376a37359a4994ca", + "dest-filename": "select-hose-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.14.tgz#ee51d84d9dcecc61e07e4aba34f229ab525c1574", + "sha512": "9648da880c9efb00590c206cbb90468b45e22d1c5e525b06a1de593fddb8091484a06b99030fdfef2f512aedbcaf04df88756175abe1074a87d08355e8fd6510", + "dest-filename": "selfsigned-1.10.14.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc", + "sha1": "0dee216a1c941ab37e9efb1788f6afc5ff5537fc", + "dest-filename": "semver-compare-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b", + "sha512": "197d08c7f089707c81f1ce329291c6200bcbc8ec0ea1bb4cffc77e4d090077cd7f6c48e03c7adf6dae355697acafb8d7fedf1487e477117f5e012e5b7be8d062", + "dest-filename": "semver-diff-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7", + "sha512": "b1ab9a0dffcf65d560acb4cd60746da576b589188a71a79b88a435049769425587da50af7b141d5f9e6c9cf1722bb433a6e76a6c2234a9715f39ab0777234319", + "dest-filename": "semver-5.7.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d", + "sha512": "6f7f5305a4d27d5eb206b6a953cf69e5f29e904da6fcdc270e870e56bb90152d7fbde320773b8f72738cdf833a0b0c56f231ff97111ae6b0680de530bb91c74f", + "dest-filename": "semver-6.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e", + "sha512": "f8607acd503d2d687ace8bd840b00b1f0bf9adbd8f1c69498b795f8aa207c51d2ebb00a079f70e25ce7dbfd7efd70f066d2b70c6ebaaa808c8f4d30038e82ad4", + "dest-filename": "semver-7.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7", + "sha512": "3e878625887c1cae014cefdaf537fa646def7a8fc0ed956c62b480e89f27cbd9dbdc1d55ae992e37ecfd384e707c4e69e87e0b721619b1e8224206c90fde1915", + "dest-filename": "semver-7.3.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820", + "sha512": "509601eb0152244dc6d349c48af479ae05a9f1cdb15ef27738f58f866bad794d082a3f2729b1b70eb8e23a62f0a671c6616015c00ebdce64e6fbe606d079b0c3", + "dest-filename": "send-0.17.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18", + "sha512": "f08f138d6e4a30e2ac6504efa318ee4886bb7e80303d618eb6cfbaa3bb208f3e35fea303f55407103c62e8f06f2b6974317526a99c8da542be4f6b5069a125bf", + "dest-filename": "serialize-error-7.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa", + "sha512": "19a340e78dfcd2e15e7d68213830561068ac2d9163d349d2e400aceb21daf672ea94ba552cef0284319e2918d99d5e0d8789f4422ee7858643ffd7c23f312a93", + "dest-filename": "serialize-javascript-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8", + "sha512": "42bdd3a2cbe0b85b7c78f5aab2f45facac905c8896fa719b629cbc5cadb83501c4f3771ac56b7e988ca64d3d7d0c615b35634b7c4c2cae44a637ae2555607d6a", + "dest-filename": "serialize-javascript-6.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239", + "sha1": "d3768d69b1e7d82e5ce050fff5b453bea12a9239", + "dest-filename": "serve-index-1.9.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa", + "sha512": "f9330d03d005c54106b82d33da67afa204a79fd31729be1f6bb9e079130969a1aff2f4f09c81242a2f901af3eddf71d29dff29452f9618cd046ccb4224b28c05", + "dest-filename": "serve-static-1.14.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7", + "sha1": "045f9782d011ae9a6803ddd382b24392b3d890f7", + "dest-filename": "set-blocking-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b", + "sha512": "2711dcd7078237af30458d1f842a17a722b9e66fd73c769f3a62b85160fb9b6088d7818c705ca9b78c3fd3e355e5ffd931bcb617a4b6c3003b7e0ca787d8164b", + "dest-filename": "set-value-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656", + "sha512": "06f13f4f0a595f8157131c4ec59c9119042feb9d4c4b09962991aabe63dc4488c3a96b9bebb9132ae20cc78ddc659ad2fdc041cf005c3435a8171b765c4148a5", + "dest-filename": "setprototypeof-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424", + "sha512": "1392c35fb5aba7ce4a8a5e5b859bf8ea3f2339e6e82aae4932660cde05467461fcc45a4f59750cb0dae53830ab928c4c11e362fd7648c2e46f6385cdc18309a7", + "dest-filename": "setprototypeof-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea", + "sha1": "44aac65b695b03398968c39f363fee5deafdf1ea", + "dest-filename": "shebang-command-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea", + "sha512": "907c6bdb366962d766acdd6a0e3aeb5ff675ad1d641bc0f1fa09292b51b87979af5ecc26704d614d6056614ce5ada630d7fc99a7a62e0d8efb62dbdb3747660c", + "dest-filename": "shebang-command-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3", + "sha1": "da42f49740c0b42db2ca9728571cb190c98efea3", + "dest-filename": "shebang-regex-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172", + "sha512": "efef9d161b5cc77df9dee05aabc0c347836ec417ad0730bb6503a19934089c711de9b4ab5dd884cb30af1b4ed9e3851874b4a1594c97b7933fca1cfc7a471bd4", + "dest-filename": "shebang-regex-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf", + "sha512": "ab95cfcada85108287906762308ad8d749af2d1be7421e36ffe1a8065156ddbd8b5cb136c71269645766f78c1ed016a85774702721aa839c12edea714efd19bf", + "dest-filename": "side-channel-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af", + "sha512": "b03978a8c1698a3706c36d94e70eb72a60f771925f06e16554d6d530a8deda47a828c2fb5f653359b7385eb9846c3c20d0d5c9737cafe3fa31edbf8959be7b91", + "dest-filename": "signal-exit-3.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787", + "sha512": "a52cafedb4930bb8a0f437206f0f40b913546f993957aa03b9d8d9a0c052af5deaa4b046eed07ece00a40118eaef121481dcf93f541ef2efab486768b8e388c9", + "dest-filename": "slice-ansi-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae", + "sha512": "f7884ad0787cacfa90976c577371ec681a0e5ca576d0c4e83e4717bf06c84962c4b3eeb8b01ab9905827da42431dbd4faf2f72acfd1dc6b088f5145c8bb4572a", + "dest-filename": "smart-buffer-4.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b", + "sha512": "3b6ee5e3168c62dfd1490e53477be9582001e4a6ff73321ca9414e33f0b87d870b9db6547353e48d300c8e87f6a4159a493c0e51deaa5077051951a3eda2309f", + "dest-filename": "snapdragon-node-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2", + "sha512": "99b2a431d40ab235f80402f86d16138f6d5e74e7fc70ded71dd6142447be667f7d85511870cbca3dcb7522a35eefe0193e2ae7f01083390047419927aa62a565", + "dest-filename": "snapdragon-util-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d", + "sha512": "16dc8e9d637fc021d355738cc2f4afdba77e928e6f5a52030face8509ecb5bcbe1f99042f107658ef7913fe72b36bb41c22a04516cbfe1d32d6c18c0e22a0d96", + "dest-filename": "snapdragon-0.8.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.2.tgz#4bc48c2da9ce4769f19dc723396b50f5c12330a3", + "sha512": "6734713c1212404ed1a73947e2d2893106c733da5a6c796e9345816b1010fb09bf52279e055068bb4a78c159d240637d426a40672810d1c0c8ca95aea8e16615", + "dest-filename": "sockjs-client-1.5.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce", + "sha512": "18980b4d9eef61bfc9b4f492675d21b0e608bc462c8db354fb33dd20771469654d5043e2bf3c64bb7d7ceb9b124ae7740dad16e2511e38f966c3ddf32d0721b9", + "dest-filename": "sockjs-0.3.24.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad", + "sha1": "441b6d4d346798f1b4e49e8920adfba0e543f9ad", + "dest-filename": "sort-keys-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34", + "sha512": "aa743b81533118dc6c88be2512e2707bf4e8f149caedf02799b184107f11a4ba2eb8a6de126d2585b415148acd4ae07e1bbb55ac0955b198044d3e679637fe23", + "dest-filename": "source-list-map-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a", + "sha512": "1edcfe467b175a4e7e3f6b25c79261dd0ebabe1423d429659b4cef9da63df3e345c7e0efd8217f7f93bfb7cc7e29a35dadd200b2bb8dce887f2a989a95ba809f", + "dest-filename": "source-map-resolve-0.5.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f", + "sha512": "b811d4dcbddccec232617297f3c7ddac6a2fc5d482a13183459e92617b524712d95331e0e4fffae87b7aba85251eef4466877e8a75e12a8dea420c17513ff2d7", + "dest-filename": "source-map-support-0.5.21.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56", + "sha512": "70f8853932d42af245220e1229549ccb88a53cf5baac580c81fb9924f3680ee32cde70b51db314c9c068270efbc45229eb3d5425024e7f1e82f46307f340e24f", + "dest-filename": "source-map-url-0.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc", + "sha1": "8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc", + "dest-filename": "source-map-0.5.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263", + "sha512": "52381aa6e99695b3219018334fb624739617513e3a17488abbc4865ead1b7303f9773fe1d0f963e9e9c9aa3cf565bab697959aa989eb55bc16396332177178ee", + "dest-filename": "source-map-0.6.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383", + "sha512": "0a40a3ea088ddd2fa7f6aad88814d7e60cacb6510d9d15b98d978d2c7a5ee9ab9ef92ac7706e55630ba3856f6ce1d637d66106b31043ac747aa08ebd7d35ec69", + "dest-filename": "source-map-0.7.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9", + "sha512": "70e61c516c210ae1c25e2e3d4611510b22442b788f8f5662cfd0e9562577b5b64ec170f8f50cc837732938b24dc61daac2ada524965a28c570f6a362e234c2d3", + "dest-filename": "spdx-correct-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d", + "sha512": "fed4eb60e0bb3cf2359d4020c77e21529a97bb2246f834c72539c850b1b8ac3ca08b8c6efed7e09aad5ed5c211c11cf0660a3834bc928beae270b919930e22e4", + "dest-filename": "spdx-exceptions-2.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679", + "sha512": "71ba87ba7b105a724d13a2a155232c31e1f91ff2fd129ca66f3a93437b8bc0d08b675438f35a166a87ea1fb9cee95d3bc655f063a3e141d43621e756c7f64ae1", + "dest-filename": "spdx-expression-parse-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95", + "sha512": "0ad97606b1623345f7300358823dc29328318519abf668bac617a36dd3bdeb49c5e840c90294d8a67d014270ca96734150b2a208dd67df0f440641caf195a0fa", + "dest-filename": "spdx-license-ids-3.0.11.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31", + "sha512": "86c2d5144e528c0e930a2b167895c52a788618ea4180c2e67ab7ced9a0b2094e6cee727fae901ea6a98589fbff1826d26ee7847802499e6490dab282fe0f0573", + "dest-filename": "spdy-transport-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b", + "sha512": "af8ea065065057e2a5f6822dbe5d49659a89286afea04901d3c03a07392247be7ddffec86edba77171ddd98a18793b06e35e7b66cb0cbbd298bd41cb723703a0", + "dest-filename": "spdy-4.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2", + "sha512": "3733558490d8a7071e5558a2f3f1eee8329f0f61be36b407952fd5fea82fefadc462e755c0470c40dc5dda587ed15ad40725cdfe826497982b3a1616bd05188b", + "dest-filename": "split-string-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f", + "sha1": "cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f", + "dest-filename": "split-0.3.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c", + "sha1": "04e6926f662895354f3dd015203633b857297e2c", + "dest-filename": "sprintf-js-1.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673", + "sha512": "544d123951070a4ed073cba5916c379ed0335eea9fed2da5bf041a0cb46751e20468a35027357a07098b2a13aa4fad5a1a17d432b5de68193ea03182cef85cba", + "dest-filename": "sprintf-js-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ssri/-/ssri-7.1.1.tgz#33e44f896a967158e3c63468e47ec46613b95b5f", + "sha512": "c3e75a0b35cdf3d3ec7932fdf4c900f9fc4911c537c1f684fda8748b49673a5a46d4260b276663cc4af2ebc60129f2ece097e84d286b4c4b0990066e359fecb7", + "dest-filename": "ssri-7.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/stat-mode/-/stat-mode-1.0.0.tgz#68b55cb61ea639ff57136f36b216a291800d1465", + "sha512": "8c7f4486d2888ee5d9d9c5b19974bc64ff345f20b789ab10c4c0d5f23ce1349a5f0dbed56d02d55b85afb31cfd419bf357e1b862849f05454a0cecb12f38bfb2", + "dest-filename": "stat-mode-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6", + "sha1": "60809c39cbff55337226fd5e0b520f341f1fb5c6", + "dest-filename": "static-extend-0.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c", + "sha1": "161c7dac177659fd9811f43771fa99381478628c", + "dest-filename": "statuses-1.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14", + "sha1": "4d5e433c185261dde623ca3f44c586bcf5c4ad14", + "dest-filename": "stream-combiner-0.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713", + "sha1": "279b225df1d582b1f54e65addd4352e18faa0713", + "dest-filename": "strict-uri-encode-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961", + "sha512": "bda7dcbfa2a3559292833d3aa0cfc7e860c1ac0b73f2f76141a9068c522f36b1c0eb2dc7085d422272f2f902eaf1d4c93d0d5bf8a0d4a8315cb647515b8e1ed7", + "dest-filename": "string-width-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010", + "sha512": "c0ac90450a63274b08a7ad84ad265d1ac8cc256b1aa79a1136284786ee86ec954effd8c807a5327af2feb57b8eaab9e0f23fdcc4a4d6c96530bd24eb8a2673fe", + "dest-filename": "string-width-4.2.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80", + "sha512": "cbdc428f0d4fdb703093c12f4e97322f6348af58fbc09dfd7fe93a96f46748ccfe9b3f421b3f4d60f7a50e4e3690ecfafaa97cc637caf28633cb78c03f9414e4", + "dest-filename": "string.prototype.trimend-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed", + "sha512": "8e1e9ef7ce0e05fbf14b9d2d758da74599e80b9fe62c528e44441fc3cb79cb2b64a14b0944dc6f23f137f6abb5b03d0eb56237382d1780a4a6716c338b062e67", + "dest-filename": "string.prototype.trimstart-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8", + "sha512": "9ff4a19ef0e2e851db6d57ef8aba3e5a88e2173bfeb3c30f30705ccd578f7d4a4324bc282d3d21b759786300426e2f29240bde104767907c8fc933ff9b345fc2", + "dest-filename": "string_decoder-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e", + "sha512": "864457f14d568c915df0bb03276c90ff0596c5aa2912c0015355df90cf00fa3d3ef392401a9a6dd7a72bd56860e8a21b6f8a2453a32a97a04e8febaea7fc0a78", + "dest-filename": "string_decoder-1.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf", + "sha1": "6a385fb8853d952d5ff05d0e8aaf94278dc63dcf", + "dest-filename": "strip-ansi-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae", + "sha512": "0ee46cd6029b06ab0c288665adf7f096e83c30791c9e98ece553e62f53c087e980df45340d3a2d7c3674776514b17a4f98f98c309e96efbdcc680dc9fa56e258", + "dest-filename": "strip-ansi-5.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9", + "sha512": "637f153d21dcaa416b0a916743dbee4979aabaebf9a1738aa46793e9a1abaf7a3719cf409556ba2417d448e0a76f1186645fbfd28a08ecaacfb944b3b54754e4", + "dest-filename": "strip-ansi-6.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3", + "sha1": "2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3", + "dest-filename": "strip-bom-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878", + "sha512": "df1bab16fe6d1208a2df7662f09b69e79c042082d1f5e877e05016d343d97fe2674ac4e657f8a87b04a0425f7b247be08e8446c0f4a1b169be21daf1077e5dd3", + "dest-filename": "strip-bom-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf", + "sha1": "bb43ff5598a6eb05d89b59fcd129c983313606bf", + "dest-filename": "strip-eof-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a", + "sha1": "3c531942e908c2697c0ec344858c286c7ca0a60a", + "dest-filename": "strip-json-comments-2.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006", + "sha512": "e9f3dcf91e22870a8fe8dfda22fd9fd60307f25395b56407a2a0b8c8aea8483555a1cba602c7c2aa39179ea89832198cc12fe61072e9ed57a196ddea97a9448a", + "dest-filename": "strip-json-comments-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631", + "sha512": "939e72c4a1f06979e9606b0ece0e1597cfad0eb5b29710c4a649c68e14e2641f1d151539ad3a3d080cdec9c8afc55decfb39532b0aece96c4cc51f799f6ea4c2", + "dest-filename": "strip-outer-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/strtok3/-/strtok3-6.2.4.tgz#302aea64c0fa25d12a0385069ba66253fdc38a81", + "sha512": "18ef0870517d1a6143bea76e22ca540700b309bab37a0c95288b12ca670c82264a7827eb37d4a8c2d5288bcf9be7d5993008c8cd566273f16df7bfa9ca747723", + "dest-filename": "strtok3-6.2.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e", + "sha512": "57b4c2391928f2bb3dac8aa44ab94c7e4a80eb70dfa060412662b590a1827128be0566f872acf4491b27a7897aad4e62c0e11dd3fd9e3efebc495db6557a27e1", + "dest-filename": "style-loader-1.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42", + "sha512": "32f8d7ce4cff04e7f2543906d2814eb41c475f6bb780a6cc1c817f7576e566c803dc158e14b987a2f229658ec1ca425d02372a442062d5660135d102f7223bbe", + "dest-filename": "sumchecker-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f", + "sha512": "423563c1d5c8b78d3c308880a825f8a142ac814d84a801b3b363e9926e1a4186e39be644584716e127c5353af8b8c35999ad1ecb87f99602eb901d1a5f440ca3", + "dest-filename": "supports-color-5.5.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3", + "sha512": "a9ed637e6d4c83b36afcd4a1e97136e203d744e115b161f10b52c8c7ffd73650fd8b0ed86501a364d8d837bc466841ba88a740f04b4d156e91d208e7557a7ec1", + "dest-filename": "supports-color-6.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da", + "sha512": "aa9080bd197db2db8e1ef78ab27ec79dc251befe74d6a21a70acd094effe2f0c5cf7ed2adb02f2bf80dfbedf34fc33e7da9a8e06c25d0e2a205c647df8ebf047", + "dest-filename": "supports-color-7.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c", + "sha512": "3295043763a876d533c6f29097bd9c505ed14391221ec1af4ac546d226bd73945b5862f6088e02ec4a4f4bc513048a659e5cd988db95e7ac3e16e371cb7b72d9", + "dest-filename": "supports-color-8.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09", + "sha512": "a2dd169d74bd7e076480871e3dee911cd935580f3e9ae3dae9c4a3791dd5f0adbbabd041d6b4c4dd1d69ec7bf4cf567201cf2ce95beff0323259febcd4c02dd3", + "dest-filename": "supports-preserve-symlinks-flag-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2", + "sha512": "e162bf6d86668fcc4bafe1d408e0c7185d59173b187df6ac2d480488c058e1f82d96d74ee81e1626d9526cf6834cba584dc195c0cdaa2e715320211c371b3790", + "dest-filename": "tapable-1.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0", + "sha512": "18dcd0bd04ce20fe91c937c4d90c5bf19565366c349fcf2fa75b33c1646298fd369a74ecc775ad9f9a9176a63dc365ddb8535482f3b084d9d0b23c02a7e92a69", + "dest-filename": "tapable-2.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/temp-file/-/temp-file-3.4.0.tgz#766ea28911c683996c248ef1a20eea04d51652c7", + "sha512": "0b9b63942fc70ad5543a2dca595a24778bc755588e9868ed2f0221e0cbb33e8fe73184d5fe9d6eaeddd19cccf62165c374a106247de4e7e28fc6da91b14606b6", + "dest-filename": "temp-file-3.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz#894764a19b0743f2f704e7c2a848c5283a696724", + "sha512": "fdf2b0dd1fa15b21df631ec1bfaa0faa69381c641cad62ed5775fa820bcfbb03cd1d29f3bd5579d73e8e69a08ebace182e3bad6063b3de91296e17ba529dacd7", + "dest-filename": "terser-webpack-plugin-2.3.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz#21641326486ecf91d8054161c816e464435bae9f", + "sha512": "2cf222b22dce978721c0068f3fcb68509dcbe2a08cd46d306a8ecbdea36fe7b0eb7b3c63ebe544cb24a93f0e01d4748ed8483f84363f30d1795e2842028aa7b1", + "dest-filename": "terser-webpack-plugin-5.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17", + "sha512": "1003e2a5335e5ac6ffdf02cf7aea75b553da5df21a53af3132755d3da7c82f54d5d393a101202b63221f16f9ef24236b4763483af0d534d4c545af917b6316cb", + "dest-filename": "terser-4.8.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc", + "sha512": "00c985f7d0cc7c40e24497f17d8e638f9c0d1ff6d83b4f5c9e24aa85fa32c5cf2c168608824272f3a1b4e14a195395639699e9955bb42ba4f1e84f5be7e0e51c", + "dest-filename": "terser-5.10.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5", + "sha1": "0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5", + "dest-filename": "through-2.3.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d", + "sha512": "78763b9c17ed813841a8ec8719537e97c805d01b9c3f4f5f328d283bf2dbd30d4e17cd1d26ffa50d5a571bad16310be47310243726cab2b10813766d28698fac", + "dest-filename": "thunky-1.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7", + "sha512": "47033b3283e88cfc6c381627c9dda1cb46f1b48955ae284db3da63e5252f63c673d6c41c406dad1b5852afc3c3c5f80407c44d28386a6c896ba086ab48d0cdb1", + "dest-filename": "tmp-promise-3.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14", + "sha512": "efa49486d7ea4762239fec6595c2393f5a326a79c73470720fcd16d6ae38ee05379a9f46f4f4a919d5a68d43874433e21d869c224eba5bbb9b0d3b8f177044b5", + "dest-filename": "tmp-0.2.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e", + "sha1": "dc5e698cbd079265bc73e0377681a4e4e83f616e", + "dest-filename": "to-fast-properties-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af", + "sha1": "297588b7b0e7e0ac08e04e672f85c1f4999e17af", + "dest-filename": "to-object-path-0.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771", + "sha512": "22adb95c1b7acc3e67a4f8652d55c614ddff832476fea38370a34dc9331de2f6e6dfd1d468e8803383ccab478c542fd3931cfe66376c739e60f72cb3f98ab4d1", + "dest-filename": "to-readable-stream-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38", + "sha1": "7c80c17b9dfebe599e27367e0d4dd5590141db38", + "dest-filename": "to-regex-range-2.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce", + "sha512": "156b6578d02d67f2a2daab6a7a3d825d339ac8e1fd6c70d017e438f15a56c835e36d8c40e18cfc883077d735ce05494e1c72a27436ea195ad352f40c3e604607", + "dest-filename": "to-regex-3.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35", + "sha512": "a39b123ca12483f0c840d987e37574fee7ab2eba7355e764521f2d18dbda797a5fa6ec2329e9e54a8c7fd8efc14e5654b447be246eece58844cfad3c3e500744", + "dest-filename": "toidentifier-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/token-types/-/token-types-4.1.1.tgz#ef9e8c8e2e0ded9f1b3f8dbaa46a3228b113ba1a", + "sha512": "843f90cae500c88daca73b08d01ee07ff8c9da0811e118e4028dfb8f74adb9e3e1029254c1c5838e71c33857485984b0351dbc1f5e21a709b8108f95d5379dd7", + "dest-filename": "token-types-4.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a", + "sha1": "8184fd347dac9cdc185992f3a6622e14b9d9ab6a", + "dest-filename": "tr46-0.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21", + "sha1": "e3646a2ea4e891312bf7eace6cfb05380bc01c21", + "dest-filename": "trim-repeated-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b", + "sha1": "405923909592d56f78a5818434b0b78489ca5f2b", + "dest-filename": "truncate-utf8-bytes-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00", + "sha512": "5e78b7e4d2b38e032bc1ebf2b074c202bb4b0e93efc9ef3357fd04e04c989f8dcfeffeeabd0c0f87d0469077b06ccba5567b5b8a099c4fbadd5f704da3dc1126", + "dest-filename": "tslib-1.14.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01", + "sha512": "efb11bc8f3e9333f8544546e00595632d9a051619ef54386d99db936a0b08888d184e7f988a1aecd27b93f6c3595aabe164472e29f8f0ae5642521a4cd310a57", + "dest-filename": "tslib-2.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c", + "sha512": "d61fcb9eaf726a3298d8f11b05a74f5e3dd5c6c0c3bbce383a7680a39d9456623322fc30b413c8b8dbe48eecc19535a97c9c946c6ddecf42920626d0923e288e", + "dest-filename": "tunnel-0.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934", + "sha512": "df847b1d39c6d172097014a7e5784377b9cd14f45c5d8459ac10763b68dd2aa60e0e5752cc102acec5a865862f76e932ef7b68612fc44aac4fbe40dffc5d1732", + "dest-filename": "type-fest-0.13.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4", + "sha512": "35ef9e138af4fe25a7a40c43f39db3dc0f8dd01b7944dfff36327045dd95147126af2c317f9bec66587847a962c65e81fb0cfff1dfa669348090dd452242372d", + "dest-filename": "type-fest-0.20.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1", + "sha512": "c864b36bbe31934506f24fa92e1e687a8622aef2225a8e6dd3fa37cc71c03b6b510e265cc563fb7f2c0d95786a6fafebeac5afc22f91b3240c5a154b7b8055b8", + "dest-filename": "type-fest-1.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131", + "sha512": "4e444aafdb144f1107f0c75fb8248fed58b3272cd134c8e3d89d9da3626bdcaca6e7df0955d124b2eccf4029e514f5b8932f50fa203e99af411a6d3a5d0072f2", + "dest-filename": "type-is-1.6.18.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080", + "sha512": "cddbbc5cc3440dea4a291f9760e5c054fb56ba2d25cb436da2152c730f9499a1e20164fc86b575aebfff1fa57ed03bc9dce435f52f7bf4cd2568b7d7f2b9bcd9", + "dest-filename": "typedarray-to-buffer-3.1.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777", + "sha1": "867ac74e3864187b1d3d47d996a78ec5c8830777", + "dest-filename": "typedarray-0.0.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3", + "sha512": "4c24c8ba5ef42f259ee882564fc41261e039e1641ef048d0154e30639d856ac8f950ac7cf0b35828280110770e30eac5175aca19b0fcbffc5c356554abd4b298", + "dest-filename": "typescript-4.5.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471", + "sha512": "b5953fdcda8addd0398291352adca2254ac40749719c690c147a6d27baba7b0759f2cd7642b383c0d6e12094ad98991dd500d76b535103c685d80d7393f629cb", + "dest-filename": "unbox-primitive-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/underscore/-/underscore-1.13.2.tgz#276cea1e8b9722a8dbed0100a407dda572125881", + "sha512": "7a4635361473ab4074f20e1b1ae5f8c1dda3671e469cacfa98a4aa14be27a8195fc8c1a21b5d200c58434cc11f6260cbe89cb4154219a7bc22441fb404fec9da", + "dest-filename": "underscore-1.13.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc", + "sha512": "c98e4fa4395f548539fb2fc1482c402510484b565cd9d0c6dd48eafac47453e26351ebd6d8986870e17eb2844e60349a01eccecce2aecb28b1843ea60649d299", + "dest-filename": "unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3", + "sha512": "e646990ab6e9e6699bcf9ba50640e46d8d12b0f3a32aa552df95692fdba530f7d29742745ec9bef44be986ff42a08645c2b7bb689a1af78018eac78c28654de5", + "dest-filename": "unicode-match-property-ecmascript-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714", + "sha512": "ed886473461efade0f358cce18a79d0e15db60805ed57110610c4e3f285c5cd309d1608006aaa3e9c93275dea95916531d5e06b823ca74101488c73ad2db0a57", + "dest-filename": "unicode-match-property-value-ecmascript-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8", + "sha512": "e597eecbdabf0c5af8b5f3bb64f7955dbd5a3e879049d78530ba58b8579b7a10c085bb9ebcbb39cb149998814dd6d3f917d5a5e08a49ad8a2383ce7fce0c991d", + "dest-filename": "unicode-property-aliases-ecmascript-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847", + "sha512": "b497d79b131e5989dccc256ced7004bc857b89ea6900b7727a958c90793072246966b686ff1c13facd8937cfa9af5fbc8c245ff34145cefafe32941e7a81785e", + "dest-filename": "union-value-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230", + "sha512": "566a748c8a76967df95135eeaf2be3ce48c6751c9ff5bda54d7b9261488f9b345c977143b58a80c0e9d3264027803f525a19e82730db4cac1a3ab67e493b7135", + "dest-filename": "unique-filename-1.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c", + "sha512": "ce85abf4e6dac402c3dc338f7e33d2ab1b787e766259b9711c881e5aa5bcc7b52a0f312d1c440bce38b672e258405094e8a9a826290e600665ad31c779b8f1db", + "dest-filename": "unique-slug-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d", + "sha512": "b8d69e8ab10fbe96564a0cf0b0f1ad536cd5493ae7ffc2f9abf21ec59987d1e1fa480ef70a6000e54e06c0e453c50019b3de530172cda9e2e83cf34ee6065f5a", + "dest-filename": "unique-string-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66", + "sha512": "ac125e2390970259b2d6957eeb5ed607d27add4e9771acc71c5d9fd9d6c98b1e17ce9505d114b765b8f414620e080bdae4ffddfc604e61a002435c3ed1acd492", + "dest-filename": "universalify-0.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717", + "sha512": "84066c2aaed8cb5d59bb50c4d0ecd68f0ee79cb6662596130d96721051d9754855f05907e4c09fa14d5731ac57a2fa725b99eae6c70faaad190cff59ca5d38a1", + "dest-filename": "universalify-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec", + "sha1": "b2bf4ee8514aae6165b4817829d21b2ef49904ec", + "dest-filename": "unpipe-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559", + "sha1": "8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559", + "dest-filename": "unset-value-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894", + "sha512": "699c06a5a9853bad60dce95f4fb390087aa11a75b8de2787f5665e3fb43137f1bf8d2e237ea524671a2bcaf26054f11cae5e4d2ff8201ec4a62cc1ee1fae0b86", + "dest-filename": "upath-1.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9", + "sha512": "22d9c80876de321f46a94cb7d6114fac3d6472e677ae9c4365b7f82940dabd7c12d1b5b99bb48b6c3429197dd462bd3bd9c6eb17984552cdebe6d52c3f08df1f", + "dest-filename": "update-notifier-5.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e", + "sha512": "eeb294cb2df7435c9cf7ca50d430262edc17d74f45ed321f5a55b561da3c5a5d628b549e1e279e8741c77cf78bd9f3172bacf4b3c79c2acf5fac2b8b26f9dd06", + "dest-filename": "uri-js-4.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72", + "sha1": "da937f7a62e21fec1fd18d49b35c2935067a6c72", + "dest-filename": "urix-0.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2", + "sha512": "dc14d5f35dbe0151c738940ef0ee4c916819e5aa2c3fb1a744e270bf32d2f615838f4d2567a674c0d6a4e36dcba7d3c164dd3937e264fcde528bc8d10251b258", + "dest-filename": "url-loader-4.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c", + "sha1": "16b5cafc07dbe3676c1b1999177823d6503acb0c", + "dest-filename": "url-parse-lax-3.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.4.tgz#e4f645a7e2a0852cc8a66b14b292a3e9a11a97fd", + "sha512": "213780072596a2abad14295cfe54599c5a6581780466bdd627a5e780c33f37d0cc226e0af335cf099d4976ed2b111c0ef38c35582e709257b6b9bc1303835306", + "dest-filename": "url-parse-1.5.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1", + "sha1": "3838e97cfc60521eb73c525a8e55bfdd9e2e28f1", + "dest-filename": "url-0.11.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f", + "sha512": "73011255794edeeae5f585a5156fd303d72c842121b6eec8289fe9e6ca09fe01a98fbbdbbc5ac063f7888a843a0f0db72a3661620888a3c1ceb359d0dafaffa1", + "dest-filename": "use-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61", + "sha1": "f45f150c4c66eee968186505ab93fcbb8ad6bf61", + "dest-filename": "utf8-byte-length-1.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf", + "sha1": "450d4dc9fa70de732762fbd2d4a28981419a0ccf", + "dest-filename": "util-deprecate-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030", + "sha512": "8beeaa03630f86fa0a2eec6724da57006860ec7a6140e494ab62ca3190f49b5e448ac91752432f29d17852e8b459878250679afa8d9cc3f66ec1e86d7ecacd90", + "dest-filename": "util.promisify-1.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c", + "sha1": "8a16a05d445657a3aea5eecc5b12a4fa5379772c", + "dest-filename": "utila-0.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713", + "sha1": "9f95710f50a267947b2ccc124741c1028427e713", + "dest-filename": "utils-merge-1.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee", + "sha512": "1e3483470ea0644e4932081cb4705c8d56a4d3cf8a1158522220f31674fd4bd69e826a7ce52fdb45e0554dbe104c5691369b49f64b9868d8676cd10e91b29bfc", + "dest-filename": "uuid-3.4.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2", + "sha512": "f8d62cd9078c5b2f865853849bdc679fa1c20e9d25ed0043ee697cccb52627ef77439345d0da1c12b9f09139175453625f7fdfa42e9a7d2f0385bfe0cfb47b7a", + "dest-filename": "uuid-8.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee", + "sha512": "97c9421262dc2d8661e276ee9cd66f40225ce69bfbf910b06bcabf2dd531f2eee5b16bcf0ca9a9a1d24024dc24021242fff745638f0ab881268ed778455883ac", + "dest-filename": "v8-compile-cache-2.3.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a", + "sha512": "0e92a6d948bfc4deff1d0282b69671a11581859f59d24aadca01bc5c280d43c6650e7c6e4265a18f9eba8fc7cde02bb7fc999b86c0e8edf70026ae2cf61dbb13", + "dest-filename": "validate-npm-package-license-3.0.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc", + "sha1": "2299f02c6ded30d4a5961b0b9f74524a18f634fc", + "dest-filename": "vary-1.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/verror/-/verror-1.10.1.tgz#4bf09eeccf4563b109ed4b3d458380c972b0cdeb", + "sha512": "bdeb9f726c6b8b87b75d2ad3d31c1f511ee482e2246b105ea2c0e0d34c835a1938f7077091252bbefb26ee773be5ed4f532bc87998fa9d2f15411633dbf4b85e", + "dest-filename": "verror-1.10.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/vue-devtools/-/vue-devtools-5.1.4.tgz#265a7458ade2affb291739176964256b597fa302", + "sha512": "1010045ef0075229ec3f3a12884969b34260b4b5d49c95ca2096cfea77ddcff47add574a04c7c9df8feb162a7ee224fb88c6d54b9940e16e8dd63ab81e3e0b0a", + "dest-filename": "vue-devtools-5.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25", + "sha512": "c74b7426ec9d228f2a08d72d743ae7d4ecc7fea0f3936fab742382dd8cee999e367e232a990ed3df142eaf291832161f1da3c74e9e19c40c7635f528d4ae9068", + "dest-filename": "watchpack-2.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df", + "sha512": "3bce103a7af489cb1b1462d2d0eddb23916cc31cd1afcfe01f05a40e5405b248523ebc905efad33318f118fe3e8966286ae2e806f7c3a64ace6ae67ed226690c", + "dest-filename": "wbuf-1.7.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871", + "sha1": "24534275e2a7bc6be7bc86611cc16ae0a5654871", + "dest-filename": "webidl-conversions-3.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a", + "sha512": "3555816b3f64f37f591ffb229eeaccf87703bc93935f04a3629d64bbee5729e382d37cfcbf9422b672bfc7e940c465c5ca175aca821ffc63a9bfce73dffc4f6a", + "dest-filename": "webpack-cli-3.3.12.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5", + "sha512": "7637a573fcc68b3f67663fd4ecf4c18b6562a2b1895c45a8ff796d90f6c3cb1097861117916d1c7bdf5f6a56a89384cf8fe02cc4b897251d0404e6f4ce1f5f29", + "dest-filename": "webpack-dev-middleware-3.7.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz#8c86b9d2812bf135d3c9bce6f07b718e30f7c3d3", + "sha512": "df1df5ae36c441628c37369c519444eb05ef505b86a47eefaf494811b6293001bd04ec62d3ddbc414d4106cc0e00fde48371f53b88624beb2ae18c809fa00d9c", + "dest-filename": "webpack-dev-server-3.11.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f", + "sha512": "717f06daf47ff395181b9f45824a0c6a6c075089124a55776c1311b1bc555d5524da3e8d95e08a8d0fd613d79883d598e30db93bdc3cc0a3f8af335916651c52", + "dest-filename": "webpack-log-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d", + "sha512": "4d4135506a135f609de368f792b198a8e6d96ce0fec45eeedbc581eed7d4a2b772b528db5932232bff15d1a9a405f4d8378fe907f1880e525967ae7b0461b5f6", + "dest-filename": "webpack-merge-4.2.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933", + "sha512": "9604d2dd786fd6508e2a8ed20394e3297323a52338b018cd579faad9ba9eb1b48fb391631a653a8e3b414a45fd6f8a96f3bbc322c0889543ce1216d9acc76379", + "dest-filename": "webpack-sources-1.4.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde", + "sha512": "fc3c8c10eac380b28a206d1f9afb73fb87545ffdc6868cf0826ea23e9f0a461be7f9e41ff7e43b196c5534c937fae08f59f757602e04c4605c9085dd1447c7d7", + "dest-filename": "webpack-sources-3.2.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/webpack/-/webpack-5.65.0.tgz#ed2891d9145ba1f0d318e4ea4f89c3fa18e6f9be", + "sha512": "439a2bda8e842acefea0a989a3b2daa9968c3a50d642c7bd4e6e65d5601f53fba32c63793dbd12a8679590dff86e93e612a10fe519d5862aac3ad5ad515c0647", + "dest-filename": "webpack-5.65.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760", + "sha512": "6f5eca783210563bdbd2cb2e4831767185d28368b3b65889e01f5676cb81e89f79daa08f2a69d5ab80f25b99a8b489971c30b57014ffd547b3ac956c2b0e738e", + "dest-filename": "websocket-driver-0.7.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42", + "sha512": "3aa79d3c818e7ec0e5a37d5437061b08531268ef66f46ff47da2078f9fdd6450cc16a3d3731e94c2ac8ecb708e11a10e83ff55b0622976a9fad96e4a868292a6", + "dest-filename": "websocket-extensions-0.1.4.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d", + "sha1": "966454e8765462e37644d3626f6742ce8b70965d", + "dest-filename": "whatwg-url-5.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6", + "sha512": "6f065dbf400a2e9a65158d8a6515fa4efcae37ba238ebee5c2483a9a5d2ba08cbd61eb92afb252dfbdaa94d5b5f14418ce060af7388671ead6a993a6127f5536", + "dest-filename": "which-boxed-primitive-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a", + "sha1": "d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a", + "dest-filename": "which-module-2.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a", + "sha512": "1f125d616ab53132106c9de7c3472ab2c1e84cd536ebb2a5ac3b866755989710d2b54b4a52139a266875d76fd36661f1c547ee26a3d748e9bbb43c9ab3439221", + "dest-filename": "which-1.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1", + "sha512": "04b2374e5d535b73ef97bd25df2ab763ae22f9ac29c17aac181616924a8cb676d782b303fb28fbae15b492e103c7325a6171a3116e6881aa4a34c10a34c8e26c", + "dest-filename": "which-2.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca", + "sha512": "36c9a85da96c5950cc1aea71679474f246bd7e56638e22ef1d501660e2ad88a33cba3b595abf5c45f7da93eb92138f3e39bf0e6da957a70c9e522c830fa40582", + "dest-filename": "widest-line-3.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09", + "sha512": "402d7f88dff6fd13d52798d82bc046b6d8f9cfcdcb9922a6bdbbeb5cf3422d94846f7d8a2950c90e5fcc3add8dd35a94d87fc593311af4f2ada3506a0e3b5ded", + "dest-filename": "wrap-ansi-5.1.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53", + "sha512": "afa94f7011b1657948732984bbb227c43321756d0a0f1a4b82814b720b9ab3109a27f48e219c0835ab4af4a63fb5ff99ae5cb038a5345038f70135d405fc495c", + "dest-filename": "wrap-ansi-6.2.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43", + "sha512": "6151888f691a98b493c70e8db198e80717d2c2c9f4c9c75eb26738a7e436d5ce733ee675a65f8d7f155dc4fb5d1ef98d54e43a5d2606e0052dcadfc58bb0f5e9", + "dest-filename": "wrap-ansi-7.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f", + "sha1": "b5243d8f3ec1aa35f1364605bc0d1036e30ab69f", + "dest-filename": "wrappy-1.0.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8", + "sha512": "02f1dcc99e499d27eade2a12ca3ac1907f725b89bb03293cffd332fc30fda2729ebbff787f0acca1c7a63b64002450259e70cdf990d2f998c0479b9ad7f3d5fd", + "dest-filename": "write-file-atomic-3.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e", + "sha512": "ce6865b68491f2ed5c9c3b03e374d7e7d9b3a0c66c2caa94c1ec9804022f4e7811dec85cd16e9a399ca5666abfee1ab25713dd8bee547764089db960c84ef67f", + "dest-filename": "ws-6.2.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b", + "sha512": "e862e00aaa36732d80dab8c2345971412e999631bf72865f65772595d23c141ff51b7082237e9977cc72d87ac55400a2f2d7e4e57ae02d0124f8fd139f3f5470", + "dest-filename": "ws-7.5.6.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b", + "sha512": "29b938371caaeff656aabfed6ab23dc88b7ffa234d14e8c15c45a04dbe3275a34704d1a0bdfd901db4bd7dd7ec9dd7e316517011de0097e9b0f37624683d7464", + "dest-filename": "ws-8.4.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13", + "sha512": "3d23611090de8d9615ee1e7406884bd3d12bf5568879faf62cc01fdce126a429233a2df8798c906005d44e3110b5925329c17413650a4e1fa8b032ec80d8a6f5", + "dest-filename": "xdg-basedir-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66", + "sha512": "c923e2323334fa92c37ed1e05d8e01cb4bacc08dd23ca2c3c3f8b75176e73bc33fa76f33a9ec425283e6405ad80feff5073846252b368b511158a240b622ebba", + "dest-filename": "xml2js-0.4.23.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3", + "sha512": "7c396c23f905131ee02ef6de71cd3fa212c6e747ee810a7caf21f3313b96f6f49ad462745d858a9e1b14c7ba227b71bdf3eaf9e9a4d0214078921b78d91dc9bc", + "dest-filename": "xmlbuilder-11.0.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5", + "sha512": "c8ca8606ab57c9e3757b74c662f80d803559de3f385b873090e5d0b30821a25e803e065669f7fd9676ef37b3076093a25ecbc63d7b634d8244882f49db0bfd12", + "dest-filename": "xmlbuilder-15.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d", + "sha1": "132ee63d2ec5565c557e20f4c22df9aca686b10d", + "dest-filename": "xmlbuilder-9.0.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/xpipe/-/xpipe-1.0.5.tgz#8dd8bf45fc3f7f55f0e054b878f43a62614dafdf", + "sha1": "8dd8bf45fc3f7f55f0e054b878f43a62614dafdf", + "dest-filename": "xpipe-1.0.5.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf", + "sha512": "24a86a4cec12aea340d4d639952ced2751ab06252874b326219b8b88368c449fa2b4577e001544f170633af2162fead2a8d0c2ef82c24859a56ff538519e2125", + "dest-filename": "y18n-4.0.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55", + "sha512": "d297c5cde81e0d62472480264cb44fd83c078dd179b3b8e8f6dbb3b5d43102120d09dbd2fb79c620da8f774d00a61a8947fd0b8403544baffeed209bf7c60e7c", + "dest-filename": "y18n-5.0.8.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd", + "sha512": "6b850641a58f1f9f663975189c01b67b09dc412e22e05e374efdc9a0033eb365430264bd36c2bc1a90cc2eb0873e4b054fb8772ba4cea14367da96fb4685f1e2", + "dest-filename": "yallist-3.1.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72", + "sha512": "df074689d672ab93c1d3ce172c44b94e9392440df08d7025216321ba6da445cbffe354a7d9e990d1dc9c416e2e6572de8f02af83a12cbdb76554bf8560472dec", + "dest-filename": "yallist-4.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38", + "sha512": "de56ec3517ff8fe03842e4997c3440ec74527d6af33b4623a9325de648c0ab7ed97a9d421206989ab1fd4371b03e207d707c9dd58d54c208068491a8c62a5bce", + "dest-filename": "yargs-parser-13.1.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0", + "sha512": "a39d23d09793a32ff82ba39971a4265ba9725d72a1abb72c4445dc0f0936a2614f244c1434e56d24abe60ebf442357c025953265c445ee4c460569915ee76b09", + "dest-filename": "yargs-parser-18.1.3.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee", + "sha512": "cb5d67184953215f824f766ff6ded52a5f90de14d0a13f5ad50cdece1865e91a76d6027f2154d6ed9df2f4459786e5010b64a19dff835f46a7b5e72903048ff3", + "dest-filename": "yargs-parser-20.2.9.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55", + "sha512": "cfd900a5850e0b0a1e67bf2b7d161859d894fe234bea6c3062592465f268c8c475c69b3e344057e57ed7991a719191e15c9ebe132d342302b1041496f45223c8", + "dest-filename": "yargs-parser-21.0.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd", + "sha512": "017dd9c3988faee37989eeb119120382a913f9986746564c2cc1c0b3cb60ee746bbb2d8d6fe8b9a3d6f082102882d334f2ad5da6bd8b5684bc2924cc62959753", + "dest-filename": "yargs-13.3.2.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8", + "sha512": "69e3dbc4399c616fbe3daa81b09f8761417009dbf82d5bdd9e1072efc139ecf228afcfce56f84cac00c51440e1f031c3151bff3bd8b794f86c10d8ceed05f4f8", + "dest-filename": "yargs-15.4.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9", + "sha512": "59400d41e5608cb6cdb04986936d1ffa794780eab3445a6219655a06b60660818034822ede55a3a328b47cd94598992f7e1099e815c835eeff5b63b66d5e2268", + "dest-filename": "yargs-17.3.1.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9", + "sha1": "c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9", + "dest-filename": "yauzl-2.10.0.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "file", + "url": "https://registry.yarnpkg.com/youtube-search-without-api-key/-/youtube-search-without-api-key-1.0.7.tgz#39b348d6416318731430a9316da7900c3744bf4f", + "sha512": "3e3c1e8c5e98029643a93168e3aff8aba210973b54b50b0fffcca07076326a43c7aa28c82a7dfafb251054f4c2f76ffe219b6ac99061a5328fd5b1bab9928ffd", + "dest-filename": "youtube-search-without-api-key-1.0.7.tgz", + "dest": "flatpak-node/yarn-mirror" + }, + { + "type": "git", + "url": "https://github.com/castlabs/electron-releases.git", + "commit": "a3484109f0f0710a65f255e7c8e235aea1f06b24", + "dest": "flatpak-node/tmp/electron-releases.git-a3484109f0f0710a65f255e7c8e235aea1f06b24" + }, + { + "type": "script", + "commands": [ + "case \"$FLATPAK_ARCH\" in", + "\"i386\")", + " export ELECTRON_BUILDER_ARCH_ARGS=\"--ia32\"", + " ;;", + "\"x86_64\")", + " export ELECTRON_BUILDER_ARCH_ARGS=\"--x64\"", + " ;;", + "\"arm\")", + " export ELECTRON_BUILDER_ARCH_ARGS=\"--armv7l\"", + " ;;", + "\"aarch64\")", + " export ELECTRON_BUILDER_ARCH_ARGS=\"--arm64\"", + " ;;", + "esac" + ], + "dest-filename": "electron-builder-arch-args.sh", + "dest": "flatpak-node" + }, + { + "type": "shell", + "commands": [ + "cd flatpak-node/tmp/electron-releases.git-a3484109f0f0710a65f255e7c8e235aea1f06b24; git archive --format tar -o ../../yarn-mirror/electron-releases.git-a3484109f0f0710a65f255e7c8e235aea1f06b24 HEAD" + ] + } +] \ No newline at end of file diff --git a/flatpak/org.cidercollective.cider.yml b/flatpak/org.cidercollective.cider.yml new file mode 100644 index 00000000..65a83a73 --- /dev/null +++ b/flatpak/org.cidercollective.cider.yml @@ -0,0 +1,84 @@ +app-id: org.cidercollective.cider +branch: main +runtime: org.freedesktop.Platform +runtime-version: '21.08' +sdk: org.freedesktop.Sdk +# Use the Electron 2 BaseApp, which adds several common libraries we'll need. +base: org.electronjs.Electron2.BaseApp +base-version: '21.08' +# Add the Node 10 SDK extension. +sdk-extensions: + - org.freedesktop.Sdk.Extension.node14 +# Electron doesn't use a traditional locale format so separate-locales is useless. +separate-locales: false +command: cider +finish-args: + # These two lines add Xorg access for graphics. + - '--share=ipc' + - '--socket=x11' + # Sound access. + - '--socket=pulseaudio' + # Network access. + - '--share=network' + # If you need to access the filesystem, also add: + # - '--filesystem=home' +modules: + # With electron-webpack and electron-builder we don't install Node to /app/node, + # because electron-builder will bundle everything for us in one piece. + # Instead we jump straight to the quick start module. + + # However, since this quick start uses yarn, we do have to install that. + - name: yarn + buildsystem: simple + build-commands: + - 'cp -a * /app' + # Only used for building, so clean it up afterwards. + cleanup: + - '*' + sources: + - type: archive + url: https://github.com/yarnpkg/yarn/releases/download/v1.22.17/yarn-v1.22.17.tar.gz + sha256: 267982c61119a055ba2b23d9cf90b02d3d16c202c03cb0c3a53b9633eae37249 + + - name: cider + buildsystem: simple + build-options: + # Add the node bin directory & yarn directory. + append-path: '/usr/lib/sdk/node14/bin:/app/yarn/bin' + env: + # Set the Electron cache directory. + # (The directory format is: /run/build/MODULE_NAME/flatpak-node/electron-cache) + ELECTRON_CACHE: '/run/build/cider/flatpak-node/electron-cache' + # Sets the directory where Node is located so way npm won't download the headers. + npm_config_nodedir: '/usr/lib/sdk/node14' + build-commands: + # Have Yarn use the offline mirror. + - 'HOME=$PWD yarn config --offline set yarn-offline-mirror $FLATPAK_BUILDER_BUILDDIR/flatpak-node/yarn-mirror' + # Download the packages. + - 'yarn install --offline' + # If you were using npm with electron-webpack/electron-builder, then the above two commands + # would look more like the npm commands in the vanilla-quick-start manifest, just without + # the --prefix. + + # Run electron-builder, passing the architecture arguments to it. + # Note that the -- is important; without that, the argument will be passed to + # yarn instead of electron-builder. + - '. flatpak-node/electron-builder-arch-args.sh; yarn run --offline electron-builder build --linux dir -- $ELECTRON_BUILDER_ARCH_ARGS' + # Copy the resulting, unpacked directory to /app. + # (A glob is used because the directory name may contain the current arch.) + - 'cp -r dist/linux*unpacked /app/cider' + # If you passed --electron-non-patented-ffmpeg, you could install it like this: + # - 'install -Dm 755 flatpak-node/libffmpeg.so -t /app/electron-webpack-quick-start' + # Install the wrapper script to start it. + - 'install -Dm 755 cider.sh /app/bin/cider' + sources: + - type: git + url: https://github.com/ciderapp/cider + branch: main + # Add the flatpak-node-generator generated sources. + - generated-sources.json + # Our runner script. + - type: script + dest-filename: cider.sh + commands: + - '/app/cider/cider' diff --git a/index.js b/index.js deleted file mode 100644 index 2d02b3a0..00000000 --- a/index.js +++ /dev/null @@ -1,262 +0,0 @@ -require('v8-compile-cache'); -const { app, components } = require('electron'), { resolve, join } = require("path"), - CiderBase = require('./src/main/cider-base'); -const customProtocols = require('./package.json').fileAssociations[0].protocols -console.log(customProtocols) -const comps = components; - - -// Analytics for debugging. -const ElectronSentry = require("@sentry/electron"); -ElectronSentry.init({ dsn: "https://68c422bfaaf44dea880b86aad5a820d2@o954055.ingest.sentry.io/6112214" }); - -const configDefaults = { - "general": { - "close_behavior": 0, // 0 = close, 1 = minimize, 2 = minimize to tray - "startup_behavior": 0, // 0 = nothing, 1 = open on startup - "discord_rpc": 1, // 0 = disabled, 1 = enabled as Cider, 2 = enabled as Apple Music - "discordClearActivityOnPause": 1, // 0 = disabled, 1 = enabled - "volume": 1 - }, - "home": { - "followedArtists": [], - "favoriteItems": [] - }, - "libraryPrefs": { - "songs": { - "sort": "name", - "sortOrder": "asc", - "size": "normal" - } - }, - "audio": { - "quality": "990", - "seamless_audio": true, - "normalization": false, - "spatial": false, - "spatial_properties": { - "presets": [], - "gain": 0.8, - "listener_position": [0, 0, 0], - "audio_position": [0, 0, 0], - "room_dimensions": { - "width": 32, - "height": 12, - "depth": 32 - }, - "room_materials": { - "left": 'metal', - "right": 'metal', - "front": 'brick-bare', - "back": 'brick-bare', - "down": 'acoustic-ceiling-tiles', - "up": 'acoustic-ceiling-tiles', - } - } - }, - "visual": { - "theme": "", - "scrollbars": 0, // 0 = show on hover, 2 = always hide, 3 = always show - "refresh_rate": 0, - "animated_artwork": "limited", // 0 = always, 1 = limited, 2 = never - "animated_artwork_qualityLevel": 1, - "bg_artwork_rotation": false, - "hw_acceleration": "default", // default, webgpu, disabled - "videoRes": 720 - }, - "lyrics": { - "enable_mxm": false, - "mxm_karaoke": false, - "mxm_language": "en", - "enable_yt": false, - }, - "lastfm": { - "enabled": false, - "scrobble_after": 50, - "auth_token": "", - "enabledRemoveFeaturingArtists": true, - "NowPlaying": "true" - }, - "advanced": { - "AudioContext": false, - "experiments": [] - } -} - -const merge = (target, source) => { - // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties - for (const key of Object.keys(source)) { - if (source[key] instanceof Object) Object.assign(source[key], merge(target[key], source[key])) - } - // Join `target` and modified `source` - Object.assign(target || {}, source) - return target -} - - -const Store = require("electron-store"); -app.cfg = new Store({ - defaults: configDefaults -}); -let currentCfg = app.cfg.get() -app.cfg.set(merge(configDefaults, currentCfg)) - -app.paths = { - ciderCache: resolve(app.getPath("userData"), "CiderCache"), - themes: resolve(app.getPath("userData"), "Themes"), - plugins: resolve(app.getPath("userData"), "Plugins"), -} - -switch (app.cfg.get("visual.hw_acceleration")) { - default: - case "default": - app.commandLine.appendSwitch('enable-accelerated-mjpeg-decode') - app.commandLine.appendSwitch('enable-accelerated-video') - app.commandLine.appendSwitch('disable-gpu-driver-bug-workarounds') - app.commandLine.appendSwitch('ignore-gpu-blacklist') - app.commandLine.appendSwitch('enable-native-gpu-memory-buffers') - app.commandLine.appendSwitch('enable-accelerated-video-decode'); - app.commandLine.appendSwitch('enable-gpu-rasterization'); - app.commandLine.appendSwitch('enable-native-gpu-memory-buffers'); - app.commandLine.appendSwitch('enable-oop-rasterization'); - break; - case "webgpu": - console.info("WebGPU is enabled."); - app.commandLine.appendSwitch('enable-unsafe-webgpu') - break; - case "disabled": - console.info("Hardware acceleration is disabled."); - app.commandLine.appendSwitch('disable-gpu') - break; -} - -// Creating the Application Window and Calling all the Functions -function CreateWindow() { - if (app.isQuiting) { - app.quit(); - return; - } - - /** CIDER **/ - const ciderwin = require("./src/main/cider-base") - app.win = ciderwin - app.win.Start() - /** CIDER **/ -} - -if (process.platform === "linux") { - app.commandLine.appendSwitch('disable-features', 'MediaSessionService'); -} - -app.commandLine.appendSwitch('no-sandbox'); -// app.commandLine.appendSwitch('js-flags', '--max-old-space-size=1024') - -/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * App Event Handlers - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - -app.whenReady().then(async() => { - if (process.platform === "win32") { - app.commandLine.appendSwitch('high-dpi-support', 'true') - app.commandLine.appendSwitch('force-device-scale-factor', '1') - app.commandLine.appendSwitch('disable-pinch'); - } - if (comps == null) { - app.on("widevine-ready", () => { - console.log('[Cider] Application is Ready. Creating Window.') - if (!app.isPackaged) { - console.info('[Cider] Running in development mode.') - require('vue-devtools').install() - } - CreateWindow() - }) - return - } - await comps.whenReady(); - console.log('components ready:', comps.status()); - - console.log('[Cider] Application is Ready. Creating Window.') - if (!app.isPackaged) { - console.info('[Cider] Running in development mode.') - require('vue-devtools').install() - } - CreateWindow() -}) - - -app.on('before-quit', () => { - console.warn(`${app.getName()} exited.`); -}); - -// Widevine Stuff -app.on('widevine-ready', (version, lastVersion) => { - if (null !== lastVersion) { - console.log('[Cider][Widevine] Widevine ' + version + ', upgraded from ' + lastVersion + ', is ready to be used!') - } else { - console.log('[Cider][Widevine] Widevine ' + version + ' is ready to be used!') - } -}) - -app.on('widevine-update-pending', (currentVersion, pendingVersion) => { - console.log('[Cider][Widevine] Widevine ' + currentVersion + ' is ready to be upgraded to ' + pendingVersion + '!') -}) - -app.on('widevine-error', (error) => { - console.log('[Cider][Widevine] Widevine installation encountered an error: ' + error) - app.exit() -}) - -if (process.defaultApp) { - if (process.argv.length >= 2) { - customProtocols.forEach((customProtocol) => { - app.setAsDefaultProtocolClient(customProtocol, process.execPath, [resolve(process.argv[1])]) - }) - } -} else { - /* - * cider - Custom Cider Protocol - * ame - Custom AME Protocol (Backwards Compat.) - * itms - iTunes HTTP Protocol - * itmss - iTunes HTTPS Protocol - * musics - macOS Client Protocol - * music - macOS Client Protocol - */ - customProtocols.forEach((customProtocol) => { - app.setAsDefaultProtocolClient(customProtocol) - }) - -} - -app.on('open-url', (event, url) => { - event.preventDefault() - if (customProtocols.some(protocol => url.includes(protocol))) { - CiderBase.LinkHandler(url) - } -}) - -app.on('second-instance', (_e, argv) => { - console.warn(`[InstanceHandler][SecondInstanceHandler] Second Instance Started with args: [${argv.join(', ')}]`) - - // Checks if first instance is authorized and if second instance has protocol args - argv.forEach((value) => { - if (customProtocols.some(protocol => value.includes(protocol))) { - CiderBase.LinkHandler(value); - } - }) - - if (argv.includes("--force-quit")) { - console.warn('[InstanceHandler][SecondInstanceHandler] Force Quit found. Quitting App.'); - // app.isQuiting = true - app.quit() - } else if (CiderBase.win && true) { // If a Second Instance has Been Started - console.warn('[InstanceHandler][SecondInstanceHandler] Showing window.'); - app.win.show() - app.win.focus() - } -}) - -if (!app.requestSingleInstanceLock() && true) { - console.warn("[InstanceHandler] Existing Instance is Blocking Second Instance."); - app.quit(); - // app.isQuiting = true -} \ No newline at end of file diff --git a/package.json b/package.json index 2f0d7fa1..51fbe550 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,11 @@ "name": "cider", "applicationId": "Cider", "productName": "Cider", - "version": "1.0.0", + "version": "1.1.0", "description": "A new look into listening and enjoying music in style and performance.", - "license": "MIT", - "author": "Cider Collective (https://cider.sh)", + "license": "AGPL-3.0", + "main": "./build/index.js", + "author": "Cider Collective (https://cider.sh)", "repository": "https://github.com/ciderapp/Cider.git", "bugs": { "url": "https://github.com/ciderapp/Cider/issues?q=is%3Aopen+is%3Aissue+label%3Abug" @@ -13,11 +14,16 @@ "homepage": "https://cider.sh/", "buildResources": "resources", "scripts": { - "init": "yarn install --force", - "start": "electron . --enable-accelerated-mjpeg-decode --enable-accelerated-video --disable-gpu-driver-bug-workarounds --ignore-gpu-blacklist --enable-native-gpu-memory-buffers", + "build": "tsc", + "watch": "tsc --watch", + "start": "run-script-os", + "start:win32": "npm run build && set ELECTRON_ENABLE_LOGGING=true && electron ./build/index.js --enable-accelerated-mjpeg-decode --enable-accelerated-video --disable-gpu-driver-bug-workarounds --ignore-gpu-blacklist --enable-native-gpu-memory-buffers", + "start:linux": "npm run build && export ELECTRON_ENABLE_LOGGING=true && electron ./build/index.js --enable-accelerated-mjpeg-decode --enable-accelerated-video --disable-gpu-driver-bug-workarounds --ignore-gpu-blacklist --enable-native-gpu-memory-buffers", + "start:darwin": "npm run build && export ELECTRON_ENABLE_LOGGING=true && electron ./build/index.js --enable-accelerated-mjpeg-decode --enable-accelerated-video --disable-gpu-driver-bug-workarounds --ignore-gpu-blacklist --enable-native-gpu-memory-buffers", "pack": "electron-builder --dir", - "dist": "electron-builder", - "msft": "electron-builder -c msft-package.json", + "dist": "npm run build && electron-builder", + "dist:all": "npm run build && electron-builder -mwl", + "msft": "npm run build && electron-builder -c msft-package.json", "postinstall": "electron-builder install-app-deps" }, "dependencies": { @@ -25,29 +31,39 @@ "discord-rpc": "^4.0.1", "ejs": "^3.1.6", "electron-fetch": "^1.7.4", - "electron-log": "^4.4.3", + "electron-log": "^4.4.4", + "electron-notarize": "^1.1.1", + "electron-packager": "^15.4.0", "electron-store": "^8.0.1", "electron-updater": "^4.6.1", "electron-window-state": "^5.0.3", "express": "^4.17.2", "get-port": "^5.1.1", + "jsonc": "^2.0.0", "lastfmapi": "^0.1.1", + "mdns-js": "github:bitfocus/node-mdns-js", "mpris-service": "^2.1.2", "music-metadata": "^7.11.4", + "qrcode": "^1.5.0", "qrcode-terminal": "^0.12.0", "react": "^17.0.2", "react-dom": "^17.0.2", + "run-script-os": "^1.1.6", "source-map-support": "^0.5.21", "v8-compile-cache": "^2.3.0", - "ws": "^8.3.0", + "ws": "^8.4.2", "xml2js": "^0.4.23", "youtube-search-without-api-key": "^1.0.7" }, "devDependencies": { + "@types/discord-rpc": "^4.0.0", + "@types/express": "^4.17.13", + "@types/ws": "^8.2.2", "electron": "https://github.com/castlabs/electron-releases.git", "electron-builder": "^22.14.5", "electron-webpack": "^2.8.2", "musickit-typescript": "^1.2.4", + "typescript": "^4.5.4", "vue-devtools": "^5.1.4", "webpack": "~5.65.0" }, @@ -74,12 +90,14 @@ } ], "build": { - "electronVersion": "16.0.6", + "electronVersion": "16.0.7", "electronDownload": { - "version": "16.0.6+wvcus", + "version": "16.0.7+wvcus", "mirror": "https://github.com/castlabs/electron-releases/releases/download/v" }, "appId": "cider", + "afterPack": "./resources/afterPack.js", + "afterSign": "./resources/notarize.js", "protocols": [ { "name": "Cider", @@ -95,9 +113,9 @@ ], "extends": null, "files": [ - "**/*", - "./src/**/*", - "./resources/icons/icon.*" + "./build/**/*", + "./resources/icons/icon.*", + "./src/**/*" ], "linux": { "target": [ @@ -119,6 +137,13 @@ "backgroundColor": "transparent", "setBuildNumber": true }, + "nsis": { + "oneClick": false, + "perMachine": false, + "allowToChangeInstallationDirectory": true, + "license": "LICENSE", + "deleteAppDataOnUninstall": true + }, "win": { "target": [ "nsis" @@ -126,13 +151,20 @@ "icon": "resources/icons/icon.ico" }, "directories": { - "buildResources": "." + "buildResources": ".", + "output": "dist" }, "mac": { + "hardenedRuntime": true, + "gatekeeperAssess": false, "icon": "./resources/icons/icon.icns", "category": "public.app-category.music", - "entitlements": "resources/entitlements.mac.plist", - "darkModeSupport": true + "entitlements": "./resources/entitlements.mac.plist", + "entitlementsInherit": "./resources/entitlements.mac.plist", + "darkModeSupport": true, + "target": [ + "dmg" + ] } } } diff --git a/resources/afterPack.js b/resources/afterPack.js new file mode 100644 index 00000000..6c677c49 --- /dev/null +++ b/resources/afterPack.js @@ -0,0 +1,18 @@ +exports.default = function(context) { + const { execSync } = require('child_process') + + if (process.platform !== 'darwin') + return + + console.log('Castlabs-evs update start') + execSync('python3 -m pip install --upgrade castlabs-evs') + console.log('Castlabs-evs update complete') + + + + console.log('VMP signing start') + + execSync('python3 -m castlabs_evs.vmp -n sign-pkg dist/mac',{stdio: 'inherit'}) + + console.log('VMP signing complete') +} \ No newline at end of file diff --git a/resources/entitlements.mac.plist b/resources/entitlements.mac.plist index 8fff4988..fcb8d4a3 100644 --- a/resources/entitlements.mac.plist +++ b/resources/entitlements.mac.plist @@ -2,11 +2,13 @@ + + com.apple.security.cs.allow-jit + com.apple.security.cs.allow-unsigned-executable-memory + com.apple.security.cs.disable-library-validation - com.apple.security.cs.allow-dyld-environment-variables - - + \ No newline at end of file diff --git a/resources/icons/icon-test.ico b/resources/icons/icon-test.ico new file mode 100644 index 00000000..d6fd03df Binary files /dev/null and b/resources/icons/icon-test.ico differ diff --git a/resources/icons/icon.ico b/resources/icons/icon.ico index f3f78e8a..d4a7449e 100644 Binary files a/resources/icons/icon.ico and b/resources/icons/icon.ico differ diff --git a/resources/notarize.js b/resources/notarize.js new file mode 100644 index 00000000..9e98e18c --- /dev/null +++ b/resources/notarize.js @@ -0,0 +1,20 @@ + + +require('dotenv').config(); + const { notarize } = require('electron-notarize'); + +exports.default = async function notarizing(context) { + const { electronPlatformName, appOutDir } = context; + if (electronPlatformName !== 'darwin') { + return; + } + + const appName = context.packager.appInfo.productFilename; + + return await notarize({ + appBundleId: 'com.ciderapp.cider', + appPath: `${appOutDir}/${appName}.app`, + appleId: process.env.APPLEID, + appleIdPassword: process.env.APPLEIDPASS, + }); +}; \ No newline at end of file diff --git a/src/i18n/README.md b/src/i18n/README.md new file mode 100644 index 00000000..fa5b5a67 --- /dev/null +++ b/src/i18n/README.md @@ -0,0 +1,8 @@ +# Cider i18n +Some notes about Cider's i18n support. +* Localization files are stored in jsonc format aka "JSON with Comments" +* The default language is English. +* The default language is used for messages that are not translated. +* Try when possible to keep the messages the similar in length to the English ones. +* Most of the strings in the content area are provided and translated by Apple themselves, and do not need to be translated. + * The language Apple Music uses are dependent on the storefront region. \ No newline at end of file diff --git a/src/i18n/de_DE.jsonc b/src/i18n/de_DE.jsonc new file mode 100644 index 00000000..0a7f9732 --- /dev/null +++ b/src/i18n/de_DE.jsonc @@ -0,0 +1,299 @@ +{ // Base File + + // i18n Info + "i18n.languageName": "Deutsch", // name of language in native language + "i18n.languageNameEnglish": "German", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@motz0815", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "Cider", + + "date.format": "${d}.${m}.${y}", + + // Dialogs + "dialog.cancel": "Abbrechen", + "dialog.ok": "OK", + + // Notification + "notification.updatingLibrarySongs": "Aktualisiere Songs...", + "notification.updatingLibraryAlbums": "Aktualisiere Alben...", + "notification.updatingLibraryArtists": "Aktualisiere Künstler...", + // Terms + "term.appleInc": "Apple Inc.", + "term.appleMusic": "Apple Music", + "term.applePodcasts": "Apple Podcasts", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "Mehr erfahren", + "term.accountSettings": "Account-Einstellungen", + "term.logout": "Abmelden", + "term.login": "Anmelden", + "term.about": "Über", + "term.privateSession": "Private Sitzung", + "term.queue": "Warteschlange", + "term.search": "Suche", + "term.library": "Mediathek", + "term.listenNow": "Jetzt Hören", + "term.browse": "Durchsuchen", + "term.radio": "Radio", + "term.recentlyAdded": "Zuletzt hinzugefügt", + "term.songs": "Songs", + "term.albums": "Alben", + "term.artists": "Künstler", + "term.podcasts": "Podcasts", + "term.playlists": "Playlists", + "term.playlist": "Playlist", + "term.play": "Play", + "term.pause": "Pause", + "term.previous": "Zurück", + "term.next": "Weiter", + "term.shuffle": "Zufällig", + "term.repeat": "Wiederholen", + "term.volume": "Lautstärke", + "term.mute": "Stummschalten", + "term.unmute": "Stummschaltung aufheben", + "term.share": "Teilen", + "term.settings": "Einstellungen", + "term.seeAll": "Alle Sehen", + "term.sortBy": "Sortieren nach", + "term.sortBy.album": "Album", + "term.sortBy.artist": "Künstler", + "term.sortBy.name": "Name", + "term.sortBy.genre": "Genre", + "term.sortBy.releaseDate": "Veröffentlichungsdatum", + "term.sortBy.duration": "Länge", + "term.sortOrder": "A-Z", + "term.sortOrder.ascending": "Aufsteigend", + "term.sortOrder.descending": "Absteigend", + "term.viewAs": "Ansehen als", + "term.viewAs.coverArt": "Cover-Bild", + "term.viewAs.list": "Liste", + "term.size": "Größe", + "term.size.normal": "Normal", + "term.size.compact": "Kompakt", + "term.enable": "Aktivieren", + "term.disable": "Deaktivieren", + "term.enabled": "Aktiv", + "term.disabled": "Nicht aktiv", + "term.connect": "Verbinden", + "term.connecting": "Verbindet", + "term.disconnect": "Trennen", + "term.authed": "Autorisiert", + "term.confirm": "Bestätigen ?", + "term.more": "Mehr", + "term.less": "Weniger", + "term.showMore": "Zeige mehr", + "term.showLess": "Zeige weniger", + "term.topSongs" : "Top Songs", + "term.latestReleases": "Letzte Veröffentlichungen", + "term.time.added": "Hinzugefügt", + "term.time.released": "Veröffentlicht", + "term.time.updated": "Aktualisiert", + "term.time.hours": "Stunden", + "term.time.hour": "Stunde", + "term.time.minutes": "Minuten", + "term.time.minute": "Minute", + "term.time.seconds": "Sekunden", + "term.time.second": "Sekunde", + "term.fullscreenView": "Vollbildansicht", + "term.defaultView": "Normale Ansicht", + "term.spacializedAudioSetting": "Räumliches Audio", + "term.clearAll": "Alle löschen", + "term.recentStations": "Letzte Stationen", + "term.language": "Sprache", + "term.funLanguages": "Spaß", + "term.noLyrics": "Lädt... / Liedtext nicht gefunden./ Instrumental.", + "term.copyright": "Copyright", + "term.rightsReserved": "All Rights Reserved.", + "term.sponsor": "Unterstütze dieses Projekt", + "term.ciderTeam": "Cider Team", + "term.developer": "Entwickler", + "term.socialTeam": "Social Team", + "term.contributors": "Mithelfer", + "term.equalizer": "Equalizer", + "term.reset": "Zurücksetzen", + "term.tracks": "Lieder", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "Videos", + "term.menu": "Menü", + "term.showAlbum": "Zeige ganzes Album", + + // Home + "home.title": "Home", + "home.recentlyPlayed": "Zuletzt gespielt", + "home.recentlyAdded": "Zuletzt hinzugefügt", + "home.artistsFeed": "Dein Künstler-Feed", + "home.artistsFeed.noArtist": "Folge zuerst einigen Künstlern, dann wirst du hier die neusten Lieder sehen.", + "home.madeForYou": "Für dich gemacht", + "home.friendsListeningTo": "Freunde hören", + "home.followedArtists": "Gefolgte Künstler", + // Errors + "error.appleMusicSubRequired": "Apple Music benötigt ein Abonnement.", + "error.connectionError": "Es ist ein Fehler aufgetreten, während sich mit Apple Music verbunden wurde.", + "error.noResults": "Keine Ergebnisse.", + "error.noResults.description": "Versuche einen anderen Suchbegriff.", + + //Podcasts + "podcast.followOnCider": "Folge auf Cider", + "podcast.followedOnCider": "Gefolgt auf Cider", + "podcast.subscribeOnItunes": "Folge auf iTunes", + "podcast.subscribedOnItunes": "Gefolgt auf iTunes", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "Episoden", + "podcast.playEpisode": "Spiele Episode", + "podcast.website": "Podcast Webseite", + + // Actions + "action.addToLibrary": "Zur Mediathek hinzufügen", + "action.addToLibrary.success": "Zur Mediathek hinzugefügt", + "action.addToLibrary.error": "Fehler beim Hinzufügen zur Mediathek", + "action.removeFromLibrary": "Aus Mediathek entfernen", + "action.removeFromLibrary.success": "Aus Mediathek entfernt", + "action.addToQueue": "Zur Warteschlange hinzufügen", + "action.addToQueue.success": "Zur Warteschlange hinzugefügt", + "action.addToQueue.error": "Fehler beim Hinzufügen zur Warteschlange", + "action.removeFromQueue": "Aus Warteschlange entfernen", + "action.removeFromQueue.success": "Aus Warteschlange entfernt", + "action.removeFromQueue.error": "Fehler beim Entfernen aus der Warteschlange", + "action.addToPlaylist": "Zur Playlist hinzufügen", + "action.removeFromPlaylist": "Aus Playlist entfernen", + "action.addToFavorites": "Zu Favoriten hinzufügen", + "action.follow": "Folgen", + "action.follow.success": "Gefolgt", + "action.follow.error": "Fehler beim Folgen", + "action.unfollow": "Entfolgen", + "action.unfollow.success": "Entfolgt", + "action.unfollow.error": "Fehler beim Entfolgen", + "action.playNext": "Spiele als Nächstes", + "action.playLater": "Spiele später", + "action.startRadio": "Starte Radio", + "action.goToArtist": "Gehe zu Künstler", + "action.goToAlbum": "Gehe zu Album", + "action.moveToTop": "Gehe zum Anfang", + "action.share": "Teilen", + "action.rename": "Umbenennen", + "action.love": "Lieben", + "action.unlove": "Entlieben", + "action.dislike": "Dislike", + "action.undoDislike": "Dislike entfernen", + "action.showWebRemoteQR": "Zeige Web-Remote QR-Code", + "action.playTracksNext": "Spiele ${app.selectedMediaItems.length} Lieder als Nächstes", + "action.playTracksLater": "Spiele ${app.selectedMediaItems.length} Lieder später", + "action.removeTracks": "Entferne ${self.selectedItems.length} Lieder aus der Warteschlange", + "action.import": "Importieren", + "action.export": "Exportieren", + + // Settings - General + "settings.header.general": "Allgemein", + "settings.header.general.description": "Passe die allgemeinen Einstellungen für Cider an.", + "settings.option.general.language": "Sprache", + + // Language optgroups + "settings.option.general.language.main": "Sprachen", + "settings.option.general.language.fun": "Lustige Sprachen", + "settings.option.general.language.unsorted": "Unsortiert", + + // Settings - Audio + "settings.header.audio": "Audio", + "settings.header.audio.description": "Passe die Audio-Einstellungen für Cider an.", + "settings.option.audio.quality": "Audioqualität", // Dropdown + "settings.header.audio.quality.high": "Hoch", + "settings.header.audio.quality.low": "Niedrig", + "settings.header.audio.quality.auto": "Auto", + "settings.option.audio.seamlessTransition": "Nahtloser Audioübergang", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "Akiviere erweiterte Funktionalität", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "Das Aktivieren der erweiterten Funktionalität ermöglicht spezielle Features wie Audio-Normalisierung, Equalizer und Visualizer, jedoch könnte dies auf einigen Systemen zu Aussetzern in der Musik führen.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Audio-Normalisierung", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Normalisiert die Lautstärke aller Lieder, um die Hörerfahrung einheitlicher zu machen.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Räumliches Audio", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Macht die Musik räumlicher (3D-Effekt) (Beachte: Dies ist kein Dolby Atmos)", + // Settings - Visual + "settings.header.visual": "Visuell", + "settings.header.visual.description": "Passe die visuellen Einstellungen für Cider an.", + "settings.option.visual.windowBackgroundStyle": "Fensterhintergrund-Stil", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "Keiner", + "settings.header.visual.windowBackgroundStyle.artwork": "Coverbild", + "settings.header.visual.windowBackgroundStyle.image": "Bild", + "settings.option.visual.animatedArtwork": "Animiertes Coverbild", // Dropdown + "settings.header.visual.animatedArtwork.always": "Immer", + "settings.header.visual.animatedArtwork.limited": "Beschränkt auf Seiten und Spezialeinträge", + "settings.header.visual.animatedArtwork.disable": "Überall deaktivieren", + "settings.option.visual.animatedArtworkQuality": "Qualität des Animierten Coverbilds", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "Niedrig", + "settings.header.visual.animatedArtworkQuality.medium": "Mittel", + "settings.header.visual.animatedArtworkQuality.high": "Hoch", + "settings.header.visual.animatedArtworkQuality.veryHigh": "Sehr hoch", + "settings.header.visual.animatedArtworkQuality.extreme": "Extrem", + "settings.option.visual.animatedWindowBackground": "Animierter Fensterhintergrund", // Toggle + "settings.option.visual.hardwareAcceleration": "Hardware-Beschleunigung", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "Erfordert Neustart der Anwendung", + "settings.header.visual.hardwareAcceleration.default": "Normal", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "Persönliche Daten anzeigen", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "Liedtext", + "settings.header.lyrics.description": "Passe die Liedtext-Einstellungen für Cider an.", + "settings.option.lyrics.enableMusixmatch": "Aktiviere Musixmatch-Liedtexte", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "Aktiviere Karaoke-Modus (nur mit Musixmatch)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Bevorzugte Sprache für Musixmatch-Übersetzung", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "Aktiviere YouTube-Liedtexte für Musikvideos", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "Konnektivität", + "settings.header.connectivity.description": "Passe die Konnektivitäts-Einstellungen für Cider an.", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown + "settings.option.connectivity.playbackNotifications": "Wiedergabe-Benachrichtigungen", // Toggle + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "Zeige als 'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "Zeige als 'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "Leere Discord Rich Presence wenn pausiert", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble Delay (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "Aktiviere LastFM Jetzt spielend", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Entferne Künstler-Featuring von Liedtitel (LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Filtere gelooptes Lied (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "Experimentell", + "settings.header.experimental.description": "Passe die experimentellen Einstellungen für Cider an.", + "settings.option.experimental.compactUI": "Kompaktes UI", // Toggle + "settings.option.experimental.closeButtonBehaviour": "Verhalten der Schließtaste", + "settings.option.experimental.closeButtonBehaviour.quit": "Cider Schließen", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "In Taskleiste minimieren", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "In den Tray minimieren", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "Räumliche Einstellungen", + "spatial.width" : "Breite", + "spatial.height" : "Höhe", + "spatial.depth" : "Tiefe", + "spatial.gain" : "Gain", + "spatial.roomMaterials" : "Raummaterialien", + "spatial.roomDimensions" : "Raumabmessungen", + "spatial.roomPositions" : "Raumpositionen", + "spatial.setDimensions" : "Setze Abmessungen", + "spatial.setPositions" : "Setze Positionen", + "spatial.up" : "Oben", + "spatial.front" : "Vorne", + "spatial.left" : "Links", + "spatial.right" : "Rechts", + "spatial.back" : "Hinten", + "spatial.down" : "Unten", + "spatial.listener" : "Hörer*in", + "spatial.audioSource" : "Audioquelle", + + // Settings - Unfinished + "settings.header.unfinished": "Unfertig", + + // Web Remote + "remote.web.title": "Cider Remote", + "remote.web.description": "Scanne den QR-Code um dein Handy mit dieser Cider-Instanz zu verbinden", + + // About + "about.thanks": "Vielen lieben Dank an das Cider Collective Team und an alle Mithelfer." +} diff --git a/src/i18n/el_GR.jsonc b/src/i18n/el_GR.jsonc new file mode 100644 index 00000000..6dc5452a --- /dev/null +++ b/src/i18n/el_GR.jsonc @@ -0,0 +1,299 @@ +{ + + // i18n Info + "i18n.languageName": "Ελληνικά", + "i18n.languageNameEnglish": "Greek", + "i18n.category": "main", + "i18n.authors": "@down-bad", + + // App info + "app.name": "Cider", + + "date.format": "${d} ${m}, ${y}", + + // Dialogs + "dialog.cancel": "Ακύρωση", + "dialog.ok": "ΟΚ", + + // Notification + "notification.updatingLibrarySongs": "Ενημέρωση βιβλιοθήκης τραγουδιών...", + "notification.updatingLibraryAlbums": "Ενημέρωση βιβλιοθήκης άλμπουμ...", + "notification.updatingLibraryArtists": "Ενημέρωση βιβλιοθήκης καλλιτεχνών...", + // Terms + "term.appleInc": "Apple Inc.", + "term.appleMusic": "Apple Music", + "term.applePodcasts": "Apple Podcasts", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "Μάθετε περισσότερα", + "term.accountSettings": "Ρυθμίσεις λογαριασμού", + "term.logout": "Αποσύνδεση", + "term.login": "Σύνδεση", + "term.about": "Σχετικά με", + "term.privateSession": "Ιδιωτική περίοδος λειτουργίας", + "term.queue": "Ουρά", + "term.search": "Εύρεση", + "term.library": "Βιβλιοθήκη", + "term.listenNow": "Ακρόαση", + "term.browse": "Περιήγηση", + "term.radio": "Ράδιο", + "term.recentlyAdded": "Πρόσφατες προσθήκες", + "term.songs": "Τραγούδια", + "term.albums": "Άλμπουμ", + "term.artists": "Καλλιτέχνες", + "term.podcasts": "Podcast", + "term.playlists": "Λίστες αναπαραγωγής", + "term.playlist": "Λίστα αναπαραγωγής", + "term.play": "Αναπαραγωγή", + "term.pause": "Παύση", + "term.previous": "Προηγούμενο", + "term.next": "Επόμενο", + "term.shuffle": "Τυχαία σειρά", + "term.repeat": "Επανάληψη", + "term.volume": "Ένταση", + "term.mute": "Σίγαση", + "term.unmute": "Κατάργηση σίγασης", + "term.share": "Κοινή Χρήση", + "term.settings": "Ρυθμίσεις", + "term.seeAll": "Προβολή όλων", + "term.sortBy": "Ταξινόμηση κατά", + "term.sortBy.album": "Άλμπουμ", + "term.sortBy.artist": "Καλλιτέχνη", + "term.sortBy.name": "Όνομα", + "term.sortBy.genre": "Είδος", + "term.sortBy.releaseDate": "Ημερομηνία κυκλοφορίας", + "term.sortBy.duration": "Διάρκεια", + "term.sortOrder": "Α-Ω", + "term.sortOrder.ascending": "Αύξουσα", + "term.sortOrder.descending": "Φθίνουσα", + "term.viewAs": "Προβολή ως", + "term.viewAs.coverArt": "Εξώφυλλο", + "term.viewAs.list": "Λίστα", + "term.size": "Μέγεθος", + "term.size.normal": "Κανονικό", + "term.size.compact": "Συμπαγή", + "term.enable": "Ενεργοποίηση", + "term.disable": "Απενεργοποίηση", + "term.enabled": "Ενεργοποιημένο", + "term.disabled": "Απενεργοποιημένο", + "term.connect": "Σύνδεση", + "term.connecting": "Γίνεται σύνδεση", + "term.disconnect": "Αποσύνδεση", + "term.authed": "Επικυρωμένο", + "term.confirm": "Σίγουρα;", + "term.more": "Περισσότερα", + "term.less": "Λιγότερα", + "term.showMore": "Εμφάνιση περισσότερων", + "term.showLess": "Εμφάνιση λιγότερων", + "term.topSongs" : "Κορυφαία τραγούδια", + "term.latestReleases": "Τελευταίες κυκλοφορίες", + "term.time.added": "Προστέθηκε", + "term.time.released": "Κυκλοφόρησε", + "term.time.updated": "Ενημερώθηκε", + "term.time.hours": "ώρες", + "term.time.hour": "ώρα", + "term.time.minutes": "λεπτά", + "term.time.minute": "λεπτό", + "term.time.seconds": "δευτερόλεπτα", + "term.time.second": "δευτερόλεπτο", + "term.fullscreenView": "Πλήρης οθόνη", + "term.defaultView": "Κανονική οθόνη", + "term.spacializedAudioSetting": "Χωρική ρύθμιση ήχου", + "term.clearAll": "Εκκαθάριση όλων", + "term.recentStations": "Πρόσφατοι σταθμοί", + "term.language": "Γλώσσα", + "term.funLanguages": "Για πλάκα", + "term.noLyrics": "Φόρτωση... / Δεν βρέθηκαν στίχοι. / Ορχηστικό.", + "term.copyright": "Copyright", + "term.rightsReserved": "Όλα τα δικαιώματα διατηρούνται.", + "term.sponsor": "Χορήγησε αυτό το έργο", + "term.ciderTeam": "Ομάδα Cider", + "term.developer": "Προγραμματιστής", + "term.socialTeam": "Κοινωνική Ομάδα", + "term.contributors": "Συνεισφέροντες", + "term.equalizer": "Ισοσταθμιστής", + "term.reset": "Επαναφορά", + "term.tracks": "τραγούδια", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "Βίντεο", + "term.menu": "Μενού", + "term.showAlbum": "Εμφάνιση ολόκληρου άλμπουμ", + + // Home + "home.title": "Αρχική", + "home.recentlyPlayed": "Έπαιξαν πρόσφατα", + "home.recentlyAdded": "Πρόσφατες προσθήκες", + "home.artistsFeed": "Ροή των καλλιτεχνών σου", + "home.artistsFeed.noArtist": "Ακολούθησε μερικούς καλλιτέχνες πρώτα και οι τελευταίες κυκλοφορίες τους θα εμφανίζονται εδώ", + "home.madeForYou": "Δημιουργήθηκε για εσάς", + "home.friendsListeningTo": "Οι φίλοι σου ακούν", + "home.followedArtists": "Καλλιτέχνες που ακολουθείτε", + // Errors + "error.appleMusicSubRequired": "Το Apple Music απαιτεί μια συνδρομή.", + "error.connectionError": "Δεν είναι δυνατή η σύνδεση με το Apple Music.", + "error.noResults": "Κανένα αποτέλεσμα.", + "error.noResults.description": "Δοκιμάστε μια νέα αναζήτηση.", + + //Podcasts + "podcast.followOnCider": "Ακολούθηση στο Cider", + "podcast.followedOnCider": "Ακολουθείτε στο Cider", + "podcast.subscribeOnItunes": "Συνδρομή στο iTunes", + "podcast.subscribedOnItunes": "Συνδρομητής στο iTunes", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "Επεισόδια", + "podcast.playEpisode": "Αναπαραγωγή επεισοδίου", + "podcast.website": "Ιστότοπος Podcast", + + // Actions + "action.addToLibrary": "Προσθήκη στη βιβλιοθήκη", + "action.addToLibrary.success": "Προστέθηκε στη βιβλιοθήκη", + "action.addToLibrary.error": "Σφάλμα Προσθήκης στη βιβλιοθήκης", + "action.removeFromLibrary": "Αφαίρεση από τη βιβλιοθήκη", + "action.removeFromLibrary.success": "Αφαιρέθηκε από τη βιβλιοθήκη", + "action.addToQueue": "Προσθήκη στην ουρά", + "action.addToQueue.success": "Προστέθηκε στην ουρά", + "action.addToQueue.error": "Προστέθηκε στην ουρά", + "action.removeFromQueue": "Αφαίρεση από την ουρά", + "action.removeFromQueue.success": "Αφαιρέθηκε από την ουρά", + "action.removeFromQueue.error": "Σφάλμα Αφαίρεσης από την ουρά", + "action.addToPlaylist": "Προσθήκη σε λίστα", + "action.removeFromPlaylist": "Αφαίρεση από λίστα", + "action.addToFavorites": "Προσθήκη στα αγαπημένα", + "action.follow": "Ακολούθηση", + "action.follow.success": "Ακολουθήθηκε", + "action.follow.error": "Σφάλμα ακολούθησης", + "action.unfollow": "Διακοπή ακολούθησης", + "action.unfollow.success": "Έγινε διακοπή ακολούθησης", + "action.unfollow.error": "Σφάλμα διακοπής ακολούθησης ", + "action.playNext": "Αναπαραγωγή ως επόμενου", + "action.playLater": "Αναπαραγωγή αργότερα", + "action.startRadio": "Έναρξη ραδιοφώνου", + "action.goToArtist": "Μετάβαση σε καλλιτέχνη", + "action.goToAlbum": "Μετάβαση σε άλμπουμ", + "action.moveToTop": "Μετακίνηση στη κορυφή", + "action.share": "Κοινή χρήση", + "action.rename": "Μετονομασία", + "action.love": "Μου αρέσει πολύ", + "action.unlove": "Αναίρεση \"Μου αρέσει\"", + "action.dislike": "Δεν μου αρέσει", + "action.undoDislike": "Αναίρεση \"Δεν μου αρέσει\"", + "action.showWebRemoteQR": "Εμφάνιση Web Remote QR", + "action.playTracksNext": "Αναπαραγωγή ${app.selectedMediaItems.length} τραγουδιών ως επόμενων", + "action.playTracksLater": "Αναπαραγωγή ${app.selectedMediaItems.length} τραγουδιών αργότερα", + "action.removeTracks": "Αφαίρεση ${self.selectedItems.length} τραγουδιών από την ουρά", + "action.import": "Εισαγωγή", + "action.export": "Εξαγωγή", + + // Settings - General + "settings.header.general": "Γενικά", + "settings.header.general.description": "Προσαρμογή γενικών ρυθμίσεων για το Cider.", + "settings.option.general.language": "Γλώσσα", + + // Language optgroups + "settings.option.general.language.main": "Γλώσσες", + "settings.option.general.language.fun": "Γλώσσες για πλάκα", + "settings.option.general.language.unsorted": "Αταξινόμητες", + + // Settings - Audio + "settings.header.audio": "Ήχος", + "settings.header.audio.description": "Προσαρμογή ρυθμίσεων ήχου για το Cider.", + "settings.option.audio.quality": "Ποιότητα Ήχου", // Dropdown + "settings.header.audio.quality.high": "Υψηλή", + "settings.header.audio.quality.low": "Χαμηλή", + "settings.header.audio.quality.auto": "Αυτόματη", + "settings.option.audio.seamlessTransition": "Αδιάκοπη Μετάβαση Ήχου", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "Ενεργοποίηση Προηγμένης Λειτουργικότητας", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "Ενεργοποιώντας τη λειτουργικότητα AudioContext θα επιτρέψει σε επεκταμένες δυνατότητες ήχου όπως Κανονικοποίηση Έντασης Ήχου, Ισοσταθμιστές και Οπτικοποιητές, ωστόσο σε κάποια συστήματα μπορεί να προκαλέσει τραύλισμα ήχου.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Κανονικοποίηση Έντασης Ήχου", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Κανονικοποιεί την ένταση για μεμονωμένα κομμάτια για μια πιο ομοιόμορφη εμπειρία ακρόασης.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Χωρικοποίηση Ήχου", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Πιο τρισδιάστατος και χωρικοποιημένος ήχος (σημείωση: Αυτό δεν είναι Dolby Atmos)", + // Settings - Visual + "settings.header.visual": "Οπτικά", + "settings.header.visual.description": "Προσαρμογή οπτικών ρυθμίσεων για το Cider.", + "settings.option.visual.windowBackgroundStyle": "Στυλ Φόντου Παραθύρου", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "Κανένα", + "settings.header.visual.windowBackgroundStyle.artwork": "Εξώφυλλο", + "settings.header.visual.windowBackgroundStyle.image": "Εικόνα", + "settings.option.visual.animatedArtwork": "Κινούμενο Εξώφυλλο", // Dropdown + "settings.header.visual.animatedArtwork.always": "Πάντα", + "settings.header.visual.animatedArtwork.limited": "Περιορισμός σε σελίδες και ειδικές καταχωρήσεις", + "settings.header.visual.animatedArtwork.disable": "Απενεργοποιημένο παντού", + "settings.option.visual.animatedArtworkQuality": "Ποιότητα Κινούμενου Εξωφύλλου", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "Χαμηλή", + "settings.header.visual.animatedArtworkQuality.medium": "Μέτρια", + "settings.header.visual.animatedArtworkQuality.high": "Υψηλή", + "settings.header.visual.animatedArtworkQuality.veryHigh": "Πολύ Υψηλή", + "settings.header.visual.animatedArtworkQuality.extreme": "Ακραία", + "settings.option.visual.animatedWindowBackground": "Κινούμενο Φόντο Παραθύρου", // Toggle + "settings.option.visual.hardwareAcceleration": "Επιτάχυνση Υλικού", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "Απαιτεί επανεκκίνηση", + "settings.header.visual.hardwareAcceleration.default": "Προεπιλογή", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "Εμφάνιση προσωπικών στοιχείων", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "Στίχοι", + "settings.header.lyrics.description": "Προσαρμογή ρυθμίσεων στίχων για το Cider.", + "settings.option.lyrics.enableMusixmatch": "Ενεργοποίηση Στίχων Musixmatch", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "Ενεργοποίηση Λειτουργίας Καραόκε (Musixmatch μόνο)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Προτιμώμενη Γλώσσα Μετάφρασης Musixmatch", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "Ενεργοποίηση Στίχων Youtube για Μουσικά Βίντεο", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "Σύνδεση", + "settings.header.connectivity.description": "Προσαρμογή ρυθμίσεων σύνδεσης για το Cider.", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown + "settings.option.connectivity.playbackNotifications": "Ειδοποιήσεις Αναπαραγωγής", // Toggle + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "Εμφάνιση ως 'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "Εμφάνιση ως 'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "Εκκαθάριση του Discord Rich Presence στην Παύση", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "Καθυστέρηση LastFM Scrobble (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "Ενεργοποίηση LastFM \"Now Playing\"", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Αφαίρεση καλλιτεχνών feature από τον τίτλο του τραγουδιού (LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Φιλτράρισμα επανειλημμένου τραγουδιού (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "Πειραματικές", + "settings.header.experimental.description": "Προσαρμογή πειραματικών ρυθμίσεων για το Cider.", + "settings.option.experimental.compactUI": "Συμπαγής Διεπαφή", // Toggle + "settings.option.experimental.closeButtonBehaviour": "Συμπεριφορά Κουμπιού Εξόδου", + "settings.option.experimental.closeButtonBehaviour.quit": "Έξοδος του Cider", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "Ελαχιστοποίηση στη γραμμή εργασιών", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "Ελαχιστοποίηση στη γωνία γραμμής εργασιών", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "Χωρικές Ιδιότητες", + "spatial.width" : "Πλάτος", + "spatial.height" : "Ύψος", + "spatial.depth" : "Βάθος", + "spatial.gain" : "Απολαβή", + "spatial.roomMaterials" : "Υλικά Δωματίου", + "spatial.roomDimensions" : "Διαστάσεις Δωματίου", + "spatial.roomPositions" : "Θέσεις Δωματίου", + "spatial.setDimensions" : "Ορισμός Διαστάσεων", + "spatial.setPositions" : "Ορισμός Θέσεων", + "spatial.up" : "Πάνω", + "spatial.front" : "Πρόσοψη", + "spatial.left" : "Αριστερά", + "spatial.right" : "Δεξιά", + "spatial.back" : "Πίσω Όψη", + "spatial.down" : "Κάτω", + "spatial.listener" : "Ακροατής", + "spatial.audioSource" : "Πηγή Ήχου", + + // Settings - Unfinished + "settings.header.unfinished": "Ημιτελής", + + // Web Remote + "remote.web.title": "Cider Remote", + "remote.web.description": "Σαρώστε τον κωδικό QR για σύζευξη του Cider με το κινητό σας", + + //About + "about.thanks": "Μεγάλα ευχαριστώ στην Ομάδα Cider Collective και σε όλους τους συνεισφέροντές μας." +} \ No newline at end of file diff --git a/src/i18n/en_GB.jsonc b/src/i18n/en_GB.jsonc new file mode 100644 index 00000000..1606ba36 --- /dev/null +++ b/src/i18n/en_GB.jsonc @@ -0,0 +1,10 @@ +{ + // i18n Info + "i18n.languageName": "English (UK) (Roadman)", // name of language in native language + "i18n.languageNameEnglish": "English (UK)", // name of language in English + "i18n.category": "fun", // main = real language, fun = fun community languages + "i18n.authors": "Core", // Authors, if you contribute to this file feel free to add your name seperated with a space + "date.format": "${d} ${m}, ${y}", + + "home.friendsListeningTo": "Mandems Listening To" +} \ No newline at end of file diff --git a/src/i18n/en_HODOR.jsonc b/src/i18n/en_HODOR.jsonc new file mode 100644 index 00000000..5075fa0f --- /dev/null +++ b/src/i18n/en_HODOR.jsonc @@ -0,0 +1,296 @@ +{ // HODOR + + // i18n Info + "i18n.languageName": "HODOR", // name of language in native language + "i18n.languageNameEnglish": "HODOR", // name of language in English + "i18n.category": "fun", // main = real language, fun = fun community languages + "i18n.authors": "HODOR", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "HODOR", + + "date.format": "${m} ${d}, ${y}", + + // Dialogs + "dialog.cancel": "HODOR", + "dialog.ok": "HODOR", + + // Notification + "notification.updatingLibrarySongs": "HODOR HODOR HODOR...", + "notification.updatingLibraryAlbums": "HODOR HODOR HODOR...", + "notification.updatingLibraryArtists": "HODOR HODOR HODOR...", + // Terms + "term.appleInc": "HODOR Inc.", + "term.appleMusic": "HODOR HODOR", + "term.applePodcasts": "HODOR HODOR", + "term.itunes": "HODOR", + "term.github": "HODOR", + "term.discord": "HODOR", + "term.learnMore": "HODOR HODOR", + "term.accountSettings": "HODOR HODOR", + "term.logout": "HODOR", + "term.login": "HODOR", + "term.about": "HODOR", + "term.privateSession": "HODOR HODOR", + "term.queue": "HODOR", + "term.search": "HODOR", + "term.library": "HODOR", + "term.listenNow": "HODOR HODOR", + "term.browse": "HODOR", + "term.radio": "HODOR", + "term.recentlyAdded": "HODOR HODOR", + "term.songs": "HODOR", + "term.albums": "HODOR", + "term.artists": "HODOR", + "term.podcasts": "HODOR", + "term.playlists": "HODOR", + "term.playlist": "HODOR", + "term.play": "HODOR", + "term.pause": "HODOR", + "term.previous": "HODOR", + "term.next": "HODOR", + "term.shuffle": "HODOR", + "term.repeat": "HODOR", + "term.volume": "HODOR", + "term.mute": "HODOR", + "term.unmute": "HODOR", + "term.share": "HODOR", + "term.settings": "HODOR", + "term.seeAll": "HODOR HODOR", + "term.sortBy": "HODOR HODOR", + "term.sortBy.album": "HODOR", + "term.sortBy.artist": "HODOR", + "term.sortBy.name": "HODOR", + "term.sortBy.genre": "HODOR", + "term.sortBy.releaseDate": "HODOR HODOR", + "term.sortBy.duration": "HODOR", + "term.sortOrder": "HODOR-HODOR", + "term.sortOrder.ascending": "HODOR", + "term.sortOrder.descending": "HODOR", + "term.viewAs": "HODOR HODOR", + "term.viewAs.coverArt": "HODOR HODOR", + "term.viewAs.list": "HODOR", + "term.size": "HODOR", + "term.size.normal": "HODOR", + "term.size.compact": "HODOR", + "term.enable": "HODOR", + "term.disable": "HODOR", + "term.enabled": "HODOR", + "term.disabled": "HODOR", + "term.connect": "HODOR", + "term.connecting": "HODOR", + "term.disconnect": "HODOR", + "term.authed": "HODOR", + "term.confirm": "HODOR ?", + "term.more": "HODOR", + "term.less": "HODOR", + "term.showMore": "HODOR HODOR", + "term.showLess": "HODOR HODOR", + "term.topSongs" : "HODOR HODOR", + "term.latestReleases": "HODOR HODOR", + "term.time.added": "HODOR", + "term.time.released": "HODOR", + "term.time.updated": "HODOR", + "term.fullscreenView": "HODOR HODOR", + "term.defaultView": "HODOR HODOR", + "term.spacializedAudioSetting": "HODOR HODOR HODOR", + "term.clearAll": "HODOR HODOR", + "term.recentStations": "HODOR HODOR", + "term.language": "HODOR", + "term.noLyrics": "HODOR... / HODOR HODOR HODOR./ HODOR.", + "term.copyright": "HODOR", + "term.rightsReserved": "HODOR HODOR HODOR.", + "term.sponsor": "HODOR HODOR HODOR", + "term.ciderTeam": "HODOR HODOR", + "term.developer": "HODOR", + "term.socialTeam": "HODOR HODOR", + "term.contributors": "HODOR", + "term.equalizer": "HODOR", + "term.reset": "HODOR", + "term.tracks": "HODOR", // Assume x amount of tracks. e.g. 50 tracks + "term.time.hours": "HODOR", + "term.time.hour": "HODOR", + "term.time.minutes": "HODOR", + "term.time.minute": "HODOR", + "term.time.seconds": "HODOR", + "term.time.second": "HODOR", + "term.funLanguages": "HODOR", + "term.videos": "HODOR", + "term.menu": "HODOR", + "term.showAlbum": "HODOR HODOR HODOR", + + // Home + "home.title": "HODOR", + "home.recentlyPlayed": "HODOR HODOR", + "home.recentlyAdded": "HODOR HODOR", + "home.artistsFeed": "HODOR HODOR HODOR", + "home.artistsFeed.noArtist": "HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR", + "home.madeForYou": "HODOR HODOR HODOR", + "home.friendsListeningTo": "HODOR HODOR HODOR", + "home.followedArtists": "HODOR HODOR", + // Errors + "error.appleMusicSubRequired": "HODOR HODOR HODOR HODOR HODOR.", + "error.connectionError": "HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR.", + "error.noResults": "HODOR HODOR.", + "error.noResults.description": "HODOR HODOR HODOR HODOR.", + + //Podcasts + "podcast.followOnCider": "HODOR HODOR HODOR", + "podcast.followedOnCider": "HODOR HODOR HODOR", + "podcast.subscribeOnItunes": "HODOR HODOR HODOR", + "podcast.subscribedOnItunes": "HODOR HODOR HODOR", + "podcast.itunesStore": "HODOR HODOR", + "podcast.episodes": "HODOR", + "podcast.playEpisode": "HODOR HODOR", + "podcast.website": "HODOR HODOR", + + // Actions + "action.addToLibrary": "HODOR HODOR HODOR", + "action.addToLibrary.success": "HODOR HODOR HODOR", + "action.addToLibrary.error": "HODOR HODOR HODOR LiHODORbrary", + "action.removeFromLibrary": "HODOR HODOR HODOR", + "action.removeFromLibrary.success": "HODOR HODOR HODOR", + "action.addToQueue": "HODOR HODOR HODOR", + "action.addToQueue.success": "HODOR HODOR HODOR", + "action.addToQueue.error": "HODOR HODOR HODOR HODOR", + "action.removeFromQueue": "HODOR HODOR HODOR", + "action.removeFromQueue.success": "HODOR HODOR HODOR", + "action.removeFromQueue.error": "HODOR HODOR HODOR HODOR", + "action.addToPlaylist": "HODOR HODOR HODOR", + "action.removeFromPlaylist": "HODOR HODOR HODOR", + "action.addToFavorites": "HODOR HODOR HODOR", + "action.follow": "HODOR", + "action.follow.success": "HODOR", + "action.follow.error": "HODOR HODOR", + "action.unfollow": "HODOR", + "action.unfollow.success": "HODOR", + "action.unfollow.error": "HODOR HODOR", + "action.playNext": "HODOR HODOR", + "action.playLater": "HODOR HODOR", + "action.startRadio": "HODOR HODOR", + "action.goToArtist": "HODOR HODOR HODOR", + "action.goToAlbum": "HODOR HODOR HODOR", + "action.moveToTop": "HODOR HODOR HODOR", + "action.share": "HODOR", + "action.rename": "HODOR", + "action.love": "HODOR", + "action.unlove": "HODOR", + "action.dislike": "HODOR", + "action.undoDislike": "HODOR HODOR", + "action.showWebRemoteQR": "HODOR HODOR HODOR HODOR", + "action.playTracksNext": "HODOR ${app.selectedMediaItems.length} HODOR HODOR", + "action.playTracksLater": "HODOR ${app.selectedMediaItems.length} HODOR HODOR", + "action.removeTracks": "HODOR ${self.selectedItems.length} HODOR HODOR HODOR", + "action.import": "HODOR", + "action.export": "HODOR", + + // Settings - General (Reserved) + "settings.header.general": "HODOR HODOR", + "settings.header.general.description": "HODOR HODOR HODOR HODOR.", + "settings.option.general.language": "HODOR", + + // Language optgroups + "settings.option.general.language.main": "HODOR", + "settings.option.general.language.fun": "HODOR HODOR", + "settings.option.general.language.unsorted": "HODOR", + + // Settings - Audio + "settings.header.audio": "HODOR", + "settings.header.audio.description": "HODOR HODOR HODOR HODOR HODOR HODOR.", + "settings.option.audio.quality": "HODOR HODOR", // Dropdown + "settings.header.audio.quality.high": "HODOR.", + "settings.header.audio.quality.low": "HODOR!", + "settings.header.audio.quality.auto": "HODOR", + "settings.option.audio.seamlessTransition": "HODOR HODOR HODOR", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "HODOR HODOR HODOR", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR , HODOR HODOR HODOR, HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "HODOR HODOR", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "HODOR HODOR", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "HODOR HODOR HODOR HODOR HODOR HODOR 3-HODOR (HODOR: HODOR HODOR HODOR HODOR HODOR)", + // Settings - Visual + "settings.header.visual": "HODOR", + "settings.header.visual.description": "HODOR HODOR HODOR HODOR HODOR HODOR.", + "settings.option.visual.windowBackgroundStyle": "HODOR HODOR HODOR", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "HODOR", + "settings.header.visual.windowBackgroundStyle.artwork": "HODOR", + "settings.option.visual.animatedArtwork": "HODOR HODOR", // Dropdown + "settings.header.visual.animatedArtwork.always": "HODOR", + "settings.header.visual.animatedArtwork.limited": "HODOR HODOR HODOR HODOR HODOR HODOR", + "settings.header.visual.animatedArtwork.disable": "HODOR HODOR", + "settings.option.visual.animatedArtworkQuality": "HODOR HODOR HODOR", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "HODOR..", + "settings.header.visual.animatedArtworkQuality.medium": "HODOR.", + "settings.header.visual.animatedArtworkQuality.high": "HODOR!", + "settings.header.visual.animatedArtworkQuality.veryHigh": "HODOR HODOR!", + "settings.header.visual.animatedArtworkQuality.extreme": "HODOOOR!!", + "settings.option.visual.animatedWindowBackground": "HODOR HODOR HODOR", // Toggle + "settings.option.visual.hardwareAcceleration": "HODOR HODOR", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "HODOR HODOR", + "settings.header.visual.hardwareAcceleration.default": "HODOR.", + "settings.header.visual.hardwareAcceleration.webGPU": "HODOR!!", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "HODOR HODOR HODOR?", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "HODOR", + "settings.header.lyrics.description": "HODOR HODOR HODOR HODOR HODOR HODOR.", + "settings.option.lyrics.enableMusixmatch": "HODOR HODOR HODOR", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "HODOR HODOR HODOR (HODOR HODOR)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "HODOR HODOR HODOR HODOR", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "HODOR HODOR HODOR HODOR HODOR HODOR", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "HODOR", + "settings.header.connectivity.description": "HODOR HODOR HODOR HODOR HODOR HODOR.", + "settings.option.connectivity.discordRPC": "HODOR HODOR HODOR", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "HODOR HODOR 'HODOR'", + "settings.header.connectivity.discordRPC.appleMusic": "HODOR HODOR 'HODOR HODOR'", + "settings.option.connectivity.discordRPC.clearOnPause": "HODOR HODOR HODOR HODOR HODOR HODOR", // Toggle + "settings.option.connectivity.lastfmScrobble": "HODOR HODOR", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "HODOR HODOR HODOR (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "HODOR HODOR HODOR HODOR", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "HODOR HODOR HODOR HODOR HODOR HODOR (HODOR)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "HODOR HODOR HODOR (HODOR)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "HODOR", + "settings.header.experimental.description": "HODOR HODOR HODOR HODOR HODOR HODOR.", + "settings.option.experimental.compactUI": "HODOR UI", // Toggle + "settings.option.experimental.closeButtonBehaviour": "HODOR HODOR HODOR", + "settings.option.experimental.closeButtonBehaviour.quit": "HODOR HODOR", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "HODOR HODOR HODOR", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "HODOR HODOR HODOR HODOR", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "HODOR HODOR", + "spatial.width" : "HODOR", + "spatial.height" : "HODOR", + "spatial.depth" : "HODOR", + "spatial.roomMaterials" : "HODOR HODOR", + "spatial.roomDimensions" : "HODOR HODOR", + "spatial.roomPositions" : "HODOR HODOR", + "spatial.setDimensions" : "HODOR HODOR", + "spatial.setPositions" : "HODOR HODOR", + "spatial.up" : "HODOR", + "spatial.front" : "HODOR", + "spatial.left" : "HODOR", + "spatial.right" : "HODOR", + "spatial.back" : "HODOR", + "spatial.down" : "HODOR", + "spatial.listener" : "HODOR", + "spatial.audioSource" : "HODOR HODOR", + + // Settings - Unfinished + "settings.header.unfinished": "HODOR", + + // Web Remote + "remote.web.title": "HODOR HODOR", + "remote.web.description": "HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR", + + //About + "about.thanks": "HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR HODOR." +} \ No newline at end of file diff --git a/src/i18n/en_SGA.jsonc b/src/i18n/en_SGA.jsonc new file mode 100644 index 00000000..d6961b5f --- /dev/null +++ b/src/i18n/en_SGA.jsonc @@ -0,0 +1,297 @@ +{ + + // i18n Info + "i18n.languageName": "┤ᖋ|:ᖋᔮᒣ╎ᔮ ᖋ|:i!⍑ᖋᕊᒷᒣ", // name of language in native language + "i18n.languageNameEnglish": "Galactic Alphabet", // name of language in English + "i18n.category": "fun", // main = real language, fun = fun community languages + "i18n.authors": "@kyw504100", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "ᔮ╎↸ᒷ∷", + + "date.format": "${m} ${d}, ${y}", + + // Dialogs + "dialog.cancel": "ᔮᖋリᔮᒷ|:", + "dialog.ok": "ᒍ·ǀ·", + + // Notification + "notification.updatingLibrarySongs": "⚍i!↸ᖋᒣ╎リ┤ |:╎ᕊ∷ᖋ∷॥ ϟᒍリ┤ϟ...", + "notification.updatingLibraryAlbums": "⚍i!↸ᖋᒣ╎リ┤ |:╎ᕊ∷ᖋ∷॥ ᖋ|:ᕊ⚍ᒲϟ...", + "notification.updatingLibraryArtists": "⚍i!↸ᖋᒣ╎リ┤ |:╎ᕊ∷ᖋ∷॥ ᖋ∷ᒣ╎ϟᒣϟ...", + // Terms + "term.appleInc": "ᖋi!i!|:ᒷ ╎リᔮ.", + "term.appleMusic": "ᖋi!i!|:ᒷ ᒲ⚍ϟ╎ᔮ", + "term.applePodcasts": "ᖋi!i!|:ᒷ i!ᒍ↸ᔮᖋϟᒣϟ", + "term.itunes": "╎ᒣ⚍リᒷϟ", + "term.github": "┤╎ᒣ⍑⚍ᕊ", + "term.discord": "↸╎ϟᔮᒍ∷↸", + "term.learnMore": "|:ᒷᖋ∷リ ᒲᒍ∷ᒷ", + "term.accountSettings": "ᖋᔮᔮᒍ⚍リᒣ ϟᒷᒣᒣ╎リ┤ϟ", + "term.logout": "|:ᒍ┤ᒍ⚍ᒣ", + "term.login": "|:ᒍ┤╎リ", + "term.about": "ᖋᕊᒍ⚍ᒣ", + "term.privateSession": "I!∷╎⍊ᖋᒣᒷ ϟᒷϟϟ╎ᒍリ", + "term.queue": "ᑑ⚍ᒷ⚍ᒷ", + "term.search": "ϟᒷᖋ∷ᔮ⍑", + "term.library": "|:╎ᕊ∷ᖋ∷॥", + "term.listenNow": "|:╎ϟᒣᒷリ", + "term.browse": "リᒍ∴", + "term.radio": "∷ᖋ↸╎ᒍ", + "term.recentlyAdded": "∷ᒷᔮᒷリᒣ|:॥ ᖋ↸↸ᒷ↸", + "term.songs": "ϟᒍリ┤ϟ", + "term.albums": "ᖋ|:ᕊ⚍ᒲϟ", + "term.artists": "ᖋ∷ᒣ╎ϟᒣϟ", + "term.podcasts": "I!ᒍ↸ᔮᖋϟᒣϟ", + "term.playlists": "i!|:ᖋ॥|:╎ϟᒣϟ", + "term.playlist": "i!|:ᖋ॥|:╎ϟᒣ", + "term.play": "i!|:ᖋ॥", + "term.pause": "I!ᖋ⚍ϟᒷ", + "term.previous": "I!∷ᒷ⍊╎ᒍ⚍ϟ", + "term.next": "リᒷ/ᒣ", + "term.shuffle": "ϟ⍑⚍⎓⎓|:ᒷ", + "term.repeat": "∷ᒷi!ᒷᖋᒣ", + "term.volume": "⍊ᒍ|:⚍ᒲᒷ", + "term.mute": "ᒲ⚍ᒣᒷ", + "term.unmute": "⚍リᒲ⚍ᒣᒷ", + "term.share": "ϟ⍑ᖋ∷ᒷ", + "term.settings": "ϟᒷᒣᒣ╎リ┤ϟ", + "term.seeAll": "ϟᒷᒷ ᖋ|:|:", + "term.sortBy": "ϟᒍ∷ᒣ ᕊ॥", + "term.sortBy.album": "ᖋ|:ᕊ⚍ᒲ", + "term.sortBy.artist": "ᖋ∷ᒣ╎ϟᒣ", + "term.sortBy.name": "リᖋᒲᒷ", + "term.sortBy.genre": "┤ᒷリ∷ᒷ", + "term.sortBy.releaseDate": "∷ᒷ|:ᒷᖋϟᒷ ↸ᖋᒣᒷ", + "term.sortBy.duration": "↸⚍∷ᖋᒣ╎ᒍリ", + "term.sortOrder": "ᖋ-∩", + "term.sortOrder.ascending": "ᖋϟᔮᒷリ↸╎リ┤", + "term.sortOrder.descending": "↸ᒷϟᔮᒷリ↸╎リ┤", + "term.viewAs": "⍊╎ᒷ∴ ᖋϟ", + "term.viewAs.coverArt": "ᔮᒍ⍊ᒷ∷ ᖋ∷ᒣ", + "term.viewAs.list": "|:╎ϟᒣ", + "term.size": "ϟ╎∩ᒷ", + "term.size.normal": "リᒍ∷ᒲᖋ|:", + "term.size.compact": "ᔮᒍᒲi!ᖋᔮᒣ", + "term.enable": "ᒷリᖋᕊ|:ᒷ", + "term.disable": "↸╎ϟᖋᕊ|:ᒷ", + "term.enabled": "ᒷリᖋᕊ|:ᒷ↸", + "term.disabled": "↸╎ϟᖋᕊ|:ᒷ↸", + "term.connect": "ᔮᒍリリᒷᔮᒣ", + "term.connecting": "ᔮᒍリリᒷᔮᒣ╎リ┤", + "term.disconnect": "↸╎ϟᔮᒍリリᒷᔮᒣ", + "term.authed": "ᖋ⚍ᒣ⍑ᒷ↸", + "term.confirm": "ᔮᒍリ⎓╎∷ᒲ ?", + "term.more": "ᒲᒍ∷ᒷ", + "term.less": "|:ᒷϟϟ", + "term.showMore": "ϟ⍑ᒍ∴ ᒲᒍ∷ᒷ", + "term.showLess": "ϟ⍑ᒍ∴ |:ᒷϟϟ", + "term.topSongs" : "ᒣᒍi! ϟᒍリ┤ϟ", + "term.latestReleases": "|:ᖋᒣᒷϟᒣ ∷ᒷ|:ᒷᖋϟᒷϟ", + "term.time.added": "ᖋ↸↸ᒷ↸", + "term.time.released": "∷ᒷ|:ᒷᖋϟᒷ↸", + "term.time.updated": "⚍i!↸ᖋᒣᒷ↸", + "term.time.hours": "⍑ᒍ⚍∷ϟ", + "term.time.hour": "⍑ᒍ⚍∷", + "term.time.minutes": "ᒲ╎リ⚍ᒣᒷϟ", + "term.time.minute": "ᒲ╎リ⚍ᒣᒷ", + "term.time.seconds": "ϟᒷᔮᒍリ↸ϟ", + "term.time.second": "ϟᒷᔮᒍリ↸", + "term.fullscreenView": "⎓⚍|:|:ϟᔮ∷ᒷᒷリ ⍊╎ᒷ∴", + "term.defaultView": "↸ᒷ⎓ᖋ⚍|:ᒣ ⍊╎ᒷ∴", + "term.spacializedAudioSetting": "ϟi!ᖋᔮ╎ᖋ|:╎∩ᒷ↸ ᖋ⚍↸╎ᒍ ϟᒷᒣᒣ╎リ┤", + "term.clearAll": "ᔮ|:ᒷᖋ∷ ᖋ|:|:", + "term.recentStations": "∷ᒷᔮᒷリᒣ ϟᒣᖋᒣ╎ᒍリϟ", + "term.language": "|:ᖋリ┤⚍ᖋ┤ᒷ", + "term.funLanguages": "⎓⚍リ", + "term.noLyrics": "|:ᒍᖋ↸╎リ┤... / |:॥∷╎ᔮϟ リᒍᒣ ⎓ᒍ⚍リ↸./ ╎リϟᒣ∷⚍ᒲᒷリᒣᖋ|:.", + "term.copyright": "ᔮᒍi!॥∷╎┤⍑ᒣ", + "term.rightsReserved": "ᖋ|:|: ∷╎┤⍑ᒣϟ ∷ᒷϟᒷ∷⍊ᒷ↸.", + "term.sponsor": "ϟi!ᒍリϟᒍ∷ ᒣ⍑╎ϟ i!∷ᒍ⋮ᒷᔮᒣ", + "term.ciderTeam": "ᔮ╎↸ᒷ∷ ᒣᒷᖋᒲ", + "term.developer": "↸ᒷ⍊ᒷ|:ᒍi!ᒷ∷", + "term.socialTeam": "ϟᒍᔮ╎ᖋ|: ᒣᒷᖋᒲ", + "term.contributors": "ᔮᒍリᒣ∷╎ᕊ⚍ᒣᒍ∷ϟ", + "term.equalizer": "ᒷᑑ⚍ᖋ|:╎∩ᒷ∷", + "term.reset": "∷ᒷϟᒷᒣ", + "term.tracks": "ᒣ∷ᖋᔮ·ǀ·ϟ", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "⍊╎↸ᒷᒍ", + "term.menu": "ᒲᒷ⚍リ", + + // Home + "home.title": "⍑ᒍᒲᒷ", + "home.recentlyPlayed": "∷ᒷᔮᒷリᒣ|:॥ i!|:ᖋ॥ᒷ↸", + "home.recentlyAdded": "∷ᒷᔮᒷリᒣ|:॥ ᖋ↸↸ᒷ↸", + "home.artistsFeed": "॥ᒍ⚍∷ ᖋ∷ᒣ╎ϟᒣϟ ⎓ᒷᒷ↸", + "home.artistsFeed.noArtist": "⎓ᒍ|:|:ᒍ∴ ϟᒍᒲᒷ ᖋ∷ᒣ╎ϟᒣϟ ⎓╎∷ϟᒣ ᖋリ↸ ᒣ⍑ᒷ╎∷ |:ᖋᒣᒷϟᒣ ∷ᒷ|:ᒷᖋϟᒷϟ ∴╎|:|: ᕊᒷ ⍑ᒷ∷ᒷ", + "home.madeForYou": "ᒲᖋ↸ᒷ ⎓ᒍ∷ ॥ᒍ⚍", + "home.friendsListeningTo": "⎓∷╎ᒷリ↸ϟ |:╎ϟᒣᒷリ╎リ┤ ᒣᒍ", + "home.followedArtists": "⎓ᒍ|:|:ᒍ∴ᒷ↸ ᖋ∷ᒣ╎ϟᒣϟ", + // Errors + "error.appleMusicSubRequired": "ᖋi!i!|:ᒷ ᒲ⚍ϟ╎ᔮ ∷ᒷᑑ⚍╎∷ᒷϟ ᖋ ϟ⚍ᕊϟᔮ∷╎i!ᒣ╎ᒍリ.", + "error.connectionError": "ᒣ⍑ᒷ∷ᒷ ∴ᖋϟ ᖋ i!∷ᒍᕊ|:ᒷᒲ ᔮᒍリリᒷᔮᒣ╎リ┤ ᒣᒍ ᖋi!i!|:ᒷ ᒲ⚍ϟ╎ᔮ.", + "error.noResults": "リᒍ ∷ᒷϟ⚍|:ᒣϟ.", + "error.noResults.description": "ᒣ∷॥ ᖋ リᒷ∴ ϟᒷᖋ∷ᔮ⍑.", + + //Podcasts + "podcast.followOnCider": "⎓ᒍ|:|:ᒍ∴ ᒍリ ᔮ╎↸ᒷ∷", + "podcast.followedOnCider": "⎓ᒍ|:|:ᒍ∴╎リ┤ ᒍリ ᔮ╎↸ᒷ∷", + "podcast.subscribeOnItunes": "ϟ⚍ᕊϟᔮ∷╎ᕊᒷ ᒍリ ╎ᒣ⚍リᒷϟ", + "podcast.subscribedOnItunes": "ϟ⚍ᕊϟᔮ∷╎ᕊᒷ↸ ᒍリ ╎ᒣ⚍リᒷϟ", + "podcast.itunesStore": "╎ᒣ⚍リᒷϟ ϟᒣᒍ∷ᒷ", + "podcast.episodes": "ᒷi!╎ϟᒍ↸ᒷϟ", + "podcast.playEpisode": "i!|:ᖋ॥ ᒷi!╎ϟᒍ↸ᒷ", + "podcast.website": "I!ᒍ↸ᔮᖋϟᒣ ∴ᒷᕊϟ╎ᒣᒷ", + + // Actions + "action.addToLibrary": "ᖋ↸↸ ᒣᒍ |:╎ᕊ∷ᖋ∷॥", + "action.addToLibrary.success": "ᖋ↸↸ᒷ↸ ᒣᒍ |:╎ᕊ∷ᖋ∷॥", + "action.addToLibrary.error": "ᒷ∷∷ᒍ∷ ᖋ↸↸╎リ┤ ᒣᒍ |:╎ᕊ∷ᖋ∷॥", + "action.removeFromLibrary": "∷ᒷᒲᒍ⍊ᒷ ⎓∷ᒍᒲ |:╎ᕊ∷ᖋ∷॥", + "action.removeFromLibrary.success": "∷ᒷᒲᒍ⍊ᒷ↸ ⎓∷ᒍᒲ |:╎ᕊ∷ᖋ∷॥", + "action.addToQueue": "ᖋ↸↸ ᒣᒍ ᑑ⚍ᒷ⚍ᒷ", + "action.addToQueue.success": "ᖋ↸↸ᒷ↸ ᒣᒍ ᑑ⚍ᒷ⚍ᒷ", + "action.addToQueue.error": "ᒷ∷∷ᒍ∷ ᖋ↸↸╎リ┤ ᒣᒍ ᑑ⚍ᒷ⚍ᒷ", + "action.removeFromQueue": "∷ᒷᒲᒍ⍊ᒷ ⎓∷ᒍᒲ ᑑ⚍ᒷ⚍ᒷ", + "action.removeFromQueue.success": "∷ᒷᒲᒍ⍊ᒷ↸ ⎓∷ᒍᒲ ᑑ⚍ᒷ⚍ᒷ", + "action.removeFromQueue.error": "ᒷ∷∷ᒍ∷ ∷ᒷᒲᒍ⍊╎リ┤ ⎓∷ᒍᒲ ᑑ⚍ᒷ⚍ᒷ", + "action.addToPlaylist": "ᖋ↸↸ ᒣᒍ i!|:ᖋ॥|:╎ϟᒣ", + "action.removeFromPlaylist": "∷ᒷᒲᒍ⍊ᒷ ⎓∷ᒍᒲ i!|:ᖋ॥|:╎ϟᒣ", + "action.addToFavorites": "ᖋ↸↸ ᒣᒍ ⎓ᖋ⍊ᒍ∷╎ᒣᒷϟ", + "action.follow": "⎓ᒍ|:|:ᒍ∴", + "action.follow.success": "⎓ᒍ|:|:ᒍ∴ᒷ↸", + "action.follow.error": "ᒷ∷∷ᒍ∷ ⎓ᒍ|:|:ᒍ∴╎リ┤", + "action.unfollow": "⚍リ⎓ᒍ|:|:ᒍ∴", + "action.unfollow.success": "⚍リ⎓ᒍ|:|:ᒍ∴ᒷ↸", + "action.unfollow.error": "ᒷ∷∷ᒍ∷ ⚍リ⎓ᒍ|:|:ᒍ∴╎リ┤", + "action.playNext": "i!|:ᖋ॥ リᒷ/ᒣ", + "action.playLater": "i!|:ᖋ॥ |:ᖋᒣᒷ∷", + "action.startRadio": "ϟᒣᖋ∷ᒣ ∷ᖋ↸╎ᒍ", + "action.goToArtist": "┤ᒍ ᒣᒍ ᖋ∷ᒣ╎ϟᒣ", + "action.goToAlbum": "┤ᒍ ᒣᒍ ᖋ|:ᕊ⚍ᒲ", + "action.moveToTop": "ᒲᒍ⍊ᒷ ᒣᒍ ᒣᒍi!", + "action.share": "ϟ⍑ᖋ∷ᒷ", + "action.rename": "∷ᒷリᖋᒲᒷ", + "action.love": "|:ᒍ⍊ᒷ", + "action.unlove": "⚍リ|:ᒍ⍊ᒷ", + "action.dislike": "↸╎ϟ|:╎·ǀ·ᒷ", + "action.undoDislike": "⚍リ↸ᒍ ↸╎ϟ|:╎·ǀ·ᒷ", + "action.showWebRemoteQR": "ϟ⍑ᒍ∴ ∴ᒷᕊ ∷ᒷᒲᒍᒣᒷ ᑑ∷", + "action.playTracksNext": "i!|:ᖋ॥ ${app.selectedMediaItems.length} ᒣ∷ᖋᔮ·ǀ·ϟ リᒷ/ᒣ", + "action.playTracksLater": "i!|:ᖋ॥ ${app.selectedMediaItems.length} ᒣ∷ᖋᔮ·ǀ·ϟ |:ᖋᒣᒷ∷", + "action.removeTracks": "∷ᒷᒲᒍ⍊ᒷ ${self.selectedItems.length} ᒣ∷ᖋᔮ·ǀ·ϟ ⎓∷ᒍᒲ ᑑ⚍ᒷ⚍ᒷ", + "action.import": "╎ᒲi!ᒍ∷ᒣ", + "action.export": "ᒷ/i!ᒍ∷ᒣ", + + // Settings - General + "settings.header.general": "┤ᒷリᒷ∷ᖋ|:", + "settings.header.general.description": "ᖋ↸⋮⚍ϟᒣ ᒣ⍑ᒷ ┤ᒷリᒷ∷ᖋ|: ϟᒷᒣᒣ╎リ┤ϟ ⎓ᒍ∷ ᔮ╎↸ᒷ∷.", + "settings.option.general.language": "|:ᖋリ┤⚍ᖋ┤ᒷ", + + // Language optgroups + "settings.option.general.language.main": "|:ᖋリ┤⚍ᖋ┤ᒷϟ", + "settings.option.general.language.fun": "⎓⚍リ |:ᖋリ┤⚍ᖋ┤ᒷϟ", + "settings.option.general.language.unsorted": "⚍リϟᒍ∷ᒣᒷ↸", + + // Settings - Audio + "settings.header.audio": "ᖋ⚍↸╎ᒍ", + "settings.header.audio.description": "ᖋ↸⋮⚍ϟᒣ ᒣ⍑ᒷ ᖋ⚍↸╎ᒍ ϟᒷᒣᒣ╎リ┤ϟ ⎓ᒍ∷ ᔮ╎↸ᒷ∷.", + "settings.option.audio.quality": "ᖋ⚍↸╎ᒍ ᑑ⚍ᖋ|:╎ᒣ॥", // Dropdown + "settings.header.audio.quality.high": "⍑╎┤⍑", + "settings.header.audio.quality.low": "|:ᒍ∴", + "settings.header.audio.quality.auto": "ᖋ⚍ᒣᒍ", + "settings.option.audio.seamlessTransition": "ϟᒷᖋᒲ|:ᒷϟϟ ᖋ⚍↸╎ᒍ ᒣ∷ᖋリϟ╎ᒣ╎ᒍリ", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "ᒷリᖋᕊ|:ᒷ ᖋ↸⍊ᖋリᔮᒷ↸ ⎓⚍リᔮᒣ╎ᒍリᖋ|:╎ᒣ॥", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "ᒷリᖋᕊ|:╎リ┤ ᖋ⚍↸╎ᒍᔮᒍリᒣᒷ/ᒣ ⎓⚍リᔮᒣ╎ᒍリᖋ|:╎ᒣ॥ ∴╎|:|: ᖋ|:|:ᒍ∴ ⎓ᒍ∷ ᒷ/ᒣᒷリ↸ᒷ↸ ᖋ⚍↸╎ᒍ ⎓ᒷᖋᒣ⚍∷ᒷϟ |:╎·ǀ·ᒷ ᖋ⚍↸╎ᒍ リᒍ∷ᒲᖋ|:╎∩ᖋᒣ╎ᒍリ , ᒷᑑ⚍ᖋ|:╎∩ᒷ∷ϟ ᖋリ↸ ⍊╎ϟ⚍ᖋ|:╎∩ᒷ∷ϟ, ⍑ᒍ∴ᒷ⍊ᒷ∷ ᒍリ ϟᒍᒲᒷ ϟ॥ϟᒣᒷᒲϟ ᒣ⍑╎ϟ ᒲᖋ॥ ᔮᖋ⚍ϟᒷ ϟᒣ⚍ᒣᒣᒷ∷╎リ┤ ╎リ ᖋ⚍↸╎ᒍ ᒣ∷ᖋᔮ·ǀ·ϟ.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "ᖋ⚍↸╎ᒍ リᒍ∷ᒲᖋ|:╎∩ᖋᒣ╎ᒍリ", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "リᒍ∷ᒲᖋ|:╎∩ᒷϟ i!ᒷᖋ·ǀ· ⍊ᒍ|:⚍ᒲᒷ ⎓ᒍ∷ ╎リ↸╎⍊╎↸⚍ᖋ|: ᒣ∷ᖋᔮ·ǀ·ϟ ᒣᒍ ᔮ∷ᒷᖋᒣᒷ ᖋ ᒲᒍ∷ᒷ ⚍リ╎⎓ᒍ∷ᒲ |:╎ϟᒣᒷリ╎リ┤ ᒷ/i!ᒷ∷╎ᒷリᔮᒷ.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "ᖋ⚍↸╎ᒍ ϟi!ᖋᒣ╎ᖋ|:╎∩ᖋᒣ╎ᒍリ", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "ϟi!ᖋᒣ╎ᖋ|:╎∩ᒷ ᖋ⚍↸╎ᒍ ᖋリ↸ ᒲᖋ·ǀ·ᒷ ᖋ⚍↸╎ᒍ ᒲᒍ∷ᒷ 3-↸╎ᒲᒷリϟ╎ᒍリᖋ|: (リᒍᒣᒷ: ᒣ⍑╎ϟ ╎ϟ リᒍᒣ ↸ᒍ|:ᕊ॥ ᖋᒣᒲᒍϟ)", + // Settings - Visual + "settings.header.visual": "⍊╎ϟ⚍ᖋ|:", + "settings.header.visual.description": "ᖋ↸⋮⚍ϟᒣ ᒣ⍑ᒷ ⍊╎ϟ⚍ᖋ| ϟᒷᒣᒣ╎リ┤ϟ ⎓ᒍ∷ ᔮ╎↸ᒷ∷.", + "settings.option.visual.windowBackgroundStyle": "∴╎リ↸ᒍ∴ ᕊᖋᔮ·ǀ·┤∷ᒍ⚍リ↸ ϟᒣ॥|:ᒷ", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "リᒍリᒷ", + "settings.header.visual.windowBackgroundStyle.artwork": "ᖋ∷ᒣ∴ᒍ∷·ǀ·", + "settings.header.visual.windowBackgroundStyle.image": "╎ᒲᖋ┤ᒷ", + "settings.option.visual.animatedArtwork": "ᖋリ╎ᒲᖋᒣᒷ↸ ᖋ∷ᒣ∴ᒍ∷·ǀ·", // Dropdown + "settings.header.visual.animatedArtwork.always": "ᖋ|:∴ᖋ॥ϟ", + "settings.header.visual.animatedArtwork.limited": "|:╎ᒲ╎ᒣᒷ↸ ᒣᒍ i!ᖋ┤ᒷϟ ᖋリ↸ ϟi!ᒷᔮ╎ᖋ|: ᒷリᒣ∷╎ᒷϟ", + "settings.header.visual.animatedArtwork.disable": "↸╎ϟᖋᕊ|:ᒷ ᒷ⍊ᒷ∷॥∴⍑ᒷ∷ᒷ", + "settings.option.visual.animatedArtworkQuality": "ᖋリ╎ᒲᖋᒣᒷ↸ ᖋ∷ᒣ∴ᒍ∷·ǀ· ᑑ⚍ᖋ|:╎ᒣ॥", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "|:ᒍ∴", + "settings.header.visual.animatedArtworkQuality.medium": "ᒲᒷ↸╎⚍ᒲ", + "settings.header.visual.animatedArtworkQuality.high": "⍑╎┤⍑", + "settings.header.visual.animatedArtworkQuality.veryHigh": "⍊ᒷ∷॥ ⍑╎┤⍑", + "settings.header.visual.animatedArtworkQuality.extreme": "ᒷ/ᒣ∷ᒷᒲᒷ", + "settings.option.visual.animatedWindowBackground": "ᖋリ╎ᒲᖋᒣᒷ↸ ∴╎リ↸ᒍ∴ ᕊᖋᔮ·ǀ·┤∷ᒍ⚍リ↸", // Toggle + "settings.option.visual.hardwareAcceleration": "⍑ᖋ∷↸∴ᖋ∷ᒷ ᖋᔮᔮᒷ|:ᒷ∷ᖋᒣ╎ᒍリ", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "∷ᒷᑑ⚍╎∷ᒷϟ ∷ᒷ|:ᖋ⚍リᔮ⍑", + "settings.header.visual.hardwareAcceleration.default": "↸ᒷ⎓ᖋ⚍|:ᒣ", + "settings.header.visual.hardwareAcceleration.webGPU": "∴ᒷᕊ┤i!⚍", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "ϟ⍑ᒍ∴ i!ᒷ∷ϟᒍリᖋ|: ╎リ⎓ᒍ", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "|:॥∷╎ᔮϟ", + "settings.header.lyrics.description": "ᖋ↸⋮⚍ϟᒣ ᒣ⍑ᒷ |:॥∷╎ᔮϟ ϟᒷᒣᒣ╎リ┤ϟ ⎓ᒍ∷ ᔮ╎↸ᒷ∷.", + "settings.option.lyrics.enableMusixmatch": "ᒷリᖋᕊ|:ᒷ ᒲ⚍ϟ╎̇/ᒲᖋᒣᔮ⍑ |:॥∷╎ᔮϟ", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "ᒷリᖋᕊ|:ᒷ ·ǀ·ᖋ∷ᖋᒍ·ǀ·ᒷ ᒲᒍ↸ᒷ (ᒲ⚍ϟ╎̇/ᒲᖋᒣᔮ⍑ ᒍリ|:॥)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "ᒲ⚍ϟ╎̇/ᒲᖋᒣᔮ⍑ ᒣ∷ᖋリϟ|:ᖋᒣ╎ᒍリ i!∷ᒷ⎓ᒷ∷∷ᒷ↸ |:ᖋリ┤⚍ᖋ┤ᒷ", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "ᒷリᖋᕊ|:ᒷ ॥ᒍ⚍ᒣ⚍ᕊᒷ |:॥∷╎ᔮϟ ⎓ᒍ∷ ᒲ⚍ϟ╎ᔮ ⍊╎↸ᒷᒍϟ", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "ᔮᒍリリᒷᔮᒣ╎⍊╎ᒣ॥", + "settings.header.connectivity.description": "ᖋ↸⋮⚍ϟᒣ ᒣ⍑ᒷ ᔮᒍリリᒷᔮᒣ╎⍊╎ᒣ॥ ϟᒷᒣᒣ╎リ┤ϟ ⎓ᒍ∷ ᔮ╎↸ᒷ∷.", + "settings.option.connectivity.discordRPC": "↸╎ϟᔮᒍ∷↸ ∷╎ᔮ⍑ i!∷ᒷϟᒷリᔮᒷ", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "↸╎ϟi!|:ᖋ॥ ᖋϟ 'ᔮ╎↸ᒷ∷'", + "settings.header.connectivity.discordRPC.appleMusic": "↸╎ϟi!|:ᖋ॥ ᖋϟ 'ᖋi!i!|:ᒷ ᒲ⚍ϟ╎ᔮ'", + "settings.option.connectivity.discordRPC.clearOnPause": "ᔮ|:ᒷᖋ∷ ↸╎ϟᔮᒍ∷↸ ∷╎ᔮ⍑ i!∷ᒷϟᒷリᔮᒷ ᒍリ i!ᖋ⚍ϟᒷ", // Toggle + "settings.option.connectivity.lastfmScrobble": "|:ᖋϟᒣ⎓ᒲ ϟᔮ∷ᒍᕊᕊ|:╎リ┤", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "|:ᖋϟᒣ⎓ᒲ ϟᔮ∷ᒍᕊᕊ|:ᒷ ↸ᒷ|:ᖋ॥ (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "ᒷリᖋᕊ|:ᒷ |:ᖋϟᒣ⎓ᒲ リᒍ∴ i!|:ᖋ॥╎リ┤", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "∷ᒷᒲᒍ⍊ᒷ ⎓ᒷᖋᒣ⚍∷╎リ┤ ᖋ∷ᒣ╎ϟᒣϟ ⎓∷ᒍᒲ ϟᒍリ┤ ᒣ╎ᒣ|:ᒷ (|:ᖋϟᒣ⎓ᒲ)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "⎓╎|:ᒣᒷ∷ |:ᒍᒍi!ᒷ↸ ᒣ∷ᖋᔮ·ǀ· (|:ᖋϟᒣ⎓ᒲ)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "ᒷ/i!ᒷ∷╎ᒲᒷリᒣᖋ|:", + "settings.header.experimental.description": "ᖋ↸⋮⚍ϟᒣ ᒣ⍑ᒷ ᒷ/i!ᒷ∷╎ᒲᒷリᒣᖋ|: ϟᒷᒣᒣ╎リ┤ϟ ⎓ᒍ∷ ᔮ╎↸ᒷ∷.", + "settings.option.experimental.compactUI": "ᔮᒍᒲi!ᖋᔮᒣ ⚍╎", // Toggle + "settings.option.experimental.closeButtonBehaviour": "ᔮ|:ᒍϟᒷ ᕊ⚍ᒣᒣᒍリ ᕊᒷ⍑ᖋ⍊╎ᒍ⚍∷", + "settings.option.experimental.closeButtonBehaviour.quit": "ᑑ⚍╎ᒣ ᔮ╎↸ᒷ∷", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "ᒲ╎リ╎ᒲ╎∩ᒷ ᒣᒍ ᒣᖋϟ·ǀ·ᕊᖋ∷", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "ᒲ╎リ╎ᒲ╎∩ᒷ ᒣᒍ ϟ॥ϟᒣᒷᒲ ᒣ∷ᖋ॥", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "ϟi!ᖋᒣ╎ᖋ|: i!∷ᒍi!ᒷ∷ᒣ╎ᒷϟ", + "spatial.width" : "∴╎↸ᒣ⍑", + "spatial.height" : "⍑ᒷ╎┤⍑ᒣ", + "spatial.depth" : "↸ᒷi!ᒣ⍑", + "spatial.gain" : "┤ᖋ╎リ", + "spatial.roomMaterials" : "∷ᒍᒍᒲ ᒲᖋᒣᒷ∷╎ᖋ|:ϟ", + "spatial.roomDimensions" : "∷ᒍᒍᒲ ↸╎ᒲᒷリϟ╎ᒍリϟ", + "spatial.roomPositions" : "∷ᒍᒍᒲ i!ᒍϟ╎ᒣ╎ᒍリϟ", + "spatial.setDimensions" : "ϟᒷᒣ ↸╎ᒲᒷリϟ╎ᒍリϟ", + "spatial.setPositions" : "ϟᒷᒣ i!ᒍϟ╎ᒣ╎ᒍリϟ", + "spatial.up" : "⚍i!", + "spatial.front" : "⎓∷ᒍリᒣ", + "spatial.left" : "|:ᒷ⎓ᒣ", + "spatial.right" : "∷╎┤⍑ᒣ", + "spatial.back" : "ᕊᖋᔮ·ǀ·", + "spatial.down" : "↸ᒍ∴リ", + "spatial.listener" : "|:╎ϟᒣᒷリᒷ∷", + "spatial.audioSource" : "ᖋ⚍↸╎ᒍ ϟᒍ⚍∷ᔮᒷ", + + // Settings - Unfinished + "settings.header.unfinished": "⚍リ⎓╎リ╎ϟ⍑ᒷ↸", + + // Web Remote + "remote.web.title": "ᔮ╎↸ᒷ∷ ∷ᒷᒲᒍᒣᒷ", + "remote.web.description": "ϟᔮᖋリ ᒣ⍑ᒷ ᑑ∷ ᔮᒍ↸ᒷ ᒣᒍ i!ᖋ╎∷ ॥ᒍ⚍∷ i!⍑ᒍリᒷ ⚍i! ∴╎ᒣ⍑ ᒣ⍑╎ϟ ᔮ╎↸ᒷ∷ ╎リϟᒣᖋリᔮᒷ", + + // About + "about.thanks": "ᒲᖋ⋮ᒍ∷ ᒣ⍑ᖋリ·ǀ·ϟ ᒣᒍ ᒣ⍑ᒷ ᔮ╎↸ᒷ∷ ᔮᒍ|:|:ᒷᔮᒣ╎⍊ᒷ ᒣᒷᖋᒲ ᖋリ↸ ᖋ|:|: ᒍ⎓ ᒍ⚍∷ ᔮᒍリᒣ∷╎ᕊ⚍ᒣᒍ∷ϟ." +} \ No newline at end of file diff --git a/src/i18n/en_US.jsonc b/src/i18n/en_US.jsonc new file mode 100644 index 00000000..59f97129 --- /dev/null +++ b/src/i18n/en_US.jsonc @@ -0,0 +1,299 @@ +{ // Base File + + // i18n Info + "i18n.languageName": "English (US)", // name of language in native language + "i18n.languageNameEnglish": "English (US)", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@maikirakiwi", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "Cider", + + "date.format": "${m} ${d}, ${y}", + + // Dialogs + "dialog.cancel": "Cancel", + "dialog.ok": "OK", + + // Notification + "notification.updatingLibrarySongs": "Updating library songs...", + "notification.updatingLibraryAlbums": "Updating library albums...", + "notification.updatingLibraryArtists": "Updating library artists...", + // Terms + "term.appleInc": "Apple Inc.", + "term.appleMusic": "Apple Music", + "term.applePodcasts": "Apple Podcasts", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "Learn more", + "term.accountSettings": "Account Settings", + "term.logout": "Logout", + "term.login": "Login", + "term.about": "About", + "term.privateSession": "Private Session", + "term.queue": "Queue", + "term.search": "Search", + "term.library": "Library", + "term.listenNow": "Listen Now", + "term.browse": "Browse", + "term.radio": "Radio", + "term.recentlyAdded": "Recently Added", + "term.songs": "Songs", + "term.albums": "Albums", + "term.artists": "Artists", + "term.podcasts": "Podcasts", + "term.playlists": "Playlists", + "term.playlist": "Playlist", + "term.play": "Play", + "term.pause": "Pause", + "term.previous": "Previous", + "term.next": "Next", + "term.shuffle": "Shuffle", + "term.repeat": "Repeat", + "term.volume": "Volume", + "term.mute": "Mute", + "term.unmute": "Unmute", + "term.share": "Share", + "term.settings": "Settings", + "term.seeAll": "See All", + "term.sortBy": "Sort By", + "term.sortBy.album": "Album", + "term.sortBy.artist": "Artist", + "term.sortBy.name": "Name", + "term.sortBy.genre": "Genre", + "term.sortBy.releaseDate": "Release Date", + "term.sortBy.duration": "Duration", + "term.sortOrder": "A-Z", + "term.sortOrder.ascending": "Ascending", + "term.sortOrder.descending": "Descending", + "term.viewAs": "View As", + "term.viewAs.coverArt": "Cover Art", + "term.viewAs.list": "List", + "term.size": "Size", + "term.size.normal": "Normal", + "term.size.compact": "Compact", + "term.enable": "Enable", + "term.disable": "Disable", + "term.enabled": "Enabled", + "term.disabled": "Disabled", + "term.connect": "Connect", + "term.connecting": "Connecting", + "term.disconnect": "Disconnect", + "term.authed": "Authed", + "term.confirm": "Confirm ?", + "term.more": "More", + "term.less": "Less", + "term.showMore": "Show more", + "term.showLess": "Show less", + "term.topSongs" : "Top Songs", + "term.latestReleases": "Latest Releases", + "term.time.added": "Added", + "term.time.released": "Released", + "term.time.updated": "Updated", + "term.time.hours": "hours", + "term.time.hour": "hour", + "term.time.minutes": "minutes", + "term.time.minute": "minute", + "term.time.seconds": "seconds", + "term.time.second": "second", + "term.fullscreenView": "Fullscreen View", + "term.defaultView": "Default View", + "term.spacializedAudioSetting": "Spacialized Audio Setting", + "term.clearAll": "Clear All", + "term.recentStations": "Recent Stations", + "term.language": "Language", + "term.funLanguages": "Fun", + "term.noLyrics": "Loading... / Lyrics not found./ Instrumental.", + "term.copyright": "Copyright", + "term.rightsReserved": "All Rights Reserved.", + "term.sponsor": "Sponsor this project", + "term.ciderTeam": "Cider Team", + "term.developer": "Developer", + "term.socialTeam": "Social Team", + "term.contributors": "Contributors", + "term.equalizer": "Equalizer", + "term.reset": "Reset", + "term.tracks": "tracks", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "Videos", + "term.menu": "Menu", + "term.showAlbum": "Show Complete Album", + + // Home + "home.title": "Home", + "home.recentlyPlayed": "Recently Played", + "home.recentlyAdded": "Recently Added", + "home.artistsFeed": "Your Artists Feed", + "home.artistsFeed.noArtist": "Follow some artists first and their latest releases will be here", + "home.madeForYou": "Made For You", + "home.friendsListeningTo": "Friends Listening To", + "home.followedArtists": "Followed Artists", + // Errors + "error.appleMusicSubRequired": "Apple Music requires a subscription.", + "error.connectionError": "There was a problem connecting to Apple Music.", + "error.noResults": "No Results.", + "error.noResults.description": "Try a new search.", + + //Podcasts + "podcast.followOnCider": "Follow On Cider", + "podcast.followedOnCider": "Following On Cider", + "podcast.subscribeOnItunes": "Subscribe On iTunes", + "podcast.subscribedOnItunes": "Subscribed On iTunes", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "Episodes", + "podcast.playEpisode": "Play Episode", + "podcast.website": "Podcast Website", + + // Actions + "action.addToLibrary": "Add to Library", + "action.addToLibrary.success": "Added to Library", + "action.addToLibrary.error": "Error Adding to Library", + "action.removeFromLibrary": "Remove from Library", + "action.removeFromLibrary.success": "Removed from Library", + "action.addToQueue": "Add to Queue", + "action.addToQueue.success": "Added to Queue", + "action.addToQueue.error": "Error Adding to Queue", + "action.removeFromQueue": "Remove from Queue", + "action.removeFromQueue.success": "Removed from Queue", + "action.removeFromQueue.error": "Error Removing from Queue", + "action.addToPlaylist": "Add to Playlist", + "action.removeFromPlaylist": "Remove from Playlist", + "action.addToFavorites": "Add to Favorites", + "action.follow": "Follow", + "action.follow.success": "Followed", + "action.follow.error": "Error Following", + "action.unfollow": "Unfollow", + "action.unfollow.success": "Unfollowed", + "action.unfollow.error": "Error Unfollowing", + "action.playNext": "Play Next", + "action.playLater": "Play Later", + "action.startRadio": "Start Radio", + "action.goToArtist": "Go to Artist", + "action.goToAlbum": "Go to Album", + "action.moveToTop": "Move to top", + "action.share": "Share", + "action.rename": "Rename", + "action.love": "Love", + "action.unlove": "Unlove", + "action.dislike": "Dislike", + "action.undoDislike": "Undo dislike", + "action.showWebRemoteQR": "Show Web Remote QR", + "action.playTracksNext": "Play ${app.selectedMediaItems.length} tracks next", + "action.playTracksLater": "Play ${app.selectedMediaItems.length} tracks later", + "action.removeTracks": "Remove ${self.selectedItems.length} tracks from queue", + "action.import": "Import", + "action.export": "Export", + + // Settings - General + "settings.header.general": "General", + "settings.header.general.description": "Adjust the general settings for Cider.", + "settings.option.general.language": "Language", + + // Language optgroups + "settings.option.general.language.main": "Languages", + "settings.option.general.language.fun": "Fun Languages", + "settings.option.general.language.unsorted": "Unsorted", + + // Settings - Audio + "settings.header.audio": "Audio", + "settings.header.audio.description": "Adjust the audio settings for Cider.", + "settings.option.audio.quality": "Audio Quality", // Dropdown + "settings.header.audio.quality.high": "High", + "settings.header.audio.quality.low": "Low", + "settings.header.audio.quality.auto": "Auto", + "settings.option.audio.seamlessTransition": "Seamless Audio Transition", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "Enable Advanced Functionality", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "Enabling AudioContext functionality will allow for extended audio features like Audio Normalization , Equalizers and Visualizers, however on some systems this may cause stuttering in audio tracks.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Audio Normalization", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Normalizes peak volume for individual tracks to create a more uniform listening experience.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Audio Spatialization", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Spatialize audio and make audio more 3-dimensional (note: This is not Dolby Atmos)", + // Settings - Visual + "settings.header.visual": "Visual", + "settings.header.visual.description": "Adjust the visual settings for Cider.", + "settings.option.visual.windowBackgroundStyle": "Window Background Style", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "None", + "settings.header.visual.windowBackgroundStyle.artwork": "Artwork", + "settings.header.visual.windowBackgroundStyle.image": "Image", + "settings.option.visual.animatedArtwork": "Animated Artwork", // Dropdown + "settings.header.visual.animatedArtwork.always": "Always", + "settings.header.visual.animatedArtwork.limited": "Limited to pages and special entries", + "settings.header.visual.animatedArtwork.disable": "Disable everywhere", + "settings.option.visual.animatedArtworkQuality": "Animated Artwork Quality", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "Low", + "settings.header.visual.animatedArtworkQuality.medium": "Medium", + "settings.header.visual.animatedArtworkQuality.high": "High", + "settings.header.visual.animatedArtworkQuality.veryHigh": "Very High", + "settings.header.visual.animatedArtworkQuality.extreme": "Extreme", + "settings.option.visual.animatedWindowBackground": "Animated Window Background", // Toggle + "settings.option.visual.hardwareAcceleration": "Hardware Acceleration", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "Requires relaunch", + "settings.header.visual.hardwareAcceleration.default": "Default", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "Show Personal Info", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "Lyrics", + "settings.header.lyrics.description": "Adjust the lyrics settings for Cider.", + "settings.option.lyrics.enableMusixmatch": "Enable Musixmatch Lyrics", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "Enable Karaoke Mode (Musixmatch only)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Musixmatch Translation Preferred Language", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "Enable Youtube Lyrics for Music Videos", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "Connectivity", + "settings.header.connectivity.description": "Adjust the connectivity settings for Cider.", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown + "settings.option.connectivity.playbackNotifications": "Playback Notifications", // Toggle + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "Display as 'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "Display as 'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "Clear Discord Rich Presence on Pause", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble Delay (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable LastFM Now Playing", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "Experimental", + "settings.header.experimental.description": "Adjust the experimental settings for Cider.", + "settings.option.experimental.compactUI": "Compact UI", // Toggle + "settings.option.experimental.closeButtonBehaviour": "Close Button Behavior", + "settings.option.experimental.closeButtonBehaviour.quit": "Quit Cider", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "Minimize to Taskbar", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "Minimize to Tray", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "Spatial Properties", + "spatial.width" : "Width", + "spatial.height" : "Height", + "spatial.depth" : "Depth", + "spatial.gain" : "Gain", + "spatial.roomMaterials" : "Room Materials", + "spatial.roomDimensions" : "Room Dimensions", + "spatial.roomPositions" : "Room Positions", + "spatial.setDimensions" : "Set Dimensions", + "spatial.setPositions" : "Set Positions", + "spatial.up" : "Up", + "spatial.front" : "Front", + "spatial.left" : "Left", + "spatial.right" : "Right", + "spatial.back" : "Back", + "spatial.down" : "Down", + "spatial.listener" : "Listener", + "spatial.audioSource" : "Audio Source", + + // Settings - Unfinished + "settings.header.unfinished": "Unfinished", + + // Web Remote + "remote.web.title": "Cider Remote", + "remote.web.description": "Scan the QR code to pair your phone up with this Cider instance", + + // About + "about.thanks": "Major thanks to the Cider Collective Team and all of our contributors." +} diff --git a/src/i18n/fr_CA.jsonc b/src/i18n/fr_CA.jsonc new file mode 100644 index 00000000..b3b2c14c --- /dev/null +++ b/src/i18n/fr_CA.jsonc @@ -0,0 +1,299 @@ +{ // Base File + + // i18n Info + "i18n.languageName": "Français (CA)", // name of language in native language + "i18n.languageNameEnglish": "French (CA)", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "brock#7527", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "Cider", + + "date.format": "${m} ${d}, ${y}", + + // Dialogs + "dialog.cancel": "Annuler", + "dialog.ok": "D'accord", + + // Notification + "notification.updatingLibrarySongs": "Rafraîchir des chansons...", + "notification.updatingLibraryAlbums": "Rafraîchir des albums...", + "notification.updatingLibraryArtists": "Rafraîchir des artistes...", + // Terms + "term.appleInc": "Apple Inc.", + "term.appleMusic": "Apple Music", + "term.applePodcasts": "Apple Podcasts", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "Savoir plus", + "term.accountSettings": "Réglages du compte", + "term.logout": "Se déconnecter", + "term.login": "Se connecter", + "term.about": "À propos", + "term.privateSession": "Session en privée", + "term.queue": "Suivants", + "term.search": "Rechercher", + "term.library": "Bibliothèque", + "term.listenNow": "À écouter", + "term.browse": "Parcourir", + "term.radio": "Radio", + "term.recentlyAdded": "Ajouté récemment", + "term.songs": "Chansons", + "term.albums": "Albums", + "term.artists": "Artistes", + "term.podcasts": "Podcasts", + "term.playlists": "Listes de lecture", + "term.playlist": "Liste de lecture", + "term.play": "Écouter", + "term.pause": "Pause", + "term.previous": "Retour", + "term.next": "Suivant", + "term.shuffle": "Lecture aléatoire", + "term.repeat": "Répéter", + "term.volume": "Volume", + "term.mute": "Assourde", + "term.unmute": "Réactiver", + "term.share": "Partager", + "term.settings": "Réglages", + "term.seeAll": "Voix tous", + "term.sortBy": "Sorter par", + "term.sortBy.album": "Album", + "term.sortBy.artist": "Artiste", + "term.sortBy.name": "Nom", + "term.sortBy.genre": "Genre", + "term.sortBy.releaseDate": "Date de sortie", + "term.sortBy.duration": "Duration", + "term.sortOrder": "A-Z", + "term.sortOrder.ascending": "Ascender", + "term.sortOrder.descending": "Descender", + "term.viewAs": "Voix comme", + "term.viewAs.coverArt": "Art de couverture", + "term.viewAs.list": "Liste", + "term.size": "Grandeur", + "term.size.normal": "Normal", + "term.size.compact": "Compacte", + "term.enable": "Activer", + "term.disable": "Désactiver", + "term.enabled": "Activée", + "term.disabled": "Désactivée", + "term.connect": "Connecter", + "term.connecting": "De liaison", + "term.disconnect": "Déconnecter", + "term.authed": "Authed", + "term.confirm": "Confirmer ?", + "term.more": "De plus", + "term.less": "De moins", + "term.showMore": "Voir plus", + "term.showLess": "Voir moins", + "term.topSongs" : "Meilleures chansons", + "term.latestReleases": "Nouvelles sorties", + "term.time.added": "Ajouté", + "term.time.released": "Publié", + "term.time.updated": "Mis à jour", + "term.time.hours": "heures", + "term.time.hour": "heur", + "term.time.minutes": "minutes", + "term.time.minute": "minute", + "term.time.seconds": "secondes", + "term.time.second": "seconde", + "term.fullscreenView": "Vue plein écran", + "term.defaultView": "Vue par défaut", + "term.spacializedAudioSetting": "Réglage audio spacialisé", + "term.clearAll": "Tout effacer", + "term.recentStations": "Stations récentes", + "term.language": "Langue", + "term.funLanguages": "Amusement", + "term.noLyrics": "Loading... / Paroles pas trouvé./ Instrumental.", + "term.copyright": "Droits d'auteur", + "term.rightsReserved": "Tous les droits sont réservés.", + "term.sponsor": "Parrainez ce projet", + "term.ciderTeam": "Team Cider", + "term.developer": "Développeur", + "term.socialTeam": "Équipe sociale", + "term.contributors": "Contributeurs", + "term.equalizer": "Égaliseur", + "term.reset": "Réinitialiser", + "term.tracks": "chansons", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "Vidéos", + "term.menu": "Menu", + "term.showAlbum": "Afficher l'album complet", + + // Home + "home.title": "Maison", + "home.recentlyPlayed": "Joué récemment", + "home.recentlyAdded": "Ajouté récemment", + "home.artistsFeed": "Votre flux d'artistes", + "home.artistsFeed.noArtist": "Suivez certains artistes en premier et leurs dernières sorties seront ici", + "home.madeForYou": "Creér pour toi", + "home.friendsListeningTo": "Amis écoutant", + "home.followedArtists": "Artistes suivis", + // Errors + "error.appleMusicSubRequired": "Apple Music nécessite un abonnement.", + "error.connectionError": "Un problème est survenu lors de la connexion à Apple Music.", + "error.noResults": "Pas de resultats.", + "error.noResults.description": "Essayez une nouvelle recherche.", + + //Podcasts + "podcast.followOnCider": "Suivez sur Cider", + "podcast.followedOnCider": "Suivi sur Cider", + "podcast.subscribeOnItunes": "S'abonner sur iTunes", + "podcast.subscribedOnItunes": "Abonné sur iTunes", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "Épisodes", + "podcast.playEpisode": "Lire l'épisode", + "podcast.website": "Site web du Podcast", + + // Actions + "action.addToLibrary": "Ajouter à biblio", + "action.addToLibrary.success": "Ajouté à biblio", + "action.addToLibrary.error": "Erreur lors de l'ajout à biblio", + "action.removeFromLibrary": "Enlever du biblio", + "action.removeFromLibrary.success": "Enlevé du biblio", + "action.addToQueue": "Ajouter à suivants", + "action.addToQueue.success": "Ajouté à suivants", + "action.addToQueue.error": "Erreur lors de l'ajout à suivants", + "action.removeFromQueue": "Enlever du suivants", + "action.removeFromQueue.success": "Enlevé du suivants", + "action.removeFromQueue.error": "Erreur lors d'enleve du suivants", + "action.addToPlaylist": "Ajoute à liste de lecture", + "action.removeFromPlaylist": "Enleve de liste de lecture", + "action.addToFavorites": "Ajoute à Favorites", + "action.follow": "Suivre", + "action.follow.success": "Suivi", + "action.follow.error": "Erreur a suivre", + "action.unfollow": "Arreter a suivi", + "action.unfollow.success": "Arreter a suivre", + "action.unfollow.error": "Erreur de arreter à suivre", + "action.playNext": "Jouer en prochaine", + "action.playLater": "Jouer plus tard", + "action.startRadio": "Commencer la radio", + "action.goToArtist": "Aller à l'artiste", + "action.goToAlbum": "Aller à l'album", + "action.moveToTop": "Déplacer vers le haut", + "action.share": "Partager", + "action.rename": "Renommer", + "action.love": "J'adore", + "action.unlove": "Je n'adore plus", + "action.dislike": "Moins de suggestions similaires", + "action.undoDislike": "Annuler le choix Moins de suggestions de ce type", + "action.showWebRemoteQR": "Demontrer la Web Remote QR", + "action.playTracksNext": "Joue ${app.selectedMediaItems.length} chansons en prochain", + "action.playTracksLater": "Joue ${app.selectedMediaItems.length} chansons plus tard", + "action.removeTracks": "Remove ${self.selectedItems.length} tracks from queue", + "action.import": "Importer", + "action.export": "Exporter", + + // Settings - General + "settings.header.general": "Réglages généraux", + "settings.header.general.description": "Réglez les réglages généraux de Cider.", + "settings.option.general.language": "Langue", + + // Language optgroups + "settings.option.general.language.main": "Langue", + "settings.option.general.language.fun": "Langues amusantes", + "settings.option.general.language.unsorted": "Non trié", + + // Settings - Audio + "settings.header.audio": "Audio", + "settings.header.audio.description": "Réglez les réglages audio de Cider.", + "settings.option.audio.quality": "Qualité audio", // Dropdown + "settings.header.audio.quality.high": "Haut", + "settings.header.audio.quality.low": "Bas", + "settings.header.audio.quality.auto": "Auto", + "settings.option.audio.seamlessTransition": "Transition audio fluide", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "Activer la fonctionnalité avancée", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "L'activation de la fonctionnalité AudioContext permettra des fonctionnalités audio étendues telles que la normalisation audio, les égaliseurs et les visualiseurs, mais sur certains systèmes, cela peut provoquer des saccades dans les chansons audio.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Normalisation audio", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Normalise le volume maximal des pistes individuelles pour créer une expérience d'écoute plus uniforme.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Audio Spatialization", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Spatialisez l'audio et rendez l'audio plus tridimensionnel (remarque: il ne s'agit pas de Dolby Atmos)", + // Settings - Visual + "settings.header.visual": "Visuel", + "settings.header.visual.description": "Ajustez les réglages visuels de Cider.", + "settings.option.visual.windowBackgroundStyle": "Style d'arrière-plan de la window", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "Rien", + "settings.header.visual.windowBackgroundStyle.artwork": "Ouvrages d'art", + "settings.header.visual.windowBackgroundStyle.image": "Image", + "settings.option.visual.animatedArtwork": "Oeuvre animée", // Dropdown + "settings.header.visual.animatedArtwork.always": "Toujours", + "settings.header.visual.animatedArtwork.limited": "Limité aux pages et aux entrées spéciales", + "settings.header.visual.animatedArtwork.disable": "Désactiver partout", + "settings.option.visual.animatedArtworkQuality": "Qualité des illustrations animées", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "Bas", + "settings.header.visual.animatedArtworkQuality.medium": "Moyen", + "settings.header.visual.animatedArtworkQuality.high": "Haut", + "settings.header.visual.animatedArtworkQuality.veryHigh": "Très haut", + "settings.header.visual.animatedArtworkQuality.extreme": "Extrême", + "settings.option.visual.animatedWindowBackground": "Fond de window animé", // Toggle + "settings.option.visual.hardwareAcceleration": "Accélération matérielle", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "Nécessite une relance", + "settings.header.visual.hardwareAcceleration.default": "Défaut", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "Afficher les informations personnelles", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "Paroles", + "settings.header.lyrics.description": "Ajustez les réglages des paroles de Cider.", + "settings.option.lyrics.enableMusixmatch": "Activer les paroles de Musixmatch", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "Activer le mode karaoké (Musixmatch uniquement)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Traduction Musixmatch langue préférée", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "Activer les paroles Youtube pour les clips vidéo", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "Connectivité", + "settings.header.connectivity.description": "Ajustez les réglages de connectivité pour Cider.", + "settings.option.connectivity.discordRPC": "Discord Riche Présence", // Dropdown + "settings.option.connectivity.playbackNotifications": "Notifications de lecture", // Toggle + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "Afficher comme 'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "Afficher comme 'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "Effacer la Discord Riche Présence en pause", // Toggle + "settings.option.connectivity.lastfmScrobble": "Scrobbling LastFM", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "Délai de scrobble LastFM (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "Activer LastFM en jouer maitenant", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Supprimer les artistes en vedette du titre de la chanson (LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Filtrer la chanson en boucle (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "Expérimental", + "settings.header.experimental.description": "Ajustez les réglages expérimentaux pour Cider.", + "settings.option.experimental.compactUI": "UI Compact", // Toggle + "settings.option.experimental.closeButtonBehaviour": "Comportement du bouton de fermeture", + "settings.option.experimental.closeButtonBehaviour.quit": "Quitter Cider", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "Réduire à la barre des tâches", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "Réduire dans le bac", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "Propriétés spatiales", + "spatial.width" : "Largeur", + "spatial.height" : "Hauteur", + "spatial.depth" : "Profondeur", + "spatial.gain" : "Gagner", + "spatial.roomMaterials" : "Matériaux de la chambre", + "spatial.roomDimensions" : "Dimensions de la chambre", + "spatial.roomPositions" : "Positions de la chambre", + "spatial.setDimensions" : "Définir les cotes", + "spatial.setPositions" : "Définir les positions", + "spatial.up" : "Haut", + "spatial.front" : "Avant", + "spatial.left" : "Gauche", + "spatial.right" : "Droite", + "spatial.back" : "Arrière", + "spatial.down" : "Bas", + "spatial.listener" : "Auditeur", + "spatial.audioSource" : "Source audio", + + // Settings - Unfinished + "settings.header.unfinished": "Inachevée", + + // Web Remote + "remote.web.title": "Cider Remote", + "remote.web.description": "Scannez le code QR pour coupler votre téléphone avec cette instance Cider", + + // About + "about.thanks": "Un grand merci à l'équipe de Cider Collective et à tous nos contributeurs." +} \ No newline at end of file diff --git a/src/i18n/fr_FR.jsonc b/src/i18n/fr_FR.jsonc new file mode 100644 index 00000000..d909879d --- /dev/null +++ b/src/i18n/fr_FR.jsonc @@ -0,0 +1,300 @@ +{ // Base File + + // i18n Info + "i18n.languageName": "Français", // name of language in native language + "i18n.languageNameEnglish": "French", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@ErwanGit", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "Cider", + + "date.format": "${d} ${m} ${y}", + + // Dialogs + "dialog.cancel": "Annuler", + "dialog.ok": "OK", + + // Notification + "notification.updatingLibrarySongs": "Mise à jour des chansons de la bibliothèque...", + "notification.updatingLibraryAlbums": "Mise à jour des albums de la bibliothèque...", + "notification.updatingLibraryArtists": "Mise à jour des artistes de la bibliothèque...", + // Terms + "term.appleInc": "Apple Inc.", + "term.appleMusic": "Apple Music", + "term.applePodcasts": "Apple Podcasts", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "En savoir plus", + "term.accountSettings": "Paramètres du compte", + "term.logout": "Déconnexion", + "term.login": "Connexion", + "term.about": "À propos", + "term.privateSession": "Session privée", + "term.queue": "File d'attente", + "term.search": "Recherche", + "term.library": "Bibliothèque", + "term.listenNow": "Écoutez maintenant", + "term.browse": "Explorer", + "term.radio": "Radio", + "term.recentlyAdded": "Ajouté récemment", + "term.songs": "Musiques", + "term.albums": "Albums", + "term.artists": "Artistes", + "term.podcasts": "Podcasts", + "term.playlists": "Playlists", + "term.playlist": "Playlist", + "term.play": "Lecture", + "term.pause": "Pause", + "term.previous": "Précédent", + "term.next": "Suivant", + "term.shuffle": "Aléatoire", + "term.repeat": "Répéter", + "term.volume": "Volume", + "term.mute": "Rendre muet", + "term.unmute": "Ne plus rendre muet", + "term.share": "Partager", + "term.settings": "Paramètres", + "term.seeAll": "Voir tout", + "term.sortBy": "Trier par", + "term.sortBy.album": "Album", + "term.sortBy.artist": "Artiste", + "term.sortBy.name": "Nom", + "term.sortBy.genre": "Genre", + "term.sortBy.releaseDate": "Date de sortie", + "term.sortBy.duration": "Durée", + "term.sortOrder": "A-Z", + "term.sortOrder.ascending": "Ascendant", + "term.sortOrder.descending": "Descendant", + "term.viewAs": "Voir comme", + "term.viewAs.coverArt": "Pochette d'album", + "term.viewAs.list": "Liste", + "term.size": "Taille", + "term.size.normal": "Normal", + "term.size.compact": "Compacte", + "term.enable": "Activer", + "term.disable": "Désactiver", + "term.enabled": "Activé", + "term.disabled": "Désactivé", + "term.connect": "Connecter", + "term.connecting": "Connexion", + "term.disconnect": "Déconnexion", + "term.authed": "Authentifié", + "term.confirm": "Confirmer ?", + "term.more": "Plus", + "term.less": "Moins", + "term.showMore": "Afficher plus", + "term.showLess": "Afficher moins", + "term.topSongs" : "Meilleurs titres", + "term.latestReleases": "Dernières sorties", + "term.time.added": "Ajouté", + "term.time.released": "Publié", + "term.time.updated": "Mis à jour", + "term.time.hours": "heures", + "term.time.hour": "heure", + "term.time.minutes": "minutes", + "term.time.minute": "minute", + "term.time.seconds": "secondes", + "term.time.second": "seconde", + "term.fullscreenView": "Vue plein écran", + "term.defaultView": "Vue par défaut", + "term.spacializedAudioSetting": "Paramètres audio spatialisés", + "term.clearAll": "Tout effacer", + "term.recentStations": "Stations récentes", + "term.language": "Langue", + "term.funLanguages": "Amusant", + "term.noLyrics": "Chargement... / Paroles non trouvé./ Instrumental.", + "term.copyright": "Copyright", + "term.rightsReserved": "Tous droits réservés.", + "term.sponsor": "Soutenez ce projet", + "term.ciderTeam": "Équipe Cider", + "term.developer": "Développeur", + "term.socialTeam": "Équipe de communication", + "term.contributors": "Contributeurs", + "term.equalizer": "Égaliseur", + "term.reset": "Réinitialiser", + "term.tracks": "musiques", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "Vidéos", + "term.menu": "Menu", + "term.showAlbum": "Afficher l'album complet", + + // Home + "home.title": "Accueil", + "home.recentlyPlayed": "Joué récemment", + "home.recentlyAdded": "Récemment ajouté", + "home.artistsFeed": "Votre file d'artistes", + "home.artistsFeed.noArtist": "Suivez d'abord certains artistes et leurs dernières sorties seront ici", + "home.madeForYou": "Fait pour vous", + "home.friendsListeningTo": "Vos amis écoutent", + "home.followedArtists": "Artistes suivis", + // Errors + "error.appleMusicSubRequired": "Apple Music nécessite un abonnement.", + "error.connectionError": "Il y a eu un problème de connexion à Apple Music.", + "error.noResults": "Aucun résultat.", + "error.noResults.description": "Essayez une nouvelle recherche.", + + //Podcasts + "podcast.followOnCider": "Suivre sur Cider", + "podcast.followedOnCider": "Suivi sur Cider", + "podcast.subscribeOnItunes": "Suivre sur iTunes", + "podcast.subscribedOnItunes": "Suivi sur iTunes", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "Épisodes", + "podcast.playEpisode": "Lire l'épisode", + "podcast.website": "Site du podcast", + + // Actions + "action.addToLibrary": "Ajouter à la bibliothèque", + "action.addToLibrary.success": "Ajouté à la bibliothèque", + "action.addToLibrary.error": "Erreur lors de l'ajout à la bibliothèque", + "action.removeFromLibrary": "Retirer de la bibliothèque", + "action.removeFromLibrary.success": "Retiré de la bibliothèque", + "action.addToQueue": "Ajouter à la file d'attente", + "action.addToQueue.success": "Ajouté à la file d'attente", + "action.addToQueue.error": "Erreur lors de l'ajout à la file d'attente", + "action.removeFromQueue": "Retirer de la file d'attente", + "action.removeFromQueue.success": "Retiré de la file d'attente", + "action.removeFromQueue.error": "Erreur lors du retrait de la file d'attente", + "action.addToPlaylist": "Ajouter à une playlist", + "action.removeFromPlaylist": "Retirer de la playlist", + "action.addToFavorites": "Ajouter aux favoris", + "action.follow": "Suivre", + "action.follow.success": "Suivi", + "action.follow.error": "Erreur lors de l'abonnement", + "action.unfollow": "Se désabonner", + "action.unfollow.success": "Désabonné", + "action.unfollow.error": "Erreur lors du désabonnement", + "action.playNext": "Jouer après", + "action.playLater": "Jouer plus tard", + "action.startRadio": "Lancer la radio", + "action.goToArtist": "Aller à l'artiste", + "action.goToAlbum": "Aller à l'album", + "action.moveToTop": "Haut de page", + "action.share": "Partager", + "action.rename": "Renommer", + "action.love": "Aimer", + "action.unlove": "Ne plus aimer", + "action.dislike": "Je n'aime pas", + "action.undoDislike": "Je n'aime plus", + "action.showWebRemoteQR": "Afficher le QR Code de la télécommande à distance", + "action.playTracksNext": "Jouer ${app.selectedMediaItems.length} musiques après", + "action.playTracksLater": "Jouer ${app.selectedMediaItems.length} musiques plus tard", + "action.removeTracks": "Retirer ${self.selectedItems.length} musiques de la file d'attente", + "action.import": "Importer", + "action.export": "Exporter", + + // Settings - General + "settings.header.general": "Général", + "settings.header.general.description": "Ajuster les paramètres généraux de Cider.", + "settings.option.general.language": "Langue", + + // Language optgroups + "settings.option.general.language.main": "Langues", + "settings.option.general.language.fun": "Langues amusantes", + "settings.option.general.language.unsorted": "Non trié", + + // Settings - Audio + "settings.header.audio": "Audio", + "settings.header.audio.description": "Ajuster les paramètres audio de Cider.", + "settings.option.audio.quality": "Qualité Audio", // Dropdown + "settings.header.audio.quality.high": "Élevée", + "settings.header.audio.quality.low": "Faible", + "settings.header.audio.quality.auto": "Automatique", + "settings.option.audio.seamlessTransition": "Fondu audio transparent", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "Activer les fonctions avancées", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "L'activation de la fonctionnalité AudioContext permet d'utiliser des fonctions audio étendues telles que la normalisation du son, les égaliseurs et les visualiseurs. Toutefois, sur certains systèmes, cela peut provoquer des bégaiements dans les pistes audio.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Normalisation du son", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Normalise le volume maximal des pistes individuelles pour créer une expérience d'écoute plus uniforme.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Spatialisation audio", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Spatialiser l'audio et rendre l'audio plus tridimensionnel (note: Ce n'est pas Dolby Atmos)", + // Settings - Visual + "settings.header.visual": "Visuel", + "settings.header.visual.description": "Ajuster les paramètres visuels de Cider.", + "settings.option.visual.windowBackgroundStyle": "Style d'arrière-plan de la fenêtre", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "Aucun", + "settings.header.visual.windowBackgroundStyle.artwork": "Pochette d'album", + "settings.header.visual.windowBackgroundStyle.image": "Image", + "settings.option.visual.animatedArtwork": "Pochette d'album animée", // Dropdown + "settings.header.visual.animatedArtwork.always": "Toujours", + "settings.header.visual.animatedArtwork.limited": "Limité aux pages et aux entrées spéciales", + "settings.header.visual.animatedArtwork.disable": "Désactiver partout", + "settings.option.visual.animatedArtworkQuality": "Qualité de la pochette d'album animée", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "Faible", + "settings.header.visual.animatedArtworkQuality.medium": "Moyen", + "settings.header.visual.animatedArtworkQuality.high": "Élevée", + "settings.header.visual.animatedArtworkQuality.veryHigh": "Très élevée", + "settings.header.visual.animatedArtworkQuality.extreme": "Extrême", + "settings.option.visual.animatedWindowBackground": "Arrière-plan de fenêtre animé", // Toggle + "settings.option.visual.hardwareAcceleration": "Accélération matérielle", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "Nécessite un relancement", + "settings.header.visual.hardwareAcceleration.default": "Défaut", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "Afficher vos informations personnelles", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "Paroles", + "settings.header.lyrics.description": "Ajuster les paramètres des paroles pour Cider.", + "settings.option.lyrics.enableMusixmatch": "Activer les paroles Musixmatch", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "Activer le mode karaoké (Musixmatch seulement)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Langue préférée pour les traductions Musixmatch", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "Activer les paroles YouTube pour les vidéos de musique", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "Connectivité", + "settings.header.connectivity.description": "Ajuster les paramètres de connectivité de Cider.", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown + "settings.option.connectivity.playbackNotifications": "Notifications de lecture", // Toggle + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "Afficher comme 'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "Afficher comme 'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "Désactiver le Discord Rich Presence quand la musique est en pause", // Toggle + "settings.option.connectivity.lastfmScrobble": "Scrobble LastFM", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "Délai de Scrobble LastFM (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "Activer la lecture en cours sur LastFM", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Supprimer les artistes en vedette du titre de la chanson (LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Filtrer les titres en boucle (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "Expérimental", + "settings.header.experimental.description": "Ajuster les paramètres expérimentaux de Cider.", + "settings.option.experimental.compactUI": "Interface utilisateur compacte", // Toggle + "settings.option.experimental.closeButtonBehaviour": "Comportement du bouton de fermeture", + "settings.option.experimental.closeButtonBehaviour.quit": "Quitter Cider", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "Réduire dans la barre des tâches", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "Réduire dans la barre d'outils", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties": "Propriétés spatiales", + "spatial.width": "Largeur", + "spatial.height": "Hauteur", + "spatial.depth": "Profondeur", + "spatial.gain": "Gain", + "spatial.roomMaterials": "Matériaux de la pièce", + "spatial.roomDimensions": "Dimensions de la pièce", + "spatial.roomPositions": "Positions de la pièce", + "spatial.setDimensions": "Définir les dimensions", + "spatial.setPositions": "Définir les positions", + "spatial.up": "Haut", + "spatial.front": "Avant", + "spatial.left": "Gauche", + "spatial.right": "Droite", + "spatial.back": "Retour", + "spatial.down": "Bas", + "spatial.listener": "Auditeur", + "spatial.audioSource": "Source Audio", + + // Settings - Unfinished + "settings.header.unfinished": "Inachevée", + + // Web Remote + "remote.web.title": "Cider Remote", + "remote.web.description": "Scanner le QR code pour associer votre téléphone avec cette instance Cider", + + // About + "about.thanks": "Un grand merci à l'équipe de la Cider Collective et à tous nos contributeurs." + } + \ No newline at end of file diff --git a/src/i18n/hu_HU.jsonc b/src/i18n/hu_HU.jsonc new file mode 100644 index 00000000..1c30c053 --- /dev/null +++ b/src/i18n/hu_HU.jsonc @@ -0,0 +1,297 @@ +{ // Base File + + // i18n Info + "i18n.languageName": "Magyar", // name of language in native language + "i18n.languageNameEnglish": "Hungarian", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@Greenoliv @Rias", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "Cider", + + "date.format": "${m} ${d}, ${y}", + + // Dialogs + "dialog.cancel": "Mégsem", + "dialog.ok": "OK", + + // Notification + "notification.updatingLibrarySongs": "Zenekönyvtár frissítése...", + "notification.updatingLibraryAlbums": "Albumok frissítése...", + "notification.updatingLibraryArtists": "Előadók frissítése...", + // Terms + "term.appleInc": "Apple Inc.", + "term.appleMusic": "Apple Music", + "term.applePodcasts": "Apple Podcastok", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "Tudj meg többet", + "term.accountSettings": "Fiókbeállítások", + "term.logout": "Kijelentkezés", + "term.login": "Bejelentkezés", + "term.about": "About", + "term.privateSession": "Privát hallgatás", + "term.queue": "Várólista", + "term.search": "Keresés", + "term.library": "Könyvtár", + "term.listenNow": "Hallgatás most", + "term.browse": "Böngészés", + "term.radio": "Rádió", + "term.recentlyAdded": "Nemrég hozzáadott", + "term.songs": "Dalok", + "term.albums": "Albumok", + "term.artists": "Előadók", + "term.podcasts": "Podcastok", + "term.playlists": "Lejátszási listák", + "term.playlist": "Lejátszási lista", + "term.play": "Lejátszás", + "term.pause": "Megállítás", + "term.previous": "Előző", + "term.next": "Következő", + "term.shuffle": "Keverés", + "term.repeat": "Ismétlés", + "term.volume": "Hangerő", + "term.mute": "Némítás", + "term.unmute": "Némítás feloldása", + "term.share": "Megosztás", + "term.settings": "Beállítások", + "term.seeAll": "Összes", + "term.sortBy": "Rendezés", + "term.sortBy.album": "Album", + "term.sortBy.artist": "Előadó", + "term.sortBy.name": "Név", + "term.sortBy.genre": "Műfaj", + "term.sortBy.releaseDate": "Kiadás dátuma", + "term.sortBy.duration": "Időtartam", + "term.sortOrder": "A-Z", + "term.sortOrder.ascending": "Növekvő", + "term.sortOrder.descending": "Csökkenő", + "term.viewAs": "Megjelenítés", + "term.viewAs.coverArt": "Borító", + "term.viewAs.list": "Lista", + "term.size": "Méret", + "term.size.normal": "Normál", + "term.size.compact": "Kompakt", + "term.enable": "Be", + "term.disable": "Ki", + "term.enabled": "Be", + "term.disabled": "Ki", + "term.connect": "Csatlakoztatás", + "term.connecting": "Csatlakozás", + "term.disconnect": "Lecsatlakozatás", + "term.authed": "Authed", + "term.confirm": "Jóváhagyás ?", + "term.more": "Több", + "term.less": "Kevesebb", + "term.showMore": "Mutass többet", + "term.showLess": "Mutass kevesebbet", + "term.topSongs" : "A legjobb dalok", + "term.latestReleases": "Új megjelenések", + "term.time.added": "Hozzáadva", + "term.time.released": "Kiadva", + "term.time.updated": "Frissítve", + "term.time.hours": "óra", + "term.time.hour": "óra", + "term.time.minutes": "perc", + "term.time.minute": "perc", + "term.time.seconds": "másodperc", + "term.time.second": "másodperc", + "term.fullscreenView": "Teljes képernyős mód", + "term.defaultView": "Alapértelmezett nézet", + "term.spacializedAudioSetting": "Térbeli hang", + "term.clearAll": "Összes törlése", + "term.recentStations": "Nemrég játszott", + "term.language": "Nyelv", + "term.funLanguages": "Játékos", + "term.noLyrics": "Betöltés... / Dalszöveg nem található. / Instrumentális.", + "term.copyright": "Copyright", + "term.rightsReserved": "Minden jog fenntartva.", + "term.sponsor": "Támogasd ezt a projektet", + "term.ciderTeam": "A Cider Csapata", + "term.developer": "Fejlesztő", + "term.socialTeam": "Social Team", + "term.contributors": "Contributors", + "term.equalizer": "Equalizer", + "term.reset": "Reset", + "term.tracks": "zeneszám", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "Videók", + "term.menu": "Menü", + + // Home + "home.title": "Kezdőlap", + "home.recentlyPlayed": "Nemrég játszott", + "home.recentlyAdded": "Nemrég hozzáadott", + "home.artistsFeed": "Az előadóid feedje", + "home.artistsFeed.noArtist": "Kövess néhány művészt, hogy a legújabb zenéik itt legyenek", + "home.madeForYou": "Személyre szabva", + "home.friendsListeningTo": "A barátok épp ezt hallgatják", + "home.followedArtists": "Követett előadók", + // Errors + "error.appleMusicSubRequired": "Apple Music előfizetés szükséges.", + "error.connectionError": "Hiba történt az Apple Musichoz való csatlakozás közben.", + "error.noResults": "Nincs találat", + "error.noResults.description": "Próbálkozzon új kereséssel", + + //Podcasts + "podcast.followOnCider": "Követés a Cideren", + "podcast.followedOnCider": "Követve a Cideren", + "podcast.subscribeOnItunes": "Feliratkozás az iTunesban", + "podcast.subscribedOnItunes": "Feliratkozva az iTunesban", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "Epizódok", + "podcast.playEpisode": "Epizód lejátszása", + "podcast.website": "Podcast Weboldala", + + // Actions + "action.addToLibrary": "Hozzáadás a Könyvtárhoz", + "action.addToLibrary.success": "Hozzáadva a Könyvtárhoz", + "action.addToLibrary.error": "Hiba történt! Sikertelen hozzáadás.", + "action.removeFromLibrary": "Törlés a Könytárból", + "action.removeFromLibrary.success": "Törölve a Könyvtárból", + "action.addToQueue": "Hozzáadás a várólistához", + "action.addToQueue.success": "Hozzáadva a várólistához", + "action.addToQueue.error": "Sikertelen hozzáadás a várólistához", + "action.removeFromQueue": "Törlés a várólistáról", + "action.removeFromQueue.success": "Törölve a várólistáról", + "action.removeFromQueue.error": "Sikertelen törlés a várólistáról", + "action.addToPlaylist": "Lejátszási listához adás", + "action.removeFromPlaylist": "Törlés a lejátszási listáról", + "action.addToFavorites": "Hozzáadás a kedvencekhez", + "action.follow": "Követés", + "action.follow.success": "Követve", + "action.follow.error": "Sikertelen követés", + "action.unfollow": "Követés visszavonása", + "action.unfollow.success": "Követés visszavonva", + "action.unfollow.error": "Sikertelen visszavonás", + "action.playNext": "Lejátszás következőként", + "action.playLater": "Lejátszás utolsóként", + "action.startRadio": "Állomás létrehozása", + "action.goToArtist": "Előadó megjelenítése", + "action.goToAlbum": "Album megjelenítése", + "action.moveToTop": "Mozgatás legfelülre", + "action.share": "Megosztás", + "action.rename": "Átnevezés", + "action.love": "Szeretem", + "action.unlove": "Mégsem szeretem", + "action.dislike": "Kevesebb ilyen javasolása", + "action.undoDislike": "A Kevesebb ilyen javasolása visszavonása", + "action.showWebRemoteQR": "Távirányító QR kód megjelenítése", + "action.playTracksNext": "Play ${app.selectedMediaItems.length} tracks next", + "action.playTracksLater": "Play ${app.selectedMediaItems.length} tracks later", + "action.removeTracks": "Remove ${self.selectedItems.length} tracks from queue", + "action.import": "Importálás", + "action.export": "Exportálás", + + // Settings - General + "settings.header.general": "General", + "settings.header.general.description": "Adjust the general settings for Cider.", + "settings.option.general.language": "Language", + + // Language optgroups + "settings.option.general.language.main": "Languages", + "settings.option.general.language.fun": "Fun Languages", + "settings.option.general.language.unsorted": "Unsorted", + + // Settings - Audio + "settings.header.audio": "Hang", + "settings.header.audio.description": "A Cider hangbeállításainak módosítása.", + "settings.option.audio.quality": "Hangminőség", // Dropdown + "settings.header.audio.quality.high": "Magas", + "settings.header.audio.quality.low": "Alacsony", + "settings.header.audio.quality.auto": "Auto", + "settings.option.audio.seamlessTransition": "Szünetmentes lejátszás", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "Haladó funkcionalitás engedélyezése", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "Az AudioContext funkció engedélyezése lehetővé teszi a fejlettebb hangfunkciókat, például a Normalizásást, az Equalizereket és a Visualizer funkciókat, azonban egyes számítógépeken ez akadozást okozhat a hangsávokban.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Normalizálás", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Normalizálja az egyes zeneszámok hangosabb részeit, hogy egységesebb hallgatási élményt hozzon létre.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Térbeli hang", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Térbeli hang és a hang háromdimenziósabbá tétele (Ez nem összekeverendő a Dolby Atmos-szal!)", + // Settings - Visual + "settings.header.visual": "Vizuális", + "settings.header.visual.description": "A Cider vizuális beállításainak módosítása.", + "settings.option.visual.windowBackgroundStyle": "Ablak háttér stílusa", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "None", + "settings.header.visual.windowBackgroundStyle.artwork": "Borító", + "settings.header.visual.windowBackgroundStyle.image": "Kép", + "settings.option.visual.animatedArtwork": "Animált borító", // Dropdown + "settings.header.visual.animatedArtwork.always": "Mindig", + "settings.header.visual.animatedArtwork.limited": "Oldalakra és speciális bejegyzésekre korlátozva.", + "settings.header.visual.animatedArtwork.disable": "Kikapcsolás mindenhol", + "settings.option.visual.animatedArtworkQuality": "Animált borító minősége", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "Alacsony", + "settings.header.visual.animatedArtworkQuality.medium": "Közepes", + "settings.header.visual.animatedArtworkQuality.high": "Magas", + "settings.header.visual.animatedArtworkQuality.veryHigh": "Nagyon magas", + "settings.header.visual.animatedArtworkQuality.extreme": "Extrém", + "settings.option.visual.animatedWindowBackground": "Animált ablakháttér", // Toggle + "settings.option.visual.hardwareAcceleration": "Hardveres gyorsítás", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "Újraindítás szükséges", + "settings.header.visual.hardwareAcceleration.default": "Alap", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "Személyes adatok mutatása", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "Dalszöveg", + "settings.header.lyrics.description": "A Cider dalszöveg beállításainak módosítása.", + "settings.option.lyrics.enableMusixmatch": "MusixMatch dalszövegek engedélyezése", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "Karaoke mód bekapcsolása (Csak MusixMatch)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "MusixMatch fordítás nyelve", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "YouTube dalszövegek engedélyezése a zenei videóknál", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "Csatlakozások", + "settings.header.connectivity.description": "A Cider csatlakozás beállításainak módosítása.", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "Megjelenítés 'Cider'-ként", + "settings.header.connectivity.discordRPC.appleMusic": "Megjelenítés 'Apple Music'-ként", + "settings.option.connectivity.discordRPC.clearOnPause": "Discord Rich Presence törlése megállításnál", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble Késleltetés (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "LastFM Now Playing engedélyezése", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Loopolt zeneszám szűrése (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "Kísérleti", + "settings.header.experimental.description": "A Cider kísérleti beállításainak módosítása.", + "settings.option.experimental.compactUI": "Kompakt UI", // Toggle + "settings.option.experimental.closeButtonBehaviour": "Bezárás gomb működése", + "settings.option.experimental.closeButtonBehaviour.quit": "Cider bezárása", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "Kis méret", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "Kicsinyítés tálcára", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "Térbeli hang", + "spatial.width" : "Szélesség", + "spatial.height" : "Magasság", + "spatial.depth" : "Hosszúság", + "spatial.gain" : "Gain", + "spatial.roomMaterials" : "Szoba felépítése", + "spatial.roomDimensions" : "Room Dimensions", + "spatial.roomPositions" : "Room Positions", + "spatial.setDimensions" : "Set Dimensions", + "spatial.setPositions" : "Set Positions", + "spatial.up" : "Fent", + "spatial.front" : "Elől", + "spatial.left" : "Balra", + "spatial.right" : "Jobbra", + "spatial.back" : "Hátul", + "spatial.down" : "Lent", + "spatial.listener" : "Listener", + "spatial.audioSource" : "Audio Source", + + // Settings - Unfinished + "settings.header.unfinished": "Félkész", + + // Web Remote + "remote.web.title": "Cider Remote", + "remote.web.description": "Olvasd be ezt a QR-kódot a telefonoddal, hogy tudd vezérelni a lejátszót.", + + // About + "about.thanks": "Köszönet a Cider Collective csapatának és minden hozzájárulónak." +} diff --git a/src/i18n/ja_JP.jsonc b/src/i18n/ja_JP.jsonc new file mode 100644 index 00000000..33ca832c --- /dev/null +++ b/src/i18n/ja_JP.jsonc @@ -0,0 +1,287 @@ +{ + // App info + "app.name": "Cider", + + "date.format": "${y}年${m}月${d}日", + + // i18n Info + "i18n.languageName": "日本語", // name of language in native language + "i18n.languageNameEnglish": "Japanese", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@maikirakiwi", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // Dialogs + "dialog.cancel": "キャンセル", + "dialog.ok": "OK", + + // Notification + "notification.updatingLibrarySongs": "ライブラリの更新中...", + "notification.updatingLibraryAlbums": "ライブラリの更新中...", + "notification.updatingLibraryArtists": "ライブラリの更新中...", + + // Terms + "term.appleMusic": "Apple Music", // Follows brand term + "term.applePodcasts": "Apple Podcasts", // Follows brand term + "term.itunes": "iTunes", // Follows brand term + "term.github": "GitHub", // Follows brand term + "term.discord": "Discord", // Follows brand term + "term.learnMore": "詳しい情報", + "term.accountSettings": "アカウント設定", + "term.logout": "サインアウト", + "term.login": "サインイン", + "term.about": "Ciderについて", + "term.privateSession": "プライベートセッション", + "term.queue": "次はこちら", + "term.search": "検索", + "term.library": "ライブラリ", + "term.listenNow": "今すぐ聴く", + "term.browse": "見つける", + "term.radio": "ラジオ", + "term.recentlyAdded": "最近追加した項目", + "term.songs": "曲", + "term.albums": "アルバム", + "term.artists": "アーティスト", + "term.podcasts": "Podcast", + "term.playlists": "プレイリスト", + "term.playlist": "プレイリスト", + "term.play": "再生", + "term.pause": "停止", + "term.previous": "戻る", + "term.next": "次へ", + "term.shuffle": "シャッフル", + "term.repeat": "リピート", + "term.volume": "音量", + "term.mute": "ミュート", + "term.unmute": "ミュート解除", + "term.share": "共有", + "term.settings": "設定", + "term.seeAll": "すべて見る", + "term.sortBy": "並べ替え", + "term.sortBy.album": "アルバム", + "term.sortBy.artist": "アーティスト", + "term.sortBy.name": "曲名", + "term.sortBy.genre": "ジャンル", + "term.sortBy.releaseDate": "配信開始日", + "term.sortBy.duration": "時間", + "term.sortOrder": "並べ替え", + "term.sortOrder.ascending": "昇順", + "term.sortOrder.descending": "降順", + "term.viewAs": "表示", + "term.viewAs.coverArt": "カバーアート", + "term.viewAs.list": "リスト", + "term.size": "サイズ", + "term.size.normal": "普通", + "term.size.compact": "コンパクト", + "term.enable": "ON", + "term.disable": "OFF", + "term.enabled": "ON", + "term.disabled": "OFF", + "term.connect": "接続", + "term.connecting": "接続中", + "term.disconnect": "切断", + "term.authed": "認証済み", + "term.confirm": "よろしいでしょうか?", + "term.more": "もっと", + "term.less": "減らす", + "term.showMore": "もっと見る", + "term.showLess": "表示数を少なくする", + "term.topSongs" : "トップソング", + "term.latestReleases": "ニューリリース", + "term.time.added": "追加日", + "term.time.released": "配信開始日", + "term.time.updated": "最終更新日", + "term.time.hours": "時間", + "term.time.hour": "時間", + "term.time.minutes": "分", + "term.time.minute": "分", + "term.time.seconds": "秒", + "term.time.second": "秒", + "term.fullscreenView": "全画面表示", + "term.defaultView": "ウィンドウ表示", + "term.spacializedAudioSetting": "オーディオ空間化設定", + "term.clearAll": "消去", + "term.recentStations": "最近の再生", + "term.language": "言語", + "term.noLyrics": "ローディング。。 / 歌詞が見つからない / 器楽曲.", + "term.copyright": "著作権", + "term.rightsReserved": "All Rights Reserved.", // Translation does not exist in Japanese + "term.sponsor": "スポンサーになりましょう", + "term.ciderTeam": "Cider チーム", + "term.developer": "開発者", + "term.socialTeam": "ソーシャル チーム", + "term.contributors": "貢献者", + "term.equalizer": "イコライザー", + "term.reset": "リセット", + "term.tracks": "曲", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "ビデオ", + "term.menu": "メニュー", + + // Home + "home.title": "ホーム", + "home.recentlyPlayed": "最近の再生", + "home.recentlyAdded": "最近追加した項目", + "home.artistsFeed": "アーティストのフィード", + "home.artistsFeed.noArtist": "自分の好きなアーティストをフォローしましょう・", + "home.madeForYou": "あなたにおすすめ", + "home.friendsListeningTo": "友達が聴いている", + "home.followedArtists": "フォローしているアーティスト", + // Errors + "error.appleMusicSubRequired": "Apple Musicのサブスクリプションが必要です。", + "error.connectionError": "Apple Musicに接続できません。", + "error.noResults": "見つかりませんでした", + "error.noResults.description": "もう一度お試しください。", + + //Podcasts + "podcast.followOnCider": "Ciderでフォロー", + "podcast.followedOnCider": "フォロー中", + "podcast.subscribeOnItunes": "iTunesで購読", + "podcast.subscribedOnItunes": "購読中", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "番組", + "podcast.playEpisode": "再生", + "podcast.website": "Podcast ウェブ", + + // Actions + "action.addToLibrary": "ライブラリに追加", + "action.addToLibrary.success": "ライブラリに追加されました", + "action.addToLibrary.error": "ライブラリへの追加に失敗しました", + "action.removeFromLibrary": "ライブラリから削除", + "action.removeFromLibrary.success": "ライブラリから削除されました", + "action.addToQueue": "「次はこちら」に項目を追加", + "action.addToQueue.success": "「次はこちら」に項目を追加されました", + "action.addToQueue.error": "操作を完了できませんでした", + "action.addToPlaylist": "プレイリストに追加", + "action.removeFromPlaylist": "プレイリストから削除", + "action.addToFavorites": "ラブに追加", + "action.removeFromQueue": "「次はこちら」から項目を削除", + "action.removeFromQueue.success": "「次はこちら」から項目を削除されました", + "action.removeFromQueue.error": "操作を完了できませんでした", + "action.follow": "フォロー", + "action.follow.success": "フォロー中", + "action.follow.error": "操作を完了できませんでした", + "action.unfollow": "フォロー解除", + "action.unfollow.success": "フォローをやめました", + "action.unfollow.error": "操作を完了できませんでした", + "action.playNext": "次に再生", + "action.playLater": "最後に再生", + "action.startRadio": "ステーションを作成", + "action.goToArtist": "アーティストへ移動", + "action.goToAlbum": "アルバムへ移動", + "action.moveToTop": "上に戻る", + "action.share": "曲を共有", + "action.rename": "名前の変更", + "action.love": "ラブ", + "action.unlove": "ラブを解除", + "action.dislike": "これに似たものをすすめない", + "action.undoDislike": "「これと似た曲のおすすめを減らす」を取り消す", + "action.showWebRemoteQR": "WEBリモコンQRコードを表示", + "action.playTracksNext": "${app.selectedMediaItems.length}曲が次に再生", + "action.playTracksLater": "${app.selectedMediaItems.length}曲が最後に再生", + "action.removeTracks": "${self.selectedItems.length}曲が「次はこちら」から削除", + "action.import": "インポート", + "action.export": "エクスポート", + + // Settings - Audio + "settings.header.audio": "オーディオ", + "settings.header.audio.description": "Ciderのオーディオ設定", + "settings.option.audio.quality": "音質", // Dropdown + "settings.header.audio.quality.high": "高品質", + "settings.header.audio.quality.low": "高効率", + "settings.header.audio.quality.auto": "自動", + "settings.option.audio.seamlessTransition": "曲間なしで再生", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "先進的な機能", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "AudioContext 機能を有効にすると、オーディオノーマライズ、空間オーディオ、イコライザーなどの機能を使用できますが、音が途切れるかもしれません。", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "オーディオノーマライズ", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "さまざまな曲の音量を均一にし、より整った音を楽しめるようにする機能です。", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "オーディオ空間化", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "オーディオを空間に分散させる機能です。 (ドルビーアトモスではありません)", + // Settings - Visual + "settings.header.visual": "ビジュアル", + "settings.header.visual.description": "Ciderのビジュアル設定", + "settings.option.visual.windowBackgroundStyle": "アプリウインドウの背景スタイル", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "なし", + "settings.header.visual.windowBackgroundStyle.artwork": "アートワーク", + "settings.option.visual.animatedArtwork": "アニメーションアートワーク", // Dropdown + "settings.header.visual.animatedArtwork.always": "常に表示", + "settings.header.visual.animatedArtwork.limited": "アーティストページのみ表示", + "settings.header.visual.animatedArtwork.disable": "オフ", + "settings.option.visual.animatedArtworkQuality": "アニメーションアートワークの品質", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "低", + "settings.header.visual.animatedArtworkQuality.medium": "中", + "settings.header.visual.animatedArtworkQuality.high": "高", + "settings.header.visual.animatedArtworkQuality.veryHigh": "超高", + "settings.header.visual.animatedArtworkQuality.extreme": "最高", + "settings.option.visual.animatedWindowBackground": "アプリウィンドウの背景をアニメーション化", // Toggle + "settings.option.visual.hardwareAcceleration": "ハードウェア アクセラレーション", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "アプリを再起動する必要があります", + "settings.header.visual.hardwareAcceleration.default": "既定", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "プロフィールを表示", // Toggle + // Settings - General (Reserved) + "settings.header.general": "一般", + "settings.header.general.description": "Ciderの一般設定", + + // Settings - Lyrics + "settings.header.lyrics": "歌詞", + "settings.header.lyrics.description": "歌詞の表示設定", + "settings.option.lyrics.enableMusixmatch": "Musixmatchで歌詞を表示する", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "カラオケモードを有効にする (Musixmatchのみ)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "歌詞の優先言語", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "YouTubeの歌詞をミュージックビデオに使用する", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "アプリと連携", + "settings.header.connectivity.description": "Ciderの連携設定", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "'Cider' を表示する", + "settings.header.connectivity.discordRPC.appleMusic": "'Apple Music' を表示する", + "settings.option.connectivity.discordRPC.clearOnPause": "一時停止時にDiscord Rich Presenceをクリアする", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble Delay (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "Enable LastFM Now Playing", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Remove featuring artists from song title (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "試験的な機能", + "settings.header.experimental.description": "開発中の実験的な機能は不完全で不安定である可能性があります", + "settings.option.experimental.compactUI": "コンパクトインターフェース", // Toggle + "settings.option.experimental.closeButtonBehaviour": "「閉じる」ボタンの動作", // Dropdown + "settings.option.experimental.closeButtonBehaviour.quit": "アプリを終了する", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "タスクバーに最小化する", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "トレイに最小化する", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "空間化のプロパティ", + "spatial.width" : "幅", + "spatial.height" : "高さ", + "spatial.depth" : "奥行", + "spatial.gain" : "ゲイン", + "spatial.roomMaterials" : "部屋のマテリアル", + "spatial.roomDimensions" : "部屋の大きさ", + "spatial.roomPositions" : "部屋の位置", + "spatial.setDimensions" : "大きさを設定", + "spatial.setPositions" : "位置を設定", + "spatial.up" : "上", + "spatial.front" : "前", + "spatial.left" : "左", + "spatial.right" : "右", + "spatial.back" : "後", + "spatial.down" : "下", + "spatial.listener" : "リスナー", + "spatial.audioSource" : "音源", + + // Settings - Unfinished + "settings.header.unfinished": "未完成", + + // Web Remote + "remote.web.title": "Cider リモート", + "remote.web.description": "QRコードを使用して、Ciderとスマートフォンをペアリングする", + + //About + "about.thanks": "Cider Collective とご協力いただいた貢献者様に感謝申し上げます。" + +} diff --git a/src/i18n/pt_BR.jsonc b/src/i18n/pt_BR.jsonc new file mode 100644 index 00000000..76ff31c5 --- /dev/null +++ b/src/i18n/pt_BR.jsonc @@ -0,0 +1,238 @@ +{ // Base File + // App info + "app.name": "Cider", + + "date.format": "${d} ${m}, ${y}", + + // Dialogs + "dialog.cancel": "Cancelar", + "dialog.ok": "OK", + + // Notification + "notification.updatingLibrarySongs": "Atualizando músicas na biblioteca...", + "notification.updatingLibraryAlbums": "Atualizando albuns na biblioteca...", + "notification.updatingLibraryArtists": "Atualizando artistas na biblioteca...", + "notification.connectionError": "Houve um problema a se conectar no Apple Music", + + // Terms + "term.appleMusic": "Apple Music", + "term.applePodcasts": "Apple Podcasts", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "Saiba Mais", + "term.accountSettings": "Definições da Conta", + "term.logout": "Sair", + "term.login": "Entrar", + "term.about": "Sobre", + "term.privateSession": "Sessão Privada", + "term.queue": "Fila", + "term.search": "Procurar", + "term.library": "Biblioteca", + "term.listenNow": "Ouça Agora", + "term.browse": "Explorar", + "term.radio": "Radio", + "term.recentlyAdded": "Adicionado Recentemente", + "term.songs": "Músicas", + "term.albums": "Albuns", + "term.artists": "Artistas", + "term.podcasts": "Podcasts", + "term.playlists": "Listas de Reprodução", + "term.playlist": "Lista de Reprodução", + "term.play": "Tocar", + "term.pause": "Pausar", + "term.previous": "Anterior", + "term.next": "Próximo", + "term.shuffle": "Aleatório", + "term.repeat": "Repetir", + "term.volume": "Volume", + "term.mute": "Mudo", + "term.unmute": "Tirar o Mudo", + "term.share": "Partilhar", + "term.settings": "Definições", + "term.seeAll": "Ver Tudo", + "term.sortBy": "Organizar Por", + "term.sortBy.album": "Album", + "term.sortBy.artist": "Artista", + "term.sortBy.name": "Nome", + "term.sortBy.genre": "Genero", + "term.sortBy.releaseDate": "Data de Lançamento", + "term.sortBy.duration": "Duração", + "term.sortOrder": "A-Z", + "term.sortOrder.ascending": "Ascendente", + "term.sortOrder.descending": "Descendente", + "term.viewAs": "Ver Como", + "term.viewAs.coverArt": "Capa", + "term.viewAs.list": "Lista", + "term.size": "Tamanho", + "term.size.normal": "Normal", + "term.size.compact": "Compacto", + "term.enable": "Ativar", + "term.disable": "Desativar", + "term.enabled": "Ativado", + "term.disabled": "Desativado", + "term.connect": "Conectar", + "term.disconnect": "Desconectar", + "term.connecting": "Conectando", + "term.confirm": "Confirmar ?", + "term.more": "Mais", + "term.less": "Menos", + "term.showMore": "Mostrar Mais", + "term.showLess": "Mostrar Menos", + "term.topSongs" : "Top de Músicas", + "term.latestReleases": "Ultimos Lançamentos", + "term.time.added": "Adicionado", + "term.time.released": "Lançado", + "term.time.updated": "Atualizado", + "term.fullscreenView": "Visualização em Tela Cheia", + "term.defaultView": "Visualização Normal", + "term.spacializedAudioSetting": "Definições de Audio Espacial", + "term.clearAll": "Limpar Tudo", + "term.language": "Idioma", + "term.recentStations": "Estações Recentes", + + // Home + "home.title": "Inicio", + "home.recentlyPlayed": "Tocado Recentemente", + "home.recentlyAdded": "Adicionado Recentemente", + "home.artistsFeed": "Novidades dos seus Artistas", + "home.madeForYou": "Feito para Você", + "home.friendsListeningTo": "Amigos Ouvindo", + "home.followedArtists": "Artistas Seguidos", + // Errors + "error.appleMusicSubRequired": "Necessário uma assinatura Apple Music.", + + // Actions + "action.addToLibrary": "Adicionar à Biblioteca", + "action.addToLibrary.success": "Adicionado à Biblioteca", + "action.addToLibrary.error": "Erro ao Adicionar na Biblioteca", + "action.removeFromLibrary": "Remover da Biblioteca", + "action.removeFromLibrary.success": "Removido da Biblioteca", + "action.addToQueue": "Adicionar à Fila", + "action.addToQueue.success": "Adicionado à Fila", + "action.addToQueue.error": "Erro ao Adicionar à Fila", + "action.removeFromQueue": "Remover da Fila", + "action.removeFromQueue.success": "Removido da Fila", + "action.removeFromQueue.error": "Erro ao Remover da Fila", + "action.addToPlaylist": "Adicionar à Lista de Reprodução", + "action.removeFromPlaylist": "Remover da Lista de Reprodução", + "action.addToFavorites": "Adicionar aos Favoritos", + "action.follow": "Seguir", + "action.follow.success": "A Seguir", + "action.follow.error": "Erro ao Seguir", + "action.unfollow": "Deixar de Seguir", + "action.unfollow.success": "Deixou de Seguir", + "action.unfollow.error": "Erro ao Deixar de Seguir", + "action.playNext": "Tocar Proximo", + "action.playLater": "Tocar por Ultimo", + "action.startRadio": "Começar Radio", + "action.goToArtist": "Ir para o Artista", + "action.goToAlbum": "Ir para o Album", + "action.moveToTop": "Mover para cima", + "action.share": "Partilhar", + "action.rename": "Mudar o Nome", + "action.love": "Gostar", + "action.unlove": "Deixar de Gostar", + "action.dislike": "Não Gostar", + "action.undoDislike": "Deixar de Não Gostar", + "action.showWebRemoteQR": "Mostrar o QR para Página Remota", + // Settings - Audio + "settings.header.audio": "Audio", + "settings.header.audio.description": "Ajustar as definições de audio no Cider.", + "settings.option.audio.quality": "Qualidade do Audio", // Dropdown + "settings.header.audio.quality.high": "Alta", + "settings.header.audio.quality.low": "Baixa", + "settings.header.audio.quality.auto": "Automatico", + "settings.option.audio.seamlessTransition": "Transição de Áudio Perfeita", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "Ativar Funcionabilidades Avançadas", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "Habilitar a funcionalidade AudioContext permitirá recursos de áudio estendidos, como Normalização de Áudio , Equalizadores e Visualizadores. No entanto, em alguns sistemas, isso pode causar travamentos nas faixas de áudio.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Normalização de Audio", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Normaliza o volume alto para faixas individuais para criar uma experiência de audição mais uniforme.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Audio Espacial", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Espacialize o áudio e torne o áudio mais tridimensional (nota: isto não é Dolby Atmos)", + // Settings - Visual + "settings.header.visual": "Visual", + "settings.header.visual.description": "Ajustar as Definições de Visual do Cider.", + "settings.option.visual.windowBackgroundStyle": "Estilo do Fundo da Janela", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "Nenhum", + "settings.header.visual.windowBackgroundStyle.artwork": "Capa", + "settings.option.visual.animatedArtwork": "Capa Animada", // Dropdown + "settings.header.visual.animatedArtwork.always": "Sempre", + "settings.header.visual.animatedArtwork.limited": "Limitado a páginas e entradas especiais", + "settings.header.visual.animatedArtwork.disable": "Desativar em Tudo", + "settings.option.visual.animatedArtworkQuality": "Qualidade da Capa Animada", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "Baixa", + "settings.header.visual.animatedArtworkQuality.medium": "Media", + "settings.header.visual.animatedArtworkQuality.high": "Alta", + "settings.header.visual.animatedArtworkQuality.veryHigh": "Muito Alta", + "settings.header.visual.animatedArtworkQuality.extreme": "Extrema", + "settings.option.visual.animatedWindowBackground": "Fundo de Janela Animado", // Toggle + "settings.option.visual.hardwareAcceleration": "Acelaração no Hardware", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "Necessário reiniciar a aplicação", + "settings.header.visual.hardwareAcceleration.default": "Normal", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + + + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "Mostrar Informaçoes Pessoais", // Toggle + // Settings - General (Reserved) + "settings.header.general": "Principal", + "settings.header.general.description": "Ajustar as definiçoes principais no Cider.", + + // Settings - Lyrics + "settings.header.lyrics": "Letras", + "settings.header.lyrics.description": "Ajustar as definições das letras no Cider.", + "settings.option.lyrics.enableMusixmatch": "Ativar Letras do Musixmatch", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "Ativar Modo Karaoke (só para Musixmatch)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Idioma Preferido para Tradução Musixmatch", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "Ativar letras do Youtube para videos musicais", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "Conectividade", + "settings.header.connectivity.description": "Ajustar as definições de conectividade no Cider.", + "settings.option.connectivity.discordRPC": "Discord Rich Presence", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "Mostrar como 'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "Mostrar como 'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "Apagar Discord Rich Presence quando estiver pausado", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "Atraso dos Scrobbles do LastFM (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "Ativar LastFM Now Playing", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Remover artistas de colaboração do nome da música (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "Experimental", + "settings.header.experimental.description": "Ajustar as definições experimental no Cider.", + "settings.option.experimental.compactUI": "UI Compacto", // Toggle + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "Propriedades do Espacial", + "spatial.width" : "Largura", + "spatial.height" : "Altura", + "spatial.depth" : "Profundidade", + "spatial.roomMaterials" : "Materiais da Sala", + "spatial.roomDimensions" : "Dimensões da Sala", + "spatial.roomPositions" : "Posições da Sala", + "spatial.setDimensions" : "Definir Dimensões", + "spatial.setPositions" : "Definir Posições", + "spatial.up" : "Acima", + "spatial.front" : "Frente", + "spatial.left" : "Esquerda", + "spatial.right" : "Direita", + "spatial.back" : "Atrás", + "spatial.down" : "Abaixo", + "spatial.listener" : "Ouvinte", + "spatial.audioSource" : "Fonte de Audio", + + + + + // Settings - Unfinished + "settings.header.unfinished": "Inacabado", + + // Web Remote + "remote.web.title": "Cider Remoto", + "remote.web.description": "Digitalize o código QR para emparelhar seu telefone com esta instância Cider" +} \ No newline at end of file diff --git a/src/i18n/tr_TR.jsonc b/src/i18n/tr_TR.jsonc new file mode 100644 index 00000000..afcf3d97 --- /dev/null +++ b/src/i18n/tr_TR.jsonc @@ -0,0 +1,299 @@ +{ + // i18n Info + "i18n.languageName": "Türkçe", // name of language in native language + "i18n.languageNameEnglish": "Turkish", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@gms10ur", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "Cider", + + "date.format": "${d} ${m}, ${y}", + + // Dialogs + "dialog.cancel": "İptal", + "dialog.ok": "Tamam", + + // Notification + "notification.updatingLibrarySongs": "Arşiv'deki şarkılar alınıyor...", + "notification.updatingLibraryAlbums": "Arşiv'deki albümler alınıyor...", + "notification.updatingLibraryArtists": "Arşiv'deki sanatçılar alınıyor...", + + // Terms + "term.appleInc": "Apple", + "term.appleMusic": "Apple Müzik", + "term.applePodcasts": "Apple Podcastler", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "Daha fazla bilgi edin", + "term.accountSettings": "Hesap Ayarları", + "term.logout": "Çıkış Yap", + "term.login": "Giriş yap", + "term.about": "Hakkında", + "term.privateSession": "Özel Oturum", + "term.queue": "Çalma Sırası", + "term.search": "Arama", + "term.library": "Arşiv", + "term.listenNow": "Şimdi Dinle", + "term.browse": "Göz At", + "term.radio": "Radyo", + "term.recentlyAdded": "Son Eklenenler", + "term.songs": "Şarkılar", + "term.albums": "Albümler", + "term.artists": "Sanatçılar", + "term.podcasts": "Podcastler", + "term.playlists": "Listeler", + "term.playlist": "Liste", + "term.play": "Oynat", + "term.pause": "Duraklat", + "term.previous": "Önceki", + "term.next": "Sonraki", + "term.shuffle": "Karıştır", + "term.repeat": "Tekrarla", + "term.volume": "Ses", + "term.mute": "Sustur", + "term.unmute": "Sesi Aç", + "term.share": "Paylaş", + "term.settings": "Ayarlar", + "term.seeAll": "Tümünü Gör", + "term.sortBy": "Sırala", + "term.sortBy.album": "Albüm", + "term.sortBy.artist": "Sanatçı", + "term.sortBy.name": "Şarkı İsmi", + "term.sortBy.genre": "Tür", + "term.sortBy.releaseDate": "Yayınlanma Tarihi", + "term.sortBy.duration": "Süre", + "term.sortOrder": "A-Z", + "term.sortOrder.ascending": "Çoğalan", + "term.sortOrder.descending": "Azalan", + "term.viewAs": "Şöyle Göster", + "term.viewAs.coverArt": "Albüm Kapağı", + "term.viewAs.list": "Liste", + "term.size": "Boyut", + "term.size.normal": "Normal", + "term.size.compact": "Daha Sıkı", + "term.enable": "Aç", + "term.disable": "Kapa", + "term.enabled": "Açık", + "term.disabled": "Kapalı", + "term.connect": "Bağlan", + "term.connecting": "Bağlanıyor", + "term.disconnect": "Bağlantıyı Kes", + "term.authed": "Bağlantı sağlandı", + "term.confirm": "Onayla?", + "term.more": "Daha Fazla", + "term.less": "Daha Az", + "term.showMore": "Daha Fazla Göster", + "term.showLess": "Daha Az Göster", + "term.topSongs" : "Popüler Parçalar", + "term.latestReleases": "Yeni Çıkan", + "term.time.added": "Şu tarihte eklendi: ", + "term.time.released": "Şu tarihte yayınalndı: ", + "term.time.updated": "Şu tarihte güncellendi: ", + "term.fullscreenView": "Tam Ekrana Geç", + "term.defaultView": "Normal Görünüme Dön", + "term.spacializedAudioSetting": "Uzamsal Ses Ayarları", + "term.clearAll": "Tümünü Temizle", + "term.recentStations": "Son İstasyonlar", + "term.language": "Dil", + "term.funLanguages": "Mizahi Diller", + "term.noLyrics": "Yükleniyor... / Şarkı Sözü Bulunamadı./ Enstrumantal.", + "term.copyright": "Copyright", + "term.rightsReserved": "Tüm Haklası Saklıdır.", + "term.sponsor": "Bu Projeye Destek Olun", + "term.ciderTeam": "Cider Ekibi", + "term.developer": "Geliştirici", + "term.socialTeam": "Sosyal Ekip", + "term.contributors": "Katkıda Bulunanlar", + "term.equalizer": "Ekolayzer", + "term.reset": "Sıfırla", + "term.tracks": "adet şarkı", // Assume x amount of tracks. e.g. 50 tracks + "term.time.hours": "saat", + "term.time.hour": "saat", + "term.time.minutes": "dakika", + "term.time.minute": "dakika", + "term.time.seconds": "saniye", + "term.time.second": "saniye", + "term.videos": "Video Klipler", + "term.menu": "Menü", + + // Home + "home.title": "Ana Sayfa", + "home.recentlyPlayed": "Son Oynatılanlar", + "home.recentlyAdded": "Son Eklenenler", + "home.artistsFeed": "Son Çıkanlar", + "home.artistsFeed.noArtist": "Birkaç sanatçı takip ettiğinizde, sanatçılarınızın son çıkan yayınları burada gözükür.", + "home.madeForYou": "Sadece Size Özel", + "home.friendsListeningTo": "Arkadaşlarınızın Dinledikleri", + "home.followedArtists": "Takip Edilen Sanatçılar", + + // Errors + "error.appleMusicSubRequired": "Apple Müzik, aktif bir abonelik gerektirir.", + "error.connectionError": "Apple Müzik ile bağlantı kurulamadı.", + "error.noResults": "Hiç sonuç yok", + "error.noResults.description": "Tekrar deneyin.", + + //Podcasts + "podcast.followOnCider": "Cider'de Takip Et", + "podcast.followedOnCider": "Cider'de Takip Ediliyor", + "podcast.subscribeOnItunes": "itunes'de Abone Ol", + "podcast.subscribedOnItunes": "iTunes'de Abone Olundu", + "podcast.itunesStore": "iTunes Mağazası", + "podcast.episodes": "Bölümler", + "podcast.playEpisode": "Bölümü Oynat", + "podcast.website": "Web Sayfası", + + // Actions + "action.addToLibrary": "Arşiv'e Ekle", + "action.addToLibrary.success": "Arşiv'e Eklendi", + "action.addToLibrary.error": "Arşiv'e Eklenemedi", + "action.removeFromLibrary": "Arşiv'den Sil", + "action.removeFromLibrary.success": "Arşiv'den Silindi", + "action.addToPlaylist": "Liste'ye Ekle", + "action.removeFromPlaylist": "Liste'den Sil", + "action.addToFavorites": "Favorilere Ekle", + "action.moveToTop": "En Başa Taşı", + "action.rename": "Yeniden Adlandır", + "action.addToQueue": "Sıraya Ekle", + "action.addToQueue.success": "Sıraya Eklendi", + "action.addToQueue.error": "Sıraya Eklenemedi", + "action.removeFromQueue": "Sıradan Kaldır", + "action.removeFromQueue.success": "Sıradan Kaldırıldı", + "action.removeFromQueue.error": "Sıradan Kaldırılamadı", + "action.follow": "Takip Et", + "action.follow.success": "Takip Ediliyor", + "action.follow.error": "Takip Edilemedi", + "action.unfollow": "Takibi Bırak", + "action.unfollow.success": "Takipten Çıkıldı", + "action.unfollow.error": "Takipten Çıkılamadı", + "action.playNext": "Sıradaki Yap", + "action.playLater": "En Son Çal", + "action.startRadio": "İstasyon Yarat", + "action.goToArtist": "Sanatçıya Git", + "action.goToAlbum": "Albüme Git", + "action.share": "Paylaş", + "action.love": "Beğen", + "action.unlove": "Beğeniyi Kaldır", + "action.dislike": "Bunun Gibileri Daha Az Öner", + "action.undoDislike": "Bunun Gibileri Daha Az Önermeyi Geri Al", + "action.showWebRemoteQR": "Uzaktan Kumanda Bağla", + "action.playTracksNext": "${app.selectedMediaItems.length} adet şarkıyı sıraya ekle", + "action.playTracksLater": "${app.selectedMediaItems.length} adet şarkıyı sıranın en sonuna ekle", + "action.removeTracks": "Sıradan ${self.selectedItems.length} adet şarkıyı kaldır", + "action.import": "Import", + "action.export": "Export", + "term.showAlbum": "Tüm Albümü Göster", + + // Settings - General (Reserved) + "settings.header.general": "Genel Ayarlar", + "settings.header.general.description": "Genel ayarları buradan düzenleyin.", + "settings.option.general.language": "Dil Seçeneği", + + // Language optgroups + "settings.option.general.language.main": "Gerçek Diller", + "settings.option.general.language.fun": "Mizahi Diller", + "settings.option.general.language.unsorted": "Henüz Tamamlanmamış Diller", + + // Settings - Audio + "settings.header.audio": "Çalma / Oynatma", + "settings.header.audio.description": "Cider'in sizin için en iyi dinleme deneyimini sağlayabilmesi için ses ayarlarınızı yapın.", + "settings.option.audio.quality": "Ses Kalitesi", // Dropdown + "settings.header.audio.quality.high": "Yüksek Kalite", + "settings.header.audio.quality.low": "Yüksek Verimlilik", + "settings.header.audio.quality.auto": "Otomatik", + "settings.option.audio.seamlessTransition": "Kesintisiz Ses Geçişi", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "Gelişmiş Ses Deneyimi", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "Gelişmiş ses deneyiminin etkinleştirilmesi, Ses Normalleştirme, Ekolayzer ve Görselleştirici gibi genişletilmiş ses özelliklerine izin verir, ancak bu durum bazı sistemlerde seste bozulmalara neden olabilir.", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "Ses Normalleştirme", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "Ses normalleştirme alçak ve yüksek sesli şarkıları dengeler ve daha düzgün bir dinleme deneyimi sağlar.", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "Uzamsal Ses", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "Sesi uzamsallaştırın ve sesi daha 3 boyutlu hale getirin (not: Bu Dolby Atmos değildir)", + + // Settings - Visual + "settings.header.visual": "Görünüm", + "settings.header.visual.description": "Cider'in nasıl gözükmesini istediğinizi ayarlayın", + "settings.option.visual.windowBackgroundStyle": "Uygulama Arka Plan Stili", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "Karanlık", + "settings.header.visual.windowBackgroundStyle.artwork": "Albüm Kapağı", + "settings.option.visual.animatedArtwork": "Hareketli Albüm Kapakları", // Dropdown + "settings.header.visual.animatedArtwork.always": "Her Zaman Açık", + "settings.header.visual.animatedArtwork.limited": "Bazı Sayfalara ve Özel Bölgelerle Sınırlı", + "settings.header.visual.animatedArtwork.disable": "Her Zaman Kapalı", + "settings.option.visual.animatedArtworkQuality": "Hareketli Albüm Kapağı Kalitesi", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "Düşük", + "settings.header.visual.animatedArtworkQuality.medium": "Orta", + "settings.header.visual.animatedArtworkQuality.high": "Yüksek", + "settings.header.visual.animatedArtworkQuality.veryHigh": "Daha Yüksek", + "settings.header.visual.animatedArtworkQuality.extreme": "Ekstrem", + "settings.option.visual.animatedWindowBackground": "Hareketli Uygulama Arka Planı", // Toggle + "settings.option.visual.hardwareAcceleration": "Donanım Hızlandırması", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "Etki etmesi için uygulamayı yeniden başlatmak gerekir.", + "settings.header.visual.hardwareAcceleration.default": "Varsayılan", + "settings.header.visual.hardwareAcceleration.webGPU": "Gelişmiş", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "Kullanıcı Adımı Göster", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "Şarkı Sözleri", + "settings.header.lyrics.description": "Cider'in şarkı sözlerini nasıl görüntülemesini istediğini buradan ayarlayın.", + "settings.option.lyrics.enableMusixmatch": "Musixmatch Kullan", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "Karaoke Modunu Etkinleştir (Sadece Musixmatch)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Musixmatch için Otomatik Çeviri Dili", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "Müzik Videoları için Şarkı Sözünü YouTube'dan Al", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "Diğer Servisler", + "settings.header.connectivity.description": "Cider'i diğer servislere bağlayarak deneyiminizi zenginleştirin.", + "settings.option.connectivity.discordRPC": "Ne Dinlediğimi Discord'da Göster", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "'Cider' Olarak", + "settings.header.connectivity.discordRPC.appleMusic": "'Apple Music' Olarak", + "settings.option.connectivity.discordRPC.clearOnPause": "Duraklatıldığında Discord'da Gösterme", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Bağlantısı", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobblalma Yüzdesi (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "Şimdi çalan şarkıyı LastFM'de göster", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "Albüm sanatçısını Scrobbledan kaldır(LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Tekrar edilen şarkıyı filtrele (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "Deneysel", + "settings.header.experimental.description": "Cider'deki deneysel özelliklere erişim sağlayın. (Not: Bazı özellikler düzgün çalışmayabilir.)", + "settings.option.experimental.compactUI": "Kompakt Arayüz", // Toggle + "settings.option.experimental.closeButtonBehaviour": "Kapat düğmesi davranışı", + "settings.option.experimental.closeButtonBehaviour.quit": "Cider'den çık", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "Simge durumuna küçült", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "Görev çubuğuna küçült", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "Uzamsal Özellikler", + "spatial.width" : "Genişlik", + "spatial.height" : "Yükseklik", + "spatial.depth" : "Derinlik", + "spatial.roomMaterials" : "Oda Materyalleri", + "spatial.roomDimensions" : "Oda Ölçüleri", + "spatial.roomPositions" : "Oda Pozisyonu", + "spatial.setDimensions" : "Ölçüleri Ayarla", + "spatial.setPositions" : "Pozisyonu Ayarla", + "spatial.up" : "Üst", + "spatial.front" : "Ön", + "spatial.left" : "Sol", + "spatial.right" : "Sağ", + "spatial.back" : "Arka", + "spatial.down" : "Aşağı", + "spatial.listener" : "Dinleyici", + "spatial.audioSource" : "Ses Kaynağı", + + // Settings - Unfinished + "settings.header.unfinished": "Geliştirme Aşamasında", + + // Web Remote + "remote.web.title": "Cider'e Bağlan", + "remote.web.description": "Telefonunuzu Bu Cider Oturumuyla Eşleştirmek için QR Kodunu Tarayın", + + //About + "about.thanks": "Cider Collective Ekibine ve tüm katkıda bulunanlara çok teşekkür ederiz." + +} \ No newline at end of file diff --git a/src/i18n/zh_CN.jsonc b/src/i18n/zh_CN.jsonc new file mode 100644 index 00000000..4052ab9e --- /dev/null +++ b/src/i18n/zh_CN.jsonc @@ -0,0 +1,288 @@ +{ + // App info + "app.name": "Cider", + + "date.format": "${y}年${m}月${d}日", + + // i18n Info + "i18n.languageName": "简体中文(中国)", // name of language in native language + "i18n.languageNameEnglish": "Simp. Chinese (China)", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@maikirakiwi", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // Dialogs + "dialog.cancel": "取消", + "dialog.ok": "确定", + + // Notification + "notification.updatingLibrarySongs": "正在更新资料库的歌曲信息...", + "notification.updatingLibraryAlbums": "正在更新资料库的专辑信息...", + "notification.updatingLibraryArtists": "正在更新资料库的艺人信息...", + + // Terms + "term.appleMusic": "Apple Music", // Follows brand term + "term.applePodcasts": "Apple Podcasts", // Follows brand term + "term.itunes": "iTunes", // Follows brand term + "term.github": "GitHub", // Follows brand term + "term.discord": "Discord", // Follows brand term + "term.learnMore": "更多信息", + "term.accountSettings": "账户设置", + "term.logout": "登出", + "term.login": "登录", + "term.about": "关于", + "term.privateSession": "私人聆听", + "term.queue": "队列", + "term.search": "搜索", + "term.library": "资料库", + "term.listenNow": "现在就听", + "term.browse": "浏览", + "term.radio": "广播", + "term.recentlyAdded": "最近添加", + "term.songs": "歌曲", + "term.albums": "专辑", + "term.artists": "艺人", + "term.podcasts": "播客", + "term.playlists": "播放列表", + "term.playlist": "播放列表", + "term.play": "播放", + "term.pause": "暂停", + "term.previous": "上一首", + "term.next": "下一首", + "term.shuffle": "随机播放", + "term.repeat": "重复播放", + "term.volume": "音量", + "term.mute": "静音", + "term.unmute": "解除静音", + "term.share": "分享", + "term.settings": "设置", + "term.seeAll": "查看全部", + "term.sortBy": "排序", + "term.sortBy.album": "专辑", + "term.sortBy.artist": "艺人", + "term.sortBy.name": "歌名", + "term.sortBy.genre": "类型", + "term.sortBy.releaseDate": "发行日期", + "term.sortBy.duration": "时长", + "term.sortOrder": "字母排序", + "term.sortOrder.ascending": "升序", + "term.sortOrder.descending": "倒序", + "term.viewAs": "显示模式", + "term.viewAs.coverArt": "专辑封面", + "term.viewAs.list": "列表", + "term.size": "大小", + "term.size.normal": "正常", + "term.size.compact": "紧凑", + "term.enable": "启用", + "term.disable": "禁用", + "term.enabled": "已启用", + "term.disabled": "已禁用", + "term.connect": "连接", + "term.connecting": "连接中", + "term.disconnect": "断开", + "term.authed": "已认证", + "term.confirm": "确认?", + "term.more": "更多", + "term.less": "较少", + "term.showMore": "显示更多", + "term.showLess": "显示更少", + "term.topSongs" : "热门歌曲", + "term.latestReleases": "最新发行", + "term.time.added": "添加于", + "term.time.released": "发行于", + "term.time.updated": "更新于", + "term.time.hours": "小时", + "term.time.hour": "小时", + "term.time.minutes": "分钟", + "term.time.minute": "分钟", + "term.time.seconds": "秒", + "term.time.second": "秒", + "term.fullscreenView": "全屏", + "term.defaultView": "默认", + "term.spacializedAudioSetting": "音频空间化设置", + "term.clearAll": "清空", + "term.recentStations": "最近播放的频道", + "term.language": "语言", + "term.noLyrics": "加载中。。/ 搜索无结果 / 纯音乐", + "term.copyright": "版权所有", + "term.rightsReserved": "保留所有权利。", + "term.sponsor": "赞助", + "term.ciderTeam": "Cider 团队", + "term.developer": "开发者", + "term.socialTeam": "媒体团队", + "term.contributors": "贡献者", + "term.equalizer": "均衡器", + "term.reset": "重置", + "term.tracks": "首歌曲", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "视频", + "term.menu": "菜单", + + // Home + "home.title": "主页", + "home.recentlyPlayed": "最近播放", + "home.recentlyAdded": "最近添加", + "home.artistsFeed": "艺人推荐", + "home.artistsFeed.noArtist": "追踪您喜爱的艺人后便可查看他们的最新发行。", + "home.madeForYou": "专属推荐", + "home.friendsListeningTo": "朋友正在听", + "home.followedArtists": "关注的艺人", + + // Errors + "error.appleMusicSubRequired": "需要订阅 Apple Music 以使用 Cider", + "error.connectionError": "无法连接到 Apple Music。", + "error.noResults": "没有结果", + "error.noResults.description": "尝试更改搜索条件。", + + //Podcasts + "podcast.followOnCider": "在 Cider 中追踪", + "podcast.followedOnCider": "已追踪", + "podcast.subscribeOnItunes": "在 iTunes 上订阅", + "podcast.subscribedOnItunes": "已订阅", + "podcast.itunesStore": "iTunes Store", // Follow brand term + "podcast.episodes": "单集", + "podcast.playEpisode": "播放单集", + "podcast.website": "Podcast 网站", + + + // Actions + "action.addToLibrary": "加入资料库", + "action.addToLibrary.success": "成功加入资料库", + "action.addToLibrary.error": "加入资料库的过程发生了错误", + "action.removeFromLibrary": "从资料库中移除", + "action.removeFromLibrary.success": "已从资料库中移除", + "action.addToQueue": "加入队列", + "action.addToQueue.success": "成功加入队列", + "action.addToQueue.error": "加入队列的过程发生了错误", + "action.removeFromQueue": "从队列中移除", + "action.removeFromQueue.success": "已从队列中移除", + "action.removeFromQueue.error": "从队列中移除的过程发生了错误", + "action.addToPlaylist": "加入播放列表", + "action.removeFromPlaylist": "从播放列表中移除", + "action.addToFavorites": "加至收藏", + "action.follow": "关注", + "action.follow.success": "已关注", + "action.follow.error": "尝试关注的过程发生了错误", + "action.unfollow": "取消关注", + "action.unfollow.success": "已取消关注", + "action.unfollow.error": "尝试取消关注的过程发生了错误", + "action.playNext": "下一首播放", + "action.playLater": "最后播放", + "action.startRadio": "开始电台", + "action.goToArtist": "前往艺人", + "action.goToAlbum": "前往专辑", + "action.moveToTop": "移到顶部", + "action.share": "分享歌曲", + "action.rename": "重命名", + "action.love": "喜欢", + "action.unlove": "踩", + "action.dislike": "减少此类建议", + "action.undoDislike": "增加此类建议", + "action.showWebRemoteQR": "显示远程控制的二维码", + "action.playTracksNext": "插播 ${app.selectedMediaItems.length} 首歌曲", + "action.playTracksLater": "最后播放 ${app.selectedMediaItems.length} 首歌曲", + "action.removeTracks": "从队列中移除 ${self.selectedItems.length} 首歌曲", + "action.import": "导入", + "action.export": "导出", + + // Settings - Audio + "settings.header.audio": "音频", + "settings.header.audio.description": "调整 Cider 的音频设置", + "settings.option.audio.quality": "音质", // Dropdown + "settings.header.audio.quality.high": "高音质", + "settings.header.audio.quality.low": "高效率", + "settings.header.audio.quality.auto": "自动", + "settings.option.audio.seamlessTransition": "无缝播放", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "进阶功能", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "启用 AudioContext 将解锁例如音量标准化和音频空间化的功能,但可能会在小部分设备上出现音频上的卡顿。", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "音量标准化", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "使所感知到的音频响度统一", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "音频空间化", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "使所感知到的音频更有立体感 (注: 这不是杜比全景声)", + // Settings - Visual + "settings.header.visual": "外观", + "settings.header.visual.description": "调整 Cider 的外观", + "settings.option.visual.windowBackgroundStyle": "窗口背景样式", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "无", + "settings.header.visual.windowBackgroundStyle.artwork": "专辑封面", + "settings.option.visual.animatedArtwork": "动态专辑封面", // Dropdown + "settings.header.visual.animatedArtwork.always": "总是显示", + "settings.header.visual.animatedArtwork.limited": "只在艺人页面和专辑封面显示", + "settings.header.visual.animatedArtwork.disable": "关闭", + "settings.option.visual.animatedArtworkQuality": "动态专辑封面画质", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "低", + "settings.header.visual.animatedArtworkQuality.medium": "中", + "settings.header.visual.animatedArtworkQuality.high": "高", + "settings.header.visual.animatedArtworkQuality.veryHigh": "非常高", + "settings.header.visual.animatedArtworkQuality.extreme": "极高", + "settings.option.visual.animatedWindowBackground": "动态窗口背景", // Toggle + "settings.option.visual.hardwareAcceleration": "硬件加速", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "需要重启 Cider 才会生效", + "settings.header.visual.hardwareAcceleration.default": "默认", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "显示个人资料", // Toggle + // Settings - General (Reserved) + "settings.header.general": "通用", + "settings.header.general.description": "调整 Cider 的通用设置", + + // Settings - Lyrics + "settings.header.lyrics": "歌词", + "settings.header.lyrics.description": "调整 Cider 的歌词设置", + "settings.option.lyrics.enableMusixmatch": "启用 Musixmatch 歌词", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "启用卡拉 OK 模式(仅 Musixmatch)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Musixmatch 歌词语言偏好", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "播放 MV 时使用 YouTube 歌词", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "外部连接", + "settings.header.connectivity.description": "调整Cider与外部应用的交互设置", + "settings.option.connectivity.discordRPC": "Discord 动态", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "显示正在玩 'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "显示正在玩 'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "暂停时清除Discord 动态", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling 记录", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble 延迟 (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "启用 LastFM 正在播放", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "从歌名里去除艺人推荐 (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "实验性功能", + "settings.header.experimental.description": "调整Cider的实验性功能", + "settings.option.experimental.compactUI": "紧凑型 UI", // Toggle + "settings.option.experimental.closeButtonBehaviour": "点击关闭按钮时", + "settings.option.experimental.closeButtonBehaviour.quit": "退出 Cider", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "最小化到任务栏", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "最小化到系统托盘", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "空间属性", + "spatial.width" : "宽度", + "spatial.height" : "高度", + "spatial.depth" : "深度", + "spatial.gain": "增益", + "spatial.roomMaterials" : "空间材质", + "spatial.roomDimensions" : "空间尺寸", + "spatial.roomPositions" : "空间位置", + "spatial.setDimensions" : "设置尺寸", + "spatial.setPositions" : "设置位置", + "spatial.up" : "上", + "spatial.front" : "前", + "spatial.left" : "左", + "spatial.right" : "右", + "spatial.back" : "后", + "spatial.down" : "下", + "spatial.listener" : "您", + "spatial.audioSource" : "音源", + + // Settings - Unfinished + "settings.header.unfinished": "未完成", + + // Web Remote + "remote.web.title": "Cider 远程控制", + "remote.web.description": "扫描以下的二维码以控制 Cider", + + //About + "about.thanks": "郑重感谢 Cider Collective 以及为这个项目提供支持的贡献者。" +} diff --git a/src/i18n/zh_HK.jsonc b/src/i18n/zh_HK.jsonc new file mode 100644 index 00000000..14bce12e --- /dev/null +++ b/src/i18n/zh_HK.jsonc @@ -0,0 +1,297 @@ +{ + + // i18n Info + "i18n.languageName": "繁體中文(香港)", // name of language in native language + "i18n.languageNameEnglish": "Trad. Chinese (Hong Kong)", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@kyw504100 @maikirakiwi", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "Cider", + + "date.format": "${y}年${m}月${d}日", + + // Dialogs + "dialog.cancel": "取消", + "dialog.ok": "確認", + + // Notification + "notification.updatingLibrarySongs": "正在更新資料庫的歌曲...", + "notification.updatingLibraryAlbums": "正在更新資料庫的專輯...", + "notification.updatingLibraryArtists": "正在更新資料庫的藝人...", + // Terms + "term.appleInc": "Apple Inc.", + "term.appleMusic": "Apple Music", // Follows brand term + "term.applePodcasts": "Apple Podcasts", // Follows brand term + "term.itunes": "iTunes", // Follows brand term + "term.github": "GitHub", // Follows brand term + "term.discord": "Discord", // Follows brand term + "term.learnMore": "了解更多", + "term.accountSettings": "帳號設定", + "term.logout": "登出", + "term.login": "登入", + "term.about": "關於", + "term.privateSession": "私人模式", + "term.queue": "待播清單", + "term.search": "搜尋", + "term.library": "資料庫", + "term.listenNow": "立即聆聽", + "term.browse": "瀏覽", + "term.radio": "廣播", + "term.recentlyAdded": "最近加入", + "term.songs": "歌曲", + "term.albums": "專輯", + "term.artists": "藝人", + "term.podcasts": "Podcasts", + "term.playlists": "播放列表", + "term.playlist": "播放列表", + "term.play": "播放", + "term.pause": "暫停", + "term.previous": "上一首", + "term.next": "下一首", + "term.shuffle": "隨機播放", + "term.repeat": "重複播放", + "term.volume": "音量", + "term.mute": "靜音", + "term.unmute": "取消靜音", + "term.share": "分享", + "term.settings": "設定", + "term.seeAll": "顯示全部", + "term.sortBy": "排序", + "term.sortBy.album": "專輯", + "term.sortBy.artist": "藝人", + "term.sortBy.name": "歌名", + "term.sortBy.genre": "音樂風格", + "term.sortBy.releaseDate": "發行日期", + "term.sortBy.duration": "時長", + "term.sortOrder": "字母排序", + "term.sortOrder.ascending": "順序", + "term.sortOrder.descending": "倒序", + "term.viewAs": "顯示模式", + "term.viewAs.coverArt": "專輯封面", + "term.viewAs.list": "列表", + "term.size": "大小", + "term.size.normal": "正常", + "term.size.compact": "緊凑", + "term.enable": "啟用", + "term.disable": "停用", + "term.enabled": "已啟用", + "term.disabled": "已停用", + "term.connect": "連結", + "term.connecting": "連結中", + "term.disconnect": "取消連結", + "term.authed": "已授權", + "term.confirm": "確認?", + "term.more": "更多", + "term.less": "較少", + "term.showMore": "顯示更多", + "term.showLess": "顯示較少", + "term.topSongs" : "熱門歌曲", + "term.latestReleases": "最新發行", + "term.time.added": "加入於", + "term.time.released": "發行於", + "term.time.updated": "更新於", + "term.time.hours": "小時", + "term.time.hour": "小時", + "term.time.minutes": "分鐘", + "term.time.minute": "分鐘", + "term.time.seconds": "秒", + "term.time.second": "秒", + "term.fullscreenView": "全螢幕檢視", + "term.defaultView": "一般檢視", + "term.spacializedAudioSetting": "空間音訊設定", + "term.clearAll": "清空", + "term.recentStations": "最近播放的頻道", + "term.language": "語言", + "term.funLanguages": "惡搞", + "term.noLyrics": "加載中... / 找不到歌詞。/ 純音樂。", + "term.copyright": "Copyright", + "term.rightsReserved": "保留一切權利。", + "term.sponsor": "贊助這個項目", + "term.ciderTeam": "Cider 團隊", + "term.developer": "開發者", + "term.socialTeam": "社交團隊", + "term.contributors": "貢獻者", + "term.equalizer": "均衡器", + "term.reset": "重設", + "term.tracks": "首歌曲", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "影片", + "term.menu": "選項", + + // Home + "home.title": "主頁", + "home.recentlyPlayed": "最近播放", + "home.recentlyAdded": "最近加入", + "home.artistsFeed": "藝人動態", + "home.artistsFeed.noArtist": "追蹤一些藝人來獲得他們的最新歌曲資訊。", + "home.madeForYou": "為您推薦", + "home.friendsListeningTo": "朋友正在聆聽", + "home.followedArtists": "追蹤的藝人", + // Errors + "error.appleMusicSubRequired": "需要訂閱Apple Music以使用Cider", + "error.connectionError": "無法連接到 Apple Music。", + "error.noResults": "沒有結果", + "error.noResults.description": "請嘗試新的搜尋內容。", + + //Podcasts + "podcast.followOnCider": "在Cider上追蹤", + "podcast.followedOnCider": "已在Cider上追蹤", + "podcast.subscribeOnItunes": "在iTunes上訂閱", + "podcast.subscribedOnItunes": "已在iTunes上訂閱", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "單集", + "podcast.playEpisode": "播放單集", + "podcast.website": "Podcast 網頁", + + // Actions + "action.addToLibrary": "加入資料庫", + "action.addToLibrary.success": "成功加入資料庫", + "action.addToLibrary.error": "加入資料庫的過程發生錯誤", + "action.removeFromLibrary": "從資料庫刪除", + "action.removeFromLibrary.success": "已從資料庫刪除", + "action.addToQueue": "加入待播清單", + "action.addToQueue.success": "成功加入待播清單", + "action.addToQueue.error": "加入待播清單的過程發生錯誤", + "action.removeFromQueue": "從待播清單刪除", + "action.removeFromQueue.success": "已從待播清單刪除", + "action.removeFromQueue.error": "從待播清單刪除的過程中發生錯誤", + "action.addToPlaylist": "加至播放列表", + "action.removeFromPlaylist": "從播放列表刪除", + "action.addToFavorites": "加至收藏", + "action.follow": "追蹤", + "action.follow.success": "追蹤中", + "action.follow.error": "追蹤的過程發生錯誤", + "action.unfollow": "取消追蹤", + "action.unfollow.success": "已取消追蹤", + "action.unfollow.error": "取消追蹤的過程發生錯誤", + "action.playNext": "插播", + "action.playLater": "稍後播放", + "action.startRadio": "建立電台", + "action.goToArtist": "前往藝人", + "action.goToAlbum": "前往專輯", + "action.moveToTop": "移動到頂部", + "action.share": "分享歌曲", + "action.rename": "重新命名", + "action.love": "喜愛", + "action.unlove": "取消喜愛", + "action.dislike": "減少此類建議", + "action.undoDislike": "還原減小此類建議", + "action.showWebRemoteQR": "顯示遙距控制二維碼", + "action.playTracksNext": "插播 ${app.selectedMediaItems.length} 首歌曲", + "action.playTracksLater": "稍後播放 ${app.selectedMediaItems.length} 首歌曲", + "action.removeTracks": "從待播清單刪除 ${self.selectedItems.length} 首歌曲", + "action.import": "匯入", + "action.export": "匯出", + + // Settings - General + "settings.header.general": "一般", + "settings.header.general.description": "調整Cider的一般設定", + "settings.option.general.language": "語言", + + // Language optgroups + "settings.option.general.language.main": "語言", + "settings.option.general.language.fun": "惡搞語言", + "settings.option.general.language.unsorted": "未分類", + + // Settings - Audio + "settings.header.audio": "音訊", + "settings.header.audio.description": "調整Cider的音訊設定", + "settings.option.audio.quality": "音訊音質", // Dropdown + "settings.header.audio.quality.high": "高素質", + "settings.header.audio.quality.low": "高效率", + "settings.header.audio.quality.auto": "自動", + "settings.option.audio.seamlessTransition": "無縫播放", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "進階功能", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "啟用 AudioContext 將解鎖類似音量平衡和均衡器的進階功能。但是會在一些電腦造成音樂卡頓。", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "音量平衡", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "將平衡輕柔和響亮的歌曲,建立更統一的聆聽體驗。", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "空間音訊", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "將音訊進行空間化處理來製造一個更立體的聆聽體驗(注:此功能不是官方的杜比全景聲)", + // Settings - Visual + "settings.header.visual": "外觀", + "settings.header.visual.description": "調整Cider的外觀", + "settings.option.visual.windowBackgroundStyle": "窗口背景樣式", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "空白", + "settings.header.visual.windowBackgroundStyle.artwork": "專輯封面", + "settings.header.visual.windowBackgroundStyle.image": "圖片", + "settings.option.visual.animatedArtwork": "動態專輯封面", // Dropdown + "settings.header.visual.animatedArtwork.always": "總是顯示", + "settings.header.visual.animatedArtwork.limited": "只在藝人頁面和專輯封面顯示", + "settings.header.visual.animatedArtwork.disable": "關閉", + "settings.option.visual.animatedArtworkQuality": "動態專輯封面品質", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "低", + "settings.header.visual.animatedArtworkQuality.medium": "中", + "settings.header.visual.animatedArtworkQuality.high": "高", + "settings.header.visual.animatedArtworkQuality.veryHigh": "非常高", + "settings.header.visual.animatedArtworkQuality.extreme": "極高", + "settings.option.visual.animatedWindowBackground": "動態窗口背景", // Toggle + "settings.option.visual.hardwareAcceleration": "硬體加速", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "需要重啓 Cider 才能生效", + "settings.header.visual.hardwareAcceleration.default": "預設", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "顯示個人檔案", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "歌詞", + "settings.header.lyrics.description": "調整Cider的歌詞設定", + "settings.option.lyrics.enableMusixmatch": "啟用 Musixmatch 歌詞", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "啟用卡拉OK模式(僅限Musixmatch)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Musixmatch 歌詞語言偏好", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "播放 MV 時使用 YouTube 歌詞", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "外部連結", + "settings.header.connectivity.description": "調整Cider與外部的連結", + "settings.option.connectivity.discordRPC": "Discord 狀態", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "顯示為'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "顯示為'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "暫停時清除 Discord 狀態", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling 記錄", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble 延遲 (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "啟用 LastFM 正在播放", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "從歌名中移除藝人推薦 (LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "實驗性功能", + "settings.header.experimental.description": "調整Cider的實驗性功能", + "settings.option.experimental.compactUI": "緊凑型 UI", // Toggle + "settings.option.experimental.closeButtonBehaviour": "關閉按鈕行為", + "settings.option.experimental.closeButtonBehaviour.quit": "結束 Cider", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "縮小至工作列", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "縮小至系統托盤", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "空間音訊屬性", + "spatial.width" : "闊度", + "spatial.height" : "高度", + "spatial.depth" : "深度", + "spatial.gain" : "增益", + "spatial.roomMaterials" : "空間材質", + "spatial.roomDimensions" : "空間大小", + "spatial.roomPositions" : "空間位置", + "spatial.setDimensions" : "大小設定", + "spatial.setPositions" : "位置設定", + "spatial.up" : "上方", + "spatial.front" : "前方", + "spatial.left" : "左方", + "spatial.right" : "右方", + "spatial.back" : "後方", + "spatial.down" : "下方", + "spatial.listener" : "觀眾", + "spatial.audioSource" : "音源", + + // Settings - Unfinished + "settings.header.unfinished": "未完成", + + // Web Remote + "remote.web.title": "遙距控制 Cider", + "remote.web.description": "掃描以下的二維碼以控制 Cider", + + //About + "about.thanks": "感謝 Cider Collective 以及所有貢獻者所作出的貢獻。" +} \ No newline at end of file diff --git a/src/i18n/zh_TW.jsonc b/src/i18n/zh_TW.jsonc new file mode 100644 index 00000000..8464491c --- /dev/null +++ b/src/i18n/zh_TW.jsonc @@ -0,0 +1,287 @@ +{ + // App info + "app.name": "Cider", + + "date.format": "${y}年${m}月${d}日", + + // i18n Info + "i18n.languageName": "繁體中文(台灣)", // name of language in native language + "i18n.languageNameEnglish": "Trad. Chinese (Taiwan)", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@maikirakiwi", // Authors, if you contribute to this file feel free to add your name seperated with a space + + + // Dialogs + "dialog.cancel": "取消", + "dialog.ok": "OK", + + // Notification + "notification.updatingLibrarySongs": "正在更新資料庫的歌曲...", + "notification.updatingLibraryAlbums": "正在更新資料庫的專輯...", + "notification.updatingLibraryArtists": "正在更新資料庫的藝人...", + // Terms + "term.appleMusic": "Apple Music", // Follows brand term + "term.applePodcasts": "Apple Podcasts", // Follows brand term + "term.itunes": "iTunes", // Follows brand term + "term.github": "GitHub", // Follows brand term + "term.discord": "Discord", // Follows brand term + "term.learnMore": "更多内容", + "term.accountSettings": "賬戶設定", + "term.logout": "登出", + "term.login": "登入", + "term.about": "關於", + "term.privateSession": "私人時段", + "term.queue": "待播清單", + "term.search": "搜尋", + "term.library": "資料庫", + "term.listenNow": "立即聆聽", + "term.browse": "瀏覽", + "term.radio": "廣播", + "term.recentlyAdded": "最近加入", + "term.songs": "歌曲", + "term.albums": "專輯", + "term.artists": "藝人", + "term.podcasts": "Podcasts", + "term.playlists": "播放列表", + "term.playlist": "播放列表", + "term.play": "播放", + "term.pause": "暫停", + "term.previous": "上一首", + "term.next": "下一首", + "term.shuffle": "隨機播放", + "term.repeat": "重複播放", + "term.volume": "音量", + "term.mute": "靜音", + "term.unmute": "取消靜音", + "term.share": "分享", + "term.settings": "設定", + "term.seeAll": "顯示全部", + "term.sortBy": "排序", + "term.sortBy.album": "專輯", + "term.sortBy.artist": "藝人", + "term.sortBy.name": "歌名", + "term.sortBy.genre": "音樂風格", + "term.sortBy.releaseDate": "發行日期", + "term.sortBy.duration": "時長", + "term.sortOrder": "字母排序", + "term.sortOrder.ascending": "升序", + "term.sortOrder.descending": "降序", + "term.viewAs": "顯示模式", + "term.viewAs.coverArt": "專輯封面", + "term.viewAs.list": "列表", + "term.size": "大小", + "term.size.normal": "正常", + "term.size.compact": "緊凑", + "term.enable": "啟用", + "term.disable": "停用", + "term.enabled": "已啟用", + "term.disabled": "已停用", + "term.connect": "連接", + "term.connecting": "連接中", + "term.disconnect": "斷開", + "term.authed": "已授權", + "term.confirm": "確定?", + "term.more": "更多", + "term.less": "更少", + "term.showMore": "顯示更多", + "term.showLess": "顯示更少", + "term.topSongs" : "熱門歌曲", + "term.latestReleases": "最新發行", + "term.time.added": "加入于", + "term.time.released": "發行于", + "term.time.updated": "更改于", + "term.time.hours": "小時", + "term.time.hour": "小時", + "term.time.minutes": "分鐘", + "term.time.minute": "分鐘", + "term.time.seconds": "秒", + "term.time.second": "秒", + "term.fullscreenView": "全螢幕顯示", + "term.defaultView": "預設顯示", + "term.spacializedAudioSetting": "音頻空間化設置", + "term.clearAll": "清空", + "term.recentStations": "最近收聽的廣播", + "term.language": "語言", + "term.noLyrics": "正在載入。。/ 無歌詞結果 / 純音樂", + "term.copyright": "版權聲明", + "term.rightsReserved": "保留所有權利。", + "term.sponsor": "贊助", + "term.ciderTeam": "Cider 團隊", + "term.developer": "開發者", + "term.socialTeam": "公關團隊", + "term.contributors": "貢獻者", + "term.equalizer": "等化器", + "term.reset": "重置", + "term.tracks": "首歌曲", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "影片", + "term.menu": "選單", + + + // Home + "home.title": "主頁", + "home.recentlyPlayed": "最近播放", + "home.recentlyAdded": "最近加入", + "home.artistsFeed": "藝人追蹤", + "home.artistsFeed.noArtist": "追蹤一些藝人來獲得他們的最新歌曲。", + "home.madeForYou": "為您推薦", + "home.friendsListeningTo": "朋友正在聆聽", + "home.followedArtists": "追蹤的藝人", + // Errors + "error.appleMusicSubRequired": "需要訂閱Apple Music以使用Cider", + "error.connectionError": "無法連接到 Apple Music。", + "error.noResults": "沒有結果", + "error.noResults.description": "嘗試新的搜尋項目。", + + //Podcasts + "podcast.followOnCider": "在 Cider 上追蹤", + "podcast.followedOnCider": "已追蹤", + "podcast.subscribeOnItunes": "在 iTunes 上訂閱", + "podcast.subscribedOnItunes": "已訂閱", + "podcast.itunesStore": "iTunes Store", // Follows brand term + "podcast.episodes": "單集", + "podcast.playEpisode": "播放單集", + "podcast.website": "Podcast 網站", + + // Actions + "action.addToLibrary": "加入資料庫", + "action.addToLibrary.success": "成功加入資料庫", + "action.addToLibrary.error": "加入資料庫的過程發生錯誤", + "action.removeFromLibrary": "從資料庫刪除", + "action.removeFromLibrary.success": "已從資料庫刪除", + "action.addToQueue": "加入待播清單", + "action.addToQueue.success": "成功加入待播清單", + "action.addToQueue.error": "加入待播清單的過程發生錯誤", + "action.removeFromQueue": "從待播清單刪除", + "action.removeFromQueue.success": "已從待播清單刪除", + "action.removeFromQueue.error": "從待播清單刪除的過程發生錯誤", + "action.addToPlaylist": "加入播放列表", + "action.removeFromPlaylist": "從播放列表刪除", + "action.addToFavorites": "加入我的最愛", + "action.follow": "追蹤", + "action.follow.success": "追蹤中", + "action.follow.error": "追蹤的過程發生錯誤", + "action.unfollow": "取消追蹤", + "action.unfollow.success": "已取消追蹤", + "action.unfollow.error": "取消追蹤的過程發生錯誤", + "action.playNext": "插播", + "action.playLater": "最後播放", + "action.startRadio": "建立電台", + "action.goToArtist": "前往藝人", + "action.goToAlbum": "前往專輯", + "action.moveToTop": "移至頂端", + "action.share": "分享歌曲", + "action.rename": "重新命名", + "action.love": "喜愛", + "action.unlove": "取消喜愛", + "action.dislike": "減少此類建議", + "action.undoDislike": "還原減小此類建議", + "action.showWebRemoteQR": "顯示遠程遙控行動條碼", + "action.playTracksNext": "插播 ${app.selectedMediaItems.length} 首歌曲", + "action.playTracksLater": "最後播放 ${app.selectedMediaItems.length} 首歌曲", + "action.removeTracks": "從待播清單刪除 ${self.selectedItems.length} 首歌曲", + "action.import": "導入", + "action.export": "導出", + + // Settings - Audio + "settings.header.audio": "音訊", + "settings.header.audio.description": "調整Cider的音訊設定", + "settings.option.audio.quality": "音訊音質", // Dropdown + "settings.header.audio.quality.high": "高品質", + "settings.header.audio.quality.low": "高效率", + "settings.header.audio.quality.auto": "自動", + "settings.option.audio.seamlessTransition": "無間斷播放", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "進階機能", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "啟用 AudioContext 將解鎖類似音訊標準化和等化器的進階機能。但是會在一些電腦造成音樂卡頓。", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "音訊標準化", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "將平衡輕柔和響亮的歌曲,建立更統一的聆聽體驗。", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "音訊空間化", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "將音訊進行空間化處理來製造一個更立體的聆聽體驗(注:此功能不是官方的杜比全景聲)", + // Settings - Visual + "settings.header.visual": "外觀", + "settings.header.visual.description": "調整Cider的外觀", + "settings.option.visual.windowBackgroundStyle": "窗口背景樣式", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "空白", + "settings.header.visual.windowBackgroundStyle.artwork": "專輯封面", + "settings.option.visual.animatedArtwork": "動態專輯封面", // Dropdown + "settings.header.visual.animatedArtwork.always": "總是顯示", + "settings.header.visual.animatedArtwork.limited": "只在藝人頁面和專輯封面顯示", + "settings.header.visual.animatedArtwork.disable": "關閉", + "settings.option.visual.animatedArtworkQuality": "動態專輯封面品質", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "低", + "settings.header.visual.animatedArtworkQuality.medium": "中", + "settings.header.visual.animatedArtworkQuality.high": "高", + "settings.header.visual.animatedArtworkQuality.veryHigh": "非常高", + "settings.header.visual.animatedArtworkQuality.extreme": "極高", + "settings.option.visual.animatedWindowBackground": "動態窗口背景", // Toggle + "settings.option.visual.hardwareAcceleration": "硬體加速", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "需要重新啟動 Cider 才會生效", + "settings.header.visual.hardwareAcceleration.default": "默認", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "顯示個人檔案", // Toggle + // Settings - General (Reserved) + "settings.header.general": "一般", + "settings.header.general.description": "調整Cider的一般設定", + + // Settings - Lyrics + "settings.header.lyrics": "歌詞", + "settings.header.lyrics.description": "調整 Cider 的歌詞設定", + "settings.option.lyrics.enableMusixmatch": "啟用 Musixmatch 歌詞", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "啟用K歌模式(僅限Musixmatch)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Musixmatch 歌詞語言偏好", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "播放 MV 時使用 YouTube 歌詞", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "外部連接", + "settings.header.connectivity.description": "調整Cider與外部的連接", + "settings.option.connectivity.discordRPC": "Discord 動態", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "顯示正在玩 'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "顯示正在玩 'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "暫停時清除 Discord 動態", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling 記錄", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble 延遲 (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "啟用 LastFM 目前聆聽", // Toggle + "settings.option.connectivity.lastfmScrobble.removeFeatured": "從歌名中移除藝人推薦 (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "實驗性功能", + "settings.header.experimental.description": "調整 Cider 的實驗性功能", + "settings.option.experimental.compactUI": "緊凑型 UI", // Toggle + "settings.option.experimental.closeButtonBehaviour": "關閉按鈕行為", // Dropdown + "settings.option.experimental.closeButtonBehaviour.quit": "退出 Cider", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "最小化到工作列", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "最小化到系統匣", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "空間化屬性", + "spatial.width" : "寬度", + "spatial.height" : "高度", + "spatial.depth" : "深度", + "spatial.gain" : "增益", + "spatial.roomMaterials" : "空間材質", + "spatial.roomDimensions" : "空間尺寸", + "spatial.roomPositions" : "空間位置", + "spatial.setDimensions" : "設定尺寸", + "spatial.setPositions" : "設定位置", + "spatial.up" : "上", + "spatial.front" : "前", + "spatial.left" : "左", + "spatial.right" : "右", + "spatial.back" : "後", + "spatial.down" : "下", + "spatial.listener" : "聽衆", + "spatial.audioSource" : "音訊來源", + + // Settings - Unfinished + "settings.header.unfinished": "未完成", + + // Web Remote + "remote.web.title": "Cider 遠控", + "remote.web.description": "掃描以下的行動條碼以控制 Cider", + + //About + "about.thanks": "著重感謝 Cider Collective 的成員以及所有為項目付出的貢獻者。" +} \ No newline at end of file diff --git a/src/i18n/zh_yue.JSONC b/src/i18n/zh_yue.JSONC new file mode 100644 index 00000000..c66d3174 --- /dev/null +++ b/src/i18n/zh_yue.JSONC @@ -0,0 +1,297 @@ +{ + + // i18n Info + "i18n.languageName": "廣東話(香港﹚", // name of language in native language + "i18n.languageNameEnglish": "Cantonese (Hong Kong)", // name of language in English + "i18n.category": "main", // main = real language, fun = fun community languages + "i18n.authors": "@tszngaiyip @strikesnc", // Authors, if you contribute to this file feel free to add your name seperated with a space + + // App info + "app.name": "Cider", + + "date.format": "${y}年${m}月${d}日", + + // Dialogs + "dialog.cancel": "取消", + "dialog.ok": "確認", + + // Notification + "notification.updatingLibrarySongs": "更新緊資料庫嘅歌曲...", + "notification.updatingLibraryAlbums": "更新緊資料庫嘅專輯...", + "notification.updatingLibraryArtists": "更新緊資料庫嘅藝人...", + // Terms + "term.appleInc": "Apple Inc.", + "term.appleMusic": "Apple Music", + "term.applePodcasts": "Apple Podcasts", + "term.itunes": "iTunes", + "term.github": "GitHub", + "term.discord": "Discord", + "term.learnMore": "想知更多", + "term.accountSettings": "帳號設定", + "term.logout": "登出", + "term.login": "登入", + "term.about": "關於", + "term.privateSession": "無痕模式", + "term.queue": "待播清單", + "term.search": "搵野", + "term.library": "資料庫", + "term.listenNow": "即刻聽", + "term.browse": "瀏覽", + "term.radio": "電台", + "term.recentlyAdded": "最近加入", + "term.songs": "歌曲", + "term.albums": "專輯", + "term.artists": "藝人", + "term.podcasts": "Podcasts", + "term.playlists": "播放清單", + "term.playlist": "播放清單", + "term.play": "播放", + "term.pause": "暫停", + "term.previous": "前一首", + "term.next": "下一首", + "term.shuffle": "隨機播放", + "term.repeat": "重複播放", + "term.volume": "音量", + "term.mute": "靜音", + "term.unmute": "取消靜音", + "term.share": "分享", + "term.settings": "設定", + "term.seeAll": "睇哂全部", + "term.sortBy": "排序", + "term.sortBy.album": "專輯", + "term.sortBy.artist": "藝人", + "term.sortBy.name": "歌名", + "term.sortBy.genre": "音樂風格", + "term.sortBy.releaseDate": "幾時出", + "term.sortBy.duration": "幾長", + "term.sortOrder": "點排", + "term.sortOrder.ascending": "順序", + "term.sortOrder.descending": "倒序", + "term.viewAs": "想點樣顯示", + "term.viewAs.coverArt": "專輯封面", + "term.viewAs.list": "列表", + "term.size": "大細", + "term.size.normal": "正常", + "term.size.compact": "迫啲", + "term.enable": "開", + "term.disable": "熄", + "term.enabled": "開左", + "term.disabled": "熄左", + "term.connect": "連結", + "term.connecting": "連緊", + "term.disconnect": "取消連結", + "term.authed": "授權咗", + "term.confirm": "確認?", + "term.more": "多啲", + "term.less": "少啲", + "term.showMore": "顯示多啲", + "term.showLess": "顯示少啲", + "term.topSongs" : "熱門歌曲", + "term.latestReleases": "最新出嘅", + "term.time.added": "加入於", + "term.time.released": "發行於", + "term.time.updated": "更新於", + "term.time.hours": "粒鐘", + "term.time.hour": "粒鐘", + "term.time.minutes": "分鐘", + "term.time.minute": "分鐘", + "term.time.seconds": "秒", + "term.time.second": "秒", + "term.fullscreenView": "用全螢幕睇", + "term.defaultView": "平時咁睇", + "term.spacializedAudioSetting": "空間音訊設定", + "term.clearAll": "清除", + "term.recentStations": "呢排聽緊嘅", + "term.language": "語言", + "term.funLanguages": "惡搞", + "term.noLyrics": "搵緊... / 搵唔到歌詞。 / 純音樂黎。", + "term.copyright": "版權", + "term.rightsReserved": "保留一切權利", + "term.sponsor": "課金俾呢個Project", + "term.ciderTeam": "Cider 團隊", + "term.developer": "開發者", + "term.socialTeam": "PR", + "term.contributors": "合作人", + "term.equalizer": "均衡器 (EQ)", + "term.reset": "重設", + "term.tracks": "首歌", // Assume x amount of tracks. e.g. 50 tracks + "term.videos": "影片", + "term.menu": "選項", + + // Home + "home.title": "主頁", + "home.recentlyPlayed": "呢排播左", + "home.recentlyAdded": "呢排加嘅", + "home.artistsFeed": "藝人動態", + "home.artistsFeed.noArtist": "Follow 一啲藝人嚟獲得佢哋嘅最新歌曲資訊。 ", + "home.madeForYou": "為你而整", + "home.friendsListeningTo": "你啲Friend聽緊", + "home.followedArtists": "Follow左嘅藝人", + // Errors + "error.appleMusicSubRequired": "需要訂閱Apple Music先可以用Cider。", + "error.connectionError": "連接唔到Apple Music。", + "error.noResults": "冇結果。", + "error.noResults.description": "重新搵過啦。", + + //Podcasts + "podcast.followOnCider": "喺Cider上Follow", + "podcast.followedOnCider": "喺Cider上Follow左", + "podcast.subscribeOnItunes": "喺iTunes上訂閱", + "podcast.subscribedOnItunes": "喺iTunes上訂閱左", + "podcast.itunesStore": "iTunes Store", + "podcast.episodes": "單集", + "podcast.playEpisode": "播呢集", + "podcast.website": "Podcast 網頁", + + // Actions + "action.addToLibrary": "加入資料庫", + "action.addToLibrary.success": "加入咗資料庫", + "action.addToLibrary.error": "加入唔到資料庫", + "action.removeFromLibrary": "喺資料庫到刪除", + "action.removeFromLibrary.success": "已經喺資料庫到刪除咗", + "action.addToQueue": "加入待播清單", + "action.addToQueue.success": "加入咗待播清單", + "action.addToQueue.error": "加入唔到待播清單", + "action.removeFromQueue": "喺待播清單刪除", + "action.removeFromQueue.success": "已經喺待播清單到刪除咗", + "action.removeFromQueue.error": "喺待播清單到刪除唔到", + "action.addToPlaylist": "加入播放清單", + "action.removeFromPlaylist": "喺播放清單到刪除", + "action.addToFavorites": "加至收藏", + "action.follow": "Follow", + "action.follow.success": "Follow緊", + "action.follow.error": "Follow唔到", + "action.unfollow": "Unfollow", + "action.unfollow.success": "Unfollow咗", + "action.unfollow.error": "Unfollow唔到", + "action.playNext": "下首即刻播", + "action.playLater": "陣間先再播", + "action.startRadio": "建立電台", + "action.goToArtist": "前往藝人", + "action.goToAlbum": "前往專輯", + "action.moveToTop": "返最頂", + "action.share": "分享歌曲", + "action.rename": "重新命名", + "action.love": "鐘意", + "action.unlove": "唔鐘意", + "action.dislike": "唔想再睇到", + "action.undoDislike": "還原唔想再睇到", + "action.showWebRemoteQR": "顯示遙距控制QR Code", + "action.playTracksNext": "插播 ${app.selectedMediaItems.length} 首歌曲", + "action.playTracksLater": "陣間播放 ${app.selectedMediaItems.length} 首歌曲", + "action.removeTracks": "喺待播清單到刪除 ${self.selectedItems.length} 首歌曲", + "action.import": "匯入", + "action.export": "匯出", + + // Settings - General + "settings.header.general": "一般", + "settings.header.general.description": "調整Cider嘅一般設定", + "settings.option.general.language": "語言", + + // Language optgroups + "settings.option.general.language.main": "語言", + "settings.option.general.language.fun": "惡搞語言", + "settings.option.general.language.unsorted": "未分類", + + // Settings - Audio + "settings.header.audio": "音訊", + "settings.header.audio.description": "調整Cider嘅音訊設定", + "settings.option.audio.quality": "音質", // Dropdown + "settings.header.audio.quality.high": "質素優先", + "settings.header.audio.quality.low": "流暢度優先", + "settings.header.audio.quality.auto": "自動", + "settings.option.audio.seamlessTransition": "無縫播放", // Toggle + "settings.option.audio.enableAdvancedFunctionality": "進階功能", // Toggle + "settings.option.audio.enableAdvancedFunctionality.description": "啟用AudioContext,解鎖類似音量平衡和均衡器嘅進階功能,但係會喺部分電腦造成音樂Lag機。", + "settings.option.audio.enableAdvancedFunctionality.audioNormalization": "音量平衡", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioNormalization.description": "平衡輕柔同響亮嘅歌曲,令你有統一嘅聆聽體驗。", + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization": "空間音訊", // Toggle + "settings.option.audio.enableAdvancedFunctionality.audioSpatialization.description": "空間化音訊,製造一個更立體嘅聆聽體驗(注意:呢個功能唔係官方嘅杜比全景聲)", + // Settings - Visual + "settings.header.visual": "外觀", + "settings.header.visual.description": "調整Cider嘅外觀", + "settings.option.visual.windowBackgroundStyle": "視窗背景樣式", // Toggle + "settings.header.visual.windowBackgroundStyle.none": "空白", + "settings.header.visual.windowBackgroundStyle.artwork": "專輯封面", + "settings.header.visual.windowBackgroundStyle.image": "圖片", + "settings.option.visual.animatedArtwork": "動態專輯封面", // Dropdown + "settings.header.visual.animatedArtwork.always": "總是顯示", + "settings.header.visual.animatedArtwork.limited": "淨係喺藝人頁面同專輯封面顯示", + "settings.header.visual.animatedArtwork.disable": "熄左佢", + "settings.option.visual.animatedArtworkQuality": "動態專輯封面品質", // Dropdown + "settings.header.visual.animatedArtworkQuality.low": "低", + "settings.header.visual.animatedArtworkQuality.medium": "中", + "settings.header.visual.animatedArtworkQuality.high": "高", + "settings.header.visual.animatedArtworkQuality.veryHigh": "非常高", + "settings.header.visual.animatedArtworkQuality.extreme": "極高", + "settings.option.visual.animatedWindowBackground": "動態視窗背景", // Toggle + "settings.option.visual.hardwareAcceleration": "硬體加速", // Dropdown + "settings.option.visual.hardwareAcceleration.description": "需要重開Cider先會生效", + "settings.header.visual.hardwareAcceleration.default": "預設", + "settings.header.visual.hardwareAcceleration.webGPU": "WebGPU", + // Refer to term.disabled for the disabled option + "settings.option.visual.showPersonalInfo": "顯示個人檔案", // Toggle + + // Settings - Lyrics + "settings.header.lyrics": "歌詞", + "settings.header.lyrics.description": "調整Cider嘅歌詞設定", + "settings.option.lyrics.enableMusixmatch": "啟用 Musixmatch 歌詞", // Toggle + "settings.option.lyrics.enableMusixmatchKaraoke": "開啟唱K模式(僅限Musixmatch)", // Toggle + "settings.option.lyrics.musixmatchPreferredLanguage": "Musixmatch 歌詞語言偏好", // Dropdown + "settings.option.lyrics.enableYoutubeLyrics": "播放MV嘅時候用YouTube字幕", // Toggle + + // Settings - Connectivity + "settings.header.connectivity": "外部連結", + "settings.header.connectivity.description": "調整Cider同外部嘅連結", + "settings.option.connectivity.discordRPC": "Discord 狀態", // Dropdown + // Refer to term.disabled for the disabled option + "settings.header.connectivity.discordRPC.cider": "顯示為'Cider'", + "settings.header.connectivity.discordRPC.appleMusic": "顯示為'Apple Music'", + "settings.option.connectivity.discordRPC.clearOnPause": "暫停時清除 Discord 狀態", // Toggle + "settings.option.connectivity.lastfmScrobble": "LastFM Scrobbling 記錄", // Option to Connect + "settings.option.connectivity.lastfmScrobble.delay": "LastFM Scrobble 延遲 (%)", + "settings.option.connectivity.lastfmScrobble.nowPlaying": "啟用 LastFM 正在播放", + "settings.option.connectivity.lastfmScrobble.removeFeatured": "從歌名中移除藝人推薦 (LastFM)", + "settings.option.connectivity.lastfmScrobble.filterLoop": "Filter looped track (LastFM)", + // Refer to term.connect for the connect button + + // Settings - Experimental + "settings.header.experimental": "實驗性功能", + "settings.header.experimental.description": "調整Cider嘅實驗性功能", + "settings.option.experimental.compactUI": "逼啲既 UI", // Toggle + "settings.option.experimental.closeButtonBehaviour": "關閉按鈕行為", + "settings.option.experimental.closeButtonBehaviour.quit": "熄左Cider佢", + "settings.option.experimental.closeButtonBehaviour.minimizeTaskbar": "收埋Cider喺工作列", + "settings.option.experimental.closeButtonBehaviour.minimizeTray": "收埋Cider喺系統托盤", + // Refer to term.disabled & term.enabled + + // Spatialization Menu + "spatial.spatialProperties" : "空間音訊屬性", + "spatial.width" : "幾闊", + "spatial.height" : "幾高", + "spatial.depth" : "幾深", + "spatial.gain" : "增益", + "spatial.roomMaterials" : "空間材質", + "spatial.roomDimensions" : "空間大小", + "spatial.roomPositions" : "空間位置", + "spatial.setDimensions" : "大小設定", + "spatial.setPositions" : "位置設定", + "spatial.up" : "上面", + "spatial.front" : "前面", + "spatial.left" : "左邊", + "spatial.right" : "右邊", + "spatial.back" : "後面", + "spatial.down" : "下面", + "spatial.listener" : "觀眾", + "spatial.audioSource" : "音源", + + // Settings - Unfinished + "settings.header.unfinished": "未搞掂", + + // Web Remote + "remote.web.title": "遙距控制 Cider", + "remote.web.description": "Scan 呢個 QR Code 去控制 Cider", + + // About + "about.thanks": "多謝 Cider Collective 同埋所有合作人作出嘅貢獻。" +} diff --git a/src/main/base/app.ts b/src/main/base/app.ts new file mode 100644 index 00000000..68e26b65 --- /dev/null +++ b/src/main/base/app.ts @@ -0,0 +1,201 @@ +import * as electron from 'electron'; +import * as path from 'path'; + +export class AppEvents { + private static protocols: any = [ + "ame", + "cider", + "itms", + "itmss", + "musics", + "music" + ] + private static plugin: any = null; + private static store: any = null; + private static win: any = null; + + constructor(store: any) { + AppEvents.store = store + AppEvents.start(store); + } + + /** + * Handles all actions that occur for the app on start (Mainly commandline arguments) + * @returns {void} + */ + private static start(store: any): void { + console.info('[AppEvents] App started'); + + /********************************************************************************************************************** + * Startup arguments handling + **********************************************************************************************************************/ + if (electron.app.commandLine.hasSwitch('version') || electron.app.commandLine.hasSwitch('v')) { + console.log(electron.app.getVersion()) + electron.app.exit() + } + + // Verbose Check + if (electron.app.commandLine.hasSwitch('verbose')) { + console.log("[Cider] User has launched the application with --verbose"); + } + + // Log File Location + if (electron.app.commandLine.hasSwitch('log') || electron.app.commandLine.hasSwitch('l')) { + console.log(path.join(electron.app.getPath('userData'), 'logs')) + electron.app.exit() + } + + // Expose GC + electron.app.commandLine.appendSwitch('js-flags','--expose_gc') + + if (process.platform === "win32") { + electron.app.setAppUserModelId("Cider") // For notification name + } + + /*********************************************************************************************************************** + * Commandline arguments + **********************************************************************************************************************/ + switch (store.visual.hw_acceleration) { + default: + case "default": + electron.app.commandLine.appendSwitch('enable-accelerated-mjpeg-decode') + electron.app.commandLine.appendSwitch('enable-accelerated-video') + electron.app.commandLine.appendSwitch('disable-gpu-driver-bug-workarounds') + electron.app.commandLine.appendSwitch('ignore-gpu-blacklist') + electron.app.commandLine.appendSwitch('enable-native-gpu-memory-buffers') + electron.app.commandLine.appendSwitch('enable-accelerated-video-decode'); + electron.app.commandLine.appendSwitch('enable-gpu-rasterization'); + electron.app.commandLine.appendSwitch('enable-native-gpu-memory-buffers'); + electron.app.commandLine.appendSwitch('enable-oop-rasterization'); + break; + + case "webgpu": + console.info("WebGPU is enabled."); + electron.app.commandLine.appendSwitch('enable-unsafe-webgpu') + break; + + case "disabled": + console.info("Hardware acceleration is disabled."); + electron.app.commandLine.appendSwitch('disable-gpu') + break; + } + + if (process.platform === "linux") { + electron.app.commandLine.appendSwitch('disable-features', 'MediaSessionService'); + } + + /*********************************************************************************************************************** + * Protocols + **********************************************************************************************************************/ + if (process.defaultApp) { + if (process.argv.length >= 2) { + this.protocols.forEach((protocol: string) => { + electron.app.setAsDefaultProtocolClient(protocol, process.execPath, [path.resolve(process.argv[1])]) + }) + } + } else { + this.protocols.forEach((protocol: string) => { + electron.app.setAsDefaultProtocolClient(protocol) + }) + } + + + } + + public quit() { + console.log('App stopped'); + } + + public ready(plug: any) { + AppEvents.plugin = plug + console.log('[AppEvents] App ready'); + } + + public bwCreated(win: Electron.BrowserWindow) { + AppEvents.win = win + + electron.app.on('open-url', (event, url) => { + event.preventDefault() + if (AppEvents.protocols.some((protocol: string) => url.includes(protocol))) { + AppEvents.LinkHandler(url) + console.log(url) + } + }) + + AppEvents.InstanceHandler() + } + + /*********************************************************************************************************************** + * Private methods + **********************************************************************************************************************/ + + private static LinkHandler(arg: string) { + if (!arg) return; + + // LastFM Auth URL + if (arg.includes('auth')) { + let authURI = arg.split('/auth/')[1] + if (authURI.startsWith('lastfm')) { // If we wanted more auth options + const authKey = authURI.split('lastfm?token=')[1]; + AppEvents.store.set('lastfm.enabled', true); + AppEvents.store.set('lastfm.auth_token', authKey); + AppEvents.win.webContents.send('LastfmAuthenticated', authKey); + AppEvents.plugin.callPlugin('lastfm', 'authenticate', authKey); + } + } + // Play + else if (arg.includes('/play/')) { //Steer away from protocol:// specific conditionals + const playParam = arg.split('/play/')[1] + + const mediaType = { + "s/": "song", + "a/": "album", + "p/": "playlist" + } + + for (const [key, value] of Object.entries(mediaType)) { + if (playParam.includes(key)) { + const id = playParam.split(key)[1] + AppEvents.win.webContents.send('play', value, id) + console.debug(`[LinkHandler] Attempting to load ${value} by id: ${id}`) + } + } + + } else if (arg.includes('music.apple.com')) { // URL (used with itms/itmss/music/musics uris) + console.log(arg) + let url = arg.split('//')[1] + console.warn(`[LinkHandler] Attempting to load url: ${url}`); + AppEvents.win.webContents.send('play', 'url', url) + } + } + + private static InstanceHandler() { + + // Detects of an existing instance is running (So if the lock has been achieved, no existing instance has been found) + const gotTheLock = electron.app.requestSingleInstanceLock() + + if (!gotTheLock) { // Runs on the new instance if another instance has been found + console.log('[Cider] Another instance has been found, quitting.') + electron.app.quit() + } else { // Runs on the first instance if no other instance has been found + electron.app.on('second-instance', (_event, startArgs) => { + console.log("[InstanceHandler] (second-instance) Instance started with " + startArgs.toString()) + + startArgs.forEach(arg => { + console.log(arg) + if (arg.includes("cider://")) { + console.debug('[InstanceHandler] (second-instance) Link detected with ' + arg) + AppEvents.LinkHandler(arg) + } else if (arg.includes("--force-quit")) { + console.warn('[InstanceHandler] (second-instance) Force Quit found. Quitting App.'); + electron.app.quit() + } else if (AppEvents.win) { + if (AppEvents.win.isMinimized()) AppEvents.win.restore() + AppEvents.win.focus() + } + }) + }) + } + + } +} diff --git a/src/main/base/plugins.ts b/src/main/base/plugins.ts new file mode 100644 index 00000000..0262d447 --- /dev/null +++ b/src/main/base/plugins.ts @@ -0,0 +1,65 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as electron from 'electron' + +export default class PluginHandler { + private basePluginsPath = path.join(__dirname, '../plugins'); + private userPluginsPath = path.join(electron.app.getPath('userData'), 'plugins'); + private readonly pluginsList: any = {}; + private readonly _store: any; + + constructor(config: any) { + this._store = config; + this.pluginsList = this.getPlugins(); + } + + public getPlugins(): any { + let plugins: any = {}; + + + if (fs.existsSync(this.basePluginsPath)) { + fs.readdirSync(this.basePluginsPath).forEach(file => { + if (file.endsWith('.ts') || file.endsWith('.js')) { + const plugin = require(path.join(this.basePluginsPath, file)).default; + if (plugins[file] || plugin.name in plugins) { + console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`); + } else { + plugins[file] = new plugin(electron.app, this._store); + } + } + }); + } + + + if (fs.existsSync(this.userPluginsPath)) { + fs.readdirSync(this.userPluginsPath).forEach(file => { + if (file.endsWith('.ts') || file.endsWith('.js')) { + const plugin = require(path.join(this.userPluginsPath, file)).default; + file = file.replace('.ts', '').replace('.js', ''); + if (plugins[file] || plugin in plugins) { + console.log(`[${plugin.name}] Plugin already loaded / Duplicate Class Name`); + } else { + plugins[file] = new plugin(electron.app, this._store); + } + } + }); + } + console.log('[PluginHandler] Loaded plugins:', Object.keys(plugins)); + return plugins; + } + + public callPlugins(event: string, ...args: any[]) { + for (const plugin in this.pluginsList) { + if (this.pluginsList[plugin][event]) { + this.pluginsList[plugin][event](...args); + } + } + } + + public callPlugin(plugin: string, event: string, ...args: any[]) { + if (this.pluginsList[plugin][event]) { + this.pluginsList[plugin][event](...args); + } + } + +} diff --git a/src/main/base/store.ts b/src/main/base/store.ts new file mode 100644 index 00000000..a1f067b6 --- /dev/null +++ b/src/main/base/store.ts @@ -0,0 +1,167 @@ +import * as Store from 'electron-store'; +import * as electron from "electron"; + +export class ConfigStore { + private _store: Store; + + private defaults: any = { + "general": { + "close_behavior": 0, // 0 = close, 1 = minimize, 2 = minimize to tray + "open_on_startup": false, + "discord_rpc": 1, // 0 = disabled, 1 = enabled as Cider, 2 = enabled as Apple Music + "discord_rpc_clear_on_pause": true, + "language": "en_US", // electron.app.getLocale().replace('-', '_') this can be used in future + "playbackNotifications": true + }, + "home": { + "followedArtists": [], + "favoriteItems": [] + }, + "libraryPrefs": { + "songs": { + "sort": "name", + "sortOrder": "asc", + "size": "normal" + } + }, + "audio": { + "volume": 1, + "lastVolume": 1, + "muted": false, + "quality": "256", + "seamless_audio": true, + "normalization": false, + "spatial": false, + "maxVolume": 1, + "volumePrecision": 0.1, + "volumeRoundMax": 0.9, + "volumeRoundMin": 0.1, + "spatial_properties": { + "presets": [], + "gain": 0.8, + "listener_position": [0, 0, 0], + "audio_position": [0, 0, 0], + "room_dimensions": { + "width": 32, + "height": 12, + "depth": 32 + }, + "room_materials": { + "left": 'metal', + "right": 'metal', + "front": 'brick-bare', + "back": 'brick-bare', + "down": 'acoustic-ceiling-tiles', + "up": 'acoustic-ceiling-tiles', + } + }, + "equalizer": { + 'preset': "default", + 'frequencies': [32, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000], + 'gain': [0,0,0,0,0,0,0,0,0,0], + 'Q' : [1,1,1,1,1,1,1,1,1,1], + 'preamp' : 0, + 'mix' : 1, + 'presets': [], + 'userGenerated': false + } + }, + "visual": { + "theme": "", + "scrollbars": 0, // 0 = show on hover, 2 = always hide, 3 = always show + "refresh_rate": 0, + "window_background_style": "artwork", // "none", "artwork", "color" + "animated_artwork": "limited", // 0 = always, 1 = limited, 2 = never + "animated_artwork_qualityLevel": 1, + "bg_artwork_rotation": false, + "hw_acceleration": "default", // default, webgpu, disabled + "showuserinfo": true, + "miniplayer_top_toggle": true + }, + "lyrics": { + "enable_mxm": false, + "mxm_karaoke": false, + "mxm_language": "en", + "enable_yt": false, + }, + "lastfm": { + "enabled": false, + "scrobble_after": 30, + "auth_token": "", + "enabledRemoveFeaturingArtists": true, + "filterLoop": true, + "NowPlaying": "true" + }, + "advanced": { + "AudioContext": false, + "experiments": [] + } + } + private migrations: any = {} + + constructor() { + this._store = new Store({ + name: 'cider-config', + defaults: this.defaults, + migrations: this.migrations, + }); + + this._store.set(this.mergeStore(this.defaults, this._store.store)) + this.ipcHandler(this._store); + } + + get store() { + return this._store.store; + } + + get(key: string) { + return this._store.get(key); + } + + set(key: string, value: any) { + this._store.set(key, value); + } + + /** + * Merge Configurations + * @param target The target configuration + * @param source The source configuration + */ + private mergeStore = (target: { [x: string]: any; }, source: { [x: string]: any; }) => { + // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties + for (const key of Object.keys(source)) { + if (key.includes('migrations')) { + continue; + } + if(source[key] instanceof Array) { + continue + } + if (source[key] instanceof Object) Object.assign(source[key], this.mergeStore(target[key], source[key])) + } + // Join `target` and modified `source` + Object.assign(target || {}, source) + return target + } + + /** + * IPC Handler + */ + private ipcHandler(cfg: Store | any): void { + electron.ipcMain.handle('getStoreValue', (event, key, defaultValue) => { + return (defaultValue ? cfg.get(key, true) : cfg.get(key)); + }); + + electron.ipcMain.handle('setStoreValue', (event, key, value) => { + cfg.set(key, value); + }); + + electron.ipcMain.on('getStore', (event) => { + event.returnValue = cfg.store + }) + + electron.ipcMain.on('setStore', (event, store) => { + cfg.store = store + }) + } + +} diff --git a/src/main/base/win.ts b/src/main/base/win.ts new file mode 100644 index 00000000..f51613f6 --- /dev/null +++ b/src/main/base/win.ts @@ -0,0 +1,612 @@ +// @ts-nocheck +import * as path from "path"; +import * as electron from "electron"; +import * as windowStateKeeper from "electron-window-state"; +import * as express from "express"; +import * as getPort from "get-port"; +import * as yt from "youtube-search-without-api-key"; +import * as fs from "fs"; +import { Stream } from "stream"; +import * as qrcode from "qrcode-terminal"; +import * as os from "os"; +import * as mm from 'music-metadata'; +import fetch from 'electron-fetch' +import {wsapi} from "./wsapi"; +import * as jsonc from "jsonc"; + +export class Win { + private win: any | undefined = null; + private app: any | undefined = null; + private store: any | undefined = null; + private devMode: boolean = !electron.app.isPackaged; + + constructor(app: electron.App, store: any) { + this.app = app; + this.store = store; + } + + private paths: any = { + srcPath: path.join(__dirname, "../../src"), + resourcePath: path.join(__dirname, "../../resources"), + ciderCache: path.resolve(electron.app.getPath("userData"), "CiderCache"), + themes: path.resolve(electron.app.getPath("userData"), "Themes"), + plugins: path.resolve(electron.app.getPath("userData"), "Plugins"), + }; + private audioStream: any = new Stream.PassThrough(); + private clientPort: number = 0; + private remotePort: number = 6942; + private EnvironmentVariables: object = { + env: { + platform: process.platform, + dev: electron.app.isPackaged, + }, + }; + private options: any = { + icon: path.join( + this.paths.resourcePath, + `icons/icon.` + (process.platform === "win32" ? "ico" : "png") + ), + width: 1024, + height: 600, + x: undefined, + y: undefined, + minWidth: 900, + minHeight: 390, + frame: false, + title: "Cider", + vibrancy: "dark", + transparent: process.platform === "darwin", + hasShadow: false, + show: false, + backgroundColor: "#1E1E1E", + webPreferences: { + nodeIntegration: true, + sandbox: true, + allowRunningInsecureContent: true, + contextIsolation: false, + webviewTag: true, + plugins: true, + nodeIntegrationInWorker: false, + webSecurity: false, + preload: path.join(this.paths.srcPath, "./preload/cider-preload.js"), + }, + }; + + /** + * Creates the browser window + */ + async createWindow(): Promise { + this.clientPort = await getPort({ port: 9000 }); + this.verifyFiles(); + + // Load the previous state with fallback to defaults + const windowState = windowStateKeeper({ + defaultWidth: 1024, + defaultHeight: 600, + }); + this.options.width = windowState.width; + this.options.height = windowState.height; + + // Start the webserver for the browser window to load + + this.startWebServer(); + + this.win = new electron.BrowserWindow(this.options); + const ws = new wsapi(this.win) + ws.InitWebSockets() + // and load the renderer. + this.startSession(); + this.startHandlers(); + + // Register listeners on Window to track size and position of the Window. + windowState.manage(this.win); + + return this.win; + } + + /** + * Verifies the files for the renderer to use (Cache, library info, etc.) + */ + private verifyFiles(): void { + const expectedDirectories = ["CiderCache"]; + const expectedFiles = [ + "library-songs.json", + "library-artists.json", + "library-albums.json", + "library-playlists.json", + "library-recentlyAdded.json", + ]; + for (let i = 0; i < expectedDirectories.length; i++) { + if ( + !fs.existsSync( + path.join(electron.app.getPath("userData"), expectedDirectories[i]) + ) + ) { + fs.mkdirSync( + path.join(electron.app.getPath("userData"), expectedDirectories[i]) + ); + } + } + for (let i = 0; i < expectedFiles.length; i++) { + const file = path.join(this.paths.ciderCache, expectedFiles[i]); + if (!fs.existsSync(file)) { + fs.writeFileSync(file, JSON.stringify([])); + } + } + } + + /** + * Starts the webserver for the renderer process. + */ + private startWebServer(): void { + const app = express(); + + app.use(express.static(path.join(this.paths.srcPath, "./renderer/"))); + app.set("views", path.join(this.paths.srcPath, "./renderer/views")); + app.set("view engine", "ejs"); + let firstRequest = true; + app.use((req, res, next) => { + // @ts-ignore + if ( + req.url.includes("audio.webm") || + (req.headers.host.includes("localhost") && + (this.devMode || req.headers["user-agent"].includes("Electron"))) + ) { + next(); + } else { + res.redirect("https://discord.gg/applemusic"); + } + }); + + app.get("/", (req, res) => { + res.render("main", this.EnvironmentVariables); + }); + + app.get("/audio.webm", (req, res) => { + try { + req.socket.setTimeout(Number.MAX_SAFE_INTEGER); + // CiderBase.requests.push({req: req, res: res}); + // var pos = CiderBase.requests.length - 1; + // req.on("close", () => { + // console.info("CLOSED", CiderBase.requests.length); + // requests.splice(pos, 1); + // console.info("CLOSED", CiderBase.requests.length); + // }); + this.audioStream.on("data", (data: any) => { + try { + res.write(data); + } catch (ex) { + console.log(ex); + } + }); + } catch (ex) { + console.log(ex); + } + }); + //app.use(express.static()) + + app.listen(this.clientPort, () => { + console.log(`Cider client port: ${this.clientPort}`); + }); + + /* + * Remote Client (I had no idea how to add it to our existing express server, so I just made another one) -@quacksire + * TODO: Broadcast the remote so that /web-remote/ can connect + * https://github.com/ciderapp/Apple-Music-Electron/blob/818ed18940ff600d76eb59d22016723a75885cd5/resources/functions/handler.js#L1173 + */ + const remote = express(); + remote.use(express.static(path.join(this.paths.srcPath, "./web-remote/"))) + remote.set("views", path.join(this.paths.srcPath, "./web-remote/views")); + remote.set("view engine", "ejs"); + getPort({port: 6942}).then((port) => { + this.remotePort = port; + // Start Remote Discovery + this.broadcastRemote() + remote.listen(this.remotePort, () => { + console.log(`Cider remote port: ${this.remotePort}`); + if (firstRequest) { + console.log("---- Ignore Me ;) ---"); + qrcode.generate(`http://${os.hostname}:${this.remotePort}`); + console.log("---- Ignore Me ;) ---"); + /* + * + * USING https://www.npmjs.com/package/qrcode-terminal for terminal + * WE SHOULD USE https://www.npmjs.com/package/qrcode for the remote (or others) for showing to user via an in-app dialog + * -@quacksire + */ + } + firstRequest = false; + }) + remote.get("/", (req, res) => { + res.render("index", this.EnvironmentVariables); + }); + }) + } + + /** + * Starts the session for the renderer process. + */ + private startSession(): void { + // intercept "https://js-cdn.music.apple.com/hls.js/2.141.1/hls.js/hls.js" and redirect to local file "./apple-hls.js" instead + this.win.webContents.session.webRequest.onBeforeRequest( + { + urls: ["https://*/*.js"], + }, + ( + details: { url: string | string[] }, + callback: (arg0: { redirectURL?: string; cancel?: boolean }) => void + ) => { + if (details.url.includes("hls.js")) { + callback({ + redirectURL: `http://localhost:${this.clientPort}/apple-hls.js`, + }); + } else { + callback({ + cancel: false, + }); + } + } + ); + + this.win.webContents.session.webRequest.onBeforeSendHeaders( + async ( + details: { url: string; requestHeaders: { [x: string]: string } }, + callback: (arg0: { requestHeaders: any }) => void + ) => { + if (details.url === "https://buy.itunes.apple.com/account/web/info") { + details.requestHeaders["sec-fetch-site"] = "same-site"; + details.requestHeaders["DNT"] = "1"; + let itspod = await this.win.webContents.executeJavaScript( + `window.localStorage.getItem("music.ampwebplay.itspod")` + ); + if (itspod != null) + details.requestHeaders["Cookie"] = `itspod=${itspod}`; + } + callback({ requestHeaders: details.requestHeaders }); + } + ); + + let location = `http://localhost:${this.clientPort}/`; + + if (electron.app.isPackaged) { + this.win.loadURL(location); + } else { + this.win.loadURL(location, { + userAgent: "Cider Development Environment", + }); + } + } + + /** + * Initializes the window handlers + */ + private startHandlers(): void { + /********************************************************************************************************************** + * ipcMain Events + ****************************************************************************************************************** */ + electron.ipcMain.on("cider-platform", (event) => { + event.returnValue = process.platform; + }); + + electron.ipcMain.on("get-i18n", (event, key) => { + let i18nBase = fs.readFileSync(path.join(__dirname, "../../src/i18n/en_US.jsonc"), "utf8"); + i18nBase = jsonc.parse(i18nBase) + try { + let i18n = fs.readFileSync(path.join(__dirname, `../../src/i18n/${key}.jsonc`), "utf8"); + i18n = jsonc.parse(i18n) + Object.assign(i18nBase, i18n) + }catch(e) { + console.error(e); + event.returnValue = e; + } + + event.returnValue = i18nBase; + + }); + + electron.ipcMain.on("get-i18n-listing", event => { + let i18nFiles = fs.readdirSync(path.join(__dirname, "../../src/i18n")).filter(file => file.endsWith(".jsonc")); + // read all the files and parse them + let i18nListing = [] + for (let i = 0; i < i18nFiles.length; i++) { + let i18n = fs.readFileSync(path.join(__dirname, `../../src/i18n/${i18nFiles[i]}`), "utf8"); + i18n = jsonc.parse(i18n) + i18nListing.push({ + "code": i18nFiles[i].replace(".jsonc", ""), + "nameNative": i18n["i18n.languageName"] ?? i18nFiles[i].replace(".jsonc", ""), + "nameEnglish": i18n["i18n.languageNameEnglish"] ?? i18nFiles[i].replace(".jsonc", ""), + "category": i18n["i18n.category"] ?? "", + "authors": i18n["i18n.authors"] ?? "" + }) + } + event.returnValue = i18nListing; + }) + + electron.ipcMain.on("get-gpu-mode", (event) => { + event.returnValue = process.platform; + }); + + electron.ipcMain.on("is-dev", (event) => { + event.returnValue = this.devMode; + }); + + electron.ipcMain.on("close", () => { + // listen for close event + this.win.close(); + }); + + electron.ipcMain.on("put-library-songs", (event, arg) => { + fs.writeFileSync( + path.join(this.paths.ciderCache, "library-songs.json"), + JSON.stringify(arg) + ); + }); + + electron.ipcMain.on("put-library-artists", (event, arg) => { + fs.writeFileSync( + path.join(this.paths.ciderCache, "library-artists.json"), + JSON.stringify(arg) + ); + }); + + electron.ipcMain.on("put-library-albums", (event, arg) => { + fs.writeFileSync( + path.join(this.paths.ciderCache, "library-albums.json"), + JSON.stringify(arg) + ); + }); + + electron.ipcMain.on("put-library-playlists", (event, arg) => { + fs.writeFileSync( + path.join(this.paths.ciderCache, "library-playlists.json"), + JSON.stringify(arg) + ); + }); + + electron.ipcMain.on("put-library-recentlyAdded", (event, arg) => { + fs.writeFileSync( + path.join(this.paths.ciderCache, "library-recentlyAdded.json"), + JSON.stringify(arg) + ); + }); + + electron.ipcMain.on("get-library-songs", (event) => { + let librarySongs = fs.readFileSync( + path.join(this.paths.ciderCache, "library-songs.json"), + "utf8" + ); + event.returnValue = JSON.parse(librarySongs); + }); + + electron.ipcMain.on("get-library-artists", (event) => { + let libraryArtists = fs.readFileSync( + path.join(this.paths.ciderCache, "library-artists.json"), + "utf8" + ); + event.returnValue = JSON.parse(libraryArtists); + }); + + electron.ipcMain.on("get-library-albums", (event) => { + let libraryAlbums = fs.readFileSync( + path.join(this.paths.ciderCache, "library-albums.json"), + "utf8" + ); + event.returnValue = JSON.parse(libraryAlbums); + }); + + electron.ipcMain.on("get-library-playlists", (event) => { + let libraryPlaylists = fs.readFileSync( + path.join(this.paths.ciderCache, "library-playlists.json"), + "utf8" + ); + event.returnValue = JSON.parse(libraryPlaylists); + }); + + electron.ipcMain.on("get-library-recentlyAdded", (event) => { + let libraryRecentlyAdded = fs.readFileSync( + path.join(this.paths.ciderCache, "library-recentlyAdded.json"), + "utf8" + ); + event.returnValue = JSON.parse(libraryRecentlyAdded); + }); + + electron.ipcMain.handle("getYTLyrics", async (event, track, artist) => { + const u = track + " " + artist + " official video"; + return await yt.search(u); + }); + + electron.ipcMain.handle("setVibrancy", (event, key, value) => { + this.win.setVibrancy(value); + }); + + electron.ipcMain.on("maximize", () => { + // listen for maximize event + if (this.win.isMaximized()) { + this.win.unmaximize(); + } else { + this.win.maximize(); + } + }); + electron.ipcMain.on("unmaximize", () => { + // listen for maximize event + this.win.unmaximize(); + }); + + electron.ipcMain.on("minimize", () => { + // listen for minimize event + this.win.minimize(); + }); + + // Set scale + electron.ipcMain.on("setScreenScale", (event, scale) => { + this.win.webContents.setZoomFactor(parseFloat(scale)); + }); + + electron.ipcMain.on("windowmin", (event, width, height) => { + this.win.setMinimumSize(width,height); + }) + + electron.ipcMain.on("windowontop", (event, ontop) => { + this.win.setAlwaysOnTop(ontop); + }); + + // Set scale + electron.ipcMain.on("windowresize", (event, width, height, lock = false) => { + this.win.setContentSize(width, height); + this.win.setResizable(!lock); + }); + + //Fullscreen + electron.ipcMain.on('setFullScreen', (event, flag) => { + this.win.setFullScreen(flag) + }) + //Fullscreen + electron.ipcMain.on('detachDT', (event, _) => { + this.win.webContents.openDevTools({ mode: 'detach' }); + }) + + + electron.ipcMain.on('play', (event, type, id) => { + this.win.webContents.executeJavaScript(` + MusicKit.getInstance().setQueue({ ${type}: '${id}'}).then(function(queue) { + MusicKit.getInstance().play(); + }); + `) + }) + + function getIp() { + let ip = false; + let alias = 0; + let ifaces = os.networkInterfaces(); + for (var dev in ifaces) { + ifaces[dev].forEach(details => { + if (details.family === 'IPv4') { + if (!/(loopback|vmware|internal|hamachi|vboxnet|virtualbox)/gi.test(dev + (alias ? ':' + alias : ''))) { + if (details.address.substring(0, 8) === '192.168.' || + details.address.substring(0, 7) === '172.16.' || + details.address.substring(0, 3) === '10.' + ) { + ip = details.address; + ++alias; + } + } + } + }); + } + return ip; + } + + //QR Code + electron.ipcMain.handle('showQR', async (event , _) => { + let url = `http://${getIp()}:${this.remotePort}`; + electron.shell.openExternal(`https://cider.sh/pair-remote?url=${btoa(encodeURI(url))}`); + /* + * Doing this because we can give them the link and let them send it via Pocket or another in-browser tool -q + */ + }) + + // Get previews for normalization + electron.ipcMain.on("getPreviewURL", (_event, url) => { + 'get url' + fetch(url) + .then(res => res.buffer()) + .then(async(buffer) => { + try { + const metadata = await mm.parseBuffer(buffer, 'audio/x-m4a'); + let SoundCheckTag = metadata.native.iTunes[1].value + console.log('sc',SoundCheckTag) + this.win.webContents.send('SoundCheckTag', SoundCheckTag) + } catch (error) { + console.error(error.message); + } + }) + }); + + /* ********************************************************************************************* + * Window Events + * **********************************************************************************************/ + if (process.platform === "win32") { + let WND_STATE = { + MINIMIZED: 0, + NORMAL: 1, + MAXIMIZED: 2, + FULL_SCREEN: 3, + }; + let wndState = WND_STATE.NORMAL; + + this.win.on("resize", (_: any) => { + const isMaximized = this.win.isMaximized(); + const isMinimized = this.win.isMinimized(); + const isFullScreen = this.win.isFullScreen(); + const state = wndState; + if (isMinimized && state !== WND_STATE.MINIMIZED) { + wndState = WND_STATE.MINIMIZED; + } else if (isFullScreen && state !== WND_STATE.FULL_SCREEN) { + wndState = WND_STATE.FULL_SCREEN; + } else if (isMaximized && state !== WND_STATE.MAXIMIZED) { + wndState = WND_STATE.MAXIMIZED; + this.win.webContents.executeJavaScript(`app.chrome.maximized = true`); + } else if (state !== WND_STATE.NORMAL) { + wndState = WND_STATE.NORMAL; + this.win.webContents.executeJavaScript( + `app.chrome.maximized = false` + ); + } + }); + } + + this.win.on("closed", () => { + this.win = null; + }); + + // Set window Handler + this.win.webContents.setWindowOpenHandler((x: any) => { + if (x.url.includes("apple") || x.url.includes("localhost")) { + return { action: "allow" }; + } + electron.shell.openExternal(x.url).catch(console.error); + return { action: "deny" }; + }); + } + private async broadcastRemote() { + function getIp() { + let ip :any = false; + let alias = 0; + const ifaces: any = os.networkInterfaces() ; + for (var dev in ifaces) { + ifaces[dev].forEach( (details: any) => { + if (details.family === 'IPv4') { + if (!/(loopback|vmware|internal|hamachi|vboxnet|virtualbox)/gi.test(dev + (alias ? ':' + alias : ''))) { + if (details.address.substring(0, 8) === '192.168.' || + details.address.substring(0, 7) === '172.16.' || + details.address.substring(0, 3) === '10.' + ) { + ip = details.address; + ++alias; + } + } + } + }) ; + } + return ip; + } + const myString = `http://${getIp()}:${this.remotePort}`; + let mdns = require('mdns-js'); + const encoded = new Buffer(myString).toString('base64'); + var x = mdns.tcp('cider-remote'); + var txt_record = { + "Ver": "131077", + 'DvSv': '3689', + 'DbId': 'D41D8CD98F00B205', + 'DvTy': 'Cider', + 'OSsi': '0x212F0', + 'txtvers': '1', + "CtlN": "Cider", + "iV": "196623" + } + let server2 = mdns.createAdvertisement(x, `${await getPort({port: 3839})}`, { name: encoded, txt: txt_record }); + server2.start(); + console.log('remote broadcasted') + } +} + diff --git a/src/main/base/wsapi.ts b/src/main/base/wsapi.ts new file mode 100644 index 00000000..bb82ec49 --- /dev/null +++ b/src/main/base/wsapi.ts @@ -0,0 +1,293 @@ +import * as ws from "ws"; +import * as http from "http"; +import * as https from "https"; +import * as url from "url"; +import * as fs from "fs"; +import * as path from "path"; +import * as electron from "electron"; +const WebSocket = ws; +const WebSocketServer = ws.Server; + +interface standardResponse { + status?: Number, + message?: String, + data?: any, + type?: string, +} + + +export class wsapi { + static clients: any; + port: any = 26369 + wss: any = null + clients: any = [] + private _win : any; + constructor(win : any) { + this._win = win; + } + + + createId() { + // create random guid + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, + v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + public async InitWebSockets () { + electron.ipcMain.on('wsapi-updatePlaybackState', (event :any, arg :any) => { + this.updatePlaybackState(arg); + }) + + electron.ipcMain.on('wsapi-returnQueue', (event :any, arg :any) => { + this.returnQueue(JSON.parse(arg)); + }); + + electron.ipcMain.on('wsapi-returnSearch', (event :any, arg :any) => { + console.log("SEARCH") + this.returnSearch(JSON.parse(arg)); + }); + + electron.ipcMain.on('wsapi-returnSearchLibrary', (event :any, arg :any) => { + this.returnSearchLibrary(JSON.parse(arg)); + }); + + electron.ipcMain.on('wsapi-returnDynamic', (event :any, arg :any, type :any) => { + this.returnDynamic(JSON.parse(arg), type); + }); + + electron.ipcMain.on('wsapi-returnMusicKitApi', (event :any, arg :any, method :any) => { + this.returnMusicKitApi(JSON.parse(arg), method); + }); + + electron.ipcMain.on('wsapi-returnLyrics', (event :any, arg :any) => { + this.returnLyrics(JSON.parse(arg)); + }); + this.wss = new WebSocketServer({ + port: this.port, + perMessageDeflate: { + zlibDeflateOptions: { + // See zlib defaults. + chunkSize: 1024, + memLevel: 7, + level: 3 + }, + zlibInflateOptions: { + chunkSize: 10 * 1024 + }, + // Other options settable: + clientNoContextTakeover: true, // Defaults to negotiated value. + serverNoContextTakeover: true, // Defaults to negotiated value. + serverMaxWindowBits: 10, // Defaults to negotiated value. + // Below options specified as default values. + concurrencyLimit: 10, // Limits zlib concurrency for perf. + threshold: 1024 // Size (in bytes) below which messages + // should not be compressed if context takeover is disabled. + } + }) + console.log(`WebSocketServer started on port: ${this.port}`); + + const defaultResponse :standardResponse = {status :0, data:{}, message:"OK", type:"generic"}; + + + this.wss.on('connection', (ws : any) => { + ws.id = this.createId(); + console.log(`Client ${ws.id} connected`) + this.clients.push(ws); + ws.on('message', function incoming(message : any) { + + }); + // ws on message + ws.on('message', (message : any) => { + let data = JSON.parse(message); + let response :standardResponse = {status :0, data:{}, message:"OK", type:"generic"}; + if (data.action) { + data.action.toLowerCase(); + } + switch (data.action) { + default: + response.message = "Action not found"; + break; + case "identify": + response.message = "Thanks for identifying!" + response.data = { + id: ws.id + } + ws.identity = { + name: data.name, + author: data.author, + description: data.description, + version: data.version + } + break; + case "play-next": + this._win.webContents.executeJavaScript(`wsapi.playNext(\`${data.type}\`,\`${data.id}\`)`); + response.message = "Play Next"; + break; + case "play-later": + this._win.webContents.executeJavaScript(`wsapi.playLater(\`${data.type}\`,\`${data.id}\`)`); + response.message = "Play Later"; + break; + case "quick-play": + this._win.webContents.executeJavaScript(`wsapi.quickPlay(\`${data.term}\`)`); + response.message = "Quick Play"; + break; + case "get-lyrics": + this._win.webContents.executeJavaScript(`wsapi.getLyrics()`); + break; + case "shuffle": + this._win.webContents.executeJavaScript(`wsapi.toggleShuffle()`); + break; + case "set-shuffle": + if(data.shuffle == true) { + this._win.webContents.executeJavaScript(`MusicKit.getInstance().shuffleMode = 1`); + }else{ + this._win.webContents.executeJavaScript(`MusicKit.getInstance().shuffleMode = 0`); + } + break; + case "repeat": + this._win.webContents.executeJavaScript(`wsapi.toggleRepeat()`); + break; + case "seek": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().seekToTime(${parseFloat(data.time)})`); + response.message = "Seek"; + break; + case "pause": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().pause()`); + response.message = "Paused"; + break; + case "play": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().play()`); + response.message = "Playing"; + break; + case "stop": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().stop()`); + response.message = "Stopped"; + break; + case "volume": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().volume = ${parseFloat(data.volume)}`); + response.message = "Volume"; + break; + case "mute": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().mute()`); + response.message = "Muted"; + break; + case "unmute": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().unmute()`); + response.message = "Unmuted"; + break; + case "next": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().skipToNextItem()`); + response.message = "Next"; + break; + case "previous": + this._win.webContents.executeJavaScript(`MusicKit.getInstance().skipToPreviousItem()`); + response.message = "Previous"; + break; + case "musickit-api": + this._win.webContents.executeJavaScript(`wsapi.musickitApi(\`${data.method}\`, \`${data.id}\`, ${JSON.stringify(data.params)} , ${data.library})`); + break; + case "musickit-library-api": + break; + case "set-autoplay": + this._win.webContents.executeJavaScript(`wsapi.setAutoplay(${data.autoplay})`); + break; + case "queue-move": + this._win.webContents.executeJavaScript(`wsapi.moveQueueItem(${data.from},${data.to})`); + break; + case "get-queue": + this._win.webContents.executeJavaScript(`wsapi.getQueue()`); + break; + case "search": + if (!data.limit) { + data.limit = 10; + } + this._win.webContents.executeJavaScript(`wsapi.search(\`${data.term}\`, \`${data.limit}\`)`); + break; + case "library-search": + if (!data.limit) { + data.limit = 10; + } + this._win.webContents.executeJavaScript(`wsapi.searchLibrary(\`${data.term}\`, \`${data.limit}\`)`); + break; + case "show-window": + this._win.show() + break; + case "hide-window": + this._win.hide() + break; + case "play-mediaitem": + this._win.webContents.executeJavaScript(`wsapi.playTrackById("${data.id}", \`${data.kind}\`)`); + response.message = "Playing track"; + break; + case "get-status": + response.data = { + isAuthorized: true + }; + response.message = "Status"; + break; + case "get-currentmediaitem": + this._win.webContents.executeJavaScript(`wsapi.getPlaybackState()`); + break; + case "quit": + electron.app.quit(); + break; + } + ws.send(JSON.stringify(response)); + }); + + ws.on('close', () => { + // remove client from list + this.clients.splice(wsapi.clients.indexOf(ws), 1); + console.log(`Client ${ws.id} disconnected`); + }); + ws.send(JSON.stringify(defaultResponse)); + }); + } + sendToClient(id : any) { + // replace the clients.forEach with a filter to find the client that requested + } + updatePlaybackState(attr : any) { + const response : standardResponse = {status: 0, data: attr, message: "OK", type:"playbackStateUpdate"}; + this.clients.forEach(function each(client: any) { + client.send(JSON.stringify(response)); + }); + } + returnMusicKitApi(results :any, method :any) { + const response : standardResponse = {status :0, data: results, message:"OK", type:`musickitapi.${method}`}; + this.clients.forEach(function each(client :any) { + client.send(JSON.stringify(response)); + }); + } + returnDynamic(results :any, type :any) { + const response : standardResponse = {status :0, data: results, message: "OK", type: type}; + this.clients.forEach(function each(client :any) { + client.send(JSON.stringify(response)); + }); + } + returnLyrics(results :any) { + const response : standardResponse = {status :0, data: results, message: "OK", type: "lyrics"}; + this.clients.forEach(function each(client :any) { + client.send(JSON.stringify(response)); + }); + } + returnSearch(results :any) { + const response : standardResponse = {status :0, data: results, message: "OK", type: "searchResults"}; + this.clients.forEach(function each(client :any) { + client.send(JSON.stringify(response)); + }); + } + returnSearchLibrary(results :any) { + const response: standardResponse = {status :0, data :results, message:"OK", type:"searchResultsLibrary"}; + this.clients.forEach(function each(client :any) { + client.send(JSON.stringify(response)); + }); + } + returnQueue(queue :any) { + const response : standardResponse = {status :0,data :queue, message:"OK", type:"queue"}; + this.clients.forEach(function each(client :any) { + client.send(JSON.stringify(response)); + }); + } +} \ No newline at end of file diff --git a/src/main/cider-base.js b/src/main/cider-base.js deleted file mode 100644 index 856e58c3..00000000 --- a/src/main/cider-base.js +++ /dev/null @@ -1,446 +0,0 @@ -const { BrowserWindow, ipcMain, shell, app, screen } = require("electron") -const { join } = require("path") -const getPort = require("get-port"); -const express = require("express"); -const path = require("path"); -const windowStateKeeper = require("electron-window-state"); -const os = require('os'); -const yt = require('youtube-search-without-api-key'); -const discord = require('./discordrpc'); -const lastfm = require('./lastfm'); -const { writeFile, writeFileSync, existsSync, mkdirSync } = require('fs'); -const fs = require('fs'); -const mpris = require('./mpris'); -const mm = require('music-metadata'); -//const mdns = require('mdns') -const qrcode = require('qrcode-terminal') -const fetch = require('electron-fetch').default; -const { Stream } = require('stream'); - -// Analytics for debugging. -const ElectronSentry = require("@sentry/electron"); -ElectronSentry.init({ dsn: "https://68c422bfaaf44dea880b86aad5a820d2@o954055.ingest.sentry.io/6112214" }); - -const CiderBase = { - win: null, - requests: [], - audiostream: new Stream.PassThrough(), - async Start() { - this.clientPort = await getPort({ port: 9000 }); - this.win = this.CreateBrowserWindow() - }, - clientPort: 0, - CreateBrowserWindow() { - this.VerifyFiles() - // Set default window sizes - const mainWindowState = windowStateKeeper({ - defaultWidth: 1024, - defaultHeight: 600 - }); - - let win = null - const options = { - icon: join(__dirname, `../../resources/icons/icon.` + (process.platform === "win32" ? "ico" : "png")), - width: mainWindowState.width, - height: mainWindowState.height, - x: mainWindowState.x, - y: mainWindowState.y, - minWidth: 844, - minHeight: 410, - frame: false, - title: "Cider", - vibrancy: 'dark', - // transparent: true, - hasShadow: false, - webPreferences: { - webviewTag: true, - plugins: true, - nodeIntegration: true, - nodeIntegrationInWorker: false, - webSecurity: false, - allowRunningInsecureContent: true, - enableRemoteModule: true, - sandbox: true, - nativeWindowOpen: true, - contextIsolation: false, - preload: join(__dirname, '../preload/cider-preload.js') - } - } - - CiderBase.InitWebServer() - - // Create the BrowserWindow - win = new BrowserWindow(options) - - // intercept "https://js-cdn.music.apple.com/hls.js/2.141.0/hls.js/hls.js" and redirect to local file "./apple-hls.js" instead - win.webContents.session.webRequest.onBeforeRequest({ - urls: ["https://*/*.js"] - }, - (details, callback) => { - if (details.url.includes("hls.js")) { - callback({ - redirectURL: `http://localhost:${CiderBase.clientPort}/apple-hls.js` - }) - } else { - callback({ - cancel: false - }) - } - } - ) - - win.webContents.session.webRequest.onBeforeSendHeaders(async(details, callback) => { - if (details.url === "https://buy.itunes.apple.com/account/web/info") { - details.requestHeaders['sec-fetch-site'] = 'same-site'; - details.requestHeaders['DNT'] = '1'; - let itspod = await win.webContents.executeJavaScript(`window.localStorage.getItem("music.ampwebplay.itspod")`) - if (itspod != null) - details.requestHeaders['Cookie'] = `itspod=${itspod}` - } - callback({ requestHeaders: details.requestHeaders }) - }) - - win.webContents.session.webRequest.onHeadersReceived((details, callback) => { - if (details.url.match(/^https:\/\/store-\d{3}\.blobstore\.apple\.com/) || details.url.startsWith("https://store-037.blobstore.apple.com")) { - details.responseHeaders['Access-Control-Allow-Origin'] = '*'; - } - callback({ responseHeaders: details.responseHeaders }) - }) - - let location = `http://localhost:${CiderBase.clientPort}/` - win.loadURL(location) - win.on("closed", () => { - win = null - }) - - // Register listeners on Window to track size and position of the Window. - mainWindowState.manage(win); - - // IPC stuff (senders) - ipcMain.on("cider-platform", (event) => { - event.returnValue = process.platform - }) - - ipcMain.on("get-gpu-mode", (event) => { - event.returnValue = process.platform - }) - - ipcMain.on("is-dev", (event) => { - event.returnValue = !app.isPackaged - }) - - // IPC stuff (listeners) - ipcMain.on('close', () => { // listen for close event - win.close(); - }) - - ipcMain.on('put-library-songs', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-songs.json"), JSON.stringify(arg)) - }) - - ipcMain.on('put-library-artists', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-artists.json"), JSON.stringify(arg)) - }) - - ipcMain.on('put-library-albums', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-albums.json"), JSON.stringify(arg)) - }) - - ipcMain.on('put-library-playlists', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-playlists.json"), JSON.stringify(arg)) - }) - - ipcMain.on('put-library-recentlyAdded', (event, arg) => { - fs.writeFileSync(join(app.paths.ciderCache, "library-recentlyAdded.json"), JSON.stringify(arg)) - }) - - ipcMain.on('get-library-songs', (event) => { - let librarySongs = fs.readFileSync(join(app.paths.ciderCache, "library-songs.json"), "utf8") - event.returnValue = JSON.parse(librarySongs) - }) - - ipcMain.on('get-library-artists', (event) => { - let libraryArtists = fs.readFileSync(join(app.paths.ciderCache, "library-artists.json"), "utf8") - event.returnValue = JSON.parse(libraryArtists) - }) - - ipcMain.on('get-library-albums', (event) => { - let libraryAlbums = fs.readFileSync(join(app.paths.ciderCache, "library-albums.json"), "utf8") - event.returnValue = JSON.parse(libraryAlbums) - }) - - ipcMain.on('get-library-playlists', (event) => { - let libraryPlaylists = fs.readFileSync(join(app.paths.ciderCache, "library-playlists.json"), "utf8") - event.returnValue = JSON.parse(libraryPlaylists) - }) - - ipcMain.on('get-library-recentlyAdded', (event) => { - let libraryRecentlyAdded = fs.readFileSync(join(app.paths.ciderCache, "library-recentlyAdded.json"), "utf8") - event.returnValue = JSON.parse(libraryRecentlyAdded) - }) - - ipcMain.handle('getYTLyrics', async(event, track, artist) => { - var u = track + " " + artist + " official video"; - const videos = await yt.search(u); - return videos - }) - - ipcMain.handle('getStoreValue', (event, key, defaultValue) => { - return (defaultValue ? app.cfg.get(key, true) : app.cfg.get(key)); - }); - - ipcMain.handle('setStoreValue', (event, key, value) => { - app.cfg.set(key, value); - }); - - ipcMain.on('getStore', (event) => { - event.returnValue = app.cfg.store - }) - - ipcMain.on('setStore', (event, store) => { - app.cfg.store = store - }) - - ipcMain.handle('setVibrancy', (event, key, value) => { - win.setVibrancy(value) - }); - - ipcMain.on('maximize', () => { // listen for maximize event - if (win.isMaximized()) { - win.unmaximize() - } else { - win.maximize() - } - }) - - ipcMain.on('minimize', () => { // listen for minimize event - win.minimize(); - }) - - ipcMain.on('setFullScreen', (event, flag) => { - win.setFullScreen(flag) - }) - - if (process.platform === "win32") { - let WND_STATE = { - MINIMIZED: 0, - NORMAL: 1, - MAXIMIZED: 2, - FULL_SCREEN: 3 - } - let wndState = WND_STATE.NORMAL - - win.on("resize", (_event) => { - const isMaximized = win.isMaximized() - const isMinimized = win.isMinimized() - const isFullScreen = win.isFullScreen() - const state = wndState; - if (isMinimized && state !== WND_STATE.MINIMIZED) { - wndState = WND_STATE.MINIMIZED - } else if (isFullScreen && state !== WND_STATE.FULL_SCREEN) { - wndState = WND_STATE.FULL_SCREEN - } else if (isMaximized && state !== WND_STATE.MAXIMIZED) { - wndState = WND_STATE.MAXIMIZED - win.webContents.executeJavaScript(`app.chrome.maximized = true`) - } else if (state !== WND_STATE.NORMAL) { - wndState = WND_STATE.NORMAL - win.webContents.executeJavaScript(`app.chrome.maximized = false`) - } - }) - } - - // Set window Handler - win.webContents.setWindowOpenHandler(({ url }) => { - if (url.includes("apple") || url.includes("localhost")) { - return { action: "allow" } - } - shell.openExternal(url).catch(() => {}) - return { - action: 'deny' - } - }) - - // Set scale - ipcMain.on('setScreenScale', (event, scale) => { - win.webContents.setZoomFactor(parseFloat(scale)) - }) - - win.webContents.setZoomFactor(screen.getPrimaryDisplay().scaleFactor) - - mpris.connect(win) - mpris.SetButtons(win, false) - - lastfm.authenticate() - // Discord - discord.connect((app.cfg.get("general.discord_rpc") == 1) ? '911790844204437504' : '886578863147192350'); - ipcMain.on('playbackStateDidChange', (_event, a) => { - app.media = a; - discord.updateActivity(a) - mpris.SetButtons(win, a) - mpris.updateState(a) - lastfm.scrobbleSong(a) - lastfm.updateNowPlayingSong(a) - }); - - ipcMain.on('nowPlayingItemDidChange', (_event, a) => { - app.media = a; - discord.updateActivity(a) - mpris.SetButtons(win, a) - mpris.updateAttributes(a) - lastfm.scrobbleSong(a) - lastfm.updateNowPlayingSong(a) - }); - - ipcMain.on("getPreviewURL", (_event, url) => { - fetch(url) - .then(res => res.buffer()) - .then(async(buffer) => { - try { - const metadata = await mm.parseBuffer(buffer, 'audio/x-m4a'); - SoundCheckTag = metadata.native.iTunes[1].value - win.webContents.send('SoundCheckTag', SoundCheckTag) - } catch (error) { - console.error(error.message); - } - }) - }); - - ipcMain.on('writeAudio', function(event, buffer) { - CiderBase.audiostream.write(Buffer.from(buffer)); - }) - - return win - }, - VerifyFiles() { - const expectedDirectories = [ - "CiderCache" - ] - const expectedFiles = [ - "library-songs.json", - "library-artists.json", - "library-albums.json", - "library-playlists.json", - "library-recentlyAdded.json", - ] - for (let i = 0; i < expectedDirectories.length; i++) { - if (!existsSync(path.join(app.getPath("userData"), expectedDirectories[i]))) { - mkdirSync(path.join(app.getPath("userData"), expectedDirectories[i])) - } - } - for (let i = 0; i < expectedFiles.length; i++) { - const file = path.join(app.paths.ciderCache, expectedFiles[i]) - if (!existsSync(file)) { - writeFileSync(file, JSON.stringify([])) - } - } - }, - EnvironmentVariables: { - "env": { - platform: os.platform(), - dev: app.isPackaged - } - }, - LinkHandler: (startArgs) => { - if (!startArgs) return; - - if (String(startArgs).includes('auth')) { - let authURI = String(startArgs).split('/auth/')[1] - if (authURI.startsWith('lastfm')) { // If we wanted more auth options - console.log("lfmtoken", String(startArgs)) - const authKey = authURI.split('lastfm?token=')[1]; - app.cfg.set('lastfm.enabled', true); - app.cfg.set('lastfm.auth_token', authKey); - CiderBase.win.webContents.send('LastfmAuthenticated', authKey); - lastfm.authenticate() - } - } else { - if (String(startArgs).includes('/play/')) { //Steer away from protocal:// specific conditionals - const playParam = String(startArgs).split('/play/')[1] - if (playParam.includes('s/')) { // setQueue can be done with album, song, url, playlist id - console.log(playParam) - let song = playParam.split('s/')[1] - console.warn(`[LinkHandler] Attempting to load song by id: ${song}`); - this.win.webContents.executeJavaScript(` - MusicKit.getInstance().setQueue({ song: '${song}'}).then(function(queue) { - MusicKit.getInstance().play(); - }); - `).catch((err) => console.error(err)); - } - - - - } - - - - - } - - }, - - async InitWebServer() { - const webapp = express(); - const webRemotePath = path.join(__dirname, '../renderer/'); - webapp.set("views", path.join(webRemotePath, "views")); - webapp.set("view engine", "ejs"); - let firstRequest = true - //const webRemoteMDNS = mdns.createAdvertisement(mdns.tcp('https'), 9000, { name: "cider", domain: 'local' }) - //webRemoteMDNS.start() - //* Prep for remote -quack - webapp.use(function(req, res, next) { - // if not localhost - if (req.url.includes("audio.webm") || (req.headers.host.includes("localhost") && req.headers["user-agent"].includes("Cider"))) { - next(); - - } else { - console.log(req.get('host')) - res.redirect("https://discord.gg/applemusic") - } - }); - webapp.use(express.static(webRemotePath)); - webapp.get('/', function(req, res) { - //if (!req.headers["user-agent"].includes("Cider")) - //res.sendFile(path.join(webRemotePath, 'index_old.html')); - if (firstRequest) { - console.log("---- Ignore Me ;) ---") - qrcode.generate(`http://${os.hostname}:9000`) //Prep for remote - console.log("---- Ignore Me ;) ---") - /* - * - * USING https://www.npmjs.com/package/qrcode-terminal for terminal - * WE SHOULD USE https://www.npmjs.com/package/qrcode for the remote (or others) - * -quack - */ - } - firstRequest = false - - res.render("main", CiderBase.EnvironmentVariables) - }); - webapp.get('/audio.webm', function(req, res) { - console.log('hi') - try { - req.connection.setTimeout(Number.MAX_SAFE_INTEGER); - // CiderBase.requests.push({req: req, res: res}); - // var pos = CiderBase.requests.length - 1; - // req.on("close", () => { - // console.info("CLOSED", CiderBase.requests.length); - // requests.splice(pos, 1); - // console.info("CLOSED", CiderBase.requests.length); - // }); - CiderBase.audiostream.on('data', (data) => { - try { - res.write(data); - } catch (ex) { - console.log(ex) - } - }) - } catch (ex) { console.log(ex) } - }); - webapp.listen(CiderBase.clientPort, function() { - console.log(`Cider hosted on: ${CiderBase.clientPort}`); - }); - }, - -} - -module.exports = CiderBase; \ No newline at end of file diff --git a/src/main/discordrpc.js b/src/main/discordrpc.js deleted file mode 100644 index 6e3b414c..00000000 --- a/src/main/discordrpc.js +++ /dev/null @@ -1,142 +0,0 @@ -const { app } = require('electron'), - DiscordRPC = require('discord-rpc') - -module.exports = { - - /** - * Connects to Discord RPC - * @param {string} clientId - */ - connect: function(clientId) { - app.discord = { isConnected: false }; - if (app.cfg.get('general.discord_rpc') == 0 || app.discord.isConnected) return; - - DiscordRPC.register(clientId) // Apparently needed for ask to join, join, spectate etc. - const client = new DiscordRPC.Client({ transport: "ipc" }); - app.discord = Object.assign(client, { error: false, activityCache: null, isConnected: false }); - - // Login to Discord - app.discord.login({ clientId }) - .then(() => { - app.discord.isConnected = true; - }) - .catch((e) => console.error(`[DiscordRPC][connect] ${e}`)); - - app.discord.on('ready', () => { - console.log(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${client.user.username} (${client.user.id})`); - }) - - // Handles Errors - app.discord.on('error', err => { - console.error(`[DiscordRPC] ${err}`); - this.disconnect() - app.discord.isConnected = false; - }); - }, - - /** - * Disconnects from Discord RPC - */ - disconnect: function() { - if (app.cfg.get('general.discord_rpc') == 0 || !app.discord.isConnected) return; - - try { - app.discord.destroy().then(() => { - app.discord.isConnected = false; - console.log('[DiscordRPC][disconnect] Disconnected from discord.') - }).catch((e) => console.error(`[DiscordRPC][disconnect] ${e}`)); - } catch (err) { - console.error(err) - } - }, - - /** - * Sets the activity of the client - * @param {object} attributes - */ - updateActivity: function(attributes) { - if (app.cfg.get('general.discord_rpc') == 0) return; - - if (!app.discord.isConnected) { - app.discord.clearActivity().catch((e) => console.error(`[DiscordRPC][updateActivity] ${e}`)); - return; - } - - // console.log('[DiscordRPC][updateActivity] Updating Discord Activity.') - - const listenURL = `https://cider.sh/p?s&id=${attributes.playParams.id}` // cider://play/s/[id] (for song) - //console.log(attributes) - let ActivityObject = { - details: attributes.name, - state: `by ${attributes.artistName}`, - startTimestamp: attributes.startTime, - endTimestamp: attributes.endTime, - largeImageKey: (attributes.artwork.url.replace('{w}', '1024').replace('{h}', '1024')) ?? 'cider', - largeImageText: attributes.albumName, - smallImageKey: (attributes.status ? 'play' : 'pause'), - smallImageText: (attributes.status ? 'Playing' : 'Paused'), - instance: true, - buttons: [ - { label: "Listen on Cider", url: listenURL }, - ] - }; - if (ActivityObject.largeImageKey == "" || ActivityObject.largeImageKey == null) { - ActivityObject.largeImageKey = (app.cfg.get("general.discord_rpc") == 1) ? "cider" : "logo" - } - - // Remove the pause/play icon and test for clear activity on pause - if (app.cfg.get('general.discordClearActivityOnPause') == 1) { - delete ActivityObject.smallImageKey - delete ActivityObject.smallImageText - } - - // Deletes the timestamp if its not greater than 0 - if (!((new Date(attributes.endTime)).getTime() > 0)) { - delete ActivityObject.startTimestamp - delete ActivityObject.endTimestamp - } - - // Artist check - if (!attributes.artistName) { - delete ActivityObject.state - } - - // Album text check - if (!ActivityObject.largeImageText || ActivityObject.largeImageText.length < 2) { - delete ActivityObject.largeImageText - } - - // Checks if the name is greater than 128 because some songs can be that long - if (ActivityObject.details.length > 128) { - ActivityObject.details = ActivityObject.details.substring(0, 125) + '...' - } - - - - - // Check if its pausing (false) or playing (true) - if (!attributes.status) { - if (app.cfg.get('general.discordClearActivityOnPause') == 1) { - app.discord.clearActivity().catch((e) => console.error(`[DiscordRPC][clearActivity] ${e}`)); - ActivityObject = null - } else { - delete ActivityObject.startTimestamp - delete ActivityObject.endTimestamp - ActivityObject.smallImageKey = 'pause' - ActivityObject.smallImageText = 'Paused' - } - } - - - if (ActivityObject && ActivityObject !== app.discord.activityCache && ActivityObject.details && ActivityObject.state) { - try { - // console.log(`[DiscordRPC][setActivity] Setting activity to ${JSON.stringify(ActivityObject)}`); - app.discord.setActivity(ActivityObject) - app.discord.activityCache = ActivityObject - } catch (err) { - console.error(`[DiscordRPC][setActivity] ${err}`) - } - - } - }, -} diff --git a/src/main/index.ts b/src/main/index.ts new file mode 100644 index 00000000..59196a9f --- /dev/null +++ b/src/main/index.ts @@ -0,0 +1,84 @@ +require('v8-compile-cache'); + +// Analytics for debugging fun yeah. +import * as sentry from '@sentry/electron'; +import * as electron from 'electron'; +import {Win} from "./base/win"; +import {ConfigStore} from "./base/store"; +import {AppEvents} from "./base/app"; +import PluginHandler from "./base/plugins"; + +sentry.init({dsn: "https://68c422bfaaf44dea880b86aad5a820d2@o954055.ingest.sentry.io/6112214"}); + +const config = new ConfigStore(); +const App = new AppEvents(config.store); +const Cider = new Win(electron.app, config.store) +const plug = new PluginHandler(config.store); + +let win: Electron.BrowserWindow; + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * App Event Handlers + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + +electron.app.on('ready', () => { + App.ready(plug); + + console.log('[Cider] Application is Ready. Creating Window.') + if (!electron.app.isPackaged) { + console.info('[Cider] Running in development mode.') + require('vue-devtools').install() + } + + electron.components.whenReady().then(async () => { + win = await Cider.createWindow() + App.bwCreated(win); + /// please dont change this for plugins to get proper and fully initialized Win objects + plug.callPlugins('onReady', win); + win.on("ready-to-show", () => { + win.show(); + }); + }); + +}); + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Renderer Event Handlers + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + +electron.ipcMain.on('playbackStateDidChange', (event, attributes) => { + plug.callPlugins('onPlaybackStateDidChange', attributes); +}); + +electron.ipcMain.on('nowPlayingItemDidChange', (event, attributes) => { + plug.callPlugins('onNowPlayingItemDidChange', attributes); +}); + +electron.app.on('before-quit', () => { + plug.callPlugins('onBeforeQuit'); + console.warn(`${electron.app.getName()} exited.`); +}); + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Widevine Event Handlers + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + +// @ts-ignore +electron.app.on('widevine-ready', (version, lastVersion) => { + if (null !== lastVersion) { + console.log('[Cider][Widevine] Widevine ' + version + ', upgraded from ' + lastVersion + ', is ready to be used!') + } else { + console.log('[Cider][Widevine] Widevine ' + version + ' is ready to be used!') + } +}) + +// @ts-ignore +electron.app.on('widevine-update-pending', (currentVersion, pendingVersion) => { + console.log('[Cider][Widevine] Widevine ' + currentVersion + ' is ready to be upgraded to ' + pendingVersion + '!') +}) + +// @ts-ignore +electron.app.on('widevine-error', (error) => { + console.log('[Cider][Widevine] Widevine installation encountered an error: ' + error) + electron.app.exit() +}) diff --git a/src/main/lastfm.js b/src/main/lastfm.js deleted file mode 100644 index b97bcb1b..00000000 --- a/src/main/lastfm.js +++ /dev/null @@ -1,153 +0,0 @@ -const {app, Notification} = require('electron'), - fs = require('fs'), - {resolve} = require('path'), - sessionPath = resolve(app.getPath('userData'), 'session.json'), - apiCredentials = require('../../resources/lfmApiCredentials.json'), - LastfmAPI = require('lastfmapi'); - -const lfm = { - authenticateFromFile: function () { - let sessionData = require(sessionPath) - console.log("[LastFM][authenticateFromFile] Logging in with Session Info.") - app.lastfm.setSessionCredentials(sessionData.name, sessionData.key) - console.log("[LastFM][authenticateFromFile] Logged in.") - }, - - authenticate: function () { - if (app.cfg.get('lastfm.auth_token')) { - app.cfg.set('lastfm.enabled', true); - } - - if (!app.cfg.get('lastfm.enabled') || !app.cfg.get('lastfm.auth_token')) { - app.cfg.set('lastfm.enabled', false); - return - } - - const lfmAPI = new LastfmAPI({ - 'api_key': apiCredentials.key, - 'secret': apiCredentials.secret - }); - - app.lastfm = Object.assign(lfmAPI, {cachedAttributes: false, cachedNowPlayingAttributes: false}); - - fs.stat(sessionPath, function (err) { - if (err) { - console.error("[LastFM][Session] Session file couldn't be opened or doesn't exist,", err) - console.log("[LastFM][Auth] Beginning authentication from configuration") - app.lastfm.authenticate(app.cfg.get('lastfm.auth_token'), function (err, session) { - if (err) { - throw err; - } - console.log("[LastFM] Successfully obtained LastFM session info,", session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"} - console.log("[LastFM] Saving session info to disk.") - let tempData = JSON.stringify(session) - fs.writeFile(sessionPath, tempData, (err) => { - if (err) - console.log("[LastFM][fs]", err) - else { - console.log("[LastFM][fs] File was written successfully.") - lfm.authenticateFromFile() - new Notification({ - title: app.getName(), - body: "Successfully logged into LastFM using Authentication Key." - }).show() - } - }) - }); - } else { - lfm.authenticateFromFile() - } - }) - }, - - scrobbleSong: async function (attributes) { - await new Promise(resolve => setTimeout(resolve, Math.round(attributes.durationInMillis * (app.cfg.get('lastfm.scrobble_after') / 100)))); - const currentAttributes = app.media; - - if (!app.lastfm || app.lastfm.cachedAttributes === attributes ) { - return - } - - if (app.lastfm.cachedAttributes) { - if (app.lastfm.cachedAttributes.playParams.id === attributes.playParams.id) return; - } - - if (currentAttributes.status && currentAttributes === attributes) { - if (fs.existsSync(sessionPath)) { - // Scrobble playing song. - if (attributes.status === true) { - app.lastfm.track.scrobble({ - 'artist': lfm.filterArtistName(attributes.artistName), - 'track': attributes.name, - 'album': attributes.albumName, - 'albumArtist': this.filterArtistName(attributes.artistName), - 'timestamp': new Date().getTime() / 1000 - }, function (err, scrobbled) { - if (err) { - return console.error('[LastFM] An error occurred while scrobbling', err); - } - - console.log('[LastFM] Successfully scrobbled: ', scrobbled); - }); - app.lastfm.cachedAttributes = attributes - } - } else { - this.authenticate(); - } - } else { - return console.log('[LastFM] Did not add ', attributes.name , '—' , lfm.filterArtistName(attributes.artistName), 'because now playing a other song.'); - } - }, - - filterArtistName: function (artist) { - if (!app.cfg.get('lastfm.enabledRemoveFeaturingArtists')) return artist; - - artist = artist.split(' '); - if (artist.includes('&')) { - artist.length = artist.indexOf('&'); - } - if (artist.includes('and')) { - artist.length = artist.indexOf('and'); - } - artist = artist.join(' '); - if (artist.includes(',')) { - artist = artist.split(',') - artist = artist[0] - } - return artist.charAt(0).toUpperCase() + artist.slice(1); - }, - - updateNowPlayingSong: function (attributes) { - if (!app.lastfm ||app.lastfm.cachedNowPlayingAttributes === attributes | !app.cfg.get('lastfm.NowPlaying')) { - return - } - - if (app.lastfm.cachedNowPlayingAttributes) { - if (app.lastfm.cachedNowPlayingAttributes.playParams.id === attributes.playParams.id) return; - } - - if (fs.existsSync(sessionPath)) { - // update Now Playing - if (attributes.status === true) { - app.lastfm.track.updateNowPlaying({ - 'artist': lfm.filterArtistName(attributes.artistName), - 'track': attributes.name, - 'album': attributes.albumName, - 'albumArtist': this.filterArtistName(attributes.artistName) - }, function (err, nowPlaying) { - if (err) { - return console.error('[LastFM] An error occurred while updating nowPlayingSong', err); - } - - console.log('[LastFM] Successfully updated nowPlayingSong', nowPlaying); - }); - app.lastfm.cachedNowPlayingAttributes = attributes - } - - } else { - this.authenticate() - } - } -} - -module.exports = lfm; \ No newline at end of file diff --git a/src/main/mpris.js b/src/main/mpris.js deleted file mode 100644 index 086945da..00000000 --- a/src/main/mpris.js +++ /dev/null @@ -1,149 +0,0 @@ -const { nativeImage } = require("electron"); -const path = require('path') - -let mediaPlayer = null; - -module.exports = { - - /** - * Connects to the MPRIS interface. - * @param {Object} win - The BrowserWindow. - */ - connect: (win) => { - if (process.platform !== "linux") return; - - const Player = require('mpris-service'); - - mediaPlayer = Player({ - name: 'Cider', - identity: 'Cider', - supportedUriSchemes: [], - supportedMimeTypes: [], - supportedInterfaces: ['player'] - }); - mediaPlayer = Object.assign(mediaPlayer, { canQuit: true, canControl: true, canPause: true, canPlay: true, canGoNext: true }) - - - let pos_atr = {durationInMillis: 0}; - mediaPlayer.getPosition = function () { - const durationInMicro = pos_atr.durationInMillis * 1000; - const percentage = parseFloat("0") || 0; - return durationInMicro * percentage; - } - - mediaPlayer.active = true - - mediaPlayer.on('playpause', async () => { - win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err)) - }); - - mediaPlayer.on('play', async () => { - win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err)) - }); - - mediaPlayer.on('pause', async () => { - win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err)) - }); - - mediaPlayer.on('next', async () => { - win.webContents.executeJavaScript('MusicKitInterop.nextTrack()').catch(err => console.error(err)) - }); - - mediaPlayer.on('previous', async () => { - win.webContents.executeJavaScript('MusicKitInterop.previousTrack()').catch(err => console.error(err)) - }); - }, - - /** - * Updates the MPRIS interface. - * @param {Object} attributes - The attributes of the track. - */ - updateAttributes: (attributes) => { - if (process.platform !== "linux") return; - - const MetaData = { - 'mpris:trackid': mediaPlayer.objectPath(`track/${attributes.playParams.id.replace(/[.]+/g, "")}`), - 'mpris:length': attributes.durationInMillis * 1000, // In microseconds - 'mpris:artUrl': (attributes.artwork.url.replace('/{w}x{h}bb', '/512x512bb')).replace('/2000x2000bb', '/35x35bb'), - 'xesam:title': `${attributes.name}`, - 'xesam:album': `${attributes.albumName}`, - 'xesam:artist': [`${attributes.artistName}`,], - 'xesam:genre': attributes.genreNames - } - - if (mediaPlayer.metadata["mpris:trackid"] === MetaData["mpris:trackid"]) { - return - } - - mediaPlayer.metadata = MetaData - }, - - /** - * Updates the playback state of the MPRIS interface. - * @param {Object} attributes - The attributes of the track. - */ - updateState: (attributes) => { - if (process.platform !== "linux") return; - - function setPlaybackIfNeeded(status) { - if (mediaPlayer.playbackStatus === status) { - return - } - mediaPlayer.playbackStatus = status; - } - - switch (attributes.status) { - case true: // Playing - setPlaybackIfNeeded('Playing'); - break; - case false: // Paused - setPlaybackIfNeeded('Paused'); - break; - default: // Stopped - setPlaybackIfNeeded('Stopped'); - break; - } - }, - - SetButtons: (win, attributes) => { - if (process.platform === 'win32') { // Set the Windows Thumbnail Toolbar Buttons - win.setThumbarButtons([ - { - tooltip: 'Previous', - icon: nativeImage.createFromPath(path.join(__dirname, 'thumbaricons/backwardPng.png')), - click() { - console.log("Clicked the bc taskbar button!") - win.webContents.executeJavaScript('MusicKitInterop.previousTrack()').catch(err => console.error(err)) - } - }, - { - tooltip: attributes.status ? 'Pause' : 'Play', - //tooltip: 'Play', - icon: attributes.status ? nativeImage.createFromPath(path.join(__dirname, 'thumbaricons/pausePng.png')) : nativeImage.createFromPath(path.join(__dirname, 'thumbaricons/playPng.png')), - click() { - console.log("Clicked the pl taskbar button!") - win.webContents.executeJavaScript('MusicKitInterop.pausePlay()').catch(err => console.error(err)) - } - }, - { - tooltip: 'Next', - icon: nativeImage.createFromPath(path.join(__dirname, 'thumbaricons/forwardPng.png')), - click() { - console.log("Clicked the fw taskbar button!") - win.webContents.executeJavaScript('MusicKitInterop.nextTrack()').catch(err => console.error(err)) - } - } - ]); - - } - }, - - /** - * Closes the MPRIS interface. - */ - clearActivity: () => { - if (process.platform !== "linux") return; - mediaPlayer.metadata = {'mpris:trackid': '/org/mpris/MediaPlayer2/TrackList/NoTrack'} - mediaPlayer.playbackStatus = 'Stopped'; - }, -} \ No newline at end of file diff --git a/src/main/plugins/Extras/examplePlugin.ts b/src/main/plugins/Extras/examplePlugin.ts new file mode 100644 index 00000000..98b6af4c --- /dev/null +++ b/src/main/plugins/Extras/examplePlugin.ts @@ -0,0 +1,60 @@ +let i = 1, k = 1; +export default class ExamplePlugin { + /** + * Private variables for interaction in plugins + */ + private _win: any; + private _app: any; + private _store: any; + + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'examplePlugin'; + public description: string = 'Example plugin'; + public version: string = '1.0.0'; + public author: string = 'Example author'; + + /** + * Runs on plugin load (Currently run on application start) + */ + constructor(app: any, store: any) { + this._app = app; + this._store = store; + console.debug(`[Plugin][${this.name}] Loading Complete.`); + } + + /** + * Runs on app ready + */ + onReady(win: any): void { + this._win = win; + console.debug(`[Plugin][${this.name}] Ready.`); + } + + /** + * Runs on app stop + */ + onBeforeQuit(): void { + console.debug(`[Plugin][${this.name}] Stopped.`); + } + + /** + * Runs on playback State Change + * @param attributes Music Attributes (attributes.state = current state) + */ + onPlaybackStateDidChange(attributes: object): void { + console.log('onPlaybackStateDidChange has been called ' + i + ' times'); + i++ + } + + /** + * Runs on song change + * @param attributes Music Attributes + */ + onNowPlayingItemDidChange(attributes: object): void { + console.log('onNowPlayingDidChange has been called ' + k + ' times'); + k++ + } + +} diff --git a/src/main/plugins/Extras/sendSongToTitlebar.ts b/src/main/plugins/Extras/sendSongToTitlebar.ts new file mode 100644 index 00000000..8b39e47d --- /dev/null +++ b/src/main/plugins/Extras/sendSongToTitlebar.ts @@ -0,0 +1,37 @@ +export default class sendSongToTitlebar { + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'sendSongToTitlebar'; + public description: string = 'Sets the app\'s titlebar to the Song title'; + public version: string = '0.0.1'; + public author: string = 'Cider Collective (credit to 8times9 via #147)'; + /** + * Runs on plugin load (Currently run on application start) + */ + private _win: any; + private _app: any; + constructor() {} + /** + * Runs on app ready + */ + onReady(win: any): void { + this._win = win; + } + /** + * Runs on app stop + */ + onBeforeQuit(): void {} + /** + * Runs on playback State Change + * @param attributes Music Attributes (attributes.state = current state) + */ + onPlaybackStateDidChange(attributes: any): void { + this._win.setTitle(`${(attributes != null && attributes.name != null && attributes.name.length > 0) ? (attributes.name + " - ") : ''}Cider`) + } + /** + * Runs on song change + * @param attributes Music Attributes + */ + onNowPlayingItemDidChange(attributes: object): void {} +} \ No newline at end of file diff --git a/src/main/plugins/discordrpc.ts b/src/main/plugins/discordrpc.ts new file mode 100644 index 00000000..3265320f --- /dev/null +++ b/src/main/plugins/discordrpc.ts @@ -0,0 +1,195 @@ +import * as RPC from 'discord-rpc' + +export default class DiscordRichPresence { + + /** + * Private variables for interaction in plugins + */ + private static _store: any; + private static _connection: boolean = false; + + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'Discord Rich Presence'; + public description: string = 'Discord RPC plugin for Cider'; + public version: string = '1.0.0'; + public author: string = 'vapormusic/Core (Cider Collective)'; + + /** + * Plugin Initialization + */ + private _client: any = null; + private _activity: RPC.Presence = { + details: '', + state: '', + largeImageKey: '', + largeImageText: '', + smallImageKey: '', + smallImageText: '', + instance: false + }; + private _activityCache: RPC.Presence = { + details: '', + state: '', + largeImageKey: '', + largeImageText: '', + smallImageKey: '', + smallImageText: '', + instance: false + }; + + /******************************************************************************************* + * Private Methods + * ****************************************************************************************/ + + /** + * Connect to Discord + * @param clientId + * @private + */ + private connect(clientId: any) { + if (DiscordRichPresence._store.general.discord_rpc == 0) { + return + } + + // Apparently needed for ask to join, join, spectate etc. + RPC.register(clientId) + + // Create the client + this._client = new RPC.Client({transport: "ipc"}); + + // Runs on Ready + this._client.on('ready', () => { + console.info(`[DiscordRPC][connect] Successfully Connected to Discord. Authed for user: ${this._client.user.id}.`); + }) + + // Handles Errors + this._client.on('error', (err: any) => { + console.error(`[DiscordRichPresence] ${err}`); + this.disconnect() + }); + + // Login to Discord + this._client.login({clientId}) + .then(() => { + DiscordRichPresence._connection = true; + }) + .catch((e: any) => console.error(`[DiscordRichPresence][connect] ${e}`)); + } + + /** + * Disconnects from Discord RPC + */ + private disconnect() { + if (!this._client) return; + + this._client.destroy().then(() => { + DiscordRichPresence._connection = false; + console.log('[DiscordRPC][disconnect] Disconnected from discord.') + }).catch((e: any) => console.error(`[DiscordRPC][disconnect] ${e}`)); + } + + /** + * Sets the activity of the client + * @param {object} attributes + */ + private updateActivity(attributes: any) { + if (!this._client) return; + + if (!DiscordRichPresence._connection) { + this._client.clearActivity().catch((e: any) => console.error(`[DiscordRichPresence][clearActivity] ${e}`)); + return; + } + + this._activity = { + details: attributes.name, + state: `${attributes.artistName ? `by ${attributes.artistName}` : ''}`, + startTimestamp: ((new Date(attributes.endTime).getTime() < 0) ? null : attributes.startTime), + endTimestamp: ((new Date(attributes.endTime).getTime() < 0) ? null : attributes.endTime), + largeImageKey: (attributes.artwork.url.replace('{w}', '1024').replace('{h}', '1024')) ?? 'cider', + largeImageText: attributes.albumName, + instance: false, // Whether the activity is in a game session + + buttons: [ + {label: "Listen on Cider", url: attributes.url.cider}, + {label: "View on Apple Music", url: attributes.url.appleMusic}, + ] + }; + + + // Checks if the name is greater than 128 because some songs can be that long + if (this._activity.details && this._activity.details.length > 128) { + this._activity.details = this._activity.details.substring(0, 125) + '...' + } + + // Check if its pausing (false) or playing (true) + if (!attributes.status) { + if (DiscordRichPresence._store.general.discord_rpc_clear_on_pause) { + this._client.clearActivity() + .catch((e: any) => console.error(`[DiscordRichPresence][clearActivity] ${e}`)); + } else { + this._activity.smallImageKey = 'pause'; + this._activity.smallImageText = 'Paused'; + delete this._activity.endTimestamp; + delete this._activity.startTimestamp; + this._client.setActivity(this._activity) + .catch((e: any) => console.error(`[DiscordRichPresence][setActivity] ${e}`)); + } + + } else if (this._activity && this._activityCache !== this._activity && this._activity.details) { + if (!DiscordRichPresence._store.general.discord_rpc_clear_on_pause) { + this._activity.smallImageKey = 'play'; + this._activity.smallImageText = 'Playing'; + } + + this._client.setActivity(this._activity) + .catch((e: any) => console.error(`[DiscordRichPresence][updateActivity] ${e}`)); + this._activityCache = this._activity; + } + + } + + /******************************************************************************************* + * Public Methods + * ****************************************************************************************/ + + /** + * Runs on plugin load (Currently run on application start) + */ + constructor(_app: any, store: any) { + DiscordRichPresence._store = store + console.debug(`[Plugin][${this.name}] Loading Complete.`); + } + + /** + * Runs on app ready + */ + onReady(_win: any): void { + this.connect((DiscordRichPresence._store.general.discord_rpc == 1) ? '911790844204437504' : '886578863147192350'); + console.debug(`[Plugin][${this.name}] Ready.`); + } + + /** + * Runs on app stop + */ + onBeforeQuit(): void { + console.debug(`[Plugin][${this.name}] Stopped.`); + } + + /** + * Runs on playback State Change + * @param attributes Music Attributes (attributes.state = current state) + */ + onPlaybackStateDidChange(attributes: object): void { + this.updateActivity(attributes) + } + + /** + * Runs on song change + * @param attributes Music Attributes + */ + onNowPlayingItemDidChange(attributes: object): void { + this.updateActivity(attributes) + } +} diff --git a/src/main/plugins/lastfm.ts b/src/main/plugins/lastfm.ts new file mode 100644 index 00000000..51ddcc34 --- /dev/null +++ b/src/main/plugins/lastfm.ts @@ -0,0 +1,253 @@ +import * as electron from 'electron'; +import * as fs from 'fs'; +import {resolve} from 'path'; + +export default class LastFMPlugin { + private sessionPath = resolve(electron.app.getPath('userData'), 'session.json'); + private apiCredentials = { + key: "f9986d12aab5a0fe66193c559435ede3", + secret: "acba3c29bd5973efa38cc2f0b63cc625" + } + /** + * Private variables for interaction in plugins + */ + private _win: any; + private _app: any; + private _lastfm: any; + private _store: any; + + private authenticateFromFile() { + let sessionData = require(this.sessionPath) + console.log("[LastFM][authenticateFromFile] Logging in with Session Info.") + this._lastfm.setSessionCredentials(sessionData.username, sessionData.key) + console.log("[LastFM][authenticateFromFile] Logged in.", sessionData.username, sessionData.key) + } + + + authenticate() { + try { + if (this._store.lastfm.auth_token) { + this._store.lastfm.enabled = true; + } + + if (!this._store.lastfm.enabled || !this._store.lastfm.auth_token) { + this._store.lastfm.enabled = false; + return + } + /// dont move this require to top , app wont load + const LastfmAPI = require('lastfmapi'); + const lfmAPI = new LastfmAPI({ + 'api_key': this.apiCredentials.key, + 'secret': this.apiCredentials.secret + }); + + this._lastfm = Object.assign(lfmAPI, {cachedAttributes: false, cachedNowPlayingAttributes: false}); + + fs.stat(this.sessionPath, (err: any) => { + if (err) { + console.error("[LastFM][Session] Session file couldn't be opened or doesn't exist,", err) + console.log("[LastFM][Auth] Beginning authentication from configuration") + console.log("[LastFM][tk]", this._store.lastfm.auth_token) + this._lastfm.authenticate(this._store.lastfm.auth_token, (err: any, session: any) => { + if (err) { + throw err; + } + console.log("[LastFM] Successfully obtained LastFM session info,", session); // {"name": "LASTFM_USERNAME", "key": "THE_USER_SESSION_KEY"} + console.log("[LastFM] Saving session info to disk.") + let tempData = JSON.stringify(session) + fs.writeFile(this.sessionPath, tempData, (err: any) => { + if (err) + console.log("[LastFM][fs]", err) + else { + console.log("[LastFM][fs] File was written successfully.") + this.authenticateFromFile() + new electron.Notification({ + title: electron.app.getName(), + body: "Successfully logged into LastFM using Authentication Key." + }).show() + } + }) + }); + } else { + this.authenticateFromFile() + } + }) + } catch (err) { + console.log(err) + } + } + + private async scrobbleSong(attributes: any) { + await new Promise(resolve => setTimeout(resolve, Math.round(attributes.durationInMillis * (this._store.lastfm.scrobble_after / 100)))); + const currentAttributes = attributes; + + if (!this._lastfm || this._lastfm.cachedAttributes === attributes) { + return + } + + if (this._lastfm.cachedAttributes) { + if (this._lastfm.cachedAttributes.playParams.id === attributes.playParams.id) return; + } + + if (currentAttributes.status && currentAttributes === attributes) { + if (fs.existsSync(this.sessionPath)) { + // Scrobble playing song. + if (attributes.status === true) { + this._lastfm.track.scrobble({ + 'artist': this.filterArtistName(attributes.artistName), + 'track': attributes.name, + 'album': attributes.albumName, + 'albumArtist': this.filterArtistName(attributes.artistName), + 'timestamp': new Date().getTime() / 1000 + }, function (err: any, scrobbled: any) { + if (err) { + return console.error('[LastFM] An error occurred while scrobbling', err); + } + + console.log('[LastFM] Successfully scrobbled: ', scrobbled); + }); + this._lastfm.cachedAttributes = attributes + } + } else { + this.authenticate(); + } + } else { + return console.log('[LastFM] Did not add ', attributes.name, '—', this.filterArtistName(attributes.artistName), 'because now playing a other song.'); + } + } + + private filterArtistName(artist: any) { + if (!this._store.lastfm.enabledRemoveFeaturingArtists) return artist; + + artist = artist.split(' '); + if (artist.includes('&')) { + artist.length = artist.indexOf('&'); + } + if (artist.includes('and')) { + artist.length = artist.indexOf('and'); + } + artist = artist.join(' '); + if (artist.includes(',')) { + artist = artist.split(',') + artist = artist[0] + } + return artist.charAt(0).toUpperCase() + artist.slice(1); + } + + private updateNowPlayingSong(attributes: any) { + if (!this._lastfm || this._lastfm.cachedNowPlayingAttributes === attributes || !this._store.lastfm.NowPlaying) { + return + } + + if (this._lastfm.cachedNowPlayingAttributes) { + if (this._lastfm.cachedNowPlayingAttributes.playParams.id === attributes.playParams.id) return; + } + + if (fs.existsSync(this.sessionPath)) { + // update Now Playing + if (attributes.status === true) { + this._lastfm.track.updateNowPlaying({ + 'artist': this.filterArtistName(attributes.artistName), + 'track': attributes.name, + 'album': attributes.albumName, + 'albumArtist': this.filterArtistName(attributes.artistName) + }, function (err: any, nowPlaying: any) { + if (err) { + return console.error('[LastFM] An error occurred while updating nowPlayingSong', err); + } + + console.log('[LastFM] Successfully updated nowPlayingSong', nowPlaying); + }); + this._lastfm.cachedNowPlayingAttributes = attributes + } + + } else { + this.authenticate() + } + } + + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'LastFMPlugin'; + public description: string = 'LastFM plugin for Cider'; + public version: string = '0.0.1'; + public author: string = 'vapormusic / Cider Collective'; + + /** + * Runs on plugin load (Currently run on application start) + */ + constructor(app: any, store: any) { + this._app = app; + this._store = store + electron.app.on('second-instance', (_e: any, argv: any) => { + // Checks if first instance is authorized and if second instance has protocol args + argv.forEach((value: any) => { + if (value.includes('auth')) { + console.log('[LastFMPlugin ok]') + let authURI = String(argv).split('/auth/')[1]; + if (authURI.startsWith('lastfm')) { // If we wanted more auth options + const authKey = authURI.split('lastfm?token=')[1]; + this._store.lastfm.enabled = true; + this._store.lastfm.auth_token = authKey; + console.log(authKey); + this._win.webContents.send('LastfmAuthenticated', authKey); + this.authenticate(); + } + } + }) + }) + electron.app.on('open-url', (event: any, arg: any) => { + console.log('[LastFMPlugin] yes') + event.preventDefault(); + if (arg.includes('auth')) { + let authURI = String(arg).split('/auth/')[1]; + if (authURI.startsWith('lastfm')) { // If we wanted more auth options + const authKey = authURI.split('lastfm?token=')[1]; + this._store.lastfm.enabled = true; + this._store.lastfm.auth_token = authKey; + this._win.webContents.send('LastfmAuthenticated', authKey); + console.log(authKey); + this.authenticate(); + } + } + }) + } + + /** + * Runs on app ready + */ + onReady(win: any): void { + this._win = win; + this.authenticate(); + } + + /** + * Runs on app stop + */ + onBeforeQuit(): void { + console.log('Example plugin stopped'); + } + + /** + * Runs on playback State Change + * @param attributes Music Attributes (attributes.state = current state) + */ + onPlaybackStateDidChange(attributes: object): void { + this.scrobbleSong(attributes) + this.updateNowPlayingSong(attributes) + } + + /** + * Runs on song change + * @param attributes Music Attributes + */ + onNowPlayingItemDidChange(attributes: object): void { + if (!this._store.lastfm.filterLoop){ + this._lastfm.cachedNowPlayingAttributes = false; + this._lastfm.cachedAttributes = false} + this.scrobbleSong(attributes) + this.updateNowPlayingSong(attributes) + } + +} \ No newline at end of file diff --git a/src/main/plugins/minimizeToTray.ts b/src/main/plugins/minimizeToTray.ts new file mode 100644 index 00000000..67bbc301 --- /dev/null +++ b/src/main/plugins/minimizeToTray.ts @@ -0,0 +1,162 @@ +import * as electron from 'electron'; +import * as path from 'path'; + + +export default class MinimizeToTray { + /** + * Private variables for interaction in plugins + */ + private _win: any; + private _app: any; + private _store: any; + private _tray: any; + private _forceQuit = false; + + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'Minimize to tray'; + public description: string = 'Allow Cider to minimize to tray'; + public version: string = '1.0.0'; + public author: string = 'vapormusic'; + + constructor(app: any, store: any) { + this._app = app; + this._store = store; + } + + private SetContextMenu(visibility : any) { + let self = this + if (visibility) { + this._tray.setContextMenu(electron.Menu.buildFromTemplate([ + // { + // label: 'Check for Updates', + // click: function () { + // app.ame.utils.checkForUpdates(true) + // } + // }, + { + label: 'Minimize to Tray', + click: function () { + if (typeof self._win.hide === 'function') { + self._win.hide(); + self.SetContextMenu(false); + } + } + }, + { + label: 'Quit', + click: function () { + self._forceQuit = true; self._app.quit(); + } + } + ])); + } else { + this._tray.setContextMenu(electron.Menu.buildFromTemplate([ + // { + // label: 'Check for Updates', + // click: function () { + // this._app.ame.utils.checkForUpdates(true) + // } + // }, + { + label: `Show ${electron.app.getName()}`, + click: function () { + if (typeof self._win.show === 'function') { + self._win.show(); + self.SetContextMenu(true); + } + } + }, + { + label: 'Quit', + click: function () { + self._forceQuit = true; self._app.quit(); + } + } + ])); + } + return true + + } + + /** + * Runs on app ready + */ + onReady(win: any): void { + this._win = win; + const winTray = electron.nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.ico`)).resize({ + width: 32, + height: 32 + }) + const macTray = electron.nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.png`)).resize({ + width: 20, + height: 20 + }) + const linuxTray = electron.nativeImage.createFromPath(path.join(__dirname, `../../resources/icons/icon.png`)).resize({ + width: 32, + height: 32 + }) + let trayIcon : any ; + if (process.platform === "win32") { + trayIcon = winTray + } else if (process.platform === "linux") { + trayIcon = linuxTray + } else if (process.platform === "darwin") { + trayIcon = macTray + } + + this._tray = new electron.Tray(trayIcon) + this._tray.setToolTip(this._app.getName()); + this.SetContextMenu(true); + + this._tray.on('double-click', () => { + if (typeof this._win.show === 'function') { + if (this._win.isVisible()) { + this._win.focus() + } else { + this._win.show() + } + } + }) + electron.ipcMain.on("minimizeTray", (event, value) => { + // listen for close event + this._win.hide(); + this.SetContextMenu(false); + }); + this._win.on("close", (e :any) => { + if (this._forceQuit || this._store.general["close_behavior"] == '0' ) { + this._app.quit(); + } else if (this._store.general["close_behavior"] == '1') { + e.preventDefault(); + this._win.minimize(); + } else { + e.preventDefault(); + this._win.hide(); + this.SetContextMenu(false); + } + }); + } + + /** + * Runs on app stop + */ + onBeforeQuit(): void { + + } + + /** + * Runs on playback State Change + * @param attributes Music Attributes (attributes.state = current state) + */ + onPlaybackStateDidChange(attributes: object): void { + } + + /** + * Runs on song change + * @param attributes Music Attributes + */ + onNowPlayingItemDidChange(attributes: object): void { + } + +} diff --git a/src/main/plugins/mpris.ts b/src/main/plugins/mpris.ts new file mode 100644 index 00000000..869cbceb --- /dev/null +++ b/src/main/plugins/mpris.ts @@ -0,0 +1,196 @@ +// @ts-ignore +import * as Player from 'mpris-service'; + +export default class MPRIS { + /** + * Private variables for interaction in plugins + */ + private _win: any; + private _app: any; + + /** + * Base Plugin Details (Eventually implemented into a GUI in settings) + */ + public name: string = 'MPRIS Service'; + public description: string = 'Handles MPRIS service calls for Linux systems.'; + public version: string = '1.0.0'; + public author: string = 'Core'; + + /** + * MPRIS Service + */ + private mpris: any; + private mprisEvents: Object = { + "playpause": "pausePlay", + "play": "pausePlay", + "pause": "pausePlay", + "next": "nextTrack", + "previous": "previousTrack", + } + + /******************************************************************************************* + * Private Methods + * ****************************************************************************************/ + + /** + * Runs a media event + * @param type - pausePlay, nextTrack, PreviousTrack + * @private + */ + private runMediaEvent(type: string) { + if (this._win) { + this._win.webContents.executeJavaScript(`MusicKitInterop.${type}()`).catch(console.error) + } + } + + /** + * Blocks non-linux systems from running this plugin + * @private + * @decorator + */ + private static linuxOnly(_target: any, _propertyKey: string, descriptor: PropertyDescriptor) { + if (process.platform !== 'linux') { + descriptor.value = function () { + return + } + } + } + + + /** + * Connects to MPRIS Service + */ + @MPRIS.linuxOnly + private connect() { + this.mpris = Player({ + name: 'Cider', + identity: 'Cider', + supportedUriSchemes: [], + supportedMimeTypes: [], + supportedInterfaces: ['player'] + }); + this.mpris = Object.assign(this.mpris, { + canQuit: true, + canControl: true, + canPause: true, + canPlay: true, + canGoNext: true, + active: true + }) + + + const pos_atr = {durationInMillis: 0}; + this.mpris.getPosition = function () { + const durationInMicro = pos_atr.durationInMillis * 1000; + const percentage = parseFloat("0") || 0; + return durationInMicro * percentage; + } + + for (const [key, value] of Object.entries(this.mprisEvents)) { + this.mpris.on(key, () => { + this.runMediaEvent(value) + }); + } + } + + /** + * Update MPRIS Player Attributes + */ + @MPRIS.linuxOnly + private updatePlayer(attributes: any) { + + const MetaData = { + 'mpris:trackid': this.mpris.objectPath(`track/${attributes.playParams.id.replace(/[.]+/g, "")}`), + 'mpris:length': attributes.durationInMillis * 1000, // In microseconds + 'mpris:artUrl': (attributes.artwork.url.replace('/{w}x{h}bb', '/512x512bb')).replace('/2000x2000bb', '/35x35bb'), + 'xesam:title': `${attributes.name}`, + 'xesam:album': `${attributes.albumName}`, + 'xesam:artist': [`${attributes.artistName}`,], + 'xesam:genre': attributes.genreNames + } + + if (this.mpris.metadata["mpris:trackid"] === MetaData["mpris:trackid"]) { + return + } + + this.mpris.metadata = MetaData + + } + + /** + * Update MPRIS Player State + * @private + * @param attributes + */ + @MPRIS.linuxOnly + private updatePlayerState(attributes: any) { + + let status = 'Stopped'; + if (attributes.status) { + status = 'Playing'; + } else if (attributes.status === false) { + status = 'Paused'; + } + + if (this.mpris.playbackStatus === status) { + return + } + this.mpris.playbackStatus = status; + } + + /** + * Clear state + * @private + */ + private clearState() { + this.mpris.metadata = {'mpris:trackid': '/org/mpris/MediaPlayer2/TrackList/NoTrack'} + this.mpris.playbackStatus = 'Stopped'; + } + + + /******************************************************************************************* + * Public Methods + * ****************************************************************************************/ + + /** + * Runs on plugin load (Currently run on application start) + */ + constructor(app: any, _store: any) { + this._app = app; + console.debug(`[Plugin][${this.name}] Loading Complete.`); + } + + /** + * Runs on app ready + */ + onReady(win: any): void { + this._win = win; + console.debug(`[Plugin][${this.name}] Ready.`); + this.connect() + } + + /** + * Runs on app stop + */ + onBeforeQuit(): void { + console.debug(`[Plugin][${this.name}] Stopped.`); + this.clearState() + } + + /** + * Runs on playback State Change + * @param attributes Music Attributes (attributes.state = current state) + */ + onPlaybackStateDidChange(attributes: object): void { + this.updatePlayerState(attributes) + } + + /** + * Runs on song change + * @param attributes Music Attributes + */ + onNowPlayingItemDidChange(attributes: object): void { + this.updatePlayer(attributes); + } + +} diff --git a/src/preload/cider-preload.js b/src/preload/cider-preload.js index 7d5296a6..0f55e657 100644 --- a/src/preload/cider-preload.js +++ b/src/preload/cider-preload.js @@ -1,102 +1,113 @@ -const electron = require('electron') - +global.ipcRenderer = require('electron').ipcRenderer; console.log('Loaded Preload') let cache = {playParams: {id: 0}, status: null, remainingTime: 0}, - playbackCache = {status: null, time: Date.now()}; + playbackCache = {status: null, time: Date.now()}; const MusicKitInterop = { - init: function () { - MusicKit.getInstance().addEventListener(MusicKit.Events.playbackStateDidChange, () => { - if (MusicKitInterop.filterTrack(MusicKitInterop.getAttributes(), true, false)) { - console.log("ayy"); - global.ipcRenderer.send('playbackStateDidChange', MusicKitInterop.getAttributes()) - // if (typeof _plugins != "undefined") { - // _plugins.execute("OnPlaybackStateChanged", {Attributes: MusicKitInterop.getAttributes()}) - // } - } - }); + init: function () { + MusicKit.getInstance().addEventListener(MusicKit.Events.playbackStateDidChange, () => { + if (MusicKitInterop.filterTrack(MusicKitInterop.getAttributes(), true, false)) { + global.ipcRenderer.send('playbackStateDidChange', MusicKitInterop.getAttributes()) + ipcRenderer.send('wsapi-updatePlaybackState', MusicKitInterop.getAttributes()); + // if (typeof _plugins != "undefined") { + // _plugins.execute("OnPlaybackStateChanged", {Attributes: MusicKitInterop.getAttributes()}) + // } + } + }); - MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, () => { - if (MusicKitInterop.filterTrack(MusicKitInterop.getAttributes(), false, true)) { - global.ipcRenderer.send('nowPlayingItemDidChange', MusicKitInterop.getAttributes()); - } - }); + /** wsapi */ + MusicKit.getInstance().addEventListener(MusicKit.Events.playbackProgressDidChange, () => { + ipcRenderer.send('wsapi-updatePlaybackState', MusicKitInterop.getAttributes()); + }); + /** wsapi */ - MusicKit.getInstance().addEventListener(MusicKit.Events.authorizationStatusDidChange, () => { - global.ipcRenderer.send('authorizationStatusDidChange', MusicKit.getInstance().authorizationStatus) - }) + MusicKit.getInstance().addEventListener(MusicKit.Events.nowPlayingItemDidChange, () => { + if (MusicKitInterop.filterTrack(MusicKitInterop.getAttributes(), false, true) || !app.cfg.lastfm.filterLoop) { + global.ipcRenderer.send('nowPlayingItemDidChange', MusicKitInterop.getAttributes()); + } + }); - MusicKit.getInstance().addEventListener(MusicKit.Events.mediaPlaybackError, (e) => { - console.warn(`[mediaPlaybackError] ${e}`); - }) - }, + MusicKit.getInstance().addEventListener(MusicKit.Events.authorizationStatusDidChange, () => { + global.ipcRenderer.send('authorizationStatusDidChange', MusicKit.getInstance().authorizationStatus) + }) - getAttributes: function () { - const nowPlayingItem = MusicKit.getInstance().nowPlayingItem; - const isPlayingExport = MusicKit.getInstance().isPlaying; - const remainingTimeExport = MusicKit.getInstance().currentPlaybackTimeRemaining; - const attributes = (nowPlayingItem != null ? nowPlayingItem.attributes : {}); + MusicKit.getInstance().addEventListener(MusicKit.Events.mediaPlaybackError, (e) => { + console.warn(`[mediaPlaybackError] ${e}`); + }) + }, - attributes.status = isPlayingExport ?? false; - attributes.name = attributes?.name ?? 'No Title Found'; - attributes.artwork = attributes?.artwork ?? { url: '' }; - attributes.artwork.url = attributes?.artwork?.url ?? ''; - attributes.playParams = attributes?.playParams ?? { id: 'no-id-found' }; - attributes.playParams.id = attributes?.playParams?.id ?? 'no-id-found'; - attributes.albumName = attributes?.albumName ?? ''; - attributes.artistName = attributes?.artistName ?? ''; - attributes.genreNames = attributes?.genreNames ?? []; - attributes.remainingTime = remainingTimeExport - ? remainingTimeExport * 1000 - : 0; - attributes.durationInMillis = attributes?.durationInMillis ?? 0; - attributes.startTime = Date.now(); - attributes.endTime = Math.round( - attributes?.playParams?.id === cache.playParams.id - ? Date.now() + attributes?.remainingTime - : attributes?.startTime + attributes?.durationInMillis - ); + getAttributes: function () { + const mk = MusicKit.getInstance() + const nowPlayingItem = mk.nowPlayingItem; + const isPlayingExport = mk.isPlaying; + const remainingTimeExport = mk.currentPlaybackTimeRemaining; + const attributes = (nowPlayingItem != null ? nowPlayingItem.attributes : {}); - return attributes; - }, + attributes.status = isPlayingExport ?? false; + attributes.name = attributes?.name ?? 'No Title Found'; + attributes.artwork = attributes?.artwork ?? {url: ''}; + attributes.artwork.url = (attributes?.artwork?.url ?? '').replace(`{f}`, "png"); + attributes.playParams = attributes?.playParams ?? {id: 'no-id-found'}; + attributes.playParams.id = attributes?.playParams?.id ?? 'no-id-found'; + attributes.url = { + cider: "cider://play/s/" + nowPlayingItem?._songId ?? 'no-id-found', + appleMusic: "https://music.apple.com/"+ mk.storefrontId +"/song/" + nowPlayingItem?._songId ?? 'no-id-found' + } + if (attributes.playParams.id === 'no-id-found') { + attributes.playParams.id = nowPlayingItem?.id ?? 'no-id-found'; + } + attributes.albumName = attributes?.albumName ?? ''; + attributes.artistName = attributes?.artistName ?? ''; + attributes.genreNames = attributes?.genreNames ?? []; + attributes.remainingTime = remainingTimeExport + ? remainingTimeExport * 1000 + : 0; + attributes.durationInMillis = attributes?.durationInMillis ?? 0; + attributes.startTime = Date.now(); + attributes.endTime = Math.round( + attributes?.playParams?.id === cache.playParams.id + ? Date.now() + attributes?.remainingTime + : attributes?.startTime + attributes?.durationInMillis + ); + return attributes; + }, - filterTrack: function (a, playbackCheck, mediaCheck) { - if (a.title === "No Title Found" || a.playParams.id === "no-id-found") { - return; - } else if (mediaCheck && a.playParams.id === cache.playParams.id) { - return; - } else if (playbackCheck && a.status === playbackCache.status) { - return; - } else if (playbackCheck && !a.status && a.remainingTime === playbackCache.time) { /* Pretty much have to do this to prevent multiple runs when a song starts playing */ - return; - } - cache = a; - if (playbackCheck) playbackCache = {status: a.status, time: a.remainingTime}; - return true; - }, + filterTrack: function (a, playbackCheck, mediaCheck) { + if (a.title === "No Title Found" || a.playParams.id === "no-id-found") { + return; + } else if (mediaCheck && a.playParams.id === cache.playParams.id) { + return; + } else if (playbackCheck && a.status === playbackCache.status) { + return; + } else if (playbackCheck && !a.status && a.remainingTime === playbackCache.time) { /* Pretty much have to do this to prevent multiple runs when a song starts playing */ + return; + } + cache = a; + if (playbackCheck) playbackCache = {status: a.status, time: a.remainingTime}; + return true; + }, - pausePlay: function () { - if (MusicKit.getInstance().isPlaying) { - MusicKit.getInstance().pause(); - } else if (MusicKit.getInstance().nowPlayingItem != null) { - MusicKit.getInstance().play().then(r => console.log(`[MusicKitInterop] Playing ${r}`)); - } - }, + pausePlay: function () { + if (MusicKit.getInstance().isPlaying) { + MusicKit.getInstance().pause(); + } else if (MusicKit.getInstance().nowPlayingItem != null) { + MusicKit.getInstance().play().then(r => console.log(`[MusicKitInterop] Playing ${r}`)); + } + }, - nextTrack: function () { - MusicKit.getInstance().skipToNextItem().then(r => console.log(`[MusicKitInterop] Skipping to Next ${r}`)); - }, + nextTrack: function () { + MusicKit.getInstance().skipToNextItem().then(r => console.log(`[MusicKitInterop] Skipping to Next ${r}`)); + }, - previousTrack: function () { - MusicKit.getInstance().skipToPreviousItem().then(r => console.log(`[MusicKitInterop] Skipping to Previous ${r}`)); - } + previousTrack: function () { + MusicKit.getInstance().skipToPreviousItem().then(r => console.log(`[MusicKitInterop] Skipping to Previous ${r}`)); + } } process.once('loaded', () => { - console.log("Setting ipcRenderer") - global.ipcRenderer = electron.ipcRenderer; - global.MusicKitInterop = MusicKitInterop; -}); \ No newline at end of file + console.log("Setting ipcRenderer") + global.MusicKitInterop = MusicKitInterop; +}); diff --git a/src/renderer/.jsbeautifyrc b/src/renderer/.jsbeautifyrc new file mode 100644 index 00000000..bde13199 --- /dev/null +++ b/src/renderer/.jsbeautifyrc @@ -0,0 +1,5 @@ +{ + "js": { + "beautify.ignore": "src/renderer/index.js" + } +} \ No newline at end of file diff --git a/src/renderer/AppHeader.svg b/src/renderer/AppHeader.svg new file mode 100644 index 00000000..d6a7b723 --- /dev/null +++ b/src/renderer/AppHeader.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/renderer/ameframework.css b/src/renderer/ameframework.css index 7da9b6a2..38c56508 100644 --- a/src/renderer/ameframework.css +++ b/src/renderer/ameframework.css @@ -27,6 +27,7 @@ .md-option-segment.md-option-segment_auto { width: auto; + white-space: nowrap; } .md-option-container .md-option-line:not(:last-child) { diff --git a/src/renderer/apple-hls.js b/src/renderer/apple-hls.js index 1f920850..854c4bc8 100644 --- a/src/renderer/apple-hls.js +++ b/src/renderer/apple-hls.js @@ -5,7 +5,7 @@ e = this, t = function() { "use strict"; - var P, e = e=>e && e.Math === Math && e, d = e("object" == typeof globalThis && globalThis) || e("object" == typeof window && window) || e("object" == typeof jy && jy) || e("object" == typeof global && global) || Function("return this")(); + var x, e = e=>e && e.Math === Math && e, d = e("object" == typeof globalThis && globalThis) || e("object" == typeof window && window) || e("object" == typeof jy && jy) || e("object" == typeof global && global) || Function("return this")(); class l { constructor() { this.keySize = null, @@ -211,7 +211,7 @@ e.register("decrypt", this.decrypt) } } - (gr = P = P || {}).MEDIA_ATTACHING = "hlsMediaAttaching", + (gr = x = x || {}).MEDIA_ATTACHING = "hlsMediaAttaching", gr.MEDIA_ATTACHED = "hlsMediaAttached", gr.MEDIA_DETACHING = "hlsMediaDetaching", gr.MEDIA_DETACHED = "hlsMediaDetached", @@ -259,7 +259,7 @@ gr.ITEM_TRANSITIONED = "hlsItemTransitioned", gr.ITEM_EVICTED = "hlsItemEvicted", gr.DATERANGE_UPDATED = "hlsDaterangeUpdated"; - var v, x = P; + var v, P = x; (dd = v = v || {}).FRAG_PARSING_INIT_SEGMENT = "hlsFragParsingInitSegment", dd.FRAG_PARSING_DATA = "hlsFragParsingData", dd.FRAG_PARSED = "hlsFragParsed", @@ -738,7 +738,7 @@ }; { const t = new D(!0,`invalid ADTS sampling index:${c}`,$.InvalidADTSSamplingIndex); - e.trigger(x.INTERNAL_ERROR, t) + e.trigger(P.INTERNAL_ERROR, t) } } class u { @@ -1201,14 +1201,14 @@ let n; if (i + 8 > t.length) return n = new D(!0,"error parsing ac-3, not enough data",$.InsufficientAC3Data), - void e.trigger(x.INTERNAL_ERROR, n); + void e.trigger(P.INTERNAL_ERROR, n); if (11 !== t[i] || 119 !== t[i + 1]) return n = new D(!0,"invalid ac-3 magic",$.InvalidAC3Magic), - void e.trigger(x.INTERNAL_ERROR, n); + void e.trigger(P.INTERNAL_ERROR, n); var s = t[i + 4] >> 6; if (3 <= s) return n = new D(!0,`invalid ac-3 samplingRateCode:${s}`,$.InvalidAC3SamplingRateCode), - void e.trigger(x.INTERNAL_ERROR, n); + void e.trigger(P.INTERNAL_ERROR, n); var a = 63 & t[i + 4] , o = t[i + 6] >> 5; let d = 0; @@ -1230,13 +1230,13 @@ let r; if (i + 8 > t.length) return r = new D(!0,"error parsing ac-3, not enough data",$.InsufficientAC3Data), - void e.trigger(x.INTERNAL_ERROR, r); + void e.trigger(P.INTERNAL_ERROR, r); if (11 !== t[i] || 119 !== t[i + 1]) return r = new D(!0,"invalid ac-3 magic",$.InvalidAC3Magic), - void e.trigger(x.INTERNAL_ERROR, r); + void e.trigger(P.INTERNAL_ERROR, r); var n = t[i + 4] >> 6; return 3 <= n ? (r = new D(!0,`invalid ac-3 samplingRateCode:${n}`,$.InvalidAC3SamplingRateCode), - void e.trigger(x.INTERNAL_ERROR, r)) : (i = 63 & t[i + 4], + void e.trigger(P.INTERNAL_ERROR, r)) : (i = 63 & t[i + 4], 2 * W[3 * i + n]) } const G = [48e3, 44100, 32e3] @@ -1290,7 +1290,7 @@ if (M.isHeader(e, l) && (l += new M(e.subarray(l),this.logger).length), 11 !== e[l] || 119 !== e[l + 1]) { const e = new D(!0,"invalid ac-3 magic",$.InvalidAC3Magic); - return void this.observer.trigger(x.INTERNAL_ERROR, e) + return void this.observer.trigger(P.INTERNAL_ERROR, e) } const t = Q(this.observer, e, l) , i = a + d * u @@ -1322,13 +1322,13 @@ for (; r < i.length; ) { if (r + 8 > i.length) return a = new D(!0,"error parsing ec-3, not enough data",$.InsufficientEC3Data), - void t.trigger(x.INTERNAL_ERROR, a); + void t.trigger(P.INTERNAL_ERROR, a); let e = 0; if (M.isHeader(i, r) && (e = new M(i.subarray(r),n).length || 0, r += e), 11 !== i[r] || 119 !== i[r + 1]) return a = new D(!0,"invalid ec-3 magic",$.InvalidEC3Magic), - void t.trigger(x.INTERNAL_ERROR, a); + void t.trigger(P.INTERNAL_ERROR, a); var l = { byteOffset: r + 2, usedBits: 0 @@ -1343,7 +1343,7 @@ o = !0; else if (1 !== u) return a = new D(!0,"reserved stream type",$.ReservedStreamType), - void t.trigger(x.INTERNAL_ERROR, a); + void t.trigger(P.INTERNAL_ERROR, a); l = 2 * (s.bsReadAndUpdate(i, l, 11) + 1); r += l, d += l + (e || 0) @@ -1383,13 +1383,13 @@ for (; r < i.length; ) { if (r + 8 > i.length) return d = new D(!0,"error parsing ec-3, not enough data",$.InsufficientEC3Data), - void t.trigger(x.INTERNAL_ERROR, d); + void t.trigger(P.INTERNAL_ERROR, d); let e = 0; if (M.isHeader(i, r) && (e = new M(i.subarray(r),n).length || 0, r += e), 11 !== i[r] || 119 !== i[r + 1]) return d = new D(!0,"invalid ec-3 magic",$.InvalidEC3Magic), - void t.trigger(x.INTERNAL_ERROR, d); + void t.trigger(P.INTERNAL_ERROR, d); const h = { byteOffset: r + 2, usedBits: 0 @@ -1407,7 +1407,7 @@ } else { if (1 !== s.strmtyp) return d = new D(!0,"reserved stream type",$.ReservedStreamType), - void t.trigger(x.INTERNAL_ERROR, d); + void t.trigger(P.INTERNAL_ERROR, d); a.num_dep_sub[a.num_ind_sub - 1]++ } if (s.frmsiz = o.bsReadAndUpdate(i, h, 11), @@ -2647,7 +2647,7 @@ this._initDTS = n; else { const e = new D(!1,"invalid initPTS or initDTS",$.InvalidInitTimestamp); - this.observer.trigger(x.INTERNAL_ERROR, e) + this.observer.trigger(P.INTERNAL_ERROR, e) } } } @@ -2696,7 +2696,7 @@ this.observer.trigger(v.FRAG_PARSING_INIT_SEGMENT, e) } else { const e = new D(!1,"no audio/video samples found",$.NoAVSamplesFound); - this.observer.trigger(x.INTERNAL_ERROR, e) + this.observer.trigger(P.INTERNAL_ERROR, e) } } remuxVideo(n, e, s, a, o) { @@ -2768,7 +2768,7 @@ l = new Uint8Array(e) } catch (n) { const M = new F(!1,`fail allocating video mdat ${e}`,$.FailedToAllocateVideoMdat,e); - return void this.observer.trigger(x.INTERNAL_ERROR, M) + return void this.observer.trigger(P.INTERNAL_ERROR, M) } const C = new DataView(l.buffer); C.setUint32(0, e), @@ -2811,8 +2811,8 @@ const n = s.maxBufferHole , l = s.maxSeekHole , c = Math.floor(Math.min(n, l) * m) - , x = (a ? u + a * m : this.nextAudioPts) - M.pts; - x > c ? (d = x - o, + , P = (a ? u + a * m : this.nextAudioPts) - M.pts; + P > c ? (d = P - o, d < 0 && (d = o)) : d = o } else d = o @@ -2953,7 +2953,7 @@ g = new Uint8Array(i) } catch (r) { const n = new F(!1,`fail allocating audio mdat ${i}`,$.FailedToAllocateAudioMdat,i); - return void this.observer.trigger(x.INTERNAL_ERROR, n) + return void this.observer.trigger(P.INTERNAL_ERROR, n) } l || (h = new DataView(g.buffer), h.setUint32(0, i), @@ -3400,11 +3400,11 @@ } function Pe(i, r, n) { return function() { - try{const e = new Array(1 + arguments.length); + try{ const e = new Array(1 + arguments.length); e[0] = r; for (var t = 1; t < e.length; t++) e[t] = arguments[t - 1]; - return i[n].apply(this, e) } catch(e){} + return i[n].apply(this, e) } catch (e){} } } function xe(e) { @@ -5039,7 +5039,7 @@ o = 0; o < O; o += 188) { if (71 !== e[o]) { const e = new D(!1,"TS packet did not start with 0x47",$.NoTSSyncByteFound); - return void this.observer.trigger(x.INTERNAL_ERROR, e) + return void this.observer.trigger(P.INTERNAL_ERROR, e) } if (d = !!(64 & e[o + 1]), l = ((31 & e[o + 1]) << 8) + e[o + 2], @@ -5534,7 +5534,7 @@ $.NoADTSHeaderInPES), this.logger.warn(tt, `parsing error:${e}`); const r = new D(t,e,i); - if (this.observer.trigger(x.INTERNAL_ERROR, r), + if (this.observer.trigger(P.INTERNAL_ERROR, r), t) return } @@ -5607,7 +5607,7 @@ for (; a + u <= l; ) { if (11 !== i[a] || 119 !== i[a + 1]) { const c = new D(!0,"invalid dolby audio magic",$.InvalidDolbyAudioMagic); - return void this.observer.trigger(x.INTERNAL_ERROR, c) + return void this.observer.trigger(P.INTERNAL_ERROR, c) } "ac3" === t.segmentCodec ? u = Q(this.observer, i, a) : "ec3" === t.segmentCodec && (u = X(this.observer, i, a, this.logger)); const c = r + s * d; @@ -5680,7 +5680,7 @@ } if (!e) { const t = new D(!0,"no demux matching with content found",$.DemuxerNotFound); - return void this.trigger(x.INTERNAL_ERROR, t) + return void this.trigger(P.INTERNAL_ERROR, t) } this.demuxer = e } @@ -5710,7 +5710,7 @@ this.init = (t,n,s)=>e=>{ const i = st() , r = this.demuxers[i] = new nt(t,n,s,this.logger); - [v.INIT_PTS_FOUND, v.FRAG_PARSING_INIT_SEGMENT, v.FRAG_PARSING_DATA, v.FRAG_PARSED, x.INTERNAL_ERROR].forEach(t=>{ + [v.INIT_PTS_FOUND, v.FRAG_PARSING_INIT_SEGMENT, v.FRAG_PARSING_DATA, v.FRAG_PARSED, P.INTERNAL_ERROR].forEach(t=>{ r.on(t, e=>this.rpc.invoke("demuxer.event", [i, t, e])(()=>{} )) } @@ -11740,6 +11740,7 @@ vttConcurrentLoadCount: 1, trottleCheckInterval: 2e3, subtitleLeadTime: 30, + lateTolerance: 2, stretchShortVideoTrack: !1, forceKeyFrameOnDiscontinuity: !0, useFirstLevelAtIncompatDiscontinuity: !0, @@ -14336,7 +14337,7 @@ var t = e.decryptdata , i = t.uri , e = e.setKeyRequestState($c.GET_REQUEST_INFO); - return this.eventEmitter.trigger(x.KEY_REQUEST_STARTED, { + return this.eventEmitter.trigger(P.KEY_REQUEST_STARTED, { keyuri: i, decryptdata: t, timestamp: Date.now() @@ -14665,7 +14666,7 @@ getKeyRequestResponse(e, t) { var i = e.decryptdata.uri , e = e.setKeyRequestState($c.GET_KEY_RESPONSE); - return this.eventEmitter.trigger(x.LICENSE_CHALLENGE_CREATED, { + return this.eventEmitter.trigger(P.LICENSE_CHALLENGE_CREATED, { keyuri: i, licenseChallenge: t, keysystem: this.systemString @@ -14868,7 +14869,7 @@ n.pos, t[ah.SessionLifespanSPC] = n.data } - this.eventEmitter.trigger(x.LICENSE_RELEASED, { + this.eventEmitter.trigger(P.LICENSE_RELEASED, { keysystem: this.systemString, itemId: this.itemId, releaseRecord: t @@ -15034,7 +15035,7 @@ getKeyRequestResponse(e, t) { var i = e.decryptdata.uri , r = e.setKeyRequestState($c.GET_KEY_RESPONSE); - return this.eventEmitter.trigger(x.LICENSE_CHALLENGE_CREATED, { + return this.eventEmitter.trigger(P.LICENSE_CHALLENGE_CREATED, { keyuri: i, licenseChallenge: t, keysystem: this.systemString, @@ -15146,7 +15147,7 @@ getKeyRequestResponse(e, t) { var i = e.decryptdata.uri , r = e.setKeyRequestState($c.GET_KEY_RESPONSE); - return this.eventEmitter.trigger(x.LICENSE_CHALLENGE_CREATED, { + return this.eventEmitter.trigger(P.LICENSE_CHALLENGE_CREATED, { keyuri: i, licenseChallenge: t, keysystem: this.systemString, @@ -15476,7 +15477,7 @@ certificate: new Uint8Array(e) })))), e && e.pipe(Ra(e=>this.onServerCertificateLoaded(e)), Un(e=>{ - throw this.eventEmitter.trigger(x.INTERNAL_ERROR, { + throw this.eventEmitter.trigger(P.INTERNAL_ERROR, { type: o, details: "certificateLoadError", fatal: !1, @@ -15565,7 +15566,7 @@ i = this.keyUriToRequest[s] = e.pipe(ur(e=>{ var t = e.decryptdata; return this.ksService.updateKeyValue(s, t.key), - this.eventEmitter.trigger(x.KEY_LOADED, e), + this.eventEmitter.trigger(P.KEY_LOADED, e), e.decryptdata } ), Un(e=>{ @@ -15639,7 +15640,7 @@ } handleKeySystemError(e) { e = new cu(e.message,void 0,void 0,$.KeySystemSetupError,void 0); - this.eventEmitter.trigger(x.INTERNAL_ERROR, e) + this.eventEmitter.trigger(P.INTERNAL_ERROR, e) } } class Ch extends Od { @@ -18085,7 +18086,7 @@ constructor(e, t, i, r) { super(e=>{ const t = wc(this.hls, this); - if (e.add(t.event(x.INLINE_STYLES_PARSED, this.onInlineStylesParsed).pipe($s(()=>this.destroy())).subscribe()), + if (e.add(t.event(P.INLINE_STYLES_PARSED, this.onInlineStylesParsed).pipe($s(()=>this.destroy())).subscribe()), e.add(vn(0, this.config.trottleCheckInterval).pipe(Ra(()=>(this.checkReadyToLoadNextSubtitleFragment(), Ul))).subscribe()), this.mediaSink.textTracks && "onchange"in this.mediaSink.textTracks) { @@ -18142,9 +18143,9 @@ this.mediaSink.mediaQuery.currentTime >= this.lastCueEndTime - this.config.subtitleLeadTime && (e = !0), this.needNextSubtitle$.next(e) } - checkReadyToLoadNextSubtitleFragment$() { - return this.checkReadyToLoadNextSubtitleFragment(), - this.needNextSubtitle$ + checkReadyToLoadNextSubtitleFragment$(e, t) { + return e.mediaSeqNum === (null === (t = t[0]) || void 0 === t ? void 0 : t.mediaSeqNum) ? Bi(!0) : (this.checkReadyToLoadNextSubtitleFragment(), + this.needNextSubtitle$) } getNextFragment(e, t) { t = t.mediaSeqNum + 1; @@ -18228,13 +18229,9 @@ ; d = e - i + 1 <= this.config.earlyFragTolerance } else if (s.startTime > o && n.mediaSeqNum !== r.startSN) { - const l = t.prevFragSN; - if (n.mediaSeqNum === l + 1 && (null === (t = t.fragInfoMap[l]) || void 0 === t ? void 0 : t.count) === (null === (a = a[l]) || void 0 === a ? void 0 : a.count)) - d = !0; - else { - const l = r.fragments[n.mediaSeqNum - r.startSN - 1]; - d = s.startTime - o < l.duration - } + const l = s.startTime - o + , i = t.prevFragSN; + d = n.mediaSeqNum === i + 1 && (null === (t = t.fragInfoMap[i]) || void 0 === t ? void 0 : t.count) === (null === (a = a[i]) || void 0 === a ? void 0 : a.count) || l <= this.config.lateTolerance } } return d ? Ap.CloseEnough : Ap.TooFar @@ -18251,54 +18248,62 @@ r = e.fragments[r]; return r && r.discoSeqNum === t.discoSeqNum && !i[t.mediaSeqNum] ? r : t } - inferSubtitleFragmentForPosition(i, r, t, e, n) { - let s, a, o, d, l; - if (ne(e.prevFragSN) && (a = e.prevFragSN - n.startSN, - o = t[e.prevFragSN]), - ne(e.nextFragSN) && (d = e.nextFragSN - n.startSN, - l = t[e.nextFragSN]), - ne(a) && 0 <= a && a < n.fragments.length && o) { - let t = o.startTime; - for (let e = a; e < n.fragments.length; ++e) { - const o = n.fragments[e]; + inferSubtitleFragmentForPosition(i, r, t, n, s) { + let a, o, e, d, l; + if (ne(n.prevFragSN) && (o = n.prevFragSN - s.startSN, + e = t[n.prevFragSN]), + ne(n.nextFragSN) && (d = n.nextFragSN - s.startSN, + l = t[n.nextFragSN]), + ne(o) && 0 <= o && o < s.fragments.length && e) { + let t = e.startTime; + const n = ne(d) ? d : s.fragments.length; + for (let e = o; e < n; ++e) { + const d = s.fragments[e]; + if (!ne(r) || d.discoSeqNum === r) { + if (e === n - 1) { + a = { + foundFrag: d, + timelineEstablished: !0 + }; + break + } + if (t + d.duration > i && e > o) { + a = { + foundFrag: d, + timelineEstablished: !0 + }; + break + } + t += d.duration + } + } + } else if (ne(d) && 0 <= d && d < s.fragments.length && l) { + let t = l.startTime; + for (let e = d - 1; 0 <= e; --e) { + const o = s.fragments[e]; if (!ne(r) || o.discoSeqNum === r) { - if (t + o.duration > i && e > a) { - s = { + if (t <= i) { + a = { foundFrag: o, timelineEstablished: !0 }; break } - t += o.duration - } - } - } else if (ne(d) && 0 <= d && d < n.fragments.length && l) { - let t = l.startTime; - for (let e = d - 1; 0 <= e; --e) { - const a = n.fragments[e]; - if (!ne(r) || a.discoSeqNum === r) { - if (t <= i) { - s = { - foundFrag: a, - timelineEstablished: !0 - }; - break - } - t -= a.duration + t -= o.duration } } } else - for (let e = 0; e < n.fragments.length; ++e) { - const t = n.fragments[e]; + for (let e = 0; e < s.fragments.length; ++e) { + const t = s.fragments[e]; if (ne(r) && t.discoSeqNum === r) { - s = { + a = { foundFrag: t, timelineEstablished: !1 }; break } } - return s + return a } generateFragmentBatch(t, i, e, r, n, s) { var a; @@ -18595,7 +18600,7 @@ } , e=>{} , e=>{ - this.hls.trigger(x.INLINE_STYLES_PARSED, { + this.hls.trigger(P.INLINE_STYLES_PARSED, { styles: e }) } @@ -19905,11 +19910,11 @@ } } class hf extends Ut { - constructor(w, A, e, t, i, r) { + constructor(w, A, e, t, i, r, n) { super(e=>{ const t = this.config , i = A.startMediaSession(w, t.maxBufferLength, t.almostDryBufferSec, t.defaultTargetDuration) - , r = Bi(w).pipe(pf(A, this._mediaQuery, this, this.hlsGapless, t, this.logger)) + , r = Bi(w).pipe(pf(A, this._mediaQuery, this, this.hlsGapless, t, this.logger, this.rtcService)) , n = this.mediaSource$.pipe(Ra(e=>e || Ti)) , s = this._mediaQuery.seekTo$.pipe((u = w, c = this._mediaQuery, @@ -20002,6 +20007,7 @@ this.hlsGapless = t, this.logger = i, this.teardownWorker = r, + this.rtcService = n, this.mediaSource$ = new gi(null), this._mediaQuery = new Yp(w,A), this.logger = i.child({ @@ -20637,7 +20643,7 @@ this.mediaSource$.value.clearLiveSeekableRange() } } - const pf = (r,n,s,a,o,d)=>e=>e.pipe(Ra(t=>{ + const pf = (r,n,s,a,o,d,i)=>e=>e.pipe(Ra(t=>{ if (!t) return Ti; const e = wc(t); @@ -20698,8 +20704,8 @@ r.readyState = e, r.ended = t.ended } - ), Un(e=>e instanceof MediaError ? (d.warn(`mediaElementError, code: ${e.code}, message: ${e.message}`), - Ui(e)) : (d.error(`media event error: ${e.message}`), + ), Un(e=>(e instanceof MediaError ? (d.warn(`mediaElementError, code: ${e.code}, message: ${e.message}`), + null == i || i.handleMediaElementError(e)) : d.error(`media event error: ${e.message}`), Ti))) } ), Ra(()=>Ti)); @@ -21325,7132 +21331,22 @@ t.warn(e) } return Of(t) - } - , Df = a=>(e,t)=>{ - let i = 0 - , r = 0; - for (var {timestamp: n, value: s} of e) { - const e = Math.pow(Math.max(0, n - t) / 1e3, a); - i += e * s, - r += e - } - return i / r - } - , Mf = { - "uniform-time-weighted": Df(0), - "linear-time-weighted": Df(1), - "quadratic-time-weighted": Df(2) - }; - class Pf { - constructor(e, t="quadratic-time-weighted", i={ - avgLatencyMs: NaN, - avgBandwidth: NaN - }) { - this.windowSize = e, - this.aggregationMethod = t, - this.latencyEntries = [], - this.bandwidthEntries = [], - this.minEntries = 1, - this.cleanUpExpiredEntries = this.cleanUpExpiredEntries.bind(this), - this.bwSubject = new gi(i) - } - get estimate$() { - return this.bwSubject.asObservable() - } - record(e) { - var {trequest: t, tfirst: i, tload: r, bitsDownloaded: e} = e; - t !== r && (this.recordLatency(t, i), - this.recordBandwidth(t, r, 1e3 * e / (r - t)), - this.bwSubject.closed || (t = this.getEstimate(), - this.bwSubject.next(t))) - } - getEstimate() { - if (this.latencyEntries.length < this.minEntries) - return { - avgLatencyMs: NaN, - avgBandwidth: NaN - }; - const e = performance.now() - this.windowSize - , t = Mf[this.aggregationMethod] - , i = this.latencyEntries.map(({start: e, end: t})=>({ - timestamp: t, - value: t - e, - duration: 1 - })); - this.bandwidthEntries = function(r) { - function n(t, i) { - if (t.length) { - for (let e = 0; e < t.length; e++) - if (t[e].start > i.start || t[e].start === i.start && t[e].end > i.end) { - t.splice(e, 0, i); - break - } - } else - t.push(i) - } - const s = [...r].sort((e,t)=>e.start !== t.start ? e.start - t.start : e.end - t.end) - , t = []; - for (; s.length; ) { - const r = s[0]; - let e; - if (s.shift(), - t.length && (e = t[t.length - 1]), - 0 === t.length || e.end <= r.start) - t.push(r); - else if (r.start === e.start) - r.end === e.end ? e.bitsPerSec += r.bitsPerSec : r.end < e.end || (e.bitsPerSec += r.bitsPerSec, - r.start = e.end, - n(s, r)); - else { - var a = e.end - , o = e.bitsPerSec; - e.end = r.start; - var i = { - start: r.start, - end: Math.min(a, r.end), - bitsPerSec: r.bitsPerSec + o - }; - if (t.push(i), - a !== r.end) { - let e = 0 - , t = 0 - , i = 0; - i = a < r.end ? (e = a, - t = r.end, - r.bitsPerSec) : (e = r.end, - t = a, - o), - n(s, { - start: e, - end: t, - bitsPerSec: i - }) - } - } - } - return t - }(this.bandwidthEntries); - var r = this.bandwidthEntries.map(({end: e, bitsPerSec: t})=>({ - timestamp: e, - duration: 1, - value: t - })); - return { - avgLatencyMs: t(i, e), - avgBandwidth: t(r, e) - } - } - getLatest() { - if (0 === this.latencyEntries.length) - return { - avgLatencyMs: NaN, - avgBandwidth: NaN - }; - var e = this.latencyEntries[this.latencyEntries.length - 1] - , t = this.bandwidthEntries[this.bandwidthEntries.length - 1]; - return { - avgLatencyMs: e.end - e.start, - avgBandwidth: t.bitsPerSec - } - } - recordLatency(e, t) { - this.latencyEntries.push({ - start: e, - end: t - }), - this.updateCleanupTimeout(t) - } - recordBandwidth(e, t, i) { - this.bandwidthEntries.push({ - start: e, - end: t, - bitsPerSec: i - }), - this.updateCleanupTimeout(t) - } - setCleanupTimeout(e) { - this.cleanupTimeout = setTimeout(this.cleanUpExpiredEntries, Math.max(e - performance.now(), 0)), - this.cleanupTimestamp = e - } - clearCleanupTimeout() { - void 0 !== this.cleanupTimeout && (clearTimeout(this.cleanupTimeout), - this.cleanupTimeout = void 0), - this.cleanupTimestamp = void 0 - } - updateCleanupTimeout(e) { - e += this.windowSize; - (!this.cleanupTimestamp || e < this.cleanupTimestamp) && (this.clearCleanupTimeout(), - this.setCleanupTimeout(e)) - } - cleanUpExpiredEntries() { - this.clearCleanupTimeout(); - const t = performance.now() - this.windowSize; - if (this.latencyEntries = this.latencyEntries.filter(e=>e.end >= t), - this.bandwidthEntries = this.bandwidthEntries.filter(e=>e.end >= t), - this.bwSubject.closed || this.bwSubject.next(this.getEstimate()), - 0 < this.latencyEntries.length || 0 < this.bandwidthEntries.length) { - const t = Math.min(...this.latencyEntries.map(e=>e.end), ...this.bandwidthEntries.map(e=>e.end)); - this.updateCleanupTimeout(t) - } - } - destroy() { - this.clearCleanupTimeout() - } - } - const xf = { - setCombinedEstimate: function(t, i, r) { - const n = qe(); - if (void 0 !== t.storage.set) { - var s = t.bandwidthHistoryStorageKey - , a = { - avgLatencyMs: i.avgLatencyMs, - avgBandwidth: i.avgBandwidth - } - , a = Object.assign({}, a, { - expires: Date.now() + t.bandwidthHistoryTTL - }); - try { - t.storage.set(s, JSON.stringify(a)) - } catch (t) { - n.warn(`Error stringifying! Not persisting bandwidth estimates: ${t.message}`) - } - i = { - maxDuration: i.maxDurationSec, - avgFragParseTimeMs: i.avgParseTimeMs, - avgFragBufferCreationDelayMs: i.avgBufferCreateMs, - avgPlaylistLoadTimeMs: i.avgPlaylistLoadTimeMs, - avgPlaylistParseTimeMs: i.avgPlaylistParseTimeMs, - avgInitFragAppendMs: i.avgInitFragAppendMs, - avgDataFragAppendMs: i.avgDataFragAppendMs - }; - let e = t.storageKeyPrefix; - r && (e += r); - try { - t.storage.set(e, JSON.stringify(i)) - } catch (t) { - n.warn(`Error stringifying! Not persisting bandwidth estimates: ${t.message}`) - } - } else - n.warn("storage.set is not supported! Not persisting bandwidth estimates") - }, - getCombinedEstimate: function(t, e) { - const i = qe(); - let r = {}; - if (void 0 === t.storage.get) - return i.warn("storage.get is not supported! unable to retreive bandwidth estimates"), - this.convertStorageJsonToCombinedEstimate(r); - try { - let e = JSON.parse(t.storage.get(t.bandwidthHistoryStorageKey)); - e = null != e && e.expires && e.expires < Date.now() ? null : { - avgLatencyMs: null == e ? void 0 : e.avgLatencyMs, - avgBandwidth: null == e ? void 0 : e.avgBandwidth - }, - r = Object.assign(Object.assign({}, r), e) - } catch (t) { - i.warn(`Unable to get persisted bandwidth history: ${t.message}`) - } - let n = t.storageKeyPrefix; - e && (n += e); - try { - const e = JSON.parse(t.storage.get(n)); - r = Object.assign(Object.assign({}, r), e) - } catch (t) { - i.warn(`Unable to get persisted bandwidth history: ${t.message}`) - } - return this.convertStorageJsonToCombinedEstimate(r) - }, - convertStorageJsonToCombinedEstimate: function(e) { - return { - avgLatencyMs: (null == e ? void 0 : e.avgLatencyMs) || NaN, - avgBandwidth: (null == e ? void 0 : e.avgBandwidth) || NaN, - maxDurationSec: (null == e ? void 0 : e.maxDuration) || NaN, - avgParseTimeMs: (null == e ? void 0 : e.avgFragParseTimeMs) || NaN, - avgBufferCreateMs: (null == e ? void 0 : e.avgFragBufferCreationDelayMs) || NaN, - avgPlaylistLoadTimeMs: (null == e ? void 0 : e.avgPlaylistLoadTimeMs) || NaN, - avgPlaylistParseTimeMs: (null == e ? void 0 : e.avgPlaylistParseTimeMs) || NaN, - avgInitFragAppendMs: (null == e ? void 0 : e.avgInitFragAppendMs) || NaN, - avgDataFragAppendMs: (null == e ? void 0 : e.avgDataFragAppendMs) || NaN - } - }, - getBandwidthEstimate: function(e, t) { - const i = this.getCombinedEstimate(e, t) - , r = { - avgLatencyMs: null == i ? void 0 : i.avgLatencyMs, - avgBandwidth: null == i ? void 0 : i.avgBandwidth - }; - return ne(r.avgLatencyMs) || (r.avgLatencyMs = NaN), - ne(r.avgBandwidth) || (r.avgBandwidth = NaN), - r - }, - getPlaylistEstimate: function(e, t) { - const i = this.getCombinedEstimate(e, t) - , r = { - avgPlaylistLoadTimeMs: null == i ? void 0 : i.avgPlaylistLoadTimeMs, - avgPlaylistParseTimeMs: null == i ? void 0 : i.avgPlaylistParseTimeMs - }; - return ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = NaN), - ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = NaN), - r - }, - getFragEstimate: function(e, t) { - const i = this.getCombinedEstimate(e, t) - , r = { - maxDurationSec: null == i ? void 0 : i.maxDurationSec, - avgParseTimeMs: null == i ? void 0 : i.avgParseTimeMs - }; - return ne(r.maxDurationSec) || (r.maxDurationSec = NaN), - ne(r.avgParseTimeMs) || (r.avgParseTimeMs = NaN), - r - }, - getBufferEstimate: function(e, t) { - const i = this.getCombinedEstimate(e, t) - , r = { - avgBufferCreateMs: null == i ? void 0 : i.avgBufferCreateMs, - avgInitFragAppendMs: null == i ? void 0 : i.avgInitFragAppendMs, - avgDataFragAppendMs: null == i ? void 0 : i.avgDataFragAppendMs - }; - return ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = NaN), - ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = NaN), - ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = NaN), - r - } - }; - var Rf = xf; - class Lf { - constructor(e=0) { - this._minSamples = e, - this._sum = 0, - this._max = Number.NEGATIVE_INFINITY, - this._numSamples = 0 - } - get avg() { - return this._numSamples < this._minSamples ? NaN : this._sum / this._numSamples - } - get max() { - return 0 < this.count ? this._max : NaN - } - get count() { - return this._numSamples - } - reset() { - this._sum = 0, - this._numSamples = 0, - this._max = Number.NEGATIVE_INFINITY - } - add(e) { - this._sum += e, - this._max = Math.max(this._max, e), - ++this._numSamples - } - } - class _f extends Od { - constructor(e, t) { - super(e), - this.id = t - } - getBandwidthEstimate(e, t) { - var i; - const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.bandwidthEstimate); - if (ne(r.avgBandwidth) && ne(r.avgLatencyMs)) - return r; - if (e) { - const i = xf.getBandwidthEstimate(e, t); - ne(r.avgBandwidth) || (r.avgBandwidth = i.avgBandwidth), - ne(r.avgLatencyMs) || (r.avgLatencyMs = i.avgLatencyMs) - } - return r - } - getPlaylistEstimate(e, t) { - var i; - const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.playlistEstimate) - , n = e=>ne(e.avgPlaylistLoadTimeMs) && ne(e.avgPlaylistParseTimeMs); - if (n(r)) - return r; - if (e) { - const i = xf.getPlaylistEstimate(e, t); - if (ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = i.avgPlaylistLoadTimeMs), - ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = i.avgPlaylistParseTimeMs), - n(r)) - return r; - ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = e.statDefaults.playlistLoadTimeMs), - ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = e.statDefaults.playlistParseTimeMs) - } - return r - } - getBufferEstimate(e, t) { - var i; - const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.bufferEstimate) - , n = e=>ne(e.avgBufferCreateMs) && ne(e.avgDataFragAppendMs) && ne(e.avgInitFragAppendMs); - if (n(r)) - return r; - if (e) { - const i = xf.getBufferEstimate(e, t); - if (ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = i.avgBufferCreateMs), - ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = i.avgDataFragAppendMs), - ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = i.avgInitFragAppendMs), - n(r)) - return r; - ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = e.statDefaults.fragBufferCreationDelayMs), - ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = e.statDefaults.dataFragAppendMs), - ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = e.statDefaults.initFragAppendMs) - } - return r - } - getFragEstimate(e, t) { - var i; - const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.fragEstimate) - , n = e=>ne(e.maxDurationSec) && ne(e.avgParseTimeMs); - if (n(r)) - return r; - if (e) { - const i = xf.getFragEstimate(e, t); - if (ne(r.maxDurationSec) || (r.maxDurationSec = i.maxDurationSec), - ne(r.avgParseTimeMs) || (r.avgParseTimeMs = i.avgParseTimeMs), - n(r)) - return r; - ne(r.maxDurationSec) || (r.maxDurationSec = e.defaultTargetDuration), - ne(r.avgParseTimeMs) || (r.avgParseTimeMs = e.statDefaults.fragParseTimeMs) - } - return r - } - getCombinedEstimate() { - return Object.assign(Object.assign(Object.assign(Object.assign({}, this.getFragEstimate()), this.getPlaylistEstimate()), this.getBufferEstimate()), this.getBandwidthEstimate()) - } - get statsEntity() { - return this.getEntity(this.id) - } - get bandwidthSample() { - var e; - return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.bandwidthSample - } - get bandwidthStatus() { - var e; - return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.bandwidthStatus - } - get fragSample() { - var e; - return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.fragSample - } - get bandwidthEstimate$() { - return this.selectEntity(this.id, "bandwidthEstimate") - } - get fragEstimate$() { - return this.selectEntity(this.id, "fragEstimate") - } - get playlistEstimate$() { - return this.selectEntity(this.id, "playlistEstimate") - } - get bufferEstimate$() { - return this.selectEntity(this.id, "bufferEstimate") - } - get bandwidthSample$() { - return this.selectEntity(this.id, ({bandwidthSample: e})=>e).pipe(Up()) - } - get fragSample$() { - return this.selectEntity(this.id, ({fragSample: e})=>e).pipe(Up()) - } - get playlistSample$() { - return this.selectEntity(this.id, ({playlistSample: e})=>e).pipe(Up()) - } - get bufferMetric$() { - return this.selectEntity(this.id, ({bufferMetric: e})=>e).pipe(Up()) - } - } - class Nf { - constructor(e) { - this.statsStore = e - } - getQuery() { - return new Od(this.statsStore) - } - getQueryForItem(e) { - return new _f(this.statsStore,e) - } - remove(e) { - this.statsStore.remove(e) - } - removeAll() { - this.statsStore.remove() - } - setBandwidthSample(e) { - this.statsStore.bandwidthSample = e - } - setFragSample(e) { - this.statsStore.fragSample = e - } - setPlaylistSample(e) { - this.statsStore.playlistSample = e - } - setBufferMetric(e) { - this.statsStore.bufferMetric = e - } - setBandwidthEstimate(e) { - this.statsStore.bandwidthEstimate = e - } - setFragEstimate(e) { - this.statsStore.fragEstimate = e - } - setPlaylistEstimate(e) { - this.statsStore.playlistEstimate = e - } - setBufferEstimate(e) { - this.statsStore.bufferEstimate = e - } - } - const Ff = new class extends pd { - constructor() { - super({}, { - name: "stats-store", - producerFn: vc - }) - } - set statsEntity(e) { - Co("statsStore.set.stats"), - sd(()=>{ - this.add(e), - this.setActive(e.id) - } - ) - } - set playlistSample(t) { - Co(`stats.set.playlistSample: ${t}`), - this.updateActive(e=>{ - e.playlistSample = t - } - ) - } - set bandwidthSample(t) { - Co(`stats.set.bandwidthSample: ${t}`), - this.updateActive(e=>{ - e.bandwidthSample = t, - e.bandwidthStatus.bandwidthSampleCount += 1, - e.bandwidthStatus.instantBw = 8e3 * t.loaded / (t.tload - t.trequest) - } - ) - } - set fragSample(t) { - Co(`stats.set.fragSample: ${t}`), - this.updateActive(e=>{ - e.fragSample = t - } - ) - } - set bufferMetric(t) { - Co(`stats.set.bufferMetric: ${t}`), - this.updateActive(e=>{ - e.bufferMetric = t - } - ) - } - set bandwidthEstimate(t) { - Co(`stats.set.bandwidthEstimate: ${t}`), - this.updateActive(e=>{ - e.bandwidthEstimate = t - } - ) - } - set fragEstimate(t) { - Co(`stats.set.fragEstimate: ${t}`), - this.updateActive(e=>{ - e.fragEstimate = t - } - ) - } - set playlistEstimate(t) { - Co(`stats.set.playlistEstimate: ${t}`), - this.updateActive(e=>{ - e.playlistEstimate = t - } - ) - } - set bufferEstimate(t) { - Co(`stats.set.bufferEstimate: ${t}`), - this.updateActive(e=>{ - e.bufferEstimate = t - } - ) - } } ; - let Bf = null; - const Uf = e=>new _f(Ff,e); - function $f(e, t) { - if (e === t) - return !0; - if (!e || !t) - return !1; - let i = Object.keys(e).length === Object.keys(t).length; - for (const r of Object.keys(e)) - i = i && (isNaN(e[r]) && isNaN(t[r]) || e[r] === t[r]); - return i - } - function Vf(f, m, g) { - return new Ut(e=>{ - (e=>{ - const t = Uf(e); - t.hasEntity(e) ? Bi(t) : (i = Ff, - e = e, - Co("stats.loading"), - i.setLoading(!0), - i.statsEntity = { - id: e, - bandwidthEstimate: { - avgLatencyMs: NaN, - avgBandwidth: NaN - }, - bandwidthStatus: { - bandwidthSampleCount: 0, - instantBw: NaN - }, - fragEstimate: { - maxDurationSec: NaN, - avgParseTimeMs: NaN - }, - playlistEstimate: { - avgPlaylistLoadTimeMs: NaN, - avgPlaylistParseTimeMs: NaN - }, - bufferEstimate: { - avgBufferCreateMs: NaN, - avgInitFragAppendMs: NaN, - avgDataFragAppendMs: NaN - } - }, - i.setLoading(!1), - Co("stats.loaded")); - var i - } - )(g.itemId); - const t = Uf(g.itemId) - , {fragSample$: i, playlistSample$: r, bandwidthSample$: n, bufferMetric$: s} = t; - return nn(r.pipe(Hi(Zi), (h = f, - p = m, - e=>e.pipe(Ql.tag("statsPlaylistProcessingEpic.in"), na((e,t)=>(e.playlistLoadTimeMs.add(t.playlistLoadTimeMs), - e.playlistParseTimeMs.add(t.playlistParseTimeMs), - e), { - playlistLoadTimeMs: new Lf(h.minPlaylistCount), - playlistParseTimeMs: new Lf(h.minPlaylistCount) - }), ur(e=>({ - avgPlaylistLoadTimeMs: e.playlistLoadTimeMs.avg, - avgPlaylistParseTimeMs: e.playlistParseTimeMs.avg - })), Es($f), Ja(e=>{ - p.setPlaylistEstimate(e) - } - )))), n.pipe(Hi(Zi), (u = f, - c = m, - n=>new Ut(e=>{ - let t = new Pf(u.bandwidthHistoryWindowSize,u.bandwidthHistoryAggregationMethod,{ - avgLatencyMs: NaN, - avgBandwidth: NaN - }); - const i = t.estimate$ - , r = nn(n.pipe(an(e=>e.complete), Ja(e=>{} - ), ur(e=>({ - trequest: e.trequest, - tfirst: e.tfirst, - tload: e.tload, - bitsDownloaded: 8 * e.loaded - })), Ql.tag("statsBandwidthProcessingEpic.in"), Ra(e=>(t.record(e), - Ti))), i.pipe(Es(), Ql.tag("statsBandwidthProcessingEpic.change"), Ja(e=>{ - c && c.setBandwidthEstimate(e) - } - ))).subscribe(e); - return ()=>{ - r.unsubscribe(), - t.destroy(), - t = void 0 - } - } - ))), i.pipe(Hi(Zi), (d = f, - l = m, - e=>e.pipe(Ql.tag("statsFragProcessingEpic.in"), na((e,t)=>(e.durationSec.add(t.durationSec), - e.fragParseMs.add(t.parseTimeMs), - e), { - durationSec: new Lf, - fragParseMs: new Lf(d.minFragmentCount) - }), ur(e=>({ - maxDurationSec: e.durationSec.max, - avgParseTimeMs: e.fragParseMs.avg - })), Es($f), Ja(e=>l.setFragEstimate(e))))), s.pipe(Hi(Zi), (a = f, - o = m, - e=>e.pipe(Ql.tag("statsBufferMetricProcessingEpic.in"), na((e,t)=>(ne(t.bufferCreationStart) && ne(t.bufferCreationEnd) && e.bufferCreateMs.add(t.bufferCreationEnd - t.bufferCreationStart), - ne(t.startInitAppend) && ne(t.endInitAppend) && e.initFragAppendMs.add(t.endInitAppend - t.startInitAppend), - ne(t.startDataAppend) && ne(t.endDataAppend) && e.dataFragAppendMs.add(t.endDataAppend - t.startDataAppend), - e), { - bufferCreateMs: new Lf, - initFragAppendMs: new Lf, - dataFragAppendMs: new Lf(a.minFragmentCount) - }), ur(e=>({ - avgBufferCreateMs: e.bufferCreateMs.avg, - avgInitFragAppendMs: e.initFragAppendMs.avg, - avgDataFragAppendMs: e.dataFragAppendMs.avg - })), Es($f), Ja(e=>{ - o.setBufferEstimate(e) - } - ))))).pipe(Ua(Ti)).subscribe(e), - ()=>{ - Rf.setCombinedEstimate(f, Object.assign(Object.assign(Object.assign(Object.assign({}, t.getFragEstimate()), t.getPlaylistEstimate()), t.getBufferEstimate()), t.getBandwidthEstimate()), g.serviceName), - m.remove(g.itemId) - } - ; - var a, o, d, l, u, c, h, p - } - ) - } - const Kf = { - isWebkitMediaElement: e=>"webkitDroppedFrameCount"in e, - isHtmlVideoElement: e=>"getVideoPlaybackQuality"in e, - timeRangeToArray(t) { - const i = []; - for (let e = 0; e < t.length; e++) - i.push([t.start(e), t.end(e)]); - return i - } - }; - class Hf extends Ut { - constructor() { - super(e=>this.works$.pipe(ur(e=>Lr(e)), zr()).subscribe(e)), - this.works$ = new zt - } - addWork(e) { - this.works$.next(e) - } - complete() { - this.works$.complete() - } - } - class jf { - constructor(e, t) { - this.hls = e, - this.sessionID = t, - this.rtcQuery = null, - this.accessLogData = this.createAccessLogEntry(), - this.accesslog = [], - this.errorlog = [] - } - destroy() { - this.rtcQuery = null, - this.accesslog = [], - this.errorlog = [], - this.accessLogData = void 0, - this.accessLogReporter = void 0 - } - setRTCQuery(e) { - this.rtcQuery = e - } - setupReporter(e) { - this.accessLogReporter = { - SessionID: this.sessionID, - ClientName: null == e ? void 0 : e.clientName, - ServiceName: null == e ? void 0 : e.serviceName - } - } - addPlayTime(e) { - var t, e = null === (t = this.rtcQuery) || void 0 === t ? void 0 : t.getEntity(e); - !e || "RTC_STATE_PLAY" === (e = e.sessionControlRecord).state && (this.accessLogData.PlayTimeWC = (this.accessLogData.PlayTimeWC || 0) + e.eventStartTime) - } - updatePlaybackInfo(e, t) { - this.accessLogData.ViFrDr = this.rtcQuery.getEntity(e).sessionControlRecord.droppedVideoFrames || 0 - } - updateStallCount(e) { - "RTC_STATE_PLAY" === this.rtcQuery.getEntity(e).sessionControlRecord.state && this.accessLogData.StallCount++ - } - updateMediaEngineStallCount(e) { - "RTC_STATE_PLAY" === this.rtcQuery.getEntity(e).sessionControlRecord.state && this.accessLogData.MediaEngineStallCount++ - } - updateCanPlay(e) { - this.accessLogData.StartupTime = this.rtcQuery.getEntity(e).sessionControlRecord.eventStartTime - } - updateFragLoaded(e, t, i) { - var r; - i.fragType === ul.Variant ? (this.accessLogData.NetBytes += i.bytes, - this.accessLogData.ADT += i.adt, - r = this.aggregateFragObserverdBitrate(i, ++this.accessLogData.fragmentCnt, this.accessLogData.NetBytes, this.accessLogData.ADT), - this.accessLogData.OBRLast = r.obrLast, - this.accessLogData.OBRMean = r.obrMean, - this.aggregateFragMinMaxBitrate(this.accessLogData, r.obr), - this.hls.realCurrentTime > i.startPTS && !t && this.accessLogData.overdue++, - this.hasGap(i.startPTS, i.endPTS, this.accessLogData.lastStartPTS, this.accessLogData.lastEndPTS) && this.addToAccessLog(e), - this.accessLogData.startPTS || (this.accessLogData.startPTS = i.startPTS), - this.accessLogData.lastStartPTS = i.startPTS, - this.accessLogData.lastEndPTS = i.endPTS, - this.accessLogData.videoBytes += i.bytes, - this.accessLogData.videoDuration += i.duration) : i.fragType === ul.AltAudio && (this.accessLogData.audioBytes += i.bytes, - this.accessLogData.audioDuration += i.duration) - } - addToAccessLog(e) { - var t = this.getVariantInfo(e) - , i = this.rtcQuery.getEntity(e).sessionControlRecord.curLevelUrl - , r = this.rtcQuery.getEntity(e).playEndedRecord.PlayType; - if (i && "" !== i) { - r = this.translateToAccessLogItem(e, i, t, r); - if (r) { - const n = this.accesslog.length - 20; - 0 < n && this.accesslog.splice(0, n), - this.accesslog.push(r) - } - this.accessLogData = this.createAccessLogEntry(); - e = this.rtcQuery.getEntity(e).switchCompleteRecord.MediaDur; - this.accessLogData.lastMediaDur = e || this.hls.bufferedDuration - } - } - addToErrorLog(e, t) { - var i = null === (r = this.rtcQuery) || void 0 === r ? void 0 : r.getEntity(e); - if (i) { - var r = Number(("mediaError" === t ? i.playErrorRecord : i.nwErrorRecord).ErrCode) - , i = i.sessionControlRecord.curLevelUrl - , r = this.translateToErrorLogItem(e, i, { - domain: t, - code: r - }); - if (r) { - const e = this.errorlog.length - 20; - 0 < e && this.errorlog.splice(0, e), - this.errorlog.push(r) - } - } - } - getAccessLog(e) { - var t; - const i = this.accesslog.slice(0) - , r = null === (t = this.rtcQuery) || void 0 === t ? void 0 : t.getEntity(e); - if (i && r) { - const t = r.sessionControlRecord.curLevelUrl; - if (t && "" !== t) { - const r = this.getVariantInfo(e) - , n = this.translateToAccessLogItem(e, t, r, this.rtcQuery.getEntity(e).playEndedRecord.PlayType); - n && (n["c-provisional-entry"] = !0, - i.push(n)) - } - } - return i - } - get errorLog() { - return this.errorlog - } - createAccessLogEntry() { - return { - fragmentCnt: 0, - overdue: 0, - startPTS: 0, - obrMax: 0, - obrMin: 0, - audioBytes: 0, - audioDuration: 0, - videoBytes: 0, - videoDuration: 0, - svrAddrChanged: 0, - svrAddr: "", - PlayTimeWC: 0, - ViFrDr: 0, - StallCount: 0, - MediaEngineStallCount: 0, - ADT: 0, - NetBytes: 0, - StartupTime: 0, - OBRMean: 0, - OBRLast: 0 - } - } - convertStringObjectToPrimitive(e) { - return e ? "object" == typeof e ? e.toString() : e : "" - } - updateSvrAddrStats(t) { - const i = fl.parseURL(t); - if (i && i.netLoc) { - const t = i.netLoc.indexOf(":"); - let e = 0 <= t ? i.netLoc.slice(0, t) : i.netLoc; - e.startsWith("//") && (e = e.slice(2)), - this.accessLogData.svrAddr ? e !== this.accessLogData.svrAddr && this.accessLogData.svrAddrChanged++ : this.accessLogData.svrAddrChanged = 0, - this.accessLogData.svrAddr = e - } - } - translateToAccessLogItem(e, t, i, r) { - t = this.convertStringObjectToPrimitive(t); - this.updateSvrAddrStats(t); - let n = this.rtcQuery.getEntity(e).switchCompleteRecord.MediaDur; - n = n || this.hls.bufferedDuration, - n = n || 0; - const s = { - uri: t, - "s-ip": this.accessLogData.svrAddr, - "s-ip-changes": this.accessLogData.svrAddrChanged, - "sc-wwan-count": -1, - "c-transfer-duration": this.accessLogData.ADT, - bytes: this.accessLogData.NetBytes, - "c-total-media-requests": this.accessLogData.fragmentCnt, - "cs-guid": this.accessLogReporter.SessionID, - "c-start-time": this.accessLogData.startPTS, - "c-startup-time": this.accessLogData.StartupTime, - "c-duration-watched": this.accessLogData.PlayTimeWC / 1e3, - "c-frames-dropped": this.accessLogData.ViFrDr, - "c-stalls": this.accessLogData.StallCount + this.accessLogData.MediaEngineStallCount, - "c-duration-downloaded": this.accessLogData.lastMediaDur ? n - this.accessLogData.lastMediaDur : n, - "c-overdue": this.accessLogData.overdue, - "c-avg-video-bitrate": 8 * this.accessLogData.videoBytes / (this.accessLogData.videoDuration || 1), - "c-observed-max-bitrate": this.accessLogData.obrMax, - "c-observed-min-bitrate": this.accessLogData.obrMin, - "sc-indicated-bitrate": i.bandwidth || 0, - "sc-indicated-avg-bitrate": i.avgBandwidth || 0, - "c-observed-bitrate": this.accessLogData.OBRMean, - "c-switch-bitrate": this.accessLogData.OBRLast, - "c-provisional-entry": !1 - }; - return s["s-playback-type"] = r, - this.accessLogData.audioBytes && (s["c-avg-audio-bitrate"] = 8 * this.accessLogData.audioBytes / (this.accessLogData.audioDuration || 1)), - s - } - translateToErrorLogItem(e, t, i) { - t = this.convertStringObjectToPrimitive(t); - return this.updateSvrAddrStats(t), - { - date: new Date, - "cs-guid": this.accessLogReporter.SessionID + "-" + e, - uri: t, - "s-ip": this.accessLogData.svrAddr, - status: "" + i.code, - domain: i.domain - } - } - hasGap(e, t, i, r) { - return void 0 !== e && void 0 !== i && (1 < e - r || 1 < i - t) - } - aggregateFragObserverdBitrate(e, t, i, r) { - r = 8 * i / (r / 1e3); - return { - obr: r, - obrLast: 8 * e.bytes / (e.adt / 1e3), - obrMean: r / t - } - } - aggregateFragMinMaxBitrate(e, t) { - (!e.obrMax || t > e.obrMax) && (e.obrMax = t), - (!e.obrMin || t < e.obrMin) && (e.obrMin = t) - } - getVariantInfo(e) { - var t = this.rtcQuery.getEntity(e).sessionControlRecord.curLevelUrl - , e = null === (e = this.rtcQuery.getEntity(e).sessionControlRecord.manifestData) || void 0 === e ? void 0 : e.variantList; - return t && e && e[t] ? e[t] : {} - } - } - const qf = (r,e,t,i,n,s)=>{ - var a, {absoluteUrl: o, byteRangeOffset: d, keyTagInfo: l, iframe: u, isInitSegment: c} = r, h = o, p = l["method"], {start: o, end: l} = d, t = xc({ - url: h - }, t); - let f, m = o, g = l, y = !1, v = ne(o) || ne(l) ? d : void 0; - if ("AES-128" === p && l && (u || c)) { - const r = l - o; - r % 16 && (g = l + (16 - r % 16)), - 0 !== o && (y = !0, - m = o - 16), - v = { - start: m, - end: g - } - } - return n && ne(r.mediaSeqNum) && r.mediaOptionType === ul.Variant && (f = [], - null === (n = t.reportHTTPResponseHeaders) || void 0 === n || n.forEach(function(e) { - vl.includes(e) ? f.push(e) : qe().warn({ - name: "load-media-fragment" - }, `${e} is not in approved privacy list. Actions required.`) - }), - 0 === f.length && (f = void 0)), - Pc({ - url: h, - byteRangeOffset: v, - checkContentLength: !0, - extendMaxTTFB: s, - collectServerInstanceInfo: f, - onProgress: i, - xhrSetup: e.xhrSetup - }, t).pipe(ur(([e,t,i])=>{ - if (y) { - const t = e; - r.keyTagInfo.iv = new Uint8Array(t.slice(0, 16)), - e = t.slice(16) - } - return [r, e, t, i] - } - ), (a = r, - e=>e.pipe(Un(e=>{ - if (e instanceof ou) - throw new au(!1,"Timeout",0,$.FragmentTimeoutError,!0,a,e.stats); - if (e instanceof tu) - throw new au(!1,e.message,e.code,{ - code: e.code, - text: "Fragment Network Error" - },!1,a); - throw e - } - )))) - } - , Qf = { - clearkey: Zc, - fairplaystreaming: pu, - playready: _c, - widevine: Nc - } - , Gf = { - getKeySystemFormat(e) { - e = Qf[e]; - return e ? e.keyFormatString : "" - }, - getKeySystemSecurityLevel(e) { - e = Qf[e]; - return e ? e.securityLevels : null - } - } - , Wf = { - NONE: "", - "AES-128": "", - "ISO-23001-7": "", - "SAMPLE-AES": "", - "SAMPLE-AES-CTR": "" - } - , zf = { - NONE: 0, - "TYPE-0": 1, - "TYPE-1": 2, - "TYPE-2": 3 - }; - function Xf(e) { - return e in zf - } - function Yf(e) { - return null == e ? 4 : zf[e] - } - const Jf = ["SDR", "PQ", "HLG"] - , Zf = { - afr: "af", - aka: "ak", - amh: "am", - ara: "ar", - arg: "an", - asm: "as", - ava: "av", - ave: "ae", - aym: "ay", - aze: "az", - bam: "bm", - bel: "be", - ben: "bn", - bih: "bh", - bod: "bo", - bos: "bs", - bre: "br", - bul: "bg", - cat: "ca", - ces: "cs", - cha: "ch", - che: "ce", - chu: "cu", - chv: "cv", - cor: "kw", - cos: "co", - cre: "cr", - cym: "cy", - dan: "da", - deu: "de", - div: "dv", - dzo: "dz", - ell: "el", - eng: "en", - epo: "eo", - est: "et", - eus: "eu", - ewe: "ee", - fao: "fo", - fas: "fa", - fin: "fi", - fra: "fr", - fry: "fy", - ful: "ff", - gla: "gd", - gle: "ga", - glg: "gl", - glv: "gv", - grn: "gn", - guj: "gu", - hat: "ht", - heb: "he", - her: "hz", - hin: "hi", - hmo: "ho", - hrv: "hr", - hun: "hu", - hye: "hy", - ibo: "ig", - ido: "io", - iii: "ii", - iku: "iu", - ile: "ie", - ina: "ia", - ind: "id", - isl: "is", - ita: "it", - jav: "jv", - jpn: "ja", - kal: "kl", - kan: "kn", - kas: "ks", - kat: "ka", - kau: "kr", - kaz: "kk", - khm: "km", - kik: "ki", - kin: "rw", - kir: "ky", - kom: "kv", - kon: "kg", - kor: "ko", - kua: "kj", - kur: "ku", - lao: "lo", - lat: "la", - lav: "lv", - lim: "li", - lit: "lt", - ltz: "lb", - lub: "lu", - lug: "lg", - mah: "mh", - mal: "ml", - mar: "mr", - mkd: "mk", - mlg: "mg", - mlt: "mt", - mol: "mo", - mon: "mn", - mri: "mi", - msa: "ms", - mya: "my", - nav: "nv", - nbl: "nr", - nde: "nd", - ndo: "ng", - nep: "ne", - nld: "nl", - nno: "nn", - nob: "nb", - nya: "ny", - oci: "oc", - oji: "oj", - ori: "or", - orm: "om", - oss: "os", - pan: "pa", - pli: "pi", - pol: "pl", - por: "pt", - pus: "ps", - que: "qu", - roh: "rm", - ron: "ro", - run: "rn", - rus: "ru", - san: "sa", - sin: "si", - slk: "sk", - slv: "sl", - sme: "se", - snd: "sd", - som: "so", - spa: "es", - sqi: "sq", - srd: "sc", - srp: "sr", - sun: "su", - swa: "sw", - swe: "sv", - tah: "ty", - tam: "ta", - tat: "tt", - tel: "te", - tgk: "tg", - tgl: "tl", - tha: "th", - tir: "ti", - ton: "to", - tuk: "tk", - tur: "tr", - uig: "ug", - ukr: "uk", - urd: "ur", - uzb: "uz", - ven: "ve", - vie: "vi", - wln: "wa", - yid: "yi", - zha: "za", - zho: "zh" - } - , em = { - isLanguageCode: e=>e in Zf, - shortenLanguageCode(e) { - let t; - var i, r; - return e && (r = 0 <= (i = e.indexOf("-")) ? e.slice(0, i) : e, - em.isLanguageCode(r) && (t = Zf[r]), - t = t || r, - 0 < i && (t += "-" + e.slice(i + 1))), - t - } - } - , tm = { - getRichestVideoCodec(e) { - if (e && e.length) { - e = e.sort((e,t)=>$p(t) - $p(e)); - return e && e.length ? e[0] : void 0 - } - }, - getRichestAudioCodec(e) { - if (e && e.length) { - e = e.sort((e,t)=>Kp(t) - Kp(e)); - return e && e.length ? e[0] : void 0 - } - }, - getRichestChannelLayoutForGroupId(t, i) { - if (t && i && i.length) { - let e; - const r = i.filter(e=>e.groupId === t); - if (r && r.length) { - const t = r.sort((e,t)=>Se.getChannelCount(t.channels) - Se.getChannelCount(e.channels)); - t && t.length && (e = t[0].channels) - } - return e - } - } - }; - function im(e) { - return new R(L,"steeringManifestParsingError",!1,e,$.FormatError) - } - class rm { - constructor(e) { - this._url = null, - this._programDateTime = null, - this._byteRange = null, - this.relurl = null, - this.baseurl = null, - this.isInitSegment = !1, - this.mediaSeqNum = NaN, - this.cc = NaN, - this.iframe = !1, - this.bitrate = NaN, - this.start = NaN, - this.duration = NaN, - this.lastByteRangeEndOffset = NaN, - this.inheritQuery = e, - this.tagList = new Array, - this.iframe = !1 - } - getMediaFragment(e, t, i) { - const r = { - mediaOptionType: i, - absoluteUrl: this.url, - start: this.start, - duration: this.duration, - mediaSeqNum: this.mediaSeqNum, - discoSeqNum: this.cc, - mediaOptionId: t, - itemId: e, - isLastFragment: !1, - isInitSegment: this.isInitSegment - }; - return null !== (e = this.byteRange) && void 0 !== e && e.length && (r.byteRangeOffset = { - start: this.byteRangeStartOffset, - end: this.byteRangeEndOffset - }), - this.iframe && (r.iframe = this.iframe), - this.levelkey && (r.keyTagInfo = this.levelkey), - this.programDateTime && (r.programDateTime = this.programDateTime), - r - } - get url() { - return !this._url && this.relurl && this.baseurl && (this._url = fl.buildAbsoluteURL(this.baseurl, this.relurl, { - alwaysNormalize: !0, - inheritQuery: this.inheritQuery - })), - this._url - } - set url(e) { - this._url = e - } - get programDateTime() { - return !this._programDateTime && this.rawProgramDateTime && (this._programDateTime = new Date(Date.parse(this.rawProgramDateTime))), - this._programDateTime - } - get byteRange() { - if (!this._byteRange) { - const i = new Array(2); - var e, t; - this.rawByteRange && (1 === (e = this.rawByteRange.split("@", 2)).length ? (t = this["lastByteRangeEndOffset"], - i[0] = t || 0) : i[0] = parseInt(e[1]), - i[1] = parseInt(e[0]) + i[0]), - this._byteRange = i - } - return this._byteRange - } - get byteRangeStartOffset() { - return this.byteRange[0] - } - get byteRangeEndOffset() { - return this.byteRange[1] - } - get rangeString() { - return 0 <= this.start && 0 <= this.duration ? `${this.start.toFixed(2)}-${(this.start + this.duration).toFixed(2)}` : "N/A" - } - get fragTag() { - return `sn/cc/levelId: ${this.mediaSeqNum}/${this.cc}` - } - } - const nm = { - parseMediaCharacteristics: e=>e ? e.split(/\s*,\s*/) : new Array, - addMediaToSelectionArray(e, t, i) { - if (void 0 === e) - return -1; - const r = e.MediaSelectionGroupOptions; - let n = r.find(e=>e.MediaSelectionOptionsMediaType === t.mediaType && e.MediaSelectionOptionsName === t.name && e.MediaSelectionOptionsExtendedLanguageTag === t.lang); - return n || (n = { - MediaSelectionOptionsMediaType: t.mediaType, - MediaSelectionOptionsExtendedLanguageTag: t.lang, - MediaSelectionOptionsIsDefault: t.default, - MediaSelectionOptionsName: t.name, - MediaSelectionOptionsPersistentID: i, - MediaSelectionOptionsTaggedMediaCharacteristics: t.characteristics - }, - t.mediaType === pl.SUBTITLE && (n.MediaSelectionOptionsDisplaysNonForcedSubtitles = t.forced ? hl.NO : hl.YES), - i++, - r.push(n)), - t.persistentID = n.MediaSelectionOptionsPersistentID, - i - }, - addDefaultClosedCaptionOption(e, t, i, r) { - e = { - itemId: e, - mediaOptionType: ul.Subtitle, - id: 0, - mediaOptionId: "cc1_" + Jd(), - mediaType: pl.CLOSEDCAPTION, - inStreamID: "CC1", - groupId: "cc", - name: "English-CC", - type: "CLOSED-CAPTIONS", - default: !1, - autoselect: !1, - forced: !1, - lang: "en", - characteristics: ["public.accessibility.transcribes-spoken-dialog", "public.accessibility.describes-music-and-sound"], - persistentID: r - }; - t.push(e), - nm.addMediaToSelectionArray(i, e, r) - } - } - , sm = { - BANDWIDTH: NaN, - "AVERAGE-BANDWIDTH": NaN - } - , am = { - "TIME-OFFSET": NaN, - "FRAME-RATE": NaN, - SCORE: NaN, - "PLANNED-DURATION": NaN, - DURATION: NaN - } - , om = /^(\d+)x(\d+)$/ - , dm = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; - class lm { - constructor(e) { - this.validTags = e - } - isKey(e) { - return e in this.validTags - } - trySetValue(e, t, i) { - return !!this.isKey(e) && (i[e] = this.parseFunc(t), - !0) - } - } - class um { - static parseTags(t) { - let i; - var r = {}; - if (!t) - return r; - for (dm.lastIndex = 0; null !== (i = dm.exec(t)); ) { - const t = i[1].toUpperCase(); - let e = i[2]; - 0 === e.indexOf('"') && e.lastIndexOf('"') === e.length - 1 && (e = e.slice(1, -1)); - for (const i of um.tagParsers) - if (i.trySetValue(t, e, r)) - break - } - return r - } - } - um.tagParsers = [new class extends lm { - parseFunc(e) { - return e - } - } - ({ - NAME: "", - TYPE: "", - DEFAULT: "", - AUTOSELECT: "", - FORCED: "", - LANGUAGE: "", - URI: "", - AUDIO: "", - "VIDEO-RANGE": "", - "CLOSED-CAPTIONS": "", - CODECS: "", - BYTERANGE: "", - "INSTREAM-ID": "", - "GROUP-ID": "", - CHANNELS: "", - CHARACTERISTICS: "", - KEYFORMAT: "", - KEYFORMATVERSIONS: "", - "DATA-ID": "", - VALUE: "", - METHOD: "", - "HDCP-LEVEL": "", - "ALLOWED-CPC": "", - SUBTITLES: "", - ID: "", - CLASS: "", - "START-DATE": "", - "END-DATE": "", - "END-ON-NEXT": "", - "SERVER-URI": "", - "PATHWAY-ID": "" - }), new class extends lm { - parseFunc(e) { - e = parseInt(e); - return e > Number.MAX_SAFE_INTEGER ? 1 / 0 : e - } - } - (sm), new class extends lm { - constructor() { - super(...arguments), - this.parseFunc = parseFloat - } - } - (am), new class extends lm { - parseFunc(e) { - let t = (e || "0x").slice(2); - t = (1 & t.length ? "0" : "") + t; - const i = new Uint8Array(t.length / 2); - for (let e = 0; e < t.length / 2; e++) { - var r = parseInt(t.slice(2 * e, 2 * e + 2), 16); - if (!ne(r)) - return; - i[e] = r - } - return i - } - } - ({ - IV: null - }), new class extends lm { - parseFunc(e) { - e = om.exec(e); - let t; - return null !== e && (t = { - width: parseInt(e[1], 10), - height: parseInt(e[2], 10) - }), - t - } - } - ({ - RESOLUTION: null - })]; - const cm = { - ExtractVariableParameter: /{\$(.*?)}/g, - LevelPlaylistFast: /#EXTINF:(\d*(?:\.\d+)?)(?:,(.*))?|(?!#)(\S.+)|#EXT-X-BYTERANGE: *(.+)|#EXT-X-PROGRAM-DATE-TIME:(.+)|#EXT-X-BITRATE:(.+)|#EXT-X-DATERANGE:(.+)|#.*/g, - LevelPlaylistSlow: /(?:(?:#(EXTM3U))|(?:#EXT-X-(PLAYLIST-TYPE):(.+))|(?:#EXT-X-(MEDIA-SEQUENCE): *(\d+))|(?:#EXT-X-(TARGETDURATION): *(\d+))|(?:#EXT-X-(KEY):(.+))|(?:#EXT-X-(START):(.+))|(?:#EXT-X-(ENDLIST))|(?:#EXT-X-(DISCONTINUITY-SEQ)UENCE:(\d+))|(?:#EXT-X-(DIS)CONTINUITY))|(?:#EXT-X-(VERSION):(\d+))|(?:#EXT-X-(MAP):(.+))|(?:#EXT-X-(I-FRAMES)-ONLY)|(?:#EXT-X-(DEFINE):(.+))|(?:(#)(.*):(.*))|(?:(#)(.*))(?:.*)\r?\n?/, - MasterPlaylist: /#EXT-X-STREAM-INF:([^\n\r]*)[\r\n]+([^\r\n]+)|#EXT-X-I-FRAME-STREAM-INF:([^\r\n]+)|#EXT-X-DEFINE:([^\n\r]*)|#EXT-X-CONTENT-STEERING:([^\n\r]*)/g, - MasterPlaylistAlternateMedia: /#EXT-X-MEDIA:(.*)/g, - SessionData: /#EXT-X-SESSION-DATA[^:]*:(.*)/g, - SessionKeys: /#EXT-X-SESSION-KEY:([^\n\r]*)/g, - VARIABLE_PLAYLIST_REGEX: /(NAME|VALUE)=\"(.*)\",(NAME|VALUE)=\"(.*)\"|(IMPORT)=\"(.*)\"/ - }; - function hm(e, t, i) { - return sl.buildAbsoluteURL(t, e, { - alwaysNormalize: !0, - inheritQuery: i - }) - } - class pm { - static isValidPlaylist(e) { - return 0 === e.indexOf("#EXTM3U") - } - static isMediaPlaylist(e) { - return 0 < e.indexOf("#EXTINF:") || 0 < e.indexOf("#EXT-X-PLAYLIST-TYPE:") - } - static replaceVariables(e, t) { - let i, r = !1; - return e && t && (i = e.replace(cm.ExtractVariableParameter, e=>{ - cm.ExtractVariableParameter.lastIndex = 0; - e = cm.ExtractVariableParameter.exec(e)[1]; - if (e && t.hasOwnProperty(e)) - return t[e]; - r = !0 - } - )), - { - updatedString: i, - error: r - } - } - static parseDecryptData(e, t, i) { - const r = um.parseTags(e) - , n = (e = r.METHOD) && e in Wf ? r.METHOD : null; - e = null !== (e = r.KEYFORMAT) && void 0 !== e ? e : null; - if (n && pm.shouldSelectKeyTag(e, n, i)) { - const s = r.URI - , i = r.IV || null; - if (s && r.IV && !i) { - const s = new R(L,_,!0,`Invalid IV: ${r.IV}`,$.PlaylistErrorInvalidEntry); - throw s.url = t, - s - } - const a = s ? sl.buildAbsoluteURL(t, s, { - alwaysNormalize: !0 - }) : t - , o = (r.KEYFORMATVERSIONS || "1").split("/").map(Number).filter(isFinite); - return new Gc(n,a,i,e,o) - } - } - static shouldSelectKeyTag(e, t, i) { - return "AES-128" === t || "NONE" === t || null == i || e === Gf.getKeySystemFormat(i) - } - static optOutClosedCaption(t) { - let i = !1 - , r = !1; - if (t) - for (let e = 0; e < t.length; ++e) { - const n = t[e]; - if (n.videoCodec && ((r = !0) !== n.iframes && n.closedcaption && "none" === n.closedcaption.toLowerCase())) { - i = !0; - break - } - } - return !r || i - } - static parseRootPlaylistAlternateMediaOptions(a, o, d, l, u, c) { - let h, p; - var f = { - MediaSelectionGroupAllowEmptySelection: 1, - MediaSelectionGroupMediaCharacteristics: ["public.audible"], - MediaSelectionGroupMediaType: pl.AUDIO, - MediaSelectionGroupOptions: [] - } - , m = { - MediaSelectionGroupAllowEmptySelection: 1, - MediaSelectionGroupMediaCharacteristics: ["public.legible"], - MediaSelectionGroupMediaType: pl.SUBTITLE, - MediaSelectionGroupOptions: [] - } - , g = { - videoAlternateOptions: [], - audioAlternateOptions: [], - subtitleAlternateOptions: [], - audioMediaSelectionGroup: f, - subtitleMediaSelectionGroup: m - }; - let y = 0; - for (cm.MasterPlaylistAlternateMedia.lastIndex = 0; null != (h = cm.MasterPlaylistAlternateMedia.exec(o)); ) { - const o = pm.replaceVariables(h[1], c); - if (o.error) { - p = new R(L,N,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); - break - } - var v = um.parseTags(o.updatedString); - let e, t, i, r = pl.UNKNOWN; - const S = nm.parseMediaCharacteristics(v.CHARACTERISTICS) - , b = v["GROUP-ID"] - , T = v.CHANNELS; - let n, s = null; - switch (v.TYPE) { - case "VIDEO": - r = pl.VIDEO, - t = g.videoAlternateOptions; - break; - case "AUDIO": - r = pl.AUDIO, - s = ul.AltAudio, - t = g.audioAlternateOptions, - i = f; - const a = l.find(e=>e.audioGroupId === b); - n = a ? a.audioCodecList : []; - break; - case "SUBTITLES": - r = pl.SUBTITLE, - s = ul.Subtitle, - t = g.subtitleAlternateOptions, - i = m; - break; - case "CLOSED-CAPTIONS": - r = pl.CLOSEDCAPTION, - s = ul.Subtitle, - e = v["INSTREAM-ID"], - t = g.subtitleAlternateOptions, - i = m - } - const E = { - itemId: a, - mediaOptionType: s, - mediaType: r, - groupId: b, - channels: T, - groupCodecList: n, - name: v.NAME, - type: v.TYPE, - default: "YES" === v.DEFAULT, - autoselect: "YES" === v.AUTOSELECT, - forced: "YES" === v.FORCED, - characteristics: S, - persistentID: y, - id: t ? t.length : 0, - mediaOptionId: `${v.NAME}_${b}_${y}`, - lang: em.shortenLanguageCode(v.LANGUAGE) - }; - v.URI && (E.url = hm(v.URI, d, u)), - E.name || (E.name = E.lang, - E.mediaType === pl.CLOSEDCAPTION && (E.name += " CC")), - E.mediaType === pl.CLOSEDCAPTION && e && (E.inStreamID = e), - t && (E.id = t.length, - t.push(E)), - y = nm.addMediaToSelectionArray(i, E, y) - } - return 0 !== g.subtitleAlternateOptions.length || pm.optOutClosedCaption(l) || nm.addDefaultClosedCaptionOption(a, g.subtitleAlternateOptions, m, y), - { - alternateMediaInfo: g, - playlistParsingError: p - } - } - static parseMediaOptionPlaylist(e, t, i=!0, r, n, s, a, o, d, l=0) { - var u; - let c = 0 - , h = 0; - const p = { - itemId: s, - mediaOptionId: a, - mediaOptionType: o, - type: "", - version: 0, - url: t, - initSegments: {}, - fragments: [], - liveOrEvent: !0, - startSN: 0, - endSN: 0, - iframesOnly: !1, - targetduration: 0, - totalduration: 0, - averagetargetduration: 0, - ptsKnown: !1 - }; - let f, m, g, y = new Gc("NONE",t,null,null,null), v = !1, S = !1, b = 0, T = null, E = new rm(i), I = 0; - const w = {}; - let A, O, k, C = !0, D = !0; - cm.LevelPlaylistFast.lastIndex = 0; - for (var M = ()=>new R(L,_,!0,"Invalid key system preference for the playlist",$.IncompatibleAsset); null !== (f = cm.LevelPlaylistFast.exec(e)); ) { - const e = f[1]; - if (e) { - E.duration = parseFloat(e); - const t = (" " + f[2]).slice(1); - E.title = t || null, - E.tagList.push(t ? ["INF", e, t] : ["INF", e]) - } else if (f[3]) { - if (ne(E.duration)) { - const e = c++; - if (E.start = h + l, - E.levelkey = y, - S && !v) { - O = M(); - break - } - if (v = !1, - S = !1, - E.mediaSeqNum = e, - E.cc = b, - E.iframe = p.iframesOnly, - E.baseurl = t, - (A = pm.replaceVariables((" " + f[3]).slice(1), w)).error) { - O = new R(L,N,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); - break - } - if (E.relurl = A.updatedString, - E.bitrate = ne(E.byteRangeEndOffset) ? 8 * (E.byteRangeEndOffset - E.byteRangeStartOffset) / E.duration : I, - null != g) { - E.rawProgramDateTime = g, - E.tagList.push(["PROGRAM-DATE-TIME", E.rawProgramDateTime]); - const e = E.programDateTime.getTime(); - p.programDateTimeMap = null !== (u = p.programDateTimeMap) && void 0 !== u ? u : {}, - p.programDateTimeMap[e] = E.mediaSeqNum, - p.dateMediaTimePairs = null !== (u = p.dateMediaTimePairs) && void 0 !== u ? u : [], - p.dateMediaTimePairs.push([e, E.start]), - g = void 0 - } - if (p.fragments.push(E.getMediaFragment(s, a, o)), - T = E, - h += E.duration, - C || !p.initSegments[b] || D) - if (p.iframesOnly && 0 < E.byteRangeStartOffset && !p.initSegments[b] && !D) { - const e = new rm(i); - if (e.url = E.url, - e.rawByteRange = Math.min(E.byteRangeStartOffset, 1316) + "@0", - e.baseurl = t, - e.isInitSegment = !0, - e.cc = b, - e.levelkey = y, - e.iframe = !0, - S && !v) { - O = M(); - break - } - v = !1, - S = !1, - p.initSegments[b] = e.getMediaFragment(s, a, o) - } else - k && (k.discoSeqNum = b, - p.initSegments[b] = k); - C = !1, - D = !1, - E = new rm(i) - } - } else if (f[4]) { - if (E.rawByteRange = (" " + f[4]).slice(1), - T) { - const e = T.byteRangeEndOffset; - e && (E.lastByteRangeEndOffset = e) - } - } else if (f[5]) - g = (" " + f[5]).slice(1); - else if (f[6]) { - const e = parseInt(f[6]); - ne(e) && (I = 1e3 * e) - } else if (f[7]) { - const e = f[7] - , t = um.parseTags(e); - t.ID && (p.daterangeTags || (p.daterangeTags = {}), - p.daterangeTags[t.ID] = t) - } else { - for (f = f[0].match(cm.LevelPlaylistSlow), - m = 1; m < f.length && void 0 === f[m]; m++) - ; - const e = pm.replaceVariables((" " + f[m + 1]).slice(1), w) - , d = pm.replaceVariables((" " + f[m + 2]).slice(1), w); - if (e.error || d.error) { - O = new R(L,N,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); - break - } - const l = e.updatedString - , P = d.updatedString; - switch (f[m]) { - case "#": - E.tagList.push(P ? [l, P] : [l]); - break; - case "PLAYLIST-TYPE": - p.type = l.toUpperCase(), - "VOD" === p.type && (p.liveOrEvent = !1); - break; - case "MEDIA-SEQUENCE": - 0 === p.fragments.length && (c = p.startSN = parseInt(l)); - break; - case "TARGETDURATION": - p.targetduration = parseFloat(l); - break; - case "VERSION": - p.version = parseInt(l); - break; - case "EXTM3U": - break; - case "ENDLIST": - p.liveOrEvent = !1; - break; - case "DIS": - b++, - E.tagList.push(["DIS"]), - C = !0; - break; - case "DISCONTINUITY-SEQ": - b = parseInt(l); - break; - case "KEY": - const e = l; - if (S = !0, - !v) { - try { - y = pm.parseDecryptData(e, t, r) - } catch (e) { - O = e - } - y && (v = !0) - } - break; - case "START": - const d = l - , u = um.parseTags(d)["TIME-OFFSET"]; - ne(u) && (p.startTimeOffset = u); - break; - case "I-FRAMES": - p.iframesOnly = !0; - break; - case "MAP": - const h = um.parseTags(l); - if (E.relurl = h.URI, - E.rawByteRange = h.BYTERANGE, - E.baseurl = t, - E.isInitSegment = !0, - E.levelkey = y, - S && !v) { - O = M(); - break - } - v = !1, - S = !1, - k = E.getMediaFragment(s, a, o), - D = !0, - E = new rm(i); - break; - case "DEFINE": - const f = cm.VARIABLE_PLAYLIST_REGEX.exec(l) - , m = "NAME" === f[1] ? f[2] : f[4] - , g = "VALUE" === f[1] ? f[2] : f[4] - , N = f[5] - , T = f[6]; - if (m || g || "IMPORT" !== N || !n.hasOwnProperty(T)) { - if (!m || N || f[1] === f[3] || w.hasOwnProperty(m)) { - O = new R(L,_,!0,$.PlaylistErrorMissingImportReference.text,$.PlaylistErrorMissingImportReference); - break - } - w[m] = g - } else - w[T] = n[T] - } - } - } - return E = T, - E && !E.relurl && (p.fragments.pop(), - h -= E.duration), - !p.liveOrEvent && 0 < p.fragments.length && (p.fragments[p.fragments.length - 1].isLastFragment = !0), - p.totalduration = h, - p.averagetargetduration = h / p.fragments.length, - p.endSN = c - 1, - { - mediaOptionDetails: p, - playlistParsingError: O - } - } - static parseRootPlaylist(t, e, i, r) { - const n = [] - , s = {}; - let a, o, d, l, u = null, c = !0; - for (cm.MasterPlaylist.lastIndex = 0; null != (a = cm.MasterPlaylist.exec(e)); ) - if (a[4]) { - a = cm.VARIABLE_PLAYLIST_REGEX.exec(a[4]); - const t = "NAME" === a[1] ? a[2] : a[4] - , e = "VALUE" === a[1] ? a[2] : a[4] - , i = a[5]; - if (!t || s.hasOwnProperty(t) || i || a[1] === a[3]) { - l = new R(L,_,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); - break - } - s[t] = e - } else if (a[5]) { - const t = pm.replaceVariables(a[5], s); - if (t.error) { - l = new R(L,_,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); - break - } - const e = um.parseTags(t.updatedString); - if ("string" != typeof e["SERVER-URI"]) { - l = new R(L,_,!0,$.PlaylistErrorInvalidSERVERURI.text,$.PlaylistErrorInvalidSERVERURI); - break - } - if (null != e["PATHWAY-ID"] && "string" != typeof e["PATHWAY-ID"]) { - l = new R(L,_,!0,$.PlaylistErrorInvalidPATHWAYID.text,$.PlaylistErrorInvalidPATHWAYID); - break - } - u = { - serverURI: hm(e["SERVER-URI"], i, !1), - initPathwayID: e["PATHWAY-ID"] || "." - } - } else { - d = pm.replaceVariables(a[1] || a[3], s); - const e = um.parseTags(d.updatedString); - if (o = pm.replaceVariables(a[2] || e.URI, s), - d.error || o.error) { - l = new R(L,_,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); - break - } - if (void 0 !== e.SCORE && !ne(e.SCORE) || e.SCORE < 0) { - l = new R(L,_,!0,$.PlaylistErrorInvalidSCORE.text,$.PlaylistErrorInvalidSCORE), - c = !1; - break - } - c && void 0 === e.SCORE && (c = !1); - const u = e.BANDWIDTH - , p = e["AVERAGE-BANDWIDTH"] - , f = p || u - , m = null !== (h = e["VIDEO-RANGE"]) && void 0 !== h ? h : "SDR"; - if (null == (h = m) || !Jf.includes(h)) - continue; - const g = { - itemId: t, - mediaOptionId: `level_${(f || 0) + n.length % 1e3 / 1e3}`, - mediaOptionType: ul.Variant, - attrs: e, - url: hm(o.updatedString, i, r), - name: e.NAME, - audioGroupId: e.AUDIO, - subtitleGroupId: e.SUBTITLES, - iframes: !!a[3], - bandwidth: u, - avgBandwidth: p, - bitrate: f, - videoRange: m, - frameRate: e["FRAME-RATE"], - allowedCPCMap: pm.parseAllowedCPC(e["ALLOWED-CPC"]), - closedcaption: e["CLOSED-CAPTIONS"], - levelCodec: e.CODECS, - score: e.SCORE, - pathwayID: e["PATHWAY-ID"] || "." - } - , y = e["HDCP-LEVEL"]; - Xf(y) && (g.hdcpLevel = y); - var h = e.RESOLUTION; - if (h && (g.width = h.width, - g.height = h.height), - e.CODECS) { - g.videoCodecList = new Array, - g.audioCodecList = new Array; - const t = e.CODECS.split(/[ ,]+/) - , i = t["length"]; - for (let e = 0; e < i; e++) { - const i = t[e]; - switch (i.slice(0, 4)) { - case "avc1": - g.videoCodec = Se.avc1toavcoti(i), - g.videoCodecList.push(g.videoCodec); - break; - case "avc3": - case "dvav": - case "dva1": - case "hev1": - case "hvc1": - case "dvh1": - case "dvhe": - case "vp09": - g.videoCodec = i, - g.videoCodecList.push(g.videoCodec); - break; - default: - g.audioCodec = i, - g.audioCodecList.push(g.audioCodec) - } - } - 1 < g.audioCodecList.length && (g.audioCodec = tm.getRichestAudioCodec(g.audioCodecList)), - 1 < g.videoCodecList.length && (g.videoCodec = tm.getRichestVideoCodec(g.videoCodecList)) - } - if (null != (l = "string" != typeof (h = g.pathwayID) ? im("invalid steering manifest PATHWAY-PRIORITY list item data type") : /^[\w\-\.]+$/.test(h) ? void 0 : im("steering manifest contains invalid pathway ID: " + h))) - break; - let cpc = g.allowedCPCMap ? JSON.stringify(g.allowedCPCMap) : "null"; - if (!cpc.includes("WIDEVINE_HARDWARE") && !g.url.includes('trickPlay') && !g.videoCodec.includes("hvc1")) - n.push(g) - } - - - - try{ - // console.log(n, window.screen.width) - let ok = (n.map( function(item){return{height : item.height, content: item}})); - let screenHeight = (app.cfg.visual.videoRes ?? window.screen.height) ; - ok.sort(function (a, b) { - return a.height - b.height; - }); - for (var i = 0; i < ok.length; i++){ - if (ok[i].height > screenHeight){ - if (i == 0){n.splice(0,n.length);n.push(ok[i].content)} - else{n.splice(0,n.length);n.push(ok[i-1].content)} - console.log('selected' , n[0].height) - break; - - } - - } - if (n.length > 1){ - n.splice(0,n.length - 1); - } - // console.log(n) - // console.log(ok) - } catch (e){ console.log(e)} - return { - variantMediaOptions: n, - contentSteeringOption: u, - masterVariableList: s, - playlistParsingError: l, - scoreAvailable: c - } - } - static parseAllowedCPC(e) { - if ("string" != typeof e) - return null; - const n = {}; - return e.split(",").forEach(e=>{ - const t = e.split(":"); - let i, r; - if (2 === t.length) - i = t[0].trim(), - r = t[1].trim(); - else { - if (!(2 < t.length)) - return; - r = t[t.length - 1].trim(), - t.pop(), - i = t.join(":") - } - if (!(i in n)) { - let e = new Array; - "" !== r && (e = r.split("/").map(e=>e.trim())), - n[i] = e - } - } - ), - n - } - static parseSessionKeys(e, t, i) { - var r; - const n = []; - for (cm.SessionData.lastIndex = 0; r = cm.SessionKeys.exec(e); ) - try { - const e = pm.parseDecryptData(r[1], t, i); - e && e.isEncrypted && n.push(e) - } catch (e) {} - return n - } - static parseSessionData(e, t) { - var i; - const r = [] - , n = new Set; - for (cm.SessionData.lastIndex = 0; null != (i = cm.SessionData.exec(e)); ) { - const e = um.parseTags(i[1]); - e.LANGUAGE = em.shortenLanguageCode(e.LANGUAGE); - const t = e.LANGUAGE ? e["DATA-ID"] + "|" + e.LANGUAGE : void 0; - "DATA-ID"in e ? t && n.has(t) || ("com.apple.hls.other-tags" === e["DATA-ID"] && (e.VALUE = function(t) { - let i; - try { - i = JSON.parse(Vc.base64DecodeToStr(t)) - } catch (e) { - i = t - } - return i - }(e.VALUE)), - r.push(e), - t && n.add(t)) : qe().error(`Error processing DATA-ID ${e["DATA-ID"]} and LANGUAGE ${e.LANGUAGE}`) - } - return { - itemList: r, - baseUrl: t - } - } - } - var fm, mm, gm, ym, vm, Sm = pm; - const bm = (e,t,i)=>{ - i = Object.assign(Object.assign({}, e), { - method: "GET", - responseType: "text", - extendMaxTTFB: i - }); - return ml(i.url) ? Mc().load(i, t).pipe(ur(e=>({ - responseText: e.data.response.data, - responseURL: e.data.response.uri, - stats: e.stats - }))) : Oc(i, t).pipe(ur(([e,t])=>({ - responseText: e.responseText, - responseURL: e.responseURL, - stats: t - }))) - } - , Tm = (e,n,t,i,s,a,o,d,r)=>{ - const {url: l, itemId: u, mediaOptionId: c, mediaOptionType: h} = e - , p = xc(e, i); - return bm({ - url: l, - xhrSetup: t.xhrSetup - }, p, r).pipe(ur(({responseText: e, stats: t})=>{ - var i = performance.now() - , r = pm.parseMediaOptionPlaylist(e, l, !0, a, d, u, c, h, s, n); - Lc(r.mediaOptionDetails); - var e = performance.now() - , r = r["mediaOptionDetails"] - , i = { - playlistLoadTimeMs: t.tload - t.trequest, - playlistParseTimeMs: e - i - }; - return o.setPlaylistSample(i), - { - mediaOptionDetails: r, - stats: t - } - } - ), (f = h, - m = c, - g = l, - e=>e.pipe(Un(e=>{ - if (e instanceof ou) - throw new nu(!1,"Timeout",0,$.PlaylistTimeoutError,!0,f,m,g); - if (e instanceof tu) - throw new nu(!1,e.message,e.code,{ - code: e.code, - text: "Playlist Network Error" - },!1,f,m,g); - throw e - } - )))); - var f, m, g - } - , Em = (f,e,m,t,g)=>Bi(e).pipe(Ra(e=>{ - const {keyTagInfo: t, isInitSegment: i, iframe: r, byteRangeOffset: n} = f - , s = t["method"] - , {start: a, end: o} = n; - if ("AES-128" !== s) - return Bi(e); - { - !t.uri || t.iv || t.format && "identity" !== t.format || (t.iv = function(t) { - const i = new Uint8Array(16); - for (let e = 12; e < 16; e++) - i[e] = t >> 8 * (15 - e) & 255; - return i - }(f.mediaSeqNum)); - const n = e - , s = t.key.buffer - , d = t.iv.buffer - , l = o && (r || i) ? o - a : void 0 - , u = !m.enableWebCrypto || !!l - , c = s.slice(0) - , h = d.slice(0) - , p = { - useJSCrypto: u, - plainTextLength: l - }; - return g.decrypt(c, h, "AES-CBC", n, p) - } - } - )); - class Im { - constructor(e) { - this.option = e - } - get name() { - return this.option.name - } - get priority() { - return this.option.priority - } - get expiry() { - return this.option.expiry - } - filter(i, e) { - const r = this.option.initFn && this.option.initFn(i, e) || (e ? Object.assign({}, e) : {}); - let t = i; - return this.option.firstPassFn && i.forEach((e,t)=>this.option.firstPassFn(e, t, r, i)), - this.option.filterFn && (t = i.filter((e,t)=>this.option.filterFn(e, t, r, i))), - null != this.option.filterFn && 0 !== t.length || !this.option.minSortingFn || (t = i.sort((e,t)=>this.option.minSortingFn(e, t, r, i))), - this.option.finalFn && this.option.finalFn(t, r, i), - t - } - } - function wm(e, t, i) { - return (t || []).reduce((e,t)=>t.filter(e, i), Array.from(e)) - } - function Am(t, e) { - return e.filter(e=>{ - return yl(t, null !== (e = e.url) && void 0 !== e ? e : null) - } - ) - } - function Om() { - return [new Im({ - name: "Remove Filter", - priority: 0, - filterFn: (t,e,i)=>!i || i.removed.every(e=>t.mediaOptionId !== e) - }), new Im({ - name: "Penalty Box Filter", - priority: 1, - filterFn: (t,e,i)=>{ - const r = performance.now(); - return !i || i.penaltyBoxQueue.every(e=>e.expiry <= r || t.mediaOptionId !== e.mediaOptionId) - } - }), new Im({ - name: "Compatible IDs Filter", - priority: 1, - filterFn: (t,e,i)=>!i || null == i.compatibleIds || i.compatibleIds.some(e=>e === t.mediaOptionId) - })] - } - class km extends Od { - constructor(e, t, i) { - super(e), - this.itemId = t, - this.mediaOptionType = i, - this.allowFilters = this._initFilters() - } - get mediaOptionList() { - var e; - return (null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.mediaOptions) || null - } - get mediaOptionList$() { - return this.mediaOptionListInfo$.pipe(ur(({mediaOptions: e})=>e)) - } - mediaOptionFromId(t) { - var e; - return null !== (e = (null !== (e = this.mediaOptionList) && void 0 !== e ? e : []).find(e=>e.mediaOptionId === t)) && void 0 !== e ? e : null - } - _getFilteredList(e) { - return wm(e.mediaOptions, this.allowFilters, e) - } - get filteredMediaOptionList() { - return this.mediaOptionListInfo ? this._getFilteredList(this.mediaOptionListInfo) : null - } - get filteredMediaOptionList$() { - return this.mediaOptionListInfo$.pipe(Ra(e=>{ - const t = [Ul] - , i = performance.now(); - for (const r of e.penaltyBoxQueue) - ne(r.expiry) && r.expiry > i && t.push(vn(r.expiry - i)); - return nn(...t).pipe(ur(()=>this._getFilteredList(e))) - } - ), yd()) - } - get preferredMediaOptionList() { - return this.filteredMediaOptionList ? Am(this.preferredHost, this.filteredMediaOptionList) : [] - } - get preferredMediaOptionList$() { - return Zd([this.preferredHost$, this.filteredMediaOptionList$]).pipe(ur(([e,t])=>Am(e, t))) - } - getNewHost(e) { - e = this.getFallbackVariant(e, !1, !0); - return null != e && e.url ? gl(e.url) : this.preferredHost - } - } - function Cm(e) { - return "PQ" === e.videoRange || "HLG" === e.videoRange - } - function Dm(e, t) { - return t.iframes === e - } - function Mm(e, t, i, r) { - return !r || i.bitrate > r.bitrate && i.bitrate <= e.bitrate ? fm.Better : i.bitrate === r.bitrate ? fm.Same : fm.Worse - } - function Pm(e, t) { - return e && !t ? -1 : !e && t ? 1 : 0 - } - (dd = fm = fm || {})[dd.Better = 1] = "Better", - dd[dd.Same = 0] = "Same", - dd[dd.Worse = -1] = "Worse"; - class xm extends km { - constructor(e, t) { - super(e, t, ul.Variant) - } - static makeFilters() { - return [...Om().concat([new Im({ - name: "HDR Filter", - priority: 1, - filterFn: (e,t,i)=>!i || (i.hasHdrLevels && i.preferHDR) === Cm(e) - }), new Im({ - name: "Viewport Filter", - priority: 1, - firstPassFn: (e,t,i)=>{ - if (i && e && !e.iframes && e.videoCodec) { - const t = !i.lowestBitrate || e.bitrate < i.lowestBitrate ? e.bitrate : i.lowestBitrate; - i.lowestBitrate = t - } - } - , - filterFn: (e,t,i)=>!(e && i && i.viewportInfo && e.videoCodec && i.lowestBitrate) || function(e, t) { - return e.width < 1.35 * t.width && e.height < 1.35 * t.height && e.width * e.height < t.width * t.height * 1.35 - }({ - width: e.width, - height: e.height - }, i.viewportInfo) || e.bitrate === i.lowestBitrate - }), new Im({ - name: "HDCP Filter", - priority: 2, - filterFn: (e,t,i)=>!i || !Xf(i.maxHdcpLevel) || Yf(e.hdcpLevel) < Yf(i.maxHdcpLevel) - })])].sort((e,t)=>{ - return (null !== (e = e.priority) && void 0 !== e ? e : Number.MAX_SAFE_INTEGER) - (null !== (t = t.priority) && void 0 !== t ? t : Number.MAX_SAFE_INTEGER) - } - ) - } - _initFilters() { - return xm.kAllowFilters - } - get preferredHost() { - var e; - return null !== (e = null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.preferredHost) && void 0 !== e ? e : null - } - get preferredHost$() { - return this.selectEntity(this.itemId, e=>{ - return null !== (e = null == e ? void 0 : e.mediaOptionListTuple[ul.Variant].preferredHost) && void 0 !== e ? e : null - } - ) - } - get mediaOptionListInfo() { - var e; - return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionListTuple[ul.Variant]) && void 0 !== e ? e : null - } - get mediaOptionListInfo$() { - return this.selectEntity(this.itemId, e=>{ - return null === (e = null == e ? void 0 : e.mediaOptionListTuple) || void 0 === e ? void 0 : e[ul.Variant] - } - ).pipe(Up()) - } - get hdrMode$() { - return this.mediaOptionListInfo$.pipe(ur(e=>!0 === e.preferHDR && e.hasHdrLevels), Es()) - } - get maxHdcpLevel$() { - return this.selectEntity(this.itemId, e=>{ - e = null === (e = null == e ? void 0 : e.mediaOptionListTuple) || void 0 === e ? void 0 : e[ul.Variant]; - return null == e ? void 0 : e.maxHdcpLevel - } - ).pipe(Es()) - } - listFallbackVariants(t, e, i, r, n) { - var s = this.mediaOptionListInfo - , a = null === (o = this.mediaOptionList) || void 0 === o ? void 0 : o.find(e=>e.mediaOptionId === t); - if (!a || !s) - return null; - var o = this.makeFilteredListFromVariant(a, e, n); - if (!o) - return null; - e = gl(a.url), - s = s.hasScore; - return xm._listFallbackVariants(o, a, e, s, i, r, n) - } - getFallbackVariant(t, e, i, r) { - var n = this.mediaOptionListInfo - , s = null === (s = this.mediaOptionList) || void 0 === s ? void 0 : s.find(e=>e.mediaOptionId === t); - if (!s || !n) - return null; - e = this.makeFilteredListFromVariant(s, e, r); - if (!e) - return null; - r = gl(s.url), - n = n.hasScore; - return xm._getFallbackVariant(e, s, r, n, i) - } - makeFilteredListFromVariant(e, t, i) { - let r = this.mediaOptionListInfo; - if (!e || !this.mediaOptionList || !r) - return null; - r = Object.assign(Object.assign({}, r), { - includeAllEligiblePathways: !0 - }); - e = Array.from(this.mediaOptionList); - let n = t ? wm(e, this.allowFilters, Object.assign(Object.assign({}, r), { - preferHDR: !1, - compatibleIds: null - })) : this._getFilteredList(r); - return n ? (i && 0 < i.length && (n = n.filter(e=>!i.includes(e.mediaOptionId))), - n) : null - } - get hasIframes() { - var e; - return null !== (e = null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.hasIframeLevels) && void 0 !== e && e - } - canSwitchToSDR(e, t, i=!1) { - var r = this.mediaOptionListInfo; - if (!this.mediaOptionList || !r) - return !1; - var n = this.mediaOptionFromId(e); - if (!n) - return !1; - if (!Cm(n)) - return !1; - var s = gl(n.url) - , e = wm(Array.from(this.mediaOptionList), this.allowFilters, Object.assign(Object.assign({}, r), { - preferHDR: !1, - compatibleIds: null - })) - , r = r.hasScore; - return null != xm._getFallbackVariant(e, n, s, r, t, i) - } - static _listFallbackVariants(e, r, n, t, s, a=!1, i=null) { - let o = !1; - const d = function(e, s, a) { - const t = [...e] - , o = gl(s.url) - , d = s.audioGroupId; - return t.sort((e,t)=>{ - let i = 0; - var r = a && ne(e.score) && ne(t.score) - , n = r ? e.score > t.score && e.score <= s.score : e.bitrate > t.bitrate && e.bitrate <= s.bitrate - , r = r ? e.score === t.score : e.bitrate === t.bitrate; - return n ? i = -1 : r ? (i = Pm(yl(o, e.url), yl(o, t.url)), - 0 === i && (i = Pm(!d || e.audioGroupId === d, !d || t.audioGroupId === d))) : i = 1, - i - } - ), - t - }(e.filter(e=>{ - var t = !(e.iframes !== r.iframes || s && yl(n, e.url)) - , i = a ? e.bitrate < r.bitrate : e.bitrate <= r.bitrate - , i = t && i; - return r.mediaOptionId === e.mediaOptionId ? (o = i, - !1) : i - } - ), r, t); - return !o || i && i.includes(r.mediaOptionId) || d.unshift(r), - d - } - static _getFallbackVariant(e, t, i, r, n, s=!1) { - let a = null; - e = (e = s ? e.filter(e=>e.bitrate < t.bitrate) : e).filter(e=>e.mediaOptionId !== t.mediaOptionId && e.iframes === t.iframes); - if (n && null != i) - for (const o of e) - Mm(t, 0, o, a) !== fm.Better || yl(i, o.url) || (a = o); - else - for (const o of e) { - const r = Mm(t, 0, o, a); - r !== fm.Better && (r !== fm.Same || !yl(i, o.url) || yl(i, a.url) && o.audioGroupId !== t.audioGroupId) || (a = o) - } - return a - } - getMatchingVariant(e, t) { - var i = this.mediaOptionFromId(e) - , r = gl(null == i ? void 0 : i.url) - , n = t.mediaOptionType === ul.AltAudio ? "audioGroupId" : "subtitleGroupId"; - let s = null; - this.mediaOptionListInfo.hasScore; - for (const e of this.filteredMediaOptionList) - if (e[n] === t.groupId) { - if (!i) { - s = e; - break - } - var a = Mm(i, 0, e, s); - a !== fm.Better && (a !== fm.Same || s.mediaOptionId === i.mediaOptionId || e.mediaOptionId !== i.mediaOptionId && !yl(r, e.url)) || (s = e) - } - return s - } - get currentPathwayID() { - var e; - return null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.currentPathwayID - } - } - function Rm(e, t) { - switch (e) { - case mm.SendAlternateToPenaltyBox: - e = mm.RetryRequest, - 401 !== t && 403 !== t && 407 !== t && t !== $.CorruptStream.code && t !== $.LivePlaylistUpdateError.code || (e = mm.SendEndCallback); - break; - case mm.RemoveAlternatePermanently: - e = mm.SendEndCallback - } - return e - } - function Lm(e, t, i, r, n, s, a, o=!1) { - const d = s.mediaOptionListQueries[n] - , l = 0 != (e.errorActionFlags & gm.MoveAllAlternatesMatchingHost) - , u = s.mediaOptionListQueries[n].mediaOptionFromId(r) - , c = a.getFallbackMediaOptionTupleFromMediaOptionId(s, n, r, u.backingMediaOptionId, !1, l, o); - let {errorAction: h, errorActionFlags: p} = e; - return s.isValidMediaOptionTuple(c) ? yl(d.preferredHost, c[n].url) && (p &= ~gm.MoveAllAlternatesMatchingHost) : (t || (h = Rm(h, i), - p = 0), - d instanceof xm && (!0 === d.mediaOptionFromId(r).iframes ? (h = mm.DoNothing, - p = 0) : !t && a.canSwitchToSDR(s, r, l, o) && (h = e.errorAction, - p = gm.SwitchToSDR))), - { - errorAction: h, - errorActionFlags: p - } - } - function _m(e) { - let t, i = 0; - switch (e) { - case 0: - t = mm.SendAlternateToPenaltyBox, - i = gm.MoveAllAlternatesMatchingHost; - break; - case 410: - t = mm.RemoveAlternatePermanently; - break; - case 500: - case 502: - case 503: - case 504: - case 404: - case 409: - case 401: - case 403: - case 407: - case $.LivePlaylistUpdateError.code: - case $.PlaylistNotReceived.code: - default: - t = mm.SendAlternateToPenaltyBox, - i = 0 - } - return { - errorAction: t, - errorActionFlags: i - } - } - function Nm(i, r, n, s, a, o, d) { - var {errorAction: l, errorActionFlags: u} = i; - let e = !0; - switch (l) { - case mm.RemoveAlternatePermanently: - case mm.SendAlternateToPenaltyBox: - { - if (null == a || null == o) - return r.handled = !1; - const i = n.itemId; - let e = o - , t = n.mediaOptionListQueries[a].mediaOptionFromId(o); - t.backingMediaOptionId && (e = t.backingMediaOptionId, - t = n.mediaOptionListQueries[a].mediaOptionFromId(e)); - var c = 0 != (u & gm.MoveAllAlternatesMatchingHost) - , h = 0 != (u & gm.MoveAllAlternatesMatchingHDCP) - , p = 0 != (u & gm.SwitchToSDR) - , f = l === mm.RemoveAlternatePermanently; - if (h && "hdcpLevel"in t) { - const r = t.hdcpLevel; - s.setMaxHdcpLevel(i, r) - } - if (p && s.switchToSDROnly(i), - c) { - const r = gl(t.url); - s.moveAllWithMatchingHosts(i, a, r, f) - } else - f ? s.removePermanently(i, a, e) : s.addToPenaltyBox(i, a, e); - if (n.enabledMediaOptionIdByType(a) === o) { - let e = [Ol, Ol, Ol]; - e = s.getFallbackMediaOptionTupleFromMediaOptionId(n, a, o, null, !1, c, d), - n.isValidMediaOptionTuple(e) ? s.setPreferredHost(i, gl(e[ul.Variant].url)) : r.fatal = !0, - r.fatal && (e = [Ol, Ol, Ol]), - s.setNextMediaOptions(n.itemId, e) - } - break - } - case mm.SendEndCallback: - r.fatal = !0; - break; - case mm.RetryRequest: - case mm.DoNothing: - default: - e = !1 - } - return r.handled = e, - e - } - function Fm(e, t) { - t instanceof ru || t instanceof nu || t instanceof au || (t instanceof uu || t instanceof lu) && oe(t.keyuri) - } - function Bm(t, i, r) { - if (t.handled = !0, - r && i < r.maxNumRetry && ne(r.retryDelayMs)) { - let e; - return e = "linear" === r.backoff ? (i + 1) * r.retryDelayMs : Math.pow(2, i) * r.retryDelayMs, - e = Math.min(r.maxRetryDelayMs, e), - Fm(0, t), - vn(e) - } - return t.fatal = !0, - Fm(0, t), - Ui(t) - } - function Um(e, t, i, r, n, s, a, o, d=!1) { - return (null == r ? void 0 : r.errorAction) === mm.RetryRequest ? Bm(e, t, i, s.logger) : $m(e, 0, r, n, s, a, o, d) - } - function $m(e, t, i, r, n, s, a, o=!1) { - const d = new Ji; - return sd(()=>{ - i && (Fm(n.logger, e), - Nm(i, e, r, n, s, a, o)), - d.error(e) - } - ), - d - } - function Vm(t, i, r, n) { - return e=>e.pipe(Un(e=>{ - if (t.logger.error(`Got demux error ${e.message}`), - e instanceof D || e instanceof F) { - mm.SendAlternateToPenaltyBox; - return $m(e, 0, { - errorAction: e.fatal ? mm.SendEndCallback : e instanceof F ? mm.SendAlternateToPenaltyBox : mm.RemoveAlternatePermanently, - errorActionFlags: 0 - }, i, t, r, n) - } - throw e - } - )) - } - function Km(e, t, i, r, n) { - e = null !== (e = null === (e = n.getKeyInfo(e)) || void 0 === e ? void 0 : e.mediaOptionIds) && void 0 !== e ? e : []; - for (const s of e) - for (const n of i.mediaOptionListQueries) - null != n.mediaOptionFromId(s) && r.updateConsecutiveTimeouts(i.itemId, n.mediaOptionType, t, "key") - } - function Hm(r, t, e, n, s, a) { - const o = n.logger - , i = s.enabledMediaOptionKeys - , d = []; - for (const t of r.mediaOptionIds) { - const r = i.some(e=>e.mediaOptionId === t) - , e = s.mediaOptionListQueries.find(e=>null != e.mediaOptionFromId(t)); - if (e) { - const n = e.mediaOptionType - , a = { - mediaOptionId: t, - mediaOptionType: n - }; - r ? d.push(a) : d.unshift(a) - } else - o.warn(`Couldn't find query for ${t}`) - } - const l = new Ji; - return sd(()=>{ - const e = r instanceof lu; - Km(r.keyuri, e, s, n, a); - let t, i = !1; - for (const {mediaOptionId: e, mediaOptionType: a} of d) - t = function(e, t, i, r, n) { - let s = { - errorAction: mm.SendAlternateToPenaltyBox, - errorActionFlags: 0 - }; - if (e instanceof lu) - s.errorAction = mm.SendAlternateToPenaltyBox; - else { - const t = e.isOkToRetry; - e.keyErrorReason === Xl.OutputRestricted ? (s.errorAction = mm.RemoveAlternatePermanently, - s.errorActionFlags |= gm.MoveAllAlternatesMatchingHDCP) : t ? s = _m(e.code) : s.errorAction = mm.RemoveAlternatePermanently - } - s.errorActionFlags &= ~gm.MoveAllAlternatesMatchingHost; - var a = r.enabledMediaOptionIdByType(i); - return t === a ? Lm(s, !1, e.code, a, i, r, n, e.isTimeout) : s - }(r, e, a, s, n), - o.error(`[Keys] handleNetworkError uri=${oe(r.keyuri)} mediaOptionId=${e} mediaOptionType=${a} action=${JSON.stringify(t)}`), - t.errorAction === mm.RetryRequest && (i = !0), - Nm(t, r, s, n, a, e); - i ? (l.next(), - l.complete()) : (Fm(0, r), - l.error(r)) - } - ), - l.pipe(Ra(()=>Bm(r, t, e, n.logger))) - } - function jm(t, i, r, n, s, a, o, d) { - return n = Math.max(0, n), - e=>e.pipe(Ja(()=>{ - null != i && o.updateConsecutiveTimeouts(t, i, !1, "load") - } - ), ya(e=>e.pipe(Kr((e,t)=>function(e, t, i, r, n, s, a, o) { - var d; - if (!(e instanceof p)) - return Ui(e); - let l, u, c, h = !1; - if (e instanceof ru) - c = { - errorAction: Rm(_m((d = e).response.code).errorAction, d.response.code), - errorActionFlags: 0 - }; - else if (e instanceof nu || e instanceof au) { - ({mediaOptionType: u, mediaOptionId: l, isTimeout: h} = e); - const t = null === (d = s.mediaOptionListQueries[u]) || void 0 === d ? void 0 : d.mediaOptionFromId(l); - if (!r && e.isTimeout && null != t && (!("iframes"in t) || !0 !== t.iframes) && (a.updateConsecutiveTimeouts(s.itemId, e.mediaOptionType, !0, "load"), - e instanceof au && e.stats)) { - const t = performance.now(); - o.setBandwidthSample(Object.assign(Object.assign({}, e.stats), { - tfirst: e.stats.tfirst || t, - tload: e.stats.tload || t, - complete: !0, - mediaOptionType: u - })) - } - c = function(e, t, i, r, n) { - var s = e.response.code; - let a = _m(s); - var {mediaOptionId: o, mediaOptionType: d} = e; - return t ? a.errorActionFlags &= ~gm.MoveAllAlternatesMatchingHost : a = function(e, t, i, r, n) { - let {errorAction: s, errorActionFlags: a} = t; - if (e.isTimeout) { - const t = e["mediaOptionType"] - , o = null !== (n = null === (n = n.getErrorInfoByType(t)) || void 0 === n ? void 0 : n.timeouts.load) && void 0 !== n ? n : 0; - !i && r <= o && (s = mm.DoNothing, - a = 0) - } - return { - errorAction: s, - errorActionFlags: a - } - }(e, a, t, i, r), - a = Lm(a, t, s, o, d, r, n, e.isTimeout), - a - }(e, r, n, s, a) - } - return Um(e, t, i, c, s, a, u, l, h) - }(e, t, Rc(e, r), s, n, a, o, d))))) - } - xm.kAllowFilters = xm.makeFilters(), - (dd = mm = mm || {})[dd.DoNothing = 0] = "DoNothing", - dd[dd.SendEndCallback = 1] = "SendEndCallback", - dd[dd.SendAlternateToPenaltyBox = 2] = "SendAlternateToPenaltyBox", - dd[dd.RemoveAlternatePermanently = 3] = "RemoveAlternatePermanently", - dd[dd.InsertDiscontinuity = 4] = "InsertDiscontinuity", - dd[dd.RetryRequest = 5] = "RetryRequest", - (dd = gm = gm || {})[dd.MoveAllAlternatesMatchingHost = 1] = "MoveAllAlternatesMatchingHost", - dd[dd.MoveAllAlternatesMatchingHDCP = 2] = "MoveAllAlternatesMatchingHDCP", - dd[dd.SwitchToSDR = 4] = "SwitchToSDR"; - class qm extends Od { - constructor(e) { - super(e) - } - get currentConfig() { - var e; - return null === (e = this.getActive()) || void 0 === e ? void 0 : e.config - } - get extendMaxTTFB() { - var e; - return null === (e = this.getActive()) || void 0 === e ? void 0 : e.extendMaxTTFB - } - get config$() { - return this.selectActive(e=>null == e ? void 0 : e.config) - } - get userSeek$() { - return this.selectActive(e=>null == e ? void 0 : e.userSeek) - } - } - w(); - class Qm extends pd { - constructor() { - super({}, { - name: "hls-store", - producerFn: vc - }) - } - } - class Gm { - constructor(e) { - this.store = e - } - getQuery() { - return new qm(this.store) - } - setHlsEntity(e) { - const t = e.id; - Co(`hls.set.entity ${t}`), - sd(()=>{ - this.store.add(de(e)), - this.store.setActive(t) - } - ) - } - removeEntity(e) { - Co(`hls.remove ${e}`), - this.store.remove(e) - } - setStartTime(t) { - this.store.updateActive(e=>{ - e.config.startPosition = t - } - ) - } - setUserSeek(t) { - this.store.updateActive(e=>{ - e.userSeek = t - } - ) - } - setExtendMaxTTFB(t) { - this.store.updateActive(e=>{ - e.extendMaxTTFB = t - } - ) - } - } - let Wm, zm; - function Xm() { - return Wm = Wm || new Gm(new Qm), - Wm - } - function Ym() { - return Xm().getQuery().currentConfig - } - function Jm(e, t, i, r) { - var n = t.mediaSeqNum - e.startSN; - if (n < 0 || n >= e.fragments.length) - return e; - const s = Object.assign(Object.assign({}, e), { - fragments: e.fragments.map(e=>Object.assign({}, e)) - }) - , a = s.fragments - , o = a[n]; - if (!Fp(t, a[n])) - return null == r || r.warn("Parsed and existing fragments don't match"), - e; - var {startDtsTs: d, startPts: e, endPts: t} = t; - o.startDtsTs = d, - o.startPts = e, - o.endPts = t, - o.start = i, - o.duration = b(o.endPts, o.startPts); - for (let e = n; 0 < e; e--) - Zm(a, e, e - 1, r); - for (let e = n; e < a.length - 1; e++) - Zm(a, e, e + 1, r); - s.totalduration = 0; - for (const l of a) - s.totalduration += l.duration; - return s.ptsKnown = !0, - eg(s), - s - } - function Zm(e, t, i, r) { - const n = e[t] - , s = e[i]; - s.startPts ? (t < i && n.start + n.duration > s.start || i < t && s.start + s.duration > n.start) && (null == r || r.warn(`overlapping segments found ${n.mediaSeqNum}->${s.mediaSeqNum}`)) : s.start = t < i ? n.start + n.duration : Math.max(n.start - s.duration, 0) - } - function eg(e) { - if (e.programDateTimeMap) { - e.dateMediaTimePairs = []; - for (var [t,i] of Object.entries(e.programDateTimeMap)) { - t = Number(t), - i = e.fragments[i - e.startSN]; - i && (i = i.start, - e.dateMediaTimePairs.push([t, i])) - } - e.dateMediaTimePairs.sort((e,t)=>e[0] - t[0]) - } - } - function tg(t, i) { - if ("VOD" === t.type || "VOD" === i.type || t.iframesOnly !== i.iframesOnly) - return i; - var r = t.mediaOptionId === i.mediaOptionId; - let n = Object.assign(Object.assign({}, i), { - initSegments: {}, - fragments: [], - ptsKnown: !1 - }); - const s = Math.max(t.startSN, n.startSN) - n.startSN - , a = Math.min(t.endSN, n.endSN) - n.startSN - , o = n.startSN - t.startSN - , d = t.fragments - , l = i.fragments; - let u = 0; - for (let e = s; e <= a; ++e) - if (d[o + e] && l[e]) { - u = d[o + e].discoSeqNum - l[e].discoSeqNum; - break - } - const c = n.initSegments; - let h = null; - for (let e = 0; e < l.length; e++) { - const p = d[o + e] - , s = l[e] - , a = Object.assign({}, s) - , f = s.discoSeqNum + u; - i.initSegments[s.discoSeqNum] && (c[f] = Object.assign(Object.assign({}, i.initSegments[s.discoSeqNum]), { - discoSeqNum: f - })), - a.discoSeqNum = f, - r && a.mediaSeqNum === (null == p ? void 0 : p.mediaSeqNum) && null != p.startPts && (a.start = p.start, - a.duration = p.duration, - a.startDtsTs = p.startDtsTs, - a.endDtsTs = p.endDtsTs, - a.startPts = p.startPts, - a.endPts = p.endPts, - h = a), - n.fragments.push(a) - } - if (h) - n = Jm(n, h, h.start); - else if (0 <= o && o < d.length) { - const t = d[o].start - , i = n.fragments; - for (let e = 0; e < l.length; e++) - i[e].start += t - } - return n.ptsKnown = n.ptsKnown || r && !0 === t.ptsKnown && t.endSN >= i.startSN, - eg(n), - n - } - function ig(e, t, i) { - let r = t.targetduration; - return ne(i.liveSyncDuration) ? r = i.liveSyncDuration : ne(i.liveSyncDurationCount) && (r = i.liveSyncDurationCount * t.targetduration), - e + Math.max(0, t.totalduration - r) - } - function rg(e, t, i, r, n) { - if (!t.ptsKnown) - return 0; - var s = t.targetduration - , a = t.fragments[0].start - , r = n.canContinuePlaybackWithoutGap(t, i, { - avgPlaylistLoadTimeMs: 0, - avgPlaylistParseTimeMs: 0 - }, r); - let o = Math.max(0, e - s); - return e < a && !r && (o = a), - o - } - function ng(e) { - return 1e3 * (e.averagetargetduration || e.targetduration) - } - function sg(e, t) { - var i = ng(e) - , t = performance.now() - t; - return e.liveOrEvent && i <= t - } - function ag(e, t) { - return function(e) { - const t = [] - , i = e.fragments; - for (const e of i) { - const {discoSeqNum: i, start: r} = e; - t.push({ - timelineOffset: r, - mediaFragment: e - }) - } - return t - }(e).find(e=>t(e.mediaFragment)) - } - function og(s, e, a, t, o) { - var i; - const d = !t.liveOrEvent || t.ptsKnown; - let r = null !== (i = ag(t, t=>{ - var e = t.mediaSeqNum >= a - , i = 0 < t.duration - , r = t.start + t.duration - , n = !d || s < r || s - r < 1 && t.isLastFragment - , r = o.every(e=>!Fp(e.frag, t)); - return e && i && n && r - } - )) && void 0 !== i ? i : null - , n = NaN; - null != r && ne(e) && r.mediaFragment.discoSeqNum !== e && (n = r.mediaFragment.discoSeqNum, - r = null); - e = o.some(e=>0 < e.frag.framesWithoutIDR); - return r && e && o[o.length - 1].frag.mediaOptionId !== t.mediaOptionId && (r = null !== (t = ag(t, e=>e.mediaSeqNum === r.mediaFragment.mediaSeqNum - 1)) && void 0 !== t ? t : r), - { - foundFrag: r, - nextDisco: n - } - } - function dg(e) { - const t = e.fragments; - return t.map(e=>e.duration).reduce((e,t)=>e + t, null !== (e = t[0].start) && void 0 !== e ? e : 0) - } - class lg extends Od { - constructor(e, t) { - super(e), - this.mediaOption = t - } - get itemId() { - return this.mediaOption.itemId - } - get mediaOptionId() { - return this.mediaOption.mediaOptionId - } - get initSegmentEntities() { - var e; - return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.initSegmentCacheEntities - } - get mediaLibraryEntity() { - return this.getEntity(this.itemId) - } - get mediaOptionDetailsEntityRecord() { - var e; - return null === (e = this.mediaLibraryEntity) || void 0 === e ? void 0 : e.mediaOptionDetailsEntityRecord - } - get mediaOptionDetailsEntity() { - return this.mediaOptionDetailsEntityRecord ? this.mediaOptionDetailsEntityRecord[this.mediaOptionId] : null - } - get mediaOptionDetails() { - var e; - return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.mediaOptionDetails - } - get playlistDuration() { - var e; - return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.playlistDuration - } - get mediaOptionDetailsEntity$() { - const {itemId: e, mediaOptionId: t} = this; - return this.selectEntity(e, e=>{ - if (null != e && e.mediaOptionDetailsEntityRecord) - return null == e ? void 0 : e.mediaOptionDetailsEntityRecord[t] - } - ) - } - get mediaOptionDetails$() { - return this.selectEntity(this.itemId, e=>{ - return null === (e = null == e ? void 0 : e.mediaOptionDetailsEntityRecord[this.mediaOptionId]) || void 0 === e ? void 0 : e.mediaOptionDetails - } - ).pipe(Up()) - } - get playlistDuration$() { - return this.mediaOptionDetailsEntity$.pipe(ur(e=>null == e ? void 0 : e.playlistDuration), Up(), Es()) - } - get live$() { - return this.mediaOptionDetails$.pipe(ur(e=>null == e ? void 0 : e.liveOrEvent), Es()) - } - } - class ug extends pd { - constructor() { - super({}, { - name: "media-library-store", - idKey: "itemId", - producerFn: vc - }) - } - } - class cg { - constructor(e) { - this.store = e - } - getQuery() { - return new Od(this.store) - } - getQueryForOption(e) { - return new lg(this.store,e) - } - createMediaLibraryEntity(e) { - var t = { - itemId: e, - mediaOptionDetailsEntityRecord: {} - }; - Co(`library.entity.create: ${e}`), - this.store.add(t) - } - setDetailsLoading(e) { - const {itemId: t, mediaOptionId: i} = e; - Co(`library.details.loading: ${i}`), - this.store.update(t, ({mediaOptionDetailsEntityRecord: e})=>{ - e[i] || (e[i] = { - initSegmentCacheEntities: {}, - unchangedCount: 0 - }), - e[i].detailsLoading = !0 - } - ) - } - archiveMediaOptionDetails(i, r, n) { - const {itemId: e, mediaOptionId: s} = i - , a = performance.now() - , o = dg(i); - Co(`library.details.loaded: ${s}`), - this.store.update(e, e=>{ - const t = e.mediaOptionDetailsEntityRecord[s]; - t.detailsLoading = !1, - t.mediaOptionDetails = i, - t.lastUpdateMillis = a, - n ? t.unchangedCount = 0 : ++t.unchangedCount, - t.playlistDuration = o, - t.stats = r, - e.liveOrEvent = i.liveOrEvent - } - ) - } - setInitSegmentLoading(e) { - const {itemId: t, mediaOptionId: i, discoSeqNum: r} = e; - Co(`library.initsegs.loading: ${i}/${r}`), - this.store.update(t, e=>{ - e.mediaOptionDetailsEntityRecord[i].initSegLoading = r - } - ) - } - archiveInitSegmentEntity(i, r) { - const {itemId: e, mediaOptionId: n, discoSeqNum: s} = i; - Co(`library.initseg.loaded: ${n}/${s}`), - this.store.update(e, ({mediaOptionDetailsEntityRecord: e})=>{ - const t = e[n]; - t.initSegmentCacheEntities[s] = [i, r], - t.initSegLoading = null - } - ) - } - updatePTSDTS(e, r, n, s) { - this.store.update(e, ({mediaOptionDetailsEntityRecord: e})=>{ - const t = e[r]; - var i; - null != t && t.mediaOptionDetails && ({variantDTS: i, timelineOffset: e} = n, - e = S(s.startDtsTs) - S(i) + e, - e = Jm(t.mediaOptionDetails, s, e), - t.mediaOptionDetails = e, - t.playlistDuration = dg(e)) - } - ) - } - remove(e) { - this.store.remove(e) - } - clear() { - this.store.remove() - } - } - function hg() { - return zm = zm || new cg(new ug), - zm - } - const pg = e=>hg().getQueryForOption(e) - , fg = (d,e,t=!1)=>{ - if (!kl(e)) - return Bi(null); - const i = e["itemId"] - , r = d["mediaLibraryService"] - , n = r.getQueryForOption(e); - n.hasEntity(i) || r.createMediaLibraryEntity(i); - var s = n.mediaOptionDetailsEntity - , a = n.mediaOptionDetails; - return null == a || t || "VOD" !== a.type && (!a.liveOrEvent || sg(a, s.lastUpdateMillis)) ? (r.setDetailsLoading(e), - function(l) { - var e; - const {logger: t, config: u, rootPlaylistQuery: c, rootPlaylistService: h, statsService: i, mediaLibraryService: p, mediaSink: r} = d - , f = r.mediaQuery - , n = u.playlistLoadPolicy - , s = u.keySystemPreference - , a = c.masterVariableList - , o = null === (e = null === (e = Xm()) || void 0 === e ? void 0 : e.getQuery()) || void 0 === e ? void 0 : e.extendMaxTTFB; - return Tm(l, c.itemStartOffset, u, n, t, s, i, a, o).pipe(Hi(Zi), ur(t=>{ - const i = p.getQueryForOption(l) - , r = i.mediaOptionDetails; - let n = t["mediaOptionDetails"]; - var e = t["stats"]; - let s = !0; - if (n.liveOrEvent) { - const d = n["mediaOptionType"]; - t = n, - s = null == r || t.endSN !== r.endSN || t.liveOrEvent !== r.liveOrEvent; - let e = n; - r && (e = tg(r, n)); - const i = c.lastLoadedMediaOptionByType(d) - , u = i ? null === (t = p.getQueryForOption(i)) || void 0 === t ? void 0 : t.mediaOptionDetails : null; - !e.ptsKnown && u && u.mediaOptionId !== (null == r ? void 0 : r.mediaOptionId) && (e = tg(u, n)), - n = e - } - n && (p.archiveMediaOptionDetails(n, e, s), - h.setLastLoadedMediaOptionByType(c.itemId, l.mediaOptionType, l)); - const a = !s && i.mediaOptionDetailsEntity.unchangedCount >= u.liveMaxUnchangedPlaylistRefresh - , o = function(e, t, i, r) { - t = rg(r.currentTime, e, t, i, r), - i = e.fragments[e.fragments.length - 1], - r = i.start + i.duration; - return { - expired: null != i && e.liveOrEvent && e.ptsKnown && r < t, - windowEnd: r, - minPosition: t - } - }(n, e.tload, u.maxBufferHole, f); - if (a || o.expired) { - e = a ? $.LivePlaylistUpdateError : { - text: `Live window too far in the past end:${o.windowEnd.toFixed(3)} minPosition:${o.minPosition}`, - code: 0 - }; - throw new nu(!1,e.text,e.code,e,!1,l.mediaOptionType,l.mediaOptionId,l.url) - } - return n - } - ), Ql.tag("getMediaOptionDetailsCommon.emit.loaded"), jm(l.itemId, l.mediaOptionType, xc(l, n), u.maxNumAddLevelToPenaltyBox, !1, c, h, i)).pipe(Cs(1)) - }(e)) : Bi(a).pipe(Ql.tag("retrieveMediaOptionDetails.emit.cached")).pipe(Cs(1)) - } - ; - const mg = (t,i)=>{ - if (!i) - return Bi(null); - const {mediaLibraryService: r, mediaParser: n} = t - , e = r.getQueryForOption(i) - , {mediaOption: s, mediaOptionDetailsEntityRecord: a, mediaOptionDetails: o} = e - , d = s["mediaOptionId"]; - if (null == a || !a[d]) - throw new Error("retrieveInitSegmentCacheEntity no details entity"); - if (!o) - throw new Error("retrieveInitSegmentCacheEntity no details"); - var l = a[d]["initSegmentCacheEntities"] - , u = o["initSegments"] - , c = i["discoSeqNum"]; - if (l[c]) { - const [t,r] = l[c]; - let e = t; - return r && (e = n.willBeTrackSwitch(i) ? t : r), - Bi(e) - } - const h = u[c]; - return h ? (r.setInitSegmentLoading(h), - yg(t, h, !1, !1).pipe(Hi(Zi), Ra(e=>gg(e, h, t)), Ql.tag("retrieveInitSegmentCacheEntity.emit"))) : Bi(null) - } - ; - function gg(e, n, t) { - const {logger: s, mediaSink: i, rootPlaylistService: r, rootPlaylistQuery: a, mediaParser: o, mediaLibraryService: d, gaplessInstance: l} = t - , u = i["mediaQuery"] - , c = d.getQueryForOption(n) - , {mediaOption: h, mediaOptionDetails: p} = c - , {itemId: f, mediaOptionId: m} = h - , {keyTagInfo: g, discoSeqNum: y, mediaOptionType: v} = n - , S = u.seeking - , b = p.liveOrEvent - , T = v === ul.Variant && p.ptsKnown; - let E, I; - n.isInitSegment ? I = new Uint8Array(e) : E = new Uint8Array(e); - var e = { - segment: E, - initSegment: I, - frag: n, - ptsKnown: T, - seeking: S, - live: b, - totalDuration: p.totalduration - }; - return o.parseInitSegment(e, null !== (e = null === navigator || void 0 === navigator ? void 0 : navigator.vendor) && void 0 !== e ? e : "").pipe(ur(e=>{ - var {track: t, moovData: i, mimeType: r} = e - , e = t["initSegment"]; - l.inGaplessMode && Se.isVideoCodec(t.codec) && (s.warn(`Video codec discovered in gapless mode codec:${t.codec}`), - l.dequeueSource("InvalidFormat")); - r = { - itemId: f, - mediaOptionId: m, - discoSeqNum: y, - initParsedData: i, - data: e, - mimeType: r, - keyTagInfo: g, - fragment: n - }; - return d.archiveInitSegmentEntity(r), - r - } - ), Vm(r, a, v, m)) - } - function yg(n, s, i, r) { - var e; - const {rootPlaylistQuery: t, rootPlaylistService: a, config: o, rtcService: d, statsService: l} = n - , {itemId: u, mediaOptionType: c} = s - , h = o.fragLoadPolicy - , p = ne(s.mediaSeqNum); - let f; - p && (f = { - getData: !1, - cb: (e,t,i,r)=>(a.updateInflightFrag(u, s.mediaOptionType, s, "loading", i), - !1) - }); - let m = !1; - return r && null === d.serverInfoInstance && (m = !0), - Jr([Sg(n, s.keyTagInfo, { - itemId: s.itemId, - mediaOptionId: s.mediaOptionId - }), qf(s, o, h, f, m, null === (e = null === (e = Xm()) || void 0 === e ? void 0 : e.getQuery()) || void 0 === e ? void 0 : e.extendMaxTTFB).pipe(Ja(([,,e,t])=>{ - i && l.setBandwidthSample(Object.assign(Object.assign({}, e), { - mediaOptionType: s.mediaOptionType - })), - r && m && (d.serverInfoInstance = t), - p && a.updateInflightFrag(u, s.mediaOptionType, s, "loaded", e) - } - ), jm(u, c, xc(s, h), o.maxNumAddLevelToPenaltyBox, !1, t, a, l))]).pipe(Cs(1), Ja(([,e])=>{ - var t; - r && ([t,,e] = e, - d.handleFragLoaded(t, e)) - } - ), Ra(([e,t])=>{ - const [i,r] = t; - return i.keyTagInfo.key = e.key, - Em(i, r, o, n.logger, n.rpcClients.crypto) - } - ), Ql.tag("getMediaFragmentCommon.emit")) - } - const vg = (i,e,t)=>{ - const {rootPlaylistService: r, rootPlaylistQuery: n} = i - , {timelineOffset: s, mediaFragment: a} = t.foundFrag - , {itemId: o, discoSeqNum: d} = a; - return r.updateInflightFrag(o, a.mediaOptionType, a, "loading", null), - Jr([Sg(i, a.keyTagInfo, { - itemId: a.itemId, - mediaOptionId: a.mediaOptionId - }), mg(i, a).pipe(Ra(t=>yg(i, a, !0, !0).pipe(Ra(e=>{ - return function(e, t, i, y, v, S) { - const r = new Uint8Array(e) - , {rootPlaylistService: n, mediaSink: s, mediaParser: a, rootPlaylistQuery: o, mediaLibraryService: b} = S - , d = s["mediaQuery"] - , l = b.getQueryForOption(y) - , {mediaOption: u, mediaOptionDetails: c} = l - , {itemId: T, mediaOptionId: E} = u - , {discoSeqNum: I, mediaSeqNum: w, mediaOptionType: h, isLastFragment: A} = y - , p = d.seeking - , f = c.liveOrEvent - , m = h === ul.Variant && c.ptsKnown - , O = { - segment: r, - frag: y, - seeking: p, - live: f, - ptsKnown: m, - totalDuration: c.totalduration, - defaultInitPTS: t, - iframeMediaStart: Np(y) ? y.iframeMediaStart : void 0, - iframeDuration: Np(y) ? y.iframeMediaDuration : void 0 - }; - let g; - if (null != i && (null === (t = y.keyTagInfo) || void 0 === t ? void 0 : t.uri) === (null === (t = i.keyTagInfo) || void 0 === t ? void 0 : t.uri)) - g = Bi(i); - else if (null != i) { - const e = Object.assign(Object.assign({}, i.fragment), { - keyTagInfo: y.keyTagInfo - }); - g = gg(i.data, e, S) - } else - g = gg(e, y, S); - return g.pipe(Ra(m=>{ - const g = performance.now(); - if (null != m) { - const g = m["data"] - , e = new Uint8Array(g); - O.initSegment = e - } - return a.parseSegment(O, "").pipe(ur(e=>{ - var t = performance.now() - , {startPTS: i, startDTS: r, endPTS: n, endDTS: s, firstKeyframePts: a, framesWithoutIDR: o, dropped: d, data1: l, data2: u, captionData: c, id3Samples: h, parsedInitSegment: e} = e - , t = { - durationSec: n.baseTime / n.timescale - i.baseTime / i.timescale, - parseTimeMs: t - g - }; - S.statsService.setFragSample(t); - let p = Object.assign({}, m); - if (e) { - const {track: g, moovData: f, mimeType: v} = e - , S = g["initSegment"]; - p = { - itemId: T, - mediaOptionId: E, - discoSeqNum: I, - initParsedData: f, - data: S, - mimeType: v, - keyTagInfo: y.keyTagInfo, - fragment: y - }, - b.archiveInitSegmentEntity(m, p) - } - e = y.keyTagInfo; - return [p, { - itemId: T, - mediaOptionId: E, - mediaSeqNum: w, - discoSeqNum: I, - startDtsTs: r, - endDtsTs: s, - timelineOffset: v, - firstKeyframePts: a, - framesWithoutIDR: o, - dropped: d, - data1: l, - data2: u, - startPts: i, - endPts: n, - keyTagInfo: e, - isLastFragment: A, - iframe: null !== (e = y.iframe) && void 0 !== e && e, - duration: y.duration, - iframeMediaDuration: Np(y) ? y.iframeMediaDuration : void 0, - captionData: c, - id3Samples: h - }] - } - )) - } - ), Vm(n, o, h, E)) - }(e, null === (e = n.getInitPTS(d)) || void 0 === e ? void 0 : e.offsetTimestamp, t, a, s, i) - } - ), Ja(e=>{} - ), Ql.tag(`retrieveMediaFragmentCacheEntity.${e}.emit`)))).pipe(Cs(1))]).pipe(Ra(([,e])=>Bi(e))) - } - ; - function Sg(e, t, i) { - const {keySystemAdapter: r, rootPlaylistQuery: n, rootPlaylistService: s, config: a} = e; - return r.getKeyFromDecryptData(t, i).pipe((o = t.uri, - d = xc({ - url: t.uri - }, a.keyLoadPolicy), - l = n, - u = s, - c = r.ksQuery, - e=>e.pipe(od(()=>{ - Km(o, !1, l, u, c) - } - ), ya(e=>e.pipe(Kr((e,t)=>{ - if (e instanceof lu || e instanceof uu) - return Hm(e, t, Rc(e, d), u, l, c); - throw e - } - )))))); - var o, d, l, u, c - } - class bg { - constructor(e, t, i) { - this.hls = e, - this.destroy$ = new zt, - this.iframeSwitchStart = 0, - this.logger = t.child({ - name: "hls-player-events" - }), - this.rtc = i, - this.subscribeAndEmit() - } - destroy() { - this.destroy$.next() - } - subscribeAndEmit() { - var e = this.loaderQueryListener(new fu(bc)) - , t = this.hls.publicQueries$.pipe(Ra(([e,t])=>nn(this.rootPlaylistQueryListener(e, t), this.mediaElementQueryListener(t, e)))); - nn(e, t, this.activeItemListener(this.hls.itemQueue)).pipe(Un(e=>{ - var t = e.message; - return this.logger.error(`Got error in HlsPlayerEvents ${t}`, e), - Ti - } - ), $a(this.destroy$), $s(()=>{} - )).subscribe() - } - activeItemListener(e) { - return e.activeItemById$.pipe(Up(), Ra(e=>{ - e = e.url; - return this.hls.trigger(P.MANIFEST_LOADING, { - url: e - }), - Ti - } - )) - } - rootPlaylistQueryListener(t, e) { - var i = t.enabledMediaOptionByType$(ul.Variant).pipe(an(e=>!!e), Ra(e=>{ - var t; - return this.hls.trigger(P.LEVEL_SWITCHING, e), - null === (t = this.rtc) || void 0 === t || t.handleLevelSwitching(e.url), - Ti - } - )) - , r = t.enabledMediaOptionByType$(ul.Variant).pipe(Ra(i=>pg(i).mediaOptionDetailsEntity$.pipe(an(e=>!0 === (null == e ? void 0 : e.detailsLoading)), Ja(e=>{ - var t = { - url: oe(null == i ? void 0 : i.url), - level: i.mediaOptionId, - type: Cl[i.mediaOptionType] - }; - return this.hls.trigger(P.LEVEL_LOADING, t), - Ti - } - )))) - , n = t.enabledMediaOptionByType$(ul.Variant).pipe(Ra(e=>{ - const t = pg(e); - let i = 0; - return t.mediaOptionDetailsEntity$.pipe(Up(), an(e=>{ - var t = null !== e.stats && !1 === e.detailsLoading && e.lastUpdateMillis > i; - return i = null !== (e = e.lastUpdateMillis) && void 0 !== e ? e : 0, - t - } - )) - } - ), Ra(e=>{ - var t = e.mediaOptionDetails - , i = e.stats - , r = { - mediaOptionId: t.mediaOptionId, - details: t, - playlistType: t.type, - stats: i - }; - if (null === (i = this.rtc) || void 0 === i || i.handleLevelLoaded(t, r.stats), - this.hls.trigger(P.LEVEL_LOADED, r), - 0 === e.unchangedCount) { - const e = { - level: 0, - details: t - }; - this.hls.trigger(P.LEVEL_UPDATED, e) - } - if (null != t && t.daterangeTags) { - const e = { - daterangeTags: t.daterangeTags - }; - this.hls.trigger(P.DATERANGE_UPDATED, e) - } - return Ti - } - )) - , s = t.enableMediaOptionSwitchedForType$(ul.AltAudio).pipe(Ra(e=>{ - e = t.alternateMediaOptionById(ul.AltAudio, e.mediaOptionId); - return e && this.triggerAudioSwitch(e), - Ti - } - )) - , a = t.rootPlaylistEntity$.pipe(an(e=>null !== e.enabledMediaOptionKeys[ul.AltAudio].mediaOptionId), Cs(1), Ra(e=>{ - const t = e.enabledMediaOptionKeys[ul.AltAudio].mediaOptionId; - return t && (e = e.mediaOptionListTuple[ul.AltAudio].mediaOptions.find(e=>e.mediaOptionId === t), - this.triggerAudioSwitch(e)), - Ti - } - )); - return nn(i, s, $l(e.textTracksCreated$, e=>e).pipe(Ra(()=>t.enabledMediaOptionByType$(ul.Subtitle).pipe(Ra(e=>{ - e = t.alternateMediaOptionById(ul.Subtitle, e.mediaOptionId); - return e ? this.hls.trigger(P.SUBTITLE_TRACK_SWITCH, { - track: Object.assign({}, e), - hidden: !1 - }) : this.hls.trigger(P.SUBTITLE_TRACK_SWITCH, { - track: void 0, - hidden: !1 - }), - Ti - } - )))), t.sessionData$.pipe(an(e=>null != e.complete), Cs(1), Ja(e=>{} - ), ur(e=>{ - this.hls.trigger(P.SESSION_DATA_COMPLETE, e) - } - )), t.getPreferredMediaOptionsByType$(ul.Variant).pipe(Oa(1), ur(e=>{ - const t = e; - null === (e = this.rtc) || void 0 === e || e.handleLevelsChanged(t), - t.forEach(e=>{} - ), - this.hls.trigger(P.LEVELS_CHANGED, { - requiresReset: !1, - levels: t - }) - } - )), t.getPreferredMediaOptionsByType$(ul.AltAudio).pipe(ur(e=>{ - this.hls.trigger(P.AUDIO_TRACKS_UPDATED, { - audioTracks: e - }) - } - )), $l(e.textTracksCreated$, e=>e).pipe(Ra(()=>t.getPreferredMediaOptionsByType$(ul.Subtitle).pipe(Cs(1), ur(e=>{ - this.hls.trigger(P.SUBTITLE_TRACKS_UPDATED, { - subtitleTracks: e - }), - this.hls.trigger(P.SUBTITLE_TRACKS_CREATED) - } - )))), n, r, a) - } - mediaElementQueryListener(s, e) { - return nn(s.seekTo$.pipe(ur(e=>{ - var t; - e && ne(e.pos) ? (null === (t = this.rtc) || void 0 === t || t.handleSeek("SEEKING"), - this.hls.trigger(P.SEEKING, { - seekToPos: e.pos - })) : null === e && (null === (e = this.rtc) || void 0 === e || e.handleSeek("SEEKED"), - this.hls.trigger(P.SEEKED)) - } - )), s.desiredRate$.pipe(xa(0), ca(), ur(e=>{ - var t = e[0] - , i = e[1]; - jp(i) ? 0 == this.iframeSwitchStart && (this.iframeSwitchStart = performance.now()) : this.iframeSwitchStart = 0, - this.hls.trigger(P.DESIRED_RATE_CHANGED, { - oldRate: t, - newRate: i - }), - null === (e = this.rtc) || void 0 === e || e.handleDesiredRateChanged(t, i) - } - )), s.sourceBufferEntityByType$(cl.AltAudio).pipe(an(e=>!!e), Es((e,t)=>e.totalBytes === t.totalBytes), ur(e=>{ - this.hls.trigger(P.BUFFER_APPENDED) - } - )), s.sourceBufferEntityByType$(cl.Variant).pipe(an(e=>!!e), Es((e,t)=>e.totalBytes === t.totalBytes), ur(e=>{ - var t; - null === (t = this.rtc) || void 0 === t || t.handleVariantBufferAppended(e.timestampOffset, e.totalBytes), - this.hls.trigger(P.BUFFER_APPENDED) - } - )), s.stallInfo$.pipe(Up(), So(s.combinedBuffer$), ur(([e])=>{ - var t; - null === (t = this.rtc) || void 0 === t || t.handleStalled(e, s.getCombinedBufferInfo(e.currentTime, 0).len), - this.hls.trigger(P.STALLED, e) - } - )), Cr([Bi(e), Zd([s.timeupdate$, s.bufferedSegmentsByType$(cl.Variant)]).pipe(so(1e3), ur(([t,e])=>null == e ? void 0 : e.find(e=>e.startPTS <= t && e.endPTS > t)), an(e=>!!e), xa(null), ca())]).pipe(Ra(([e,[t,i]])=>{ - var r = null == i ? void 0 : i.frag - , t = null == t ? void 0 : t.frag; - if (r && !Fp(t, r) && (this.hls.trigger(P.FRAG_CHANGED, i), - this.hls.inGaplessMode && this.checkAndTriggerReadyForNext(s, i), - !t || r.mediaOptionId !== t.mediaOptionId)) { - const s = e.mediaOptionListQueries[ul.Variant].mediaOptionFromId(r.mediaOptionId); - if (!s) - return this.logger.warn("variantInfo is undefined in fragChangeMonitor"), - Ti; - const n = t ? t.mediaOptionId : "" - , i = r.mediaOptionId; - s.iframes && (performance.now(), - this.iframeSwitchStart), - null === (r = this.rtc) || void 0 === r || r.handleLevelSwitched({ - url: s.url, - mediaOptionId: s.mediaOptionId, - oldVariant: "" !== n ? n : void 0, - newVariant: i - }), - this.hls.trigger(P.LEVEL_SWITCHED, s) - } - return Ti - } - )), s.isBufferedToEnd$(this.hls.config.maxBufferHole, !1).pipe(an(e=>!0 === e), Hi(Zi), ur(e=>{ - if (e && !this.hls.itemQueue.isPreloading() && this.hls.inGaplessMode) { - const i = s.getCombinedBufferInfo(s.currentTime, 0); - var t = 0; - i && (t = i.end, - e = s.mediaElementDuration, - 0 < t && e - s.currentTime < 10 && this.hls.trigger(P.READY_FOR_NEXT_ITEM, { - duration: t - })) - } - } - ))) - } - checkAndTriggerReadyForNext(e, t) { - var i, r; - t && t.frag && (i = e.currentTime, - (r = e.getCombinedBufferInfo(i, 0)) && (i = r.end, - r = e.mediaElementDuration, - e = e.bufferMonitorInfo, - e = Math.max(e.almostDryWaterLevelSeconds, e.lowWaterLevelSeconds / 2), - (r - t.endPTS <= e || t.frag.isLastFragment) && this.hls.inGaplessMode && !this.hls.isPreloading && this.hls.trigger(P.READY_FOR_NEXT_ITEM, { - duration: i - }))) - } - loaderQueryListener(e) { - return nn(e.unresolvedUriLoading$.pipe(ur(e=>e.map(e=>{ - e = { - uri: e.uri, - responseType: e.responseType, - userAgent: e.userAgent - }; - this.hls.trigger(P.UNRESOLVED_URI_LOADING, e) - } - )))) - } - triggerAudioSwitch(e) { - e && this.hls.trigger(P.AUDIO_TRACK_SWITCHED, { - id: e.id - }) - } - triggerManifestLoaded(e) { - e = { - levels: e.rootMediaOptionsTuple[ul.Variant], - audioTracks: e.rootMediaOptionsTuple[ul.AltAudio], - subtitleTracks: e.rootMediaOptionsTuple[ul.Subtitle], - url: e.baseUrl, - audioMediaSelectionGroup: e.audioMediaSelectionGroup, - subtitleMediaSelectionGroup: e.subtitleMediaSelectionGroup, - stats: e.stats, - isMediaPlaylist: e.isMediaPlaylist - }; - this.hls.trigger(P.MANIFEST_LOADED, e) - } - triggerManifestParsed(e) { - var t = { - levels: e.mediaOptionListQueries[ul.Variant].filteredMediaOptionList, - firstLevel: 0, - audio: !1, - video: !0, - altAudio: !1, - audioTracks: e.mediaOptionListQueries[ul.AltAudio].filteredMediaOptionList, - audioMediaSelectionGroup: e.audioMediaSelectionGroup, - subtitleMediaSelectionGroup: e.subtitleMediaSelectionGroup, - stats: e.loadStats - }; - null === (e = this.rtc) || void 0 === e || e.handleManifestParsed(t), - this.hls.trigger(P.MANIFEST_PARSED, t) - } - urlRedactedManifestLoaded(e) { - const t = Object.assign({}, e); - return t.url = oe(t.url), - t.levels = le(t.levels), - t.audioTracks = ue(t.audioTracks), - t.subtitleTracks = ue(t.subtitleTracks), - t - } - urlRedactedManifestParsed(e) { - const t = Object.assign({}, e); - return t.levels = le(t.levels), - t.audioTracks = ue(t.audioTracks), - t - } - } - (w = ym = ym || {}).LowBandwidth = "LowBandwidth", - w.HighBandwidth = "HighBandwidth", - w.PreferredListChanged = "PreferredListChanged", - w.IframeModeChange = "IframeModeChange", - w.None = ""; - const Tg = { - minValidBitrate: 2e6, - maxValidBitrate: 5e6, - maxPreferredBitrate: 3e6, - minValidHeight: 480, - maxValidHeight: 720 - }; - function Eg(e, a, o, d, l, u) { - return e.reduce((e,t)=>{ - if (t.iframes) - return e; - let i = e; - const r = (n = t.score, - s = a && o && d && l && !Ig(t, a, o, d, l, u) ? ll.INVALID : ll.VALID, - new Hp(s,n)); - var n, s; - return (!e || r.isGreaterThan(e.bestRank) || r.isEqualTo(e.bestRank) && t.bandwidth < e.selected.bandwidth) && (i = { - selected: t, - bestRank: r - }), - i - } - , null).selected - } - function Ig(e, t, i, r, n, s) { - var {targetDuration: a, targetStartupMs: o} = i - , d = r["avgPlaylistLoadTimeMs"] - , l = n["avgParseTimeMs"] - , {avgBufferCreateMs: i, avgInitFragAppendMs: r, avgDataFragAppendMs: n} = s - , {avgBandwidth: s, avgLatencyMs: t} = t; - return e.bandwidth <= s && (e.avgBandwidth || e.bandwidth) * a / s * 1e3 + d + i + +(t + l + (r + n)) <= o - } - const wg = { - name: "abr" - }; - function Ag(e, t) { - return ne(e) ? Math.min(e, t) : t - } - function Og(e) { - return ne(null == e ? void 0 : e.avgBandwidth) - } - function kg(e, t) { - return e.getCurrentWaterLevelByType(cl.Variant, t) / (0 !== e.playbackRate ? Math.abs(e.playbackRate) : 1) - } - function Cg(t, i, e, r) { - if (e) - return t; - let n = -1; - if (t < 0) - return n; - for (let e = t; e < i.length; ++e) { - const t = Mg(i[e], r); - if (t.altAudio && t.subtitle) { - n = e; - break - } - } - return n - } - function Dg(t, e, i, r, n, s, a) { - const o = i.preferredMediaOptions[ul.Variant].filter(e=>e.iframes === t); - if (!o.length) - return { - variantMediaOption: Ol.mediaOptionId, - holdOffDuration: 0, - lowestCandidate: null - }; - let d = 0; - const l = i.nextMinAutoOptionId; - if (l !== Ol.mediaOptionId) { - const t = o.findIndex(e=>e.mediaOptionId === l); - 0 <= t && (d = t) - } - if (d = Cg(d, o, t, i), - d < 0) - return { - variantMediaOption: Ol.mediaOptionId, - holdOffDuration: 0, - lowestCandidate: null - }; - let u = o.length - 1; - const c = i.nextMaxAutoOptionId; - if (c !== Ol.mediaOptionId) { - const t = o.findIndex(e=>e.mediaOptionId === c); - 0 <= t && (u = t) - } - var h = i.variantMediaOptionById(r.mediaOptionId) - , p = r.mediaOptionDetails - , f = (null == h ? void 0 : h.iframes) !== t ? 0 : kg(n, e.maxBufferHole); - let m, g; - if (t) { - const t = e.desiredIframeFPS; - g = p ? p.targetduration / t : 0, - g = Math.max(1 / t, g) - } else - g = p ? p.targetduration : 0; - h = e.abrBandWidthUpFactor, - p = e.abrBandWidthFactor; - return m = Pg(o, g, d, u, f, t, s.getCombinedEstimate(), s.bandwidthStatus, p, h, e, i, r, n, a), - m.variantMediaOption === Ol.mediaOptionId && (m = Pg(o, g, d, u, f + Ag(g, e.maxStarvationDelay), t, s.getCombinedEstimate(), s.bandwidthStatus, p, h, e, i, r, n, a), - m.variantMediaOption === Ol.mediaOptionId && 0 <= d && (m.variantMediaOption = o[d].mediaOptionId, - m.alternates = t ? null : Mg(o[d], i))), - m - } - function Mg(e, t) { - var i = t.enabledMediaOptionKeys - , r = i[ul.AltAudio] - , r = kl(r) ? t.mediaOptionListQueries[ul.AltAudio].getMatchingAlternate(r.mediaOptionId, e) : Ol - , i = i[ul.Subtitle]; - return { - altAudio: r, - subtitle: kl(i) ? t.mediaOptionListQueries[ul.Subtitle].getMatchingAlternate(i.mediaOptionId, e) : Ol - } - } - function Pg(i, r, n, e, s, a, o, d, t, l, u, c, h, p, f) { - "bandwidth-history-controller" !== u.abrBandwidthEstimator && f.warn(`Unsupported configuration: ${u.abrBandwidthEstimator} for ABR bandwidth estimator`); - const m = d.bandwidthSampleCount - , g = c.abrStatus - , y = p.maxBufferSize - , v = u.minTargetDurations || 1 - , S = c.mediaOptionListQueries[ul.Variant].mediaOptionListInfo.hasScore; - if (!i.length) - return { - variantMediaOption: Ol.mediaOptionId, - holdOffDuration: -1, - lowestCandidate: null - }; - const b = c.enabledMediaOptionIdByType(ul.Variant) - , T = c.variantMediaOptionById(b) - , E = null != i.find(e=>e.mediaOptionId === b) - , I = T && T.iframes === a - , w = T && I ? T.score : void 0 - , A = T && I ? T.frameRate : void 0 - , O = T && I ? T.height : void 0 - , k = I ? kg(p, u.maxBufferHole) : 0; - e = Math.max(0, Math.min(i.length - 1, e)), - n = Math.max(0, Math.min(i.length - 1, n)); - var C = h.mediaOptionDetailsEntityRecord - , D = xg(o.avgBandwidth, l, t, m); - let M; - for (let t = e; t >= n; t--) { - const n = i[t]; - let e = n.mediaOptionId; - const l = n.score - , u = C && C[e] ? C[e].mediaOptionDetails : void 0 - , h = C && C[e] ? C[e].lastUpdateMillis : null - , p = u ? u.totalduration / u.fragments.length : r - , f = null != T && n.bitrate > T.bitrate - , B = null != T && n.bitrate < T.bitrate - , m = !(null != A && (f && n.frameRate < A || B && n.frameRate > A)) - , U = !(f && null != O && O > n.height) - , $ = !(B && (n.bitrate === T.bitrate - 1 || n.bitrate === T.bitrate + 1)) - , V = !(S && f && null != w && (l < w || l === w && T && n.bitrate >= T.bitrate)) - , K = n.iframes === a; - if (ne(p) && K && m && U && $ && V) { - var {adjustedbw: P, bitrate: x, fetchDuration: R, rejectLevelDueToPeakBW: L, canFitMultipleSegments: _, requireAlternates: N, alternates: F} = function(e, t, i, r, n, s, a, o, d, l, u, c) { - var h = n ? a.bwUp : a.bwDown - , n = e.bitrate - , a = t ? t.totalduration / t.fragments.length : o - , s = Rg(e, t, o, h, ne(s.avgPlaylistLoadTimeMs) ? s.avgPlaylistLoadTimeMs : s.avgLatencyMs, l) - , l = e.bandwidth - , i = n < h && h < l && i <= 2 * a - , d = r * ((l || n || 0) * ((null == t ? void 0 : t.targetduration) || a)) / 8 <= d; - let p = null; - u = !u; - return u && (p = Mg(e, c), - p.altAudio && p.subtitle || (p = null)), - { - adjustedbw: h, - bitrate: n, - fetchDuration: s, - rejectLevelDueToPeakBW: i, - canFitMultipleSegments: d, - requireAlternates: u, - alternates: p - } - }(n, u, k, v, f, o, D, r, y, h, a, c); - if (N && Boolean(F) && (M = e), - x < P && _ && !L && (!N || Boolean(F)) && (a || !R || R < s)) - return L = P, - N = g, - P = (P = d).instantBw, - (N.fragDownloadSlow || N.fragDownloadTooSlow || ne(P) && P < L) && E && I && k <= 2 * p && f && (e = b), - { - variantMediaOption: e, - holdOffDuration: R, - alternates: F, - lowestCandidate: M - } - } - } - return { - variantMediaOption: Ol.mediaOptionId, - holdOffDuration: -1, - lowestCandidate: M - } - } - function xg(e, t, i, r) { - let n, s; - return 4 <= r ? (n = e * t, - s = e * i) : n = s = e / 1.8, - { - bwUp: n, - bwDown: s - } - } - function Rg(e, t, i, r, n, s) { - let a = e.bitrate * (t ? t.totalduration / t.fragments.length : i) / r; - return null == t || !t.liveOrEvent || t.ptsKnown && !_g(t.totalduration, n, s) || (a *= 2), - ne(n) && (!ne(s) || null != t && t.liveOrEvent) && (a += n / 1e3), - a - } - function Lg(t, e) { - let i = 1 / 0; - if (t === Ol.mediaOptionId) - return i; - var r = e.find(e=>e.mediaOptionId === t); - if (!r) - return 1 / 0; - const n = r.iframes - , s = r.bitrate - , a = r.frameRate - , o = e.find(e=>e.iframes === n && (void 0 === a || e.frameRate >= a) && e.bitrate > s); - return o && (i = o.bitrate), - i - } - function _g(e, t, i) { - return t = ne(t) ? t : 0, - !ne(i) || performance.now() - i + t > 1e3 * e - } - function Ng(e, t) { - return (null == e ? void 0 : e.fragDownloadSlow) === (null == t ? void 0 : t.fragDownloadSlow) && e.fragDownloadTooSlow === (null == t ? void 0 : t.fragDownloadTooSlow) - } - function Fg(e) { - return "loading" === (null == e ? void 0 : e.state) && ne(null === (e = e.bwSample) || void 0 === e ? void 0 : e.trequest) - } - const Bg = 2e3; - function Ug(e, t, i, r) { - let {fragDownloadSlow: n, fragDownloadTooSlow: s} = t; - var a = i.variantMediaOptionById(e.mediaOptionId).bitrate - , t = e.bwSample; - r = r.child(wg); - i = t.total || Math.max(t.loaded, Math.round(e.duration * a / 8)), - a = performance.now() - t.tfirst, - i = t.loaded * e.duration * 1e3 / i; - return a >= Bg && 1e3 <= a - i && (n || r.warn(`flow indicates low bandwidth, after time/duration behind real time: ${a}/${a - i}`), - n = !0), - a >= 1e3 * e.duration && (s || r.warn(`too much time spent downloading fragment, likely to switch down ${a} > ${1e3 * e.duration}`), - s = !0), - { - fragDownloadSlow: n, - fragDownloadTooSlow: s - } - } - function $g(e, t, i, r, n) { - var s; - const a = n.logger.child(wg) - , o = r.isIframeRate - , d = i.mediaOptionListQueries[ul.Variant].preferredMediaOptionList - , l = i.enabledMediaOptionKeys[ul.Variant]; - let u = e; - if (u !== ym.None || d.some(e=>e.mediaOptionId === l.mediaOptionId) || (u = ym.PreferredListChanged), - u !== ym.None && !(o && u !== ym.IframeModeChange && r.getBufferedSegmentsByType(cl.Variant).filter(e=>e.frag.iframe).length < t.minFramesBeforeSwitchingLevel)) { - const c = Uf(i.itemId) - , h = pg(l) - , p = [Ol, Ol, Ol] - , f = function(e, t, i, r, n, s, a) { - let o = t.nextMaxAutoOptionId; - if (o === Ol.mediaOptionId || Og(s.getBandwidthEstimate())) - return d = e, - l = t, - u = r, - e = n, - r = s, - s = a.child({ - name: "abr" - }), - a = e.isIframeRate, - l.enabledMediaOptionIdByType(ul.Variant), - Dg(a, d, l, u, e, r, s); - if (n.isIframeRate) - return { - variantMediaOption: o, - holdOffDuration: 0, - lowestCandidate: null - }; - { - const c = t.variantMediaOptionById(o) - , h = t.enabledAlternateMediaOptionByType(ul.Subtitle) - , n = t.enabledAlternateMediaOptionByType(ul.AltAudio) - , p = null == n ? void 0 : n.persistentID - , f = null == h ? void 0 : h.persistentID - , m = !t.preferHDR - , g = i.getBestMediaOptionTupleFromVariantAndPersistentId(t, c, p, f, void 0, [], m, !1, !1); - return t.isValidMediaOptionTuple(g) ? (o = g[ul.Variant].mediaOptionId, - { - variantMediaOption: o, - holdOffDuration: 0, - alternates: { - altAudio: g[ul.AltAudio], - subtitle: g[ul.Subtitle] - }, - lowestCandidate: null - }) : { - variantMediaOption: t.enabledMediaOptionKeys[ul.Variant].mediaOptionId, - holdOffDuration: 0, - lowestCandidate: null - } - } - var d, l, u - }(t, i, n, h, r, c, a); - if (f.variantMediaOption !== l.mediaOptionId) { - p[ul.Variant] = { - itemId: i.itemId, - mediaOptionId: f.variantMediaOption - }; - for (const e of [ul.AltAudio, ul.Subtitle]) { - const t = i.enabledMediaOptionIdByType(e); - if (t !== Ol.mediaOptionId) { - const r = e === ul.AltAudio ? null === (s = f.alternates) || void 0 === s ? void 0 : s.altAudio : null === (s = f.alternates) || void 0 === s ? void 0 : s.subtitle; - p[e] = r || { - itemId: i.itemId, - mediaOptionId: t - } - } - } - return n.setEnabledMediaOptions(i.itemId, p), - 1 - } - } - } - const Vg = { - name: "iframes" - } - , Kg = new pd({},{ - name: "item-queue", - producerFn: vc, - idKey: "itemId", - resettable: !0 - }) - , Hg = new class extends Od { - } - (Kg); - class jg { - constructor() { - this.firstItem = !0, - this.playingEntity = null, - this.loadingEntity = null - } - static createItem(e, t, i, r, n) { - const s = new Date - , a = `${s.getHours()}:${s.getMinutes()}:${s.getSeconds()}`; - qe(); - var o = function(e) { - e = sl.parseURL(e).fragment.substr(1); - if (0 === e.length) - return null; - const t = new URLSearchParams(e); - if (!t.has("t")) - return null; - e = Number(t.get("t")); - return ne(e) ? e : null - }(t); - if (o) - i = o; - else { - const e = Ym(); - ne(null == e ? void 0 : e.startPosition) && (i = e.startPosition) - } - return { - itemId: `${e}_${a}`, - name: e, - url: t, - serviceName: n, - createTime: a, - initialSeekTime: i, - itemStartOffset: 0, - platformInfo: r, - config: {} - } - } - get activeItemById$() { - return Hg.selectActiveId().pipe(ur(e=>Hg.getActive())) - } - get removedItems$() { - return Hg.selectEntityAction(To.Remove).pipe(ur(e=>e)) - } - get activeItem() { - return Hg.getActive() - } - get queueItems$() { - return Hg.selectAll().pipe(ur(e=>null != e ? e : [])) - } - get isFirstItem() { - return this.firstItem - } - get playingItem() { - return this.playingEntity - } - get loadingItem() { - return this.loadingEntity - } - addQueueItem(e, t, i, r, n, s) { - Hg.getCount(); - const a = jg.createItem(e, t, i, r, s); - null != this.playingEntity && (a.initialSeekTime = void 0), - n && (a.itemStartOffset = n, - this.firstItem = !1, - this.playingEntity = this.activeItem, - this.loadingEntity = a), - Co(`queue.add.item: ${e}`), - sd(()=>{ - Kg.add(a), - Kg.setActive(a.itemId) - } - ) - } - updatePlayingItemId() { - this.playingEntity = this.loadingEntity, - this.loadingEntity = null, - this.clearAllButActive() - } - resetLoadingItem() { - this.removeQueueItem(this.loadingEntity.itemId), - this.loadingEntity = null, - sd(()=>{ - Kg.setActive(this.playingEntity.itemId) - } - ) - } - isPreloading() { - return null !== this.playingEntity && null !== this.loadingEntity - } - setQueueItem(t, i, r, n, s) { - Co("queue.set.item"), - this.loadingEntity = null, - sd(()=>{ - Kg.reset(); - var e = jg.createItem(t, i, r, n, s); - Kg.add(e), - Kg.setActive(e.itemId) - } - ), - this.playingEntity = this.activeItem - } - removeQueueItem(e) { - Kg.remove(e) - } - clearQueue() { - Kg.reset() - } - clearAllButActive() { - var e; - const t = null === (e = this.activeItem) || void 0 === e ? void 0 : e.itemId; - sd(()=>{ - Hg.getAll().forEach(e=>{ - e.itemId !== t && Kg.remove(e.itemId) - } - ) - } - ) - } - set earlyAudioSelection(t) { - Kg.updateActive(e=>{ - e.earlySelection || (e.earlySelection = {}), - e.earlySelection.audioPersistentId = t - } - ) - } - get earlyAudioSelection() { - var e; - return null === (e = this.activeItem.earlySelection) || void 0 === e ? void 0 : e.audioPersistentId - } - set earlySubtitleSelection(t) { - Kg.updateActive(e=>{ - e.earlySelection || (e.earlySelection = {}), - e.earlySelection.subtitlePersistentId = t - } - ) - } - get earlySubtitleSelection() { - var e; - return null === (e = this.activeItem.earlySelection) || void 0 === e ? void 0 : e.subtitlePersistentId - } - } - function qg(e, t, i, r, n, s) { - return $m(e, 0, Lm({ - errorAction: mm.RemoveAlternatePermanently, - errorActionFlags: 0 - }, !1, e.response.code, i, t, s, n), s, n, t, i).pipe(Un(e=>{ - throw !1 === e.fatal && r.resetMediaSource(), - e - } - )) - } - function Qg(e, t) { - if (!e || 0 === e.length) - return 0; - const i = [...e].sort((e,t)=>t[0] - e[0]) - , r = t.getTime() - , n = null !== (t = i.find(([e])=>r >= e)) && void 0 !== t ? t : i[i.length - 1] - , [s,a] = n - , o = a + (r - s) / 1e3; - return Math.max(0, o) - } - function Gg(e, t) { - if (e && 0 !== e.length) { - const i = [...e].sort((e,t)=>t[1] - e[1]) - , r = null !== (e = i.find(([,e])=>e <= t)) && void 0 !== e ? e : i[i.length - 1] - , [n,s] = r; - return new Date(n + 1e3 * (t - s)) - } - } - function Wg(l, e, u, c, h, p) { - return e.child({ - name: "seek" - }), - e=>e.pipe(Ra((e,t)=>{ - var i, r, n, s, a, o, d = u.mediaQuery.seekTo$.pipe(Up()); - return i = 0 === t, - r = l, - n = h, - s = p, - (null == (t = e) ? Ti : t instanceof Date ? (a = t, - o = s, - n.enabledMediaOptionByType$(ul.Variant).pipe(Ra(e=>o.getQueryForOption(e).mediaOptionDetails$), ur(e=>Qg(e.dateMediaTimePairs, a)), Cs(1))) : function(n, e, s, a, t) { - let i = a.enabledMediaOptionByType$(ul.Variant).pipe(Ra(e=>t.getQueryForOption(e).mediaOptionDetails$), an(e=>ne(null == e ? void 0 : e.totalduration)), Cs(1), ur(e=>{ - var t = !e.liveOrEvent - , i = e.totalduration - , r = a.itemStartOffset; - return t ? ne(n) ? 0 <= n ? n : r + (i + n) : r + (ne(e.startTimeOffset) ? e.startTimeOffset : 0) : !ne(n) || n < 0 || 0 === n && s.liveEdgeForZeroStartPositon ? ig(0, e, s) : n - } - )); - return e && (i = i.pipe(Ja(e=>{} - ))), - i - }(t, i, r, n, s)).pipe($s(()=>{ - null != e && c.setPendingSeek(h.itemId, void 0) - } - ), $a(d)) - } - ), Ja(e=>{ - ne(e) && (u.seekTo = e) - } - )) - } - class zg { - constructor(e, t, i, r, n, s) { - this.logger = e, - this._rootPlaylistService = t, - this._rootQuery = i, - this._mediaQuery = r, - this._iframeMachine = n, - this._anchorMSNs = [NaN, NaN], - this._avDetails = [null, null], - this.logger = e.child({ - name: "fpicker" - }), - this._discoSeqNum = NaN, - this.lookUpTolerance = Math.max(s.maxBufferHole, s.maxFragLookUpTolerance) - } - destroy() { - this._anchorMSNs = [NaN, NaN], - this._avDetails = [null, null], - this._rootQuery = null, - this._mediaQuery = null, - this._rootPlaylistService = null, - this._iframeMachine = null - } - get discoSeqNum() { - return this._discoSeqNum - } - get _discoSeqNum() { - return this._rootQuery.discoSeqNum - } - set _discoSeqNum(e) { - this._rootPlaylistService.setDiscoSeqNum(this._rootQuery.itemId, e) - } - get anchorMSNs() { - return this._anchorMSNs - } - _resolvePosition(e, t, i) { - let r = e; - t = this._avDetails[t]; - if ((null == t ? void 0 : t.mediaOptionId) !== (null == i ? void 0 : i.mediaOptionId) && i.liveOrEvent && !1 === i.ptsKnown) - if (null != (null == t ? void 0 : t.dateMediaTimePairs) && i.dateMediaTimePairs) { - const n = Gg(t.dateMediaTimePairs, e); - r = Qg(i.dateMediaTimePairs, n) - } else { - const e = 3 * i.targetduration - , n = i.fragments[0].start + i.totalduration; - r = Math.max(0, n - e) - } - return r - } - _updateAnchorByPosition(e, t) { - let i = NaN; - const r = t[cl.Variant]; - if (r) { - const t = r.fragments - , n = this._resolvePosition(e, cl.Variant, r); - if (i = Bl.ccForTime(t, n), - !ne(i)) { - const r = t[0] - , s = t[t.length - 1] - , a = r.start - , o = s.start + s.duration; - this.logger.warn(`${e.toFixed(3)} out of range [${a.toFixed(3)},${o.toFixed(3)}]`), - e <= a ? i = r.discoSeqNum : e >= o && (i = s.discoSeqNum) - } - } else - this.logger.warn("No variant details for anchoring"); - this._updateAnchor(i, t) - } - _updateAnchor(e, n) { - const s = e !== this._discoSeqNum; - s && (this._discoSeqNum = e), - Ml.forEach(e=>{ - const t = this._avDetails[e] - , i = n[e] - , r = (null == t ? void 0 : t.mediaOptionId) !== (null == i ? void 0 : i.mediaOptionId); - if (s || r) - this._updateAnchorForType(xl(e), i); - else if (i) { - const {mediaOptionId: n, ptsKnown: s, dateMediaTimePairs: t} = i; - this._avDetails[e] = { - mediaOptionId: n, - ptsKnown: s, - dateMediaTimePairs: t - } - } - } - ) - } - getNextFragments(e, i) { - const {position: r, bufferInfoTuple: t, switchContexts: n} = e - , s = t.map((e,t)=>Xg(r, i[t], n[t], null == e ? void 0 : e.buffered, this.lookUpTolerance)).reduce((e,t)=>Math.min(t, e), Number.POSITIVE_INFINITY); - return this._updateAnchorByPosition(s, i), - this._getNextFragmentsInternal(e, i) - } - _getNextFragmentsInternal(i, r) { - const n = [null, null]; - r.forEach((e,t)=>{ - n[t] = this._getNextFragmentForType(i, r, t) - } - ); - var e = n[cl.Variant] - , t = n[cl.AltAudio] - , s = null === (a = null == e ? void 0 : e.foundFrag) || void 0 === a ? void 0 : a.mediaFragment - , a = null === (a = null == t ? void 0 : t.foundFrag) || void 0 === a ? void 0 : a.mediaFragment; - if (s && a && (a.start > s.start + s.duration ? (this.logger.warn("Audio too far ahead"), - n[cl.AltAudio] = zg.noopResult) : s.start > a.start + a.duration && !this._mediaQuery.isIframeRate && (this.logger.warn("Video too far ahead"), - n[cl.Variant] = zg.noopResult)), - !isFinite(null == e ? void 0 : e.nextDisco) || null != t && !ne(t.nextDisco)) - return n; - { - const o = n[cl.Variant].nextDisco; - return this._updateAnchor(o, r), - this._getNextFragmentsInternal(i, r) - } - } - _getNextFragmentForType(e, t, i) { - var {position: r, bufferInfoTuple: n, switchContexts: s} = e - , a = t[i] - , o = null !== (l = null === (c = n[i]) || void 0 === c ? void 0 : c.buffered) && void 0 !== l ? l : { - start: r, - end: r, - len: 0 - } - , d = this._mediaQuery.getBufferedSegmentsByType(i) - , l = null !== (c = null === (e = s[i]) || void 0 === e ? void 0 : e.userInitiated) && void 0 !== c && c - , u = Xg(r, a, s[i], o, this.lookUpTolerance); - if (!a) - return null; - var {highWaterLevelSeconds: e, lowWaterLevelSeconds: c} = this._mediaQuery.bufferMonitorInfo - , r = o.len; - if (!l && e <= r) - return zg.noopResult; - var e = i === cl.Variant ? cl.AltAudio : cl.Variant - , n = null === (n = n[e]) || void 0 === n ? void 0 : n.buffered - , e = null !== (e = null === (e = s[e]) || void 0 === e ? void 0 : e.userInitiated) && void 0 !== e && e; - let h = !1; - i === cl.Variant && c <= r && 1 < this._mediaQuery.expectedSbCount && null != n && n.end < o.end && (e || n.end - n.start < c) && (h = !0); - let p, f = null, m = NaN; - if (this._mediaQuery.isIframeRate && i === cl.Variant && a.iframesOnly) { - const g = function(e, t, i) { - e = i.nextFragment(a.fragments, (null == e ? void 0 : e.fragments) || [], t, u); - if (!e) - return null; - var {frag: t, newMediaRootTime: e} = e; - return { - foundFrag: { - timelineOffset: t.iframeMediaStart, - mediaFragment: t - }, - nextDisco: NaN, - newMediaRootTime: e - } - }(t[cl.AltAudio], this._mediaQuery.desiredRate, this._iframeMachine); - if (g) { - ({foundFrag: f, nextDisco: m, newMediaRootTime: p} = g); - const i = f.mediaFragment; - i.discoSeqNum !== this._discoSeqNum && this._updateAnchor(i.discoSeqNum, t) - } - } else { - const g = this._anchorMSNs[i]; - ({foundFrag: f, nextDisco: m, newMediaRootTime: p} = og(u, this._discoSeqNum, g, a, d)) - } - return h && this._rootQuery.getInitPTS(null == f ? void 0 : f.mediaFragment.discoSeqNum) ? zg.noopResult : { - foundFrag: f, - nextDisco: m, - newMediaRootTime: p - } - } - _updateAnchorForType(e, t) { - var i, r, n; - if (!t) - return this._anchorMSNs[e] = NaN, - void (this._avDetails[e] = null); - ne(this._discoSeqNum) ? (n = this._discoSeqNum, - n = null !== (r = null == (n = (r = t.fragments, - i = n, - r.find(e=>e.discoSeqNum === i))) ? void 0 : n.mediaSeqNum) && void 0 !== r ? r : t.startSN, - this._anchorMSNs[e] = n, - {mediaOptionId: r, ptsKnown: n, dateMediaTimePairs: t} = t, - this._avDetails[e] = { - mediaOptionId: r, - ptsKnown: n, - dateMediaTimePairs: t - }) : this.logger.warn("Trying to anchor with non-finite discoSeqNum") - } - } - function Xg(e, t, i, r, n) { - r = null != r ? r : { - start: e, - end: e, - len: 0 - }; - i = null !== (i = null == i ? void 0 : i.userInitiated) && void 0 !== i && i, - n = null != t && t.iframesOnly ? 0 : n; - return i || 0 === r.len ? e : r.end + n - } - zg.noopResult = { - foundFrag: null, - nextDisco: NaN - }; - const Yg = { - name: "avpipe" - }; - function Jg(r) { - const {config: o, rootPlaylistService: d, rootPlaylistQuery: l, mediaSink: e, gaplessInstance: t} = r - , u = e.mediaQuery - , i = Zd(Ml.map(e=>l.enabledMediaOptionSwitchForType$(e).pipe(Ja(e=>{} - )))).pipe(Ra(e=>{ - if (!kl({ - itemId: l.itemId, - mediaOptionId: e[ul.Variant].toId - })) - throw new V(!0,`No valid variant enabled id:${e[ul.Variant].toId}`,$.NoValidAlternates); - e = e.map(({fromId: e, toId: t},i)=>function(t, i, r, n, s) { - var e, a, o; - const {rootPlaylistQuery: d, rootPlaylistService: l, mediaSink: u, mediaParser: c, config: h, iframeMachine: p} = t - , f = u.mediaQuery; - if (!n || !s || n === s) - return Ul; - switch (r) { - case ul.Variant: - { - c.reset(ul.Variant); - const t = xl(r) - , l = d.variantMediaOptionById(n) - , g = d.variantMediaOptionById(s); - if (null == g || null == l) - return Ul; - let e = NaN; - if (l.iframes !== g.iframes || !g.iframes && p.isStarted) { - if (u.toggleTrickPlaybackMode(g.iframes), - !g.iframes && p.isStarted) { - const t = u.mediaQuery.autoPausedRestartTime - , i = t || p.iframeClockTimeSeconds; - u.autoPausedRestartTime = void 0, - e = i, - p.stop() - } - return u.pause(), - u.flushData(t, 0, 1 / 0, !0).pipe(Ja(()=>{ - isFinite(e) && (u.seekTo = e) - } - )) - } - if (!h.allowFastSwitchUp || g.iframes) - return Ul; - var m = pg(l).mediaOptionDetails; - if (null != m && null != g && l.bitrate < g.bitrate) { - const r = m.targetduration - , n = pg(g) - , s = n.mediaOptionDetails - , c = n.mediaOptionDetailsEntity.lastUpdateMillis - , p = f.getCurrentWaterLevelByType(t, h.maxBufferHole) - , y = function(e, t, i, r, n, s, a, o) { - if (n.nextMaxAutoOptionId !== Ol.mediaOptionId && !Og(s.getBandwidthEstimate())) - return Number.POSITIVE_INFINITY; - a = xg(s.getBandwidthEstimate().avgBandwidth, a.abrBandWidthUpFactor, a.abrBandWidthFactor, s.bandwidthStatus.bandwidthSampleCount), - s = ne(s.getPlaylistEstimate().avgPlaylistLoadTimeMs) ? s.getPlaylistEstimate().avgPlaylistLoadTimeMs : s.getBandwidthEstimate().avgLatencyMs, - a = t.bitrate > e.bitrate ? a.bwUp : a.bwDown; - return null == i || !i.liveOrEvent || i.ptsKnown && !_g(i.totalduration, s, o) ? Rg(t, i, r, a, s, o) : Number.POSITIVE_INFINITY - }(l, g, s, r, d.abrStatus, i, h, c) + h.maxStarvationDelay - , v = f.currentTime + y - , S = null === (o = null === (a = f.sourceBufferEntityByType(t)) || void 0 === a ? void 0 : a.bufferedSegments) || void 0 === o ? void 0 : o.find(e=>e.startPTS >= v); - let e; - if (S) { - const t = S.endPTS - S.startPTS; - e = S.startPTS + Math.min(Math.max(t - h.maxFragLookUpTolerance, .5 * t), .75 * t) - } - if (ne(e) && p >= y) - return u.flushData(t, e, 1 / 0) - } - } - break; - case ul.AltAudio: - e = d, - m = s, - o = "Nah" === (a = n) ? null : e.alternateMediaOptionById(ul.AltAudio, a), - o = Boolean(o && o.url), - m = "Nah" === a ? null : e.alternateMediaOptionById(ul.AltAudio, m), - m = Boolean(m && m.url), - o && !m && (l.setEnabledMediaOptionSwitchContextByType(d.itemId, ul.AltAudio, s, void 0), - u.resetMediaSource(f.currentTime)), - c.reset(ul.AltAudio) - } - return Ul - }(r, n, i, e, t)); - return Xr(Bi(!0), Jr(e).pipe(Js(!1))) - } - ), Ql.tag("mediaOptionSwitch.audiovideo.out")) - , n = Uf(l.itemId) - , s = r.logger.child(Yg) - , a = new zg(s,d,l,u,r.iframeMachine,o); - return Zd([l.anchorTime$.pipe(Ql.tag("anchorTime.audiovideo.in")), i]).pipe(Ra(([i,e])=>e ? Ti : u.needData$(o.maxBufferHole, t.inGaplessMode, t.isPreloading).pipe(ur(e=>{ - var t = [l.enabledMediaOptionSwitchContexts[ul.Variant], l.enabledMediaOptionSwitchContexts[ul.AltAudio]]; - return u.getSourceBufferInfoAction(e, i, t, o.maxBufferHole) - } - ), Ls(e=>{ - if (!e) - return Ti; - e = Bi(e).pipe(Zg(r, a), ty(r)); - return hn($l(function(e) { - const {mediaSink: t, rootPlaylistQuery: i, rootPlaylistService: r} = e - , n = t.mediaQuery - , s = e.logger.child(wg); - return nn((a = i, - o = s, - Zd([n.fellBelowLowWater$, a.getInFlightFragByType$(ul.Variant)]).pipe(Ra(e=>{ - var [,t] = e; - if (!Fg(t)) - return Ti; - const i = performance.now() - t.bwSample.trequest - , r = Bg - i - , n = 1e3 * t.duration - i - , s = [Ul]; - return 0 < r && s.push(vn(r)), - 0 < n && s.push(vn(n)), - nn(...s).pipe(Js(e)) - } - ), na((e,[t,i])=>{ - const r = Object.assign({}, e); - return t && (r.fragDownloadSlow = !0), - Ug(i, r, a, o) - } - , { - fragDownloadSlow: !1, - fragDownloadTooSlow: !1 - }), xa({ - fragDownloadSlow: !1, - fragDownloadTooSlow: !1 - }), Es(Ng))), function(r) { - const s = r.mediaSink.mediaQuery - , {rootPlaylistQuery: e, config: a} = r; - return s.desiredRate$.pipe(Ra(t=>0 === t ? Ti : Zd([e.getInFlightFragByType$(ul.Variant), e.mediaOptionListQueries[ul.Variant].preferredMediaOptionList$.pipe(ur(e=>e.filter(Dm.bind(null, jp(t)))))])), so(100), Ra(e=>{ - const [t,i] = e; - if (!Fg(t) || i.findIndex(e=>e.mediaOptionId === t.mediaOptionId) <= 0) - return Ti; - var r = performance.now() - t.bwSample.trequest - , n = Ag(t.duration, a.maxStarvationDelay) - , n = Math.min(1e3 * n, 500 * t.duration / s.playbackRate); - return vn(Math.max(0, n - r), 100).pipe(Js(e)) - } - )).pipe(na((e,[t,i])=>function(t, i, r, e) { - let {fragDownloadSlow: n, fragDownloadTooSlow: s} = t; - const {config: a, rootPlaylistService: o, rootPlaylistQuery: d, mediaSink: l, statsService: u, mediaLibraryService: c} = e - , h = e.logger.child(wg) - , p = l.mediaQuery; - if (p.paused) - return t; - e = i.bwSample; - if (!ne(e.tfirst)) - return t; - const f = performance.now() - , m = f - e.trequest - , g = Ag(i.duration, a.maxStarvationDelay) - , y = ul.Variant - , v = i.mediaOptionId - , S = d.variantMediaOptionById(v) - , b = c.getQueryForOption(S) - , T = S.bitrate - , E = Math.max(1, 8e3 * e.loaded / m) - , I = 8 * ((ne(e.total) ? e.total : Math.max(e.loaded, Math.round(i.duration * T / 8))) - e.loaded) / E - , w = kg(p, a.maxBufferHole); - let A; - if (ne(w) && 0 < w && !ne(null === (O = p.seekTo) || void 0 === O ? void 0 : O.pos)) - A = w; - else { - const _ = m / 1e3; - A = _ < g ? g - _ : g - } - var O = n; - ({fragDownloadSlow: n, fragDownloadTooSlow: s} = Ug(i, t, d, h)); - t = 2 * ((null === (t = b.mediaOptionDetails) || void 0 === t ? void 0 : t.targetduration) || i.duration); - if (!(w <= t && (I >= A || n))) - return Xm().getQuery().extendMaxTTFB && Xm().setExtendMaxTTFB(0), - { - fragDownloadSlow: n, - fragDownloadTooSlow: s - }; - O || h.warn(`likely to stall ${se({ - maxTimeToLoadSec: A, - minSwitchDuration: t, - stats: e, - elapsedMs: m, - remainingTimeSec: I, - instantBw: E, - bufferAheadSec: w, - fragDownloadSlow: n - })}`), - n = !0, - Xm().getQuery().extendMaxTTFB || Xm().setExtendMaxTTFB(6e5); - O = I >= A; - let k; - const C = i.itemId - , D = u.getQueryForItem(C) - , M = D.getCombinedEstimate() - , P = Object.assign(Object.assign({}, M), { - avgBandwidth: E - }) - , x = D.bandwidthStatus - , R = S.iframes - , L = Cg(0, r, R, d); - if (L < 0) - return { - fragDownloadSlow: n, - fragDownloadTooSlow: s - }; - t = Math.max(L, r.findIndex(e=>e && e.mediaOptionId === S.mediaOptionId)); - if (O) { - let e = Pg(r, i.duration, L, t, A, R, P, x, 1, 1, a, d, b, p, h); - const N = Ol.mediaOptionId; - k = e.variantMediaOption !== N || (e = Pg(r, i.duration, L, t, I, R, P, x, 1, 1, a, d, b, p, h)).variantMediaOption !== N ? e.variantMediaOption : e.lowestCandidate - } else { - const _ = Cg(0, r.slice(L, t).reverse(), R, d) - , i = t - 1 - _; - (0 <= _ || t === L) && (k = r[i].mediaOptionId) - } - if (null != k && k !== d.abrStatus.nextMaxAutoOptionId && o.setNextMaxAutoOptionId(C, k), - O) - throw h.warn(`loading too slow, abort fragment loading and switch to level ${k}`), - u.setBandwidthSample(Object.assign(Object.assign({}, e), { - tfirst: e.tfirst || f, - tload: e.tload || f, - complete: !0, - mediaOptionType: y - })), - s = !0, - new du({ - mediaOptionType: y, - mediaOptionId: v - },k,$.FragmentAbortError); - return { - fragDownloadSlow: n, - fragDownloadTooSlow: s - } - }(e, t, i, r), { - fragDownloadSlow: !1, - fragDownloadTooSlow: !1 - }), xa({ - fragDownloadSlow: !1, - fragDownloadTooSlow: !1 - }), Es(Ng)) - }(e)).pipe(xa({ - fragDownloadSlow: !1, - fragDownloadTooSlow: !1 - }), na((e,t)=>({ - fragDownloadSlow: e.fragDownloadSlow || t.fragDownloadSlow, - fragDownloadTooSlow: e.fragDownloadTooSlow || t.fragDownloadTooSlow - })), Es(Ng), ur(e=>(r.setFragLoadSlow(i.itemId, e), - !1)), Un(e=>{ - if (e instanceof du) { - const e = { - fragDownloadSlow: !0, - fragDownloadTooSlow: !0 - }; - return r.setFragLoadSlow(i.itemId, e), - Bi(!0) - } - return Ui(e) - } - )); - var a, o - }(r), e=>e), e).pipe(Cs(1), $s(()=>{ - Ml.forEach(e=>{ - d.updateInflightFrag(l.itemId, e, null, null, null) - } - ) - } - )) - } - ))), ur(()=>{ - if (!l.getEntity(l.itemId).manualMode) { - let e = ym.None; - var i, r, n, s; - i = bf(), - r = u, - n = o, - s = null == r ? void 0 : r.clientWidth, - a = null == r ? void 0 : r.clientHeight, - r = "object" == typeof window && window.devicePixelRatio ? window.devicePixelRatio : 1, - a = s && a ? { - width: s * r, - height: a * r - } : void 0, - r = (r = (null === (r = i.getQuery()) || void 0 === r ? void 0 : r.viewportInfo) || {}) && a && (r.width !== a.width || r.height !== a.height), - n.useViewportSizeForLevelCap && r && (i.updateViewportInfo(a), - 1) && (e = ym.PreferredListChanged); - let t = !1; - var a = l.enabledVariantMediaOption; - !function(e, t) { - const i = d.logger.child(wg) - , r = e.abrStatus - , n = r.fragDownloadSlow || r.fragDownloadTooSlow - , s = ne(null === (t = t.seekTo) || void 0 === t ? void 0 : t.pos); - return n && !r.fragDownloadTooSlow && s ? (i.warn("could be ignoring low bandwidth due to seek"), - 0) : n - }(l, u) ? function(e, t) { - const i = Uf(t.itemId) - , r = i.getBandwidthEstimate() - , n = t.abrStatus; - if (Og(r)) { - var t = (null === (t = i.bandwidthStatus) || void 0 === t ? void 0 : t.bandwidthSampleCount) || 0 - , t = xg(r.avgBandwidth, e.abrBandWidthUpFactor, e.abrBandWidthFactor, t)["bwUp"]; - return t > n.highBWTrigger - } - }(o, l) && (e = ym.HighBandwidth, - d.setNextMinAutoOptionId(a.itemId, a.mediaOptionId)) : (e = ym.LowBandwidth, - l.nextMaxAutoOptionId === Ol.mediaOptionId && (d.setNextMaxAutoOptionId(a.itemId, a.mediaOptionId), - t = !0)), - $g(e, o, l, u, d), - t ? d.setNextMaxAutoOptionId(a.itemId, Ol.mediaOptionId) : e === ym.HighBandwidth && d.setNextMinAutoOptionId(a.itemId, Ol.mediaOptionId) - } - } - ), $s(()=>{} - )) - } - const Zg = (r,n)=>e=>{ - const {rootPlaylistQuery: t, mediaSink: a} = r - , i = r.logger.child(Yg); - return e.pipe(Hi(Zi), So(t.enabledMediaOptionKeys$), Ra(([s,e])=>bn(ey(s, ul.Variant, r, e).pipe(Ja(e=>{ - var e = e.detailsEntity; - if (!e.mediaOptionDetails.liveOrEvent || e.mediaOptionDetails.ptsKnown) { - const t = e.playlistDuration - , i = (null === (e = s.bufferInfoTuple[0]) || void 0 === e ? void 0 : e.buffered.end) || 0 - , r = (null === (e = s.bufferInfoTuple[1]) || void 0 === e ? void 0 : e.buffered.end) || 0 - , n = Math.max(i, r); - a.msDuration = ne(a.msDuration) ? Math.max(a.msDuration, t, n) : t - } - } - )), ey(s, ul.AltAudio, r, e)).pipe(ur(e=>({ - action: s, - detailsAndContext: e - })))), Ra(({action: e, detailsAndContext: t})=>function t(i, r, n, s, l) { - var e; - const {mediaSink: u, iframeMachine: c, rootPlaylistQuery: a} = n - , o = [l[ul.Variant].detailsEntity.mediaOptionDetails, null === (e = null === (e = l[ul.AltAudio]) || void 0 === e ? void 0 : e.detailsEntity) || void 0 === e ? void 0 : e.mediaOptionDetails]; - let d = r.getNextFragments(s, o); - const h = d.reduce((e,t)=>Math.max(e, ne(null == t ? void 0 : t.newMediaRootTime) ? t.newMediaRootTime : -1 / 0), -1 / 0); - return ne(h) && (u.seekTo = h, - d = [null, null]), - d.every(e=>null == (null == e ? void 0 : e.foundFrag)) ? Bi(null) : bn(...d.map((e,d)=>e && null != e.foundFrag ? vg(n, d, e).pipe(Ja(e=>{ - const t = e[1] - , i = l[d].switchContext; - t.switchPosition = null == i ? void 0 : i.switchPosition; - const r = null !== (e = null == i ? void 0 : i.userInitiated) && void 0 !== e && e - , n = u["mediaQuery"] - , {desiredRate: s, isIframeRate: a} = n - , o = a && c.isStarted && s && s < 0 && s !== c.iframeRate; - (r || o) && (t.flushBeforeAppend = { - start: 0, - end: Number.POSITIVE_INFINITY - }) - } - )) : Bi(null))).pipe(ur(e=>function(g, e, t, i) { - const {rootPlaylistService: r, rootPlaylistQuery: n, mediaSink: s, mediaLibraryService: a, config: y} = e - , v = s.mediaQuery - , o = n.itemId - , d = v.isIframeRate; - let l = n.getInitPTS(t); - if (null == l || !d && l.iframeMode !== d) { - const c = null !== (e = null === (e = i[ul.Variant]) || void 0 === e ? void 0 : e[1].startDtsTs) && void 0 !== e ? e : null; - if (null == c) - return g.warn("updatePTSInfo: Variant data missing."), - null; - const n = null !== (e = null === (e = i[ul.Variant]) || void 0 === e ? void 0 : e[1].timelineOffset) && void 0 !== e ? e : 0 - , s = B(n, c.timescale) - , a = { - baseTime: c.baseTime - s.baseTime, - timescale: c.timescale - }; - r.setInitPTS(o, t, c, n, a, d), - l = { - variantDTS: c, - timelineOffset: n, - offsetTimestamp: a, - iframeMode: d - } - } - i.forEach(e=>{ - e && !ne(e[1].iframeMediaDuration) && a.updatePTSDTS(o, e[1].mediaOptionId, l, e[1]) - } - ); - const S = [null, null]; - if (i[ul.Variant]) { - const [g,c] = i[ul.Variant]; - let e = l.offsetTimestamp; - if (d) { - const g = c.startDtsTs - , i = B(c.timelineOffset, g.timescale); - e = { - baseTime: g.baseTime - i.baseTime, - timescale: g.timescale - } - } - S[cl.Variant] = { - initSeg: g, - dataSeg: c, - offsetTimestamp: e - } - } - if (i[ul.AltAudio]) { - const [g,c] = i[ul.AltAudio]; - S[cl.AltAudio] = { - initSeg: g, - dataSeg: c, - offsetTimestamp: l.offsetTimestamp - } - } - const u = S.map((e,t)=>{ - const i = null == e ? void 0 : e.dataSeg; - if (i) { - const {itemId: r, mediaOptionId: n, mediaSeqNum: s, discoSeqNum: a, startPts: o, endPts: d, duration: l, iframe: u} = i - , c = e["offsetTimestamp"] - , h = b(o, c) - , p = b(d, c) - , f = pg(i) - , m = S[0]; - return m && m.dataSeg.dropped || i.flushBeforeAppend || !((null === (e = null === (e = v.getBufferInfo(h, y.maxBufferHole)[t]) || void 0 === e ? void 0 : e.buffered) || void 0 === e ? void 0 : e.len) >= p - h) ? { - start: h, - duration: u ? l : p - h, - itemId: r, - mediaOptionId: n, - mediaSeqNum: s, - discoSeqNum: a, - targetDuration: f.mediaOptionDetails.targetduration - } : (g.warn(`${Cl[t]} Discarding append due to complete overlap with existing buffer`), - S[t] = null) - } - return null - } - ); - return u.every(e=>!e) ? null : { - appendDataTuple: S, - inFlightFrags: u, - initPTSInfo: l - } - }(i, n, r.discoSeqNum, e)), Ra(e=>{ - if (e) - return Bi(e); - { - const e = function(e, r) { - const n = e.enabledMediaOptionKeys - , s = [null, null] - , a = [null, null]; - return Ml.map(e=>{ - var t; - if (kl(n[e])) { - const i = pg(n[e]).mediaOptionDetailsEntity; - a[e] = null === (t = i.mediaOptionDetails) || void 0 === t ? void 0 : t.ptsKnown, - s[e] = { - detailsEntity: i, - switchContext: null === (e = r[e]) || void 0 === e ? void 0 : e.switchContext - } - } - } - ), - s - }(a, l); - return t(i, r, n, s, e) - } - } - )) - }(i, n, r, e, t)), Ql.tag("mediaProducerEpic.emit")) - } - ; - function ey(e, i, t, r) { - const {rootPlaylistQuery: n, mediaLibraryService: s} = t - , a = r[i]; - if (t.logger.child({ - name: Cl[i] - }), - !a || "Nah" === a.mediaOptionId) - return Bi({ - detailsEntity: null, - switchContext: null - }); - const o = s.getQueryForOption(a); - return Cr([Bi(e), o.mediaOptionDetailsEntity$.pipe(Es((e,t)=>(null == e ? void 0 : e.lastUpdateMillis) === (null == t ? void 0 : t.lastUpdateMillis)))]).pipe(an(([,e])=>{ - if (i === ul.AltAudio && !n.altMediaOptionHasValidUrl(i, a.mediaOptionId)) - return !0; - var t = null == e ? void 0 : e.mediaOptionDetails; - return null != t && (e = null !== (e = e.lastUpdateMillis) && void 0 !== e ? e : 0, - !t.liveOrEvent || !t.ptsKnown || !_g(null == t ? void 0 : t.totalduration, 0, e)) - } - ), Cs(1), So(n.enabledMediaOptionSwitchContextsByType$(i)), ur(([[,e],t])=>({ - detailsEntity: e, - switchContext: t - }))) - } - const ty = t=>e=>{ - const {rootPlaylistQuery: g, rootPlaylistService: y, mediaSink: v, legibleSystemAdapter: o, statsService: d, rtcService: l} = t; - return e.pipe(Ql.tag("mediaConsumerEpic.in"), Ra(e=>{ - if (!e) - return Bi(!1); - const {appendDataTuple: r, inFlightFrags: m, initPTSInfo: t} = e - , i = t["offsetTimestamp"]; - return m.forEach((e,t)=>{ - e && y.updateInflightFrag(e.itemId, t, e, "appending", null) - } - ), - r.forEach(e=>{ - e && (e = e.dataSeg, - o.addLegibleSamples(i, e.captionData, e.id3Samples, e.endPts)) - } - ), - v.appendData(r, (e,t,i,r,n)=>{ - var s, a, o, d, l, u, c, h, p, f = null !== (f = m[t].targetDuration) && void 0 !== f ? f : 10; - return s = v, - a = e, - o = t, - d = i, - l = f, - u = r, - c = g, - h = y, - p = n, - e=>e.pipe(Ja(()=>{ - h.updateConsecutiveTimeouts(c.itemId, o, !1, "append") - } - ), ya(e=>e.pipe(Kr((e,t)=>{ - var i = e instanceof rf && e.isTimeout; - if (h.updateConsecutiveTimeouts(c.itemId, o, i, "append"), - i) - return function(e, t, i, r, n, s, a, o) { - let d = { - errorAction: mm.SendAlternateToPenaltyBox, - errorActionFlags: 0 - }; - var l = s.getCurrentWaterLevel(i.maxBufferHole) - , u = l < i.almostDryBufferSec; - let c = NaN; - s = i.appendErrorMaxRetry, - i = a.rootPlaylistEntity.errorsByType[r].timeouts.append; - u && s <= i || s <= t ? d.errorAction = mm.SendEndCallback : c = 1e3 * l; - s = { - retryDelayMs: c, - maxNumRetry: s, - maxRetryDelayMs: c - }; - return d = Lm(d, !1, e.response.code, n, r, a, o), - Um(e, t, s, d, a, o, r, n).pipe() - }(e, t, u, o, d, p, c, h); - if (e instanceof nf) - return function(e, t, i, r, n, s, a, o, d, l) { - var u = t.type - , u = o.getCurrentWaterLevelByType(u, n.maxBufferHole); - if (u >= n.almostDryBufferSec) { - const t = 1e3 * r - , n = { - errorAction: mm.RetryRequest, - errorActionFlags: 0 - }; - return 1e3 * u < t && (l.hasFallbackMediaOptionTuple(d, s, a, !1) ? n.errorAction = mm.SendAlternateToPenaltyBox : n.errorAction = mm.SendEndCallback), - Um(e, i, { - retryDelayMs: t, - maxNumRetry: 1 / 0, - maxRetryDelayMs: t - }, n, d, l, s, a) - } - return i < n.appendErrorMaxRetry ? t.remove(0, Number.POSITIVE_INFINITY) : (e.fatal = !0, - Ui(e)) - }(e, a, t, l, u, o, d, p, c, h); - if (e instanceof af) { - const {mediaOptionType: a, mediaOptionId: o} = e; - return qg(e, a, o, s, h, c) - } - throw e - } - )))) - } - , g.highestVideoCodec).pipe(ur(e=>{ - m.forEach((e,t)=>{ - e && y.updateInflightFrag(e.itemId, t, e, "appended", null) - } - ); - var t = e.filter(e=>(null == e ? void 0 : e.fragmentType) === ul.Variant); - t.length && (d.setBufferMetric(t[0]), - null == l || l.handleFragBuffered(t[0])); - e = r[cl.AltAudio]; - if (null !== (t = null == e ? void 0 : e.dataSeg) && void 0 !== t && t.flushBeforeAppend || ne(null === (t = null == e ? void 0 : e.dataSeg) || void 0 === t ? void 0 : t.switchPosition)) { - const {itemId: i, mediaOptionId: r} = e.dataSeg; - y.setEnabledMediaOptionSwitchContextByType(i, ul.AltAudio, r, void 0) - } - return !0 - } - ), (n = v, - s = y, - a = g, - e=>e.pipe(Un(e=>{ - if (e instanceof tf) { - var {mediaOptionType: t, mediaOptionId: i} = e; - return qg(e, t, i, n, s, a) - } - throw e - } - )))); - var n, s, a - } - )) - } - ; - function iy(e) { - const {logger: r, rootPlaylistService: n, rootPlaylistQuery: t} = e - , s = t.itemId; - return e=>e.pipe(ya(e=>e.pipe(Kr(e=>{ - if (r.error(`Got error in pipeline ${e.message} fatal:${null == e ? void 0 : e.fatal} handled:${null == e ? void 0 : e.handled}`), - !(e instanceof p) || e.fatal) - throw e; - return e.handled ? (t = n, - i = s, - vn(0).pipe(ur(()=>{ - t.updateEnabledMediaOptions(i) - } - ))) : Ti; - var t, i - } - )))) - } - const ry = ()=>e=>e.pipe(Ql.tag("mediaFragmentPipelineEpic.in"), Ra(i=>{ - if (!i) - return Ti; - const {logger: e, config: t, platformService: r, rootPlaylistService: n, rootPlaylistQuery: s, keySystemAdapter: a, mediaSink: o, mediaParser: d, gaplessInstance: l, mediaLibraryService: u} = i - , c = s["itemId"] - , h = o["mediaQuery"] - , p = a.keyStatusChange$.pipe((f = i, - e=>e.pipe(Ra(e=>{ - const {decryptdata: t, status: i, error: r} = e - , n = f["rootPlaylistQuery"]; - if ("needs-renewal" === i) - return Sg(f, t, null); - if ("error" !== i || !(r instanceof uu || r instanceof lu) || r.handled) - return Ti; - { - const {rootPlaylistService: e, keySystemAdapter: t} = f; - return Hm(r, 0, null, e, n, t.ksQuery) - } - } - ), Ra(()=>Ti)))); - var f; - const m = r.getQuery() - , g = m.displaySupportsHdr$.pipe(Es(), Ra(e=>(n.setHDRPreference(c, e, !0), - Ti))) - , y = m.viewportInfo$.pipe(Es((e,t)=>e && t && e.width === t.width && e.height === t.height), Ja(e=>{ - t.useViewportSizeForLevelCap && n.setViewportInfo(c, e) - } - ), Ua(Ti)) - , v = Zd([s.hdrMode$.pipe(Es()), s.maxHdcpLevel$.pipe(Es())]).pipe(Ra(([])=>(l.inGaplessMode || 0 !== s.itemStartOffset || (o.resetMediaSource(), - d.reset()), - Ti))) - , S = nn(function(i) { - const {rootPlaylistQuery: t, mediaSink: r} = i - , e = t.enabledMediaOptions$.pipe(Up(), Ja(e=>{ - e = e[ul.AltAudio], - e = kl(e) && null != (null == e ? void 0 : e.url) ? 2 : 1; - r.setExpectedSbCount(e) - } - )) - , n = t.enabledMediaOptionByType$(ul.Variant).pipe(an(e=>kl(e)), Ra(e=>pg(e).mediaOptionDetails$), Cs(1), Ja(e=>{ - r.bufferMonitorTargetDuration = e.targetduration - } - )) - , s = Dl.map(e=>t.enabledMediaOptionByType$(e).pipe(Ql.tag("mediaOptionRetrieve.switch"), Ra(t=>{ - if (!t || !t.url || !kl(t)) - return Ti; - var e = r.mediaQuery.desiredRate$.pipe(ur(e=>0 !== e), Es()); - return fg(i, t).pipe(Ql.tag("mediaOptionRetrieve.first"), Ua(e), Ra(e=>e ? function e(t, i) { - const r = t.mediaLibraryService; - return function(e) { - if (!e) - return Ti; - var {mediaOptionDetails: t, lastUpdateMillis: i, unchangedCount: e} = e; - if (null == t || !t.liveOrEvent) - return Ti; - if (sg(t, i)) - return vn(0).pipe(Ja(()=>{} - )); - let r = ng(t); - return 0 < e && (r /= 2, - r = Math.max(r, 5e3)), - r -= performance.now() - i, - r += 0, - r = Math.max(1e3, Math.round(r)), - vn(r).pipe(Ja(()=>{} - )) - }(r.getQueryForOption(i).mediaOptionDetailsEntity).pipe(Ra(()=>fg(t, i, !0)), Ra(()=>e(t, i))) - }(i, t) : Ti)) - } - ))); - return nn(e, n, nn(...s)).pipe(Ua(Ti)) - }(i), Jg(i), function(t) { - const {rootPlaylistQuery: i, mediaSink: e} = t; - return $l(e.mediaQuery.mediaElementEntity$, e=>!!e).pipe(Ra(e=>i.anchorTime$.pipe(Up(), Ql.tag("anchorTime.subtitle.in"), (s=>e=>{ - const {rootPlaylistQuery: i, rootPlaylistService: t, legibleSystemAdapter: r} = s - , n = i.enabledAlternateMediaOptionByType(ul.Subtitle); - if (r.gotTracks) - r.selectedTrack = n; - else { - const s = i.preferredMediaOptions[ul.Subtitle]; - r.setTracks(s, n, i.getDisabledMediaOption(ul.Subtitle)) - } - return e.pipe(Ql.tag("subtitleEpic.select.in"), Ra(()=>(r.anchorTimeChanged(), - nn(r.nativeSubtitleTrackChange$.pipe(Ra(e=>(e.mediaOptionId !== r.selectedMediaOption.mediaOptionId && t.setEnabledMediaOptionByType(e.itemId, ul.Subtitle, e), - Ti))), i.enabledMediaOptionByType$(ul.Subtitle).pipe(ur(e=>{ - const t = kl(e) ? i.alternateMediaOptionById(ul.Subtitle, e.mediaOptionId) : e; - return r.selectedMediaOption = t, - t - } - )).pipe(Es((e,t)=>(null == e ? void 0 : e.mediaOptionId) === (null == t ? void 0 : t.mediaOptionId)))))), Ql.tag("subtitleEpic.select.emit")) - } - )(t), (s=>e=>{ - const {mediaSink: t, rootPlaylistQuery: i, legibleSystemAdapter: r, logger: n} = s; - return e.pipe(Ql.tag("subtitleEpic.process.in"), Ra(e=>{ - if (!e || !e.url || !kl(e)) - return Bi([null, null, null]); - return Zd([pg(e).mediaOptionDetails$, i.discoSeqNum$.pipe(an(e=>ne(e)))]).pipe(Ra(([e,t])=>((i,r,e)=>{ - const {legibleSystemAdapter: n, rootPlaylistQuery: t} = i; - return t.initPTS$(e).pipe(Ra(t=>t ? n.findFrags$(r, e).pipe(Ra(e=>r && (null == e ? void 0 : e.foundFrags) ? ny(i, t.offsetTimestamp, e, r) : Ul)) : sn)) - } - )(s, e, t))) - } - ), Ql.tag("subtitleEpic.process.emit")) - } - )(t)))) - }(i), p).pipe(Js(void 0), iy(i)) - , b = h.seekTo$.pipe(ur(e=>null == e ? void 0 : e.pos), an(e=>ne(e)), Es((e,t)=>Math.abs(e - t) < Number.EPSILON), Ra(e=>(n.setAnchorTime(c, e), - Ti))) - , T = h.gotPlaying$.pipe(an(e=>e), Ja(e=>{ - s.mediaOptionListQueries[ul.Variant].filteredMediaOptionList.forEach(e=>{} - ) - } - ), Cs(1), Ua(Ti)); - return nn(s.pendingSeek$.pipe(Wg(t, e, o, n, s, u)), function() { - const {config: s, mediaSink: a, rootPlaylistQuery: e, mediaLibraryService: t} = i - , o = i.logger.child({ - name: "live" - }) - , d = a.mediaQuery; - return e.enabledMediaOptionByType$(ul.Variant).pipe(an(kl), Ra(e=>t.getQueryForOption(e).mediaOptionDetailsEntity$.pipe(an(e=>{ - var t; - return (null === (t = null == e ? void 0 : e.mediaOptionDetails) || void 0 === t ? void 0 : t.ptsKnown) && e.mediaOptionDetails.liveOrEvent - } - ), Es((e,t)=>(null == e ? void 0 : e.lastUpdateMillis) === (null == t ? void 0 : t.lastUpdateMillis)))), ur(e=>{ - var t = e.mediaOptionDetails - , i = d.currentTime - , r = d.msDuration; - let n = NaN; - return i < rg(i, t, e.lastUpdateMillis, s.maxBufferHole, d) && (n = ig(t.fragments[0].start, t, s), - n >= r && (o.warn(`seekTo position > duration, updating ${a.msDuration}->${e.playlistDuration}`), - a.msDuration = e.playlistDuration), - a.seekTo = n), - n - } - )) - }(), b, S, g, y, v, function() { - const e = i.mediaSink.mediaQuery; - return Cr([Bi(i), e.desiredRate$.pipe(ca())]).pipe(Ra(([e,[t,i]])=>{ - const {rootPlaylistQuery: s, rootPlaylistService: r, config: a, mediaSink: n, mediaLibraryService: o, statsService: d} = e - , l = n.mediaQuery; - if (jp(t) !== jp(i)) - $g(ym.IframeModeChange, a, s, l, r); - else if (0 === t && 1 === i && !Ml.every(e=>{ - const t = s.enabledMediaOptionKeys[e] - , i = o.getQueryForOption(t) - , r = d.getQueryForItem(s.itemId) - , n = i.mediaOptionDetailsEntity; - return !(null !== (e = null == n ? void 0 : n.mediaOptionDetails) && void 0 !== e && e.ptsKnown) || l.canContinuePlaybackWithoutGap(n.mediaOptionDetails, n.lastUpdateMillis, r.getPlaylistEstimate(), a.maxBufferHole) - } - )) - return n.pause(), - n.flushAll(0, 1 / 0, !0); - return Ti - } - ), Ua(Ti)) - }(), function(e) { - const s = e.rootPlaylistQuery - , t = e.mediaSink.mediaQuery - , i = s.enabledMediaOptionByType$(ul.Variant); - return Cr([Bi(e), t.desiredRate$.pipe(ca()), i]).pipe(Es((e,t)=>e[1] === t[1]), Ra(([e,[t,i],r])=>{ - t = jp(t), - i = jp(i); - if (t === i) - return Ti; - const n = e["rootPlaylistService"]; - return i ? e.rootPlaylistQuery.nextMaxAutoOptionId === Ol.mediaOptionId && n.setNextMaxAutoOptionId(e.rootPlaylistQuery.itemId, r.mediaOptionId) : n.setNextMaxAutoOptionId(s.itemId, Ol.mediaOptionId), - Ti - } - )) - }(i), T).pipe(Ql.tag("mediaFragmentPiplineEpic.emit"), Js(void 0)) - } - )) - , ny = (i,r,t,n)=>{ - const s = i.legibleSystemAdapter; - return Lr(t.foundFrags).pipe(ur(e=>{ - return ((e,t,i)=>{ - const {rootPlaylistQuery: r, legibleSystemAdapter: n} = e; - return Yr(()=>((t,i)=>yg(e, i, !1, !1).pipe(ur(e=>({ - initPTS: t, - data: e, - mediaFragment: i - })), Ql.tag("retrieveSubtitleFragmentCacheEntity.emit")))(t, i).pipe(ur(({initPTS: e, data: t, mediaFragment: i})=>({ - frag: i, - cueRange: function(e, t, i, r, n) { - if (e) - return n.processSubtitleFrag(e, t, i, r) - }(r.enabledAlternateMediaOptionByType(ul.Subtitle), i, e, t, n) - })))) - } - )(i, r, e).pipe((t = e=>s.checkReadyToLoadNextSubtitleFragment$().pipe(an(e=>e)), - function(e) { - return e.lift(new ms(t)) - } - )); - var t - } - ), Wr(i.config.vttConcurrentLoadCount), Ja(e=>{ - s.reviewParsedFrag(e, t, n) !== Ap.CloseEnough && i.legibleSystemAdapter.tryAgain$.next(!0) - } - )) - } - , sy = (e,t)=>{ - let i, r = ""; - return i = e.videoCodec && e.audioCodec ? (r = `${e.videoCodec}, ${e.audioCodec}`, - t = null != t ? t : "video/mp4", - "audiovideo") : e.videoCodec ? (r = `${e.videoCodec}`, - t = null != t ? t : "video/mp4", - "video") : (r = `${null !== (e = e.audioCodec) && void 0 !== e ? e : ""}`, - t = null != t ? t : "audio/mp4", - "audio"), - { - mimeType: `${t};codecs=${r}`, - codec: r, - container: t, - type: i - } - } - ; - class ay { - constructor(e, t, i) { - this.config = e, - this.logger = t, - this.demuxClient = i, - this.typeSupported = { - mp4: MediaSource.isTypeSupported("video/mp4"), - mpeg: MediaSource.isTypeSupported("audio/mpeg"), - mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'), - ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"'), - ec3: MediaSource.isTypeSupported('audio/mp4; codecs="ec-3"') - }, - this.demuxers = [], - this.lastInitFrags = [], - this.lastFrags = [] - } - parseInitSegment(h, e) { - return this.getDemuxerInfo(h, this.lastInitFrags, e, this.demuxClient).pipe(Ra(({demuxer: e, contiguous: t, trackSwitch: i, discontinuity: r, accurateTimeOffset: n})=>{ - const s = h["frag"] - , {keyTagInfo: a, start: o, mediaOptionType: d} = s; - if (this.lastInitFrags[d] = s, - h.initSegment) { - const e = We.remuxInitSegment(new Uint8Array(h.initSegment), this.logger, a) - , t = Je.parseInitSegment(e) - , {mimeType: i, type: r, codec: n, container: s} = sy(t); - return Bi({ - moovData: t, - mimeType: i, - track: { - type: r, - codec: n, - initSegment: e, - container: s - } - }) - } - const l = h.segment || h.initSegment - , u = l ? h.initSegment : void 0 - , c = wc(e.observer); - return Bi(c.event(v.FRAG_PARSING_INIT_SEGMENT).pipe(ur(this.handleInitSegmentData)), c.event(x.INTERNAL_ERROR).pipe(Ra(this.handleError)), e.pushWithoutTransfer(l, a, u, o, r, i, t, h.totalDuration, n, void 0, h.iframeMediaStart, h.iframeDuration).pipe(Ua(Ti))).pipe(Wr(), Cs(1)) - } - )) - } - parseSegment(y, e) { - return this.getDemuxerInfo(y, this.lastFrags, e, this.demuxClient).pipe(Ra(({demuxer: e, contiguous: t, trackSwitch: i, discontinuity: r, accurateTimeOffset: n})=>{ - const {frag: h, defaultInitPTS: p} = y - , {keyTagInfo: s, start: a, duration: f, mediaOptionType: m} = h; - let g; - this.lastFrags[m] = h; - const o = wc(e.observer); - return Bi(o.event(v.FRAG_PARSING_INIT_SEGMENT).pipe(Ra(e=>{ - var t; - return e.track.initSegment.byteLength !== (null === (t = y.initSegment) || void 0 === t ? void 0 : t.byteLength) && (g = this.handleInitSegmentData(e)), - Ti - } - )), o.event(v.FRAG_PARSING_DATA).pipe(ur(e=>{ - var {startPTS: t, startDTS: i, firstKeyframePts: r, framesWithoutIDR: n, dropped: s, data1: a, data2: o, captionData: d, id3Samples: l} = e; - let {endPTS: u, endDTS: c} = e; - return null == u && (this.logger.warn(`${Cl[m]} ${Bp(h)}: null endPTS parsed, using duration ${f}`), - u = Object.assign(Object.assign({}, t), { - baseTime: t.baseTime + B(f, t.timescale).baseTime - })), - null == c && (this.logger.warn(`${Cl[m]} ${Bp(h)}: null endDTS parsed, using duration ${f}`), - c = Object.assign(Object.assign({}, i), { - baseTime: i.baseTime + B(f, i.timescale).baseTime - })), - ne(y.iframeMediaStart) || function(e, t, i, r) { - let n = NaN - , s = NaN; - if (ne(i)) - s = i, - n = .01, - isFinite(s) && isFinite(r) && (s += r); - else { - { - const o = void 0 - } - } - var {startPTS: a, startDTS: i, endPTS: r, endDTS: t} = t; - if (!(0 <= a.baseTime && 0 <= i.baseTime && 0 < e.duration && (null == r || 0 < b(r, a)) && (null == t || 0 < b(t, i)) && (!ne(n) || !ne(s) || Math.abs(S(i) - s) <= n))) - throw new D(!1,`Failed demuxer sanity check frag=${Bp(e)} parsed=${JSON.stringify({ - startPTS: a, - endPTS: r, - startDTS: i, - endDTS: t - })} ${se({ - expectedStartDTS: s, - fudge: n - })}`,$.FailedDemuxerSanityCheck) - }(h, e, (p, - y.iframeMediaStart), this.config.audioPrimingDelay), - { - startPTS: t, - endPTS: u, - startDTS: i, - endDTS: c, - firstKeyframePts: r, - framesWithoutIDR: n, - dropped: s, - data1: a, - data2: o, - captionData: d, - id3Samples: l, - parsedInitSegment: g - } - } - )), o.event(x.INTERNAL_ERROR).pipe(Ra(this.handleError)), e.push(y.segment, s, y.initSegment, a, r, i, t, y.totalDuration, n, p, y.iframeMediaStart, y.iframeDuration).pipe(Ua(Ti))).pipe(Wr(), Cs(1)) - } - )) - } - reset(e) { - if (null == e) - return this.demuxers.forEach(e=>{ - e && e.destroy() - } - ), - void (this.demuxers = []); - const t = this.demuxers[e]; - null == t || t.destroy(), - this.demuxers[e] = null - } - destroy(e) { - null != e ? this.reset(e) : this.reset() - } - willBeTrackSwitch(e, t) { - var {mediaOptionType: i, mediaOptionId: e} = e - , i = (t || this.lastFrags)[i]; - return !(i && i.mediaOptionId === e) - } - getDemuxerInfo(e, r, t, i) { - const {frag: n, ptsKnown: s, seeking: a, live: o} = e - , {discoSeqNum: d, mediaSeqNum: l, mediaOptionType: u} = n; - return Yr(()=>{ - var e = this.demuxers[u]; - return e ? Bi(e) : i.init(this.typeSupported, this.config, t).pipe(Ja(e=>this.demuxers[u] = e)) - } - ).pipe(ur(e=>{ - var t = r[u] - , i = this.willBeTrackSwitch(n, r); - return { - demuxer: e, - trackSwitch: i, - discontinuity: !(t && d === t.discoSeqNum), - contiguous: !!t && !i && t.mediaSeqNum + 1 === l, - accurateTimeOffset: !a && (s || !o) - } - } - )) - } - handleInitSegmentData(e) { - var t = e["track"] - , i = t["initSegment"] - , r = Je.parseInitSegment(i) - , {mimeType: n, type: s, codec: a, container: e} = sy(r, t.container); - return { - moovData: r, - mimeType: n, - track: Object.assign(Object.assign({}, t), { - type: s, - codec: a, - initSegment: i, - container: e - }) - } - } - handleError(e) { - return Ui(e) - } - } - function oy(e) { - return Math.min(e.targetduration, 15) - } - function dy(e, t, i, r) { - if (200 === t && r && 10 < r.length) { - if (Sm.isValidPlaylist(r)) - return !0; - { - const t = new R(o,_,!0,"response doesnt have #EXTM3U tag",$.PlaylistErrorMissingEXTM3U); - throw t.url = e, - t - } - } - return !1 - } - const ly = { - name: "pltfrm" - }; - function uy(e, t) { - t = Ih.getKeySystemSecurityLevel(t); - return null != e && void 0 !== t[e] - } - function cy(e) { - return e.every(e=>e.iframes) - } - function hy(e, t) { - return !ne(e) || !ne(t) || e <= t - } - function py() { - const n = new Set - , s = new Set; - return e=>{ - const i = (e,t)=>{ - t = t ? "audio" : "video"; - n.has(e) || s.has(e) || (((e,t)=>{ - let i = MediaSource.isTypeSupported(`${e}/mp4;codecs=${t}`); - return "mp4a.40.34" !== t || i || (i = MediaSource.isTypeSupported(`${e}/mpeg`)), - i - } - )(t, e) ? n : s).add(e) - } - , t = (e,t)=>(i(e, t), - s.has(e)); - let r = !1; - return e.audioCodecList && (r = e.audioCodecList.some(e=>t(e, !0))), - !r && e.videoCodecList && (r = e.videoCodecList.some(e=>t(e, !1))), - !r - } - } - function fy(e, t) { - for (const i in e) - if (e[i].type === t) - return e[i]; - return {} - } - function my(e, t, i) { - t.filter(e=>!i.includes(e)).map(e=>e.mediaOptionId) - } - function gy(e, i, s) { - const a = new Map - , r = new Array; - return e.forEach(t=>{ - var e = Array(); - !function(e, t, i) { - var r = qc.getCapabilities(t.videoCodecList, t.audioCodecList) - , t = JSON.stringify(r); - let n; - a.has(t) ? n = a.get(t) : (n = Ih.requestKeySystemAccess(e, r, void 0, s).pipe(ur(()=>!0), Un(e=>(s.warn(`Request key system error: ${e.message}`), - Bi(!1))), Aa({ - bufferSize: 1, - refCount: !0 - })), - a.set(t, n)), - i.push(n) - }(i, t, e); - e = Jr(e).pipe(ur(e=>{ - if (void 0 === e.find(e=>!1 === e)) - return t - } - )); - r.push(e) - } - ), - Jr(r).pipe(ur(e=>e.filter(e=>Boolean(e)))) - } - function yy(e, r) { - const o = new Set - , d = new Set - , l = !MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.2"; channels="-1"') - , u = l && !MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.2"; channels="2"; features="INVALID"') - , t = e.filter(e=>{ - let t = !1; - var i; - return e.audioCodecList && e.audioGroupId && (i = tm.getRichestChannelLayoutForGroupId(e.audioGroupId, r), - 0 < e.audioCodecList.length && i && (t = ((e,t)=>{ - var i, r, n, s = Se.isDolbyAtmos(e, t); - if (u || l && !s) { - n = `${i = e}/${r = t}`, - o.has(n) || d.has(n) || (((e,t)=>{ - const i = t.split("/") - , r = parseInt(i[0]); - let n, s; - if (1 < i.length) { - const t = i[1].split(",")[0]; - n = `audio/mp4;codecs="${e}";channels="${r}";features="${t}"`, - s = `audio/mp4;codecs="${e}";channels="8";features="${t}"` - } else - n = `audio/mp4;codecs="${e}";channels="${r}"`; - let a = MediaSource.isTypeSupported(n); - return !a && s && (a = MediaSource.isTypeSupported(s)), - a - } - )(i, r) ? o : d).add(n); - const a = `${e}/${t}`; - return d.has(a) - } - return !!s - } - )(tm.getRichestAudioCodec(e.audioCodecList), i))), - !t - } - ); - return my(0, e, t), - t - } - function vy(e, t, d) { - const n = 0 < (null == t ? void 0 : t.length) - , i = e.filter(o=>{ - var e = function() { - if (!d) - return { - highestPlayableAverageBitRate: void 0, - highestPlayablePeakBitRate: void 0, - highestPlayableWidth: void 0, - highestPlayableHeight: void 0, - highestPlayableFrameRate: void 0 - }; - const e = o.videoCodec - , t = o.videoRange - , i = d.videoDynamicRangeFormats - , r = d.videoCodecs - , n = Se.getDynamicRangeType(t, e) - , s = Se.getCompressionType(e) - , a = function(e, t, i, r) { - if (!r && !i) - return {}; - var n, s, t = i ? fy(i, t) : {}, r = r ? fy(r, e) : {}; - let a, o; - return o = e === pe.SDR ? (a = t, - r) : (a = r, - t), - n = Object.assign({}, a), - s = o, - Object.keys(s).forEach(e=>{ - n[e] || (n[e] = s[e]) - } - ), - n - }(n, s, r, i); - return s !== fe.VP09 && (a.highestPlayablePeakBitRateForClearContent = void 0), - a - }() - , t = e["highestPlayablePeakBitRateForClearContent"] - , i = o.allowedCPCMap || n - , r = hy(o.bandwidth, e.highestPlayablePeakBitRate); - return (i || !t ? r : r || hy(o.bandwidth, t)) && hy(o.avgBandwidth, e.highestPlayableAverageBitRate) && hy(o.width, e.highestPlayableWidth) && hy(o.height, e.highestPlayableHeight) && hy(o.frameRate, e.highestPlayableFrameRate) - } - ); - return my(0, e, i), - i - } - function Sy(e, a, o, d, l, u) { - var r = (null == d ? void 0 : d.maxHdcpLevel) || void 0; - let c = [...e]; - (0 < l.disableVideoCodecList.size || 0 < l.disableAudioCodecList.size) && (c = function(e, t, i) { - let r = e.filter(e=>!e.videoCodec || e.videoCodecList.every(e=>{ - e = $p(e); - return !t.has(e) - } - )); - return r = r.filter(e=>!(!e.iframes && e.audioCodec) || e.audioCodecList.every(e=>{ - e = Kp(e); - return !i.has(e) - } - )), - my(0, e, r), - r - }(c, l.disableVideoCodecList, l.disableAudioCodecList)), - r && Xf(r) && (c = function(e) { - const t = Yf(r) - , i = e.filter(e=>{ - e = e.hdcpLevel; - return !e || Yf(e) <= t - } - ); - return my(0, e, i), - i - }(c)); - var t = null == d ? void 0 : d.maxSecurityLevel - , e = null == l ? void 0 : l.keySystemPreference; - t && e && uy(t, e) && (c = function(e, t, i) { - function r(e) { - return uy(e, i) ? n[e] : -1 - } - const n = Ih.getKeySystemSecurityLevel(i) - , s = Ih.getKeySystemFormat(i) - , a = r(t) - , o = e.filter(e=>{ - e = null !== (e = null === (e = e.allowedCPCMap) || void 0 === e ? void 0 : e[s]) && void 0 !== e ? e : []; - let t = !0; - for (const i of e) - if (t = r(i) <= a, - !t) - break; - return t - } - ); - return my(0, e, o), - [...o] - }(c, t, e)), - c = c.map(t=>{ - var e; - return t.audioCodecList && t.audioGroupId && ((e = null == (e = a.find(e=>e.groupId === t.audioGroupId)) ? void 0 : e.channels) && (t.audioChannelCount = parseInt(e))), - t - } - ); - const h = !(null == l || !l.useMediaKeySystemAccessFilter) && e && navigator && "function" == typeof navigator.requestMediaKeySystemAccess; - return (h ? gy(c, e, u) : Bi(c)).pipe(Ra(e=>{ - if (0 === e.length || cy(e)) - throw new R(L,f,void 0,"no media option with compatible codecs found in playlist",void 0); - h && my(0, c, e); - const t = navigator && navigator.mediaCapabilities - , n = !(null == l || !l.useMediaCapabilities) && t && "function" == typeof t.decodingInfo; - let i; - return i = n ? function(e, n, s) { - const a = [] - , o = py() - , d = function(o) { - const d = new Map - , l = navigator && navigator.mediaCapabilities; - return (i,e,t,n,r)=>{ - const s = { - type: "media-source" - }; - n ? s.video = function(e) { - const t = { - contentType: `video/mp4;codecs=${e}`, - width: i.width, - height: i.height, - bitrate: i.bandwidth || i.avgBandwidth, - framerate: i.iframes ? 8 : i.frameRate - }; - if (i.videoRange) - switch (i.videoRange) { - case "PQ": - Se.isDolby(e) ? (t.hdrMetadataType = vm.DoVi, - t.colorGamut = "rec2020") : (Se.isHEVC(e) || Se.isVP09(e)) && (t.hdrMetadataType = vm.HDR10, - t.colorGamut = "rec2020"), - t.transferFunction = "pq"; - break; - case "HLG": - t.colorGamut = "rec2020", - t.transferFunction = "hlg" - } - return t - }(t) : s.audio = function(e, t, i) { - const r = { - contentType: `audio/mp4;codecs=${e}` - } - , n = tm.getRichestChannelLayoutForGroupId(t.audioGroupId, i); - return n && (r.channels = Se.getChannelCount(n).toString(), - r.spatialRendering = Se.isDolbyAtmos(e, n)), - r - }(t, i, e); - e = JSON.stringify(s); - let a; - return d.has(e) ? a = d.get(e) : (a = Lr(l.decodingInfo(s)).pipe(ur(e=>{ - const t = e.configuration || e.supportedConfiguration - , i = t instanceof Object && (!s.video || null == Object.keys(s.video).find(e=>!(e in t.video))) && (!s.audio || null == Object.keys(s.audio).find(e=>!(e in t.audio))) - , r = e.supported && (!n || e.powerEfficient) && i; - return r || o.warn(ly, `Unsupported config ${e.supported}/${e.powerEfficient}/${i} ${JSON.stringify(s)} supportedConfig=${JSON.stringify(t)}`), - r - } - )), - d.set(e, a)), - [...r, a] - } - }(s); - return e.forEach(t=>{ - var e; - let i = []; - if (null === (e = t.videoCodecList) || void 0 === e || e.forEach(e=>{ - i = d(t, n, e, !0, i) - } - ), - 0 < (null === (e = t.audioCodecList) || void 0 === e ? void 0 : e.length)) { - const s = tm.getRichestAudioCodec(t.audioCodecList); - i = d(t, n, s, !1, i) - } - let r = Bi(t); - 0 < i.length && (r = Jr(i).pipe(ur(e=>null == e.find(e=>!1 === e) ? t : null), Un(e=>(s.warn(ly, `decodingInfo errror: ${e.message}`), - Bi(o(t) ? t : null))))), - a.push(r) - } - ), - Jr(a).pipe(ur(e=>e.filter(e=>Boolean(e)))) - }(e, a, u) : Bi(e = yy((r = e, - s = py(), - s = r.filter(s), - my(0, r, s), - e = s), a)), - i.pipe(ur(e=>{ - if (0 === e.length || cy(e)) - throw new R(L,f,void 0,"no media option with compatible codecs found in manifest",void 0); - if (0 === (t = e = vy(e, o, d), - r = t.filter(e=>!e.iframes || !e.width || !e.height || e.width * e.height <= 2488320), - my(0, t, r), - (e = r).length) || cy(e)) - throw new R(L,f,void 0,"no media option with compatible codecs found in manifest",void 0); - var t; - let i = (null == d ? void 0 : d.videoDynamicRangeFormats) || []; - n && 0 === i.length && (i = [{ - type: pe.SDR - }, { - type: pe.HDR - }, { - type: pe.HDR10 - }, { - type: pe.DolbyVision - }, { - type: pe.HLG - }]); - var {hdrMediaOptions: r, sdrMediaOptions: e} = function(e, t) { - const i = t.reduce((e,t)=>{ - switch (t.type) { - case pe.DolbyVision: - e.doViSupported = !0; - break; - case pe.HDR10: - e.hdr10Supported = !0; - break; - case pe.HLG: - e.hlgSupported = !0 - } - return e - } - , { - doViSupported: !1, - hdr10Supported: !1, - hlgSupported: !1 - }) - , {doViSupported: r, hdr10Supported: n, hlgSupported: s} = i; - return e.reduce((e,t)=>{ - var i; - switch (Se.getDynamicRangeType(t.videoRange, null !== (i = t.videoCodec) && void 0 !== i ? i : "")) { - case pe.HDR: - case pe.HDR10: - n && e.hdrMediaOptions.push(t); - break; - case pe.DolbyVision: - r && e.hdrMediaOptions.push(t); - break; - case pe.HLG: - s && e.hdrMediaOptions.push(t); - break; - default: - "SDR" !== t.videoRange && null != t.videoRange || e.sdrMediaOptions.push(t) - } - return e - } - , { - hdrMediaOptions: new Array, - sdrMediaOptions: new Array - }) - }(e, i); - if (0 === r.length && 0 === e.length || cy(r) && cy(e)) - throw new R(L,"manifestIncompatibleVideoRangeError",void 0,"mediaOption with compatible VIDEO-RANGE not found in manifest",void 0); - return { - hdrMediaOptions: r, - sdrMediaOptions: e - } - } - ), Un(e=>{ - throw e instanceof R && (e.fatal = !0, - e.response = $.IncompatibleAsset), - e - } - )); - var r, s - } - )) - } - function by(e, t) { - return t.mediaOptionId !== e.mediaOptionId && t.persistentID === e.persistentID && t.groupId !== e.groupId - } - (w = vm = vm || {}).HDR10 = "smpteSt2086", - w.DoVi = "smpteSt2094-10", - w.HDR10Plus = "smpteSt2094-40"; - class Ty extends km { - constructor(e, t, i) { - super(e, t, i) - } - static makeFilters() { - return Om() - } - _initFilters() { - return Ty.kAllowFilters - } - get _mediaOptionType() { - return this.mediaOptionType - } - get preferredHost() { - return null - } - get preferredHost$() { - return Bi(null) - } - get mediaOptionListInfo() { - var e; - return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionListTuple[this._mediaOptionType]) && void 0 !== e ? e : null - } - get mediaOptionListInfo$() { - return this.selectEntity(this.itemId, e=>e && e.mediaOptionListTuple ? e.mediaOptionListTuple[this._mediaOptionType] : null).pipe(Up()) - } - getFallbackVariant(t, e, i, r) { - var n; - const s = null === (n = this.mediaOptionList) || void 0 === n ? void 0 : n.find(e=>e.mediaOptionId === t); - if (!s) - return null; - const a = this.filteredMediaOptionList; - if (!a) - return null; - const o = gl(s.url); - if (i) - return null !== (i = a.find(e=>by(s, e) && !yl(o, e.url))) && void 0 !== i ? i : null; - let d = null; - for (const t of a) - !by(s, t) || d && !yl(o, t.url) || (d = t); - return d - } - getMatchingAlternateWithPersistentId(t, i, r) { - var e; - return null !== (e = this.preferredMediaOptionList.find(e=>!(0 < (null == r ? void 0 : r.length) && r.includes(e.mediaOptionId)) && (!ne(t) || e.persistentID === t) && (!i || this.matchGroup(e, i.audioGroupId, i.subtitleGroupId, i.closedcaption)))) && void 0 !== e ? e : null - } - matchGroup(e, t, i, r) { - let n = !1; - switch (e.type) { - case "CLOSED-CAPTIONS": - n = !r || e.groupId === r; - break; - case "SUBTITLES": - n = !i || e.groupId === i; - break; - case "AUDIO": - n = !t || e.groupId === t - } - return n - } - getMatchingAlternate(e, t) { - e = this.mediaOptionFromId(e); - return this.getMatchingAlternateWithPersistentId(null == e ? void 0 : e.persistentID, t, []) - } - packageAlternateMediaOption(e, t, i) { - return t.mediaType === pl.CLOSEDCAPTION ? this.augmentClosedCaptionsWithForcedSubtitles(null == e ? void 0 : e.subtitleGroupId, t, i) : t - } - augmentClosedCaptionsWithForcedSubtitles(e, t, i) { - i = this.pairForcedSubtitleMediaOptionWithClosedCaption(e, t, i); - return i ? Object.assign(Object.assign({}, t), { - url: i.url, - backingMediaOptionId: i.mediaOptionId - }) : t - } - pairForcedSubtitleMediaOptionWithClosedCaption(t, i, r) { - let n; - if (i && i.mediaType === pl.CLOSEDCAPTION) { - let e = this.mediaOptionList; - r && (e = this.preferredMediaOptionList), - n = Ty.pairForcedSubtitleMediaOptionWithClosedCaptionInList(t, i, e) - } - return n - } - static pairForcedSubtitleMediaOptionWithClosedCaptionInList(t, i, e) { - return e.find(function(e) { - return e.mediaType === pl.SUBTITLE && e.lang === i.lang && e.forced && e.autoselect && (!t || e.groupId === t) - }) - } - } - Ty.kAllowFilters = Ty.makeFilters(); - class Ey extends Od { - constructor(e, t) { - super(e), - this.itemId = t, - this.mediaOptionListQueries = [new xm(e,this.itemId), new Ty(e,this.itemId,ul.AltAudio), new Ty(e,this.itemId,ul.Subtitle)] - } - get rootPlaylistEntity() { - return this.getEntity(this.itemId) - } - get rootMediaOptionsTuple() { - var e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.mediaOptionListTuple; - return e ? [e[0].mediaOptions, e[1].mediaOptions, e[2].mediaOptions] : [[], [], []] - } - get itemStartOffset() { - var e, t; - return null !== (e = this.rootPlaylistEntity) && void 0 !== e && e.itemStartOffset && ne(null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.itemStartOffset) ? null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.itemStartOffset : 0 - } - get highestVideoCodec() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.highestVideoCodec - } - get baseUrl() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.baseUrl - } - get anchorTime() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.anchorTime - } - get discoSeqNum() { - var e; - return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.discoSeqNum) && void 0 !== e ? e : NaN - } - get discoSeqNum$() { - return this.selectEntity(this.itemId, "discoSeqNum") - } - get audioMediaSelectionGroup() { - var e; - return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.audioMediaSelectionGroup) && void 0 !== e ? e : null - } - get subtitleMediaSelectionGroup() { - var e; - return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.subtitleMediaSelectionGroup) && void 0 !== e ? e : null - } - get audioMediaSelectionOptions() { - var e; - return null !== (e = null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.audioMediaSelectionGroup) || void 0 === e ? void 0 : e.MediaSelectionGroupOptions) && void 0 !== e ? e : [] - } - get subtitleMediaSelectionOptions() { - var e; - return null !== (e = null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.subtitleMediaSelectionGroup) || void 0 === e ? void 0 : e.MediaSelectionGroupOptions) && void 0 !== e ? e : [] - } - get contentSteeringOption() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.contentSteeringOption - } - get masterVariableList() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.masterVariableList - } - get loadStats() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.loadStats - } - get isMediaPlaylist() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.isMediaPlaylist - } - getInitPTS(e) { - var t; - return null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.initPtsRecord[e] - } - get abrStatus$() { - return this.selectEntity(this.itemId, e=>null == e ? void 0 : e.abrStatus) - } - get abrStatus() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus - } - get nextMaxAutoOptionId() { - var e; - return null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus) || void 0 === e ? void 0 : e.nextMaxAutoOptionId - } - get nextMinAutoOptionId() { - var e; - return null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus) || void 0 === e ? void 0 : e.nextMinAutoOptionId - } - initPTS$(t) { - return this.selectEntity(this.itemId, ({initPtsRecord: e})=>e[t]) - } - get rootPlaylistEntity$() { - return this.selectEntity(this.itemId).pipe(an(e=>Boolean(e)), ur(e=>e)) - } - get rootPlaylistEntityAdded$() { - return this.selectEntityAction(To.Add).pipe(ur(e=>e.map(e=>this.getEntity(e)))) - } - get rootMediaOptionsTuple$() { - return Zd([this.selectEntity(this.itemId, e=>e.mediaOptionListTuple[0].mediaOptions), this.selectEntity(this.itemId, e=>e.mediaOptionListTuple[1].mediaOptions), this.selectEntity(this.itemId, e=>e.mediaOptionListTuple[2].mediaOptions)]) - } - get sessionData() { - var e; - return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.sessionData - } - get sessionData$() { - return this.selectEntity(this.itemId, ({sessionData: e})=>e).pipe(Up()) - } - get anchorTime$() { - return this.selectEntity(this.itemId, "anchorTime").pipe(Ra(e=>ne(e) ? e !== this.anchorTime ? (qe().warn(`anchorTime doesn't match stored value! ${e} !== ${this.anchorTime}`), - Ti) : Bi(e) : Ti)) - } - get pendingSeek$() { - return this.selectEntity(this.itemId, ({pendingSeek: e})=>e).pipe(Es((e,t)=>e === t || "number" == typeof e && "number" == typeof t && isNaN(e) && isNaN(t))) - } - get enabledMediaOptionKeys$() { - return this.selectEntity(this.itemId, "enabledMediaOptionKeys").pipe(an(e=>Boolean(e))) - } - get enabledMediaOptionKeys() { - var e; - return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.enabledMediaOptionKeys) && void 0 !== e ? e : [Ol, Ol, Ol] - } - get enabledMediaOptionSwitchContexts() { - var e; - return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionSwitchContexts) && void 0 !== e ? e : [null, null, null] - } - enabledMediaOptionSwitchContextsByType$(t) { - return this.selectEntity(this.itemId, "mediaOptionSwitchContexts").pipe(ur(e=>null == e ? void 0 : e[t])) - } - get enabledMediaOptions$() { - return Zd([this.enabledMediaOptionByType$(ul.Variant), this.enabledMediaOptionByType$(ul.AltAudio), this.enabledMediaOptionByType$(ul.Subtitle)]) - } - get enabledAVOptions$() { - return Zd([this.enabledMediaOptionByType$(ul.Variant), this.enabledMediaOptionByType$(ul.AltAudio)]) - } - rawEnabledMediaOptionByType$(t) { - return this.enabledMediaOptionKeys$.pipe(ur(e=>{ - const i = e[t]; - return kl(i) && this.rootMediaOptionsTuple[t].find(e=>{ - return t = i, - e.itemId === t.itemId && e.mediaOptionId === t.mediaOptionId; - var t - } - ) || Ol - } - )) - } - enabledMediaOptionByType$(e) { - return this.rawEnabledMediaOptionByType$(e).pipe(Es((e,t)=>e.mediaOptionId === t.mediaOptionId && e.url === t.url)) - } - enabledMediaOptionSwitchForType$(e) { - return this.rawEnabledMediaOptionByType$(e).pipe(So(this.enabledMediaOptionSwitchContextsByType$(e)), xa(null), ca(), ur(([e,t])=>({ - fromId: null == e ? void 0 : e[0].mediaOptionId, - toId: null == t ? void 0 : t[0].mediaOptionId, - switchContext: null == t ? void 0 : t[1] - })), Es((e,t)=>e.fromId === t.fromId && e.toId === t.toId)) - } - enableMediaOptionSwitchedForType$(t) { - return this.enabledMediaOptionByType$(t).pipe(Ra(e=>$l(Cr([Bi(e), this.enabledMediaOptionSwitchContextsByType$(t).pipe(ca())]), ([,e])=>e[0] && !e[1])), ur(([e])=>e)) - } - enabledMediaOptionIdByType(e) { - return this.getEntity(this.itemId).enabledMediaOptionKeys[e].mediaOptionId - } - variantMediaOptionById(e) { - return this.mediaOptionListQueries[ul.Variant].mediaOptionFromId(e) - } - alternateMediaOptionById(e, t) { - return this.mediaOptionListQueries[e].mediaOptionFromId(t) - } - enabledAlternateMediaOptionByType(e) { - var t = this.enabledMediaOptionIdByType(e); - return this.alternateMediaOptionById(e, t) - } - get enabledVariantMediaOption() { - var e = this.enabledMediaOptionIdByType(ul.Variant); - return this.variantMediaOptionById(e) - } - lastLoadedMediaOptionByType(e) { - var t; - return null === (t = this.getEntity(this.itemId).lastLoadedMediaOptionKeys) || void 0 === t ? void 0 : t[e] - } - get nextMediaOptionsKeys$() { - return this.selectEntity(this.itemId, "nextMediaOptionKeys") - } - get preferredMediaOptions() { - return [this.mediaOptionListQueries[0].preferredMediaOptionList, this.mediaOptionListQueries[1].preferredMediaOptionList, this.mediaOptionListQueries[2].preferredMediaOptionList] - } - get preferredMediaOptions$() { - return Zd([this.mediaOptionListQueries[0].preferredMediaOptionList$, this.mediaOptionListQueries[1].preferredMediaOptionList$, this.mediaOptionListQueries[2].preferredMediaOptionList$]) - } - get filteredMediaOptions() { - return [this.mediaOptionListQueries[0].filteredMediaOptionList, this.mediaOptionListQueries[1].filteredMediaOptionList, this.mediaOptionListQueries[2].filteredMediaOptionList] - } - getDisabledMediaOption(e) { - return { - itemId: this.itemId, - mediaOptionType: e, - mediaOptionId: "Nah" - } - } - getEnabledMediaOptionMask() { - return this.enabledMediaOptionKeys.map(e=>kl(e)) - } - getPreferredMediaOptionsByType$(e) { - return this.mediaOptionListQueries[e].preferredMediaOptionList$ - } - altMediaOptionHasValidUrl(e, t) { - t = this.alternateMediaOptionById(e, t); - return Boolean(null == t ? void 0 : t.url) - } - get hdrMode$() { - return this.mediaOptionListQueries[ul.Variant].hdrMode$ - } - get maxHdcpLevel$() { - return this.mediaOptionListQueries[ul.Variant].maxHdcpLevel$ - } - get currentPathwayID() { - return this.mediaOptionListQueries[ul.Variant].currentPathwayID - } - get preferredHost() { - return this.mediaOptionListQueries[ul.Variant].preferredHost - } - getErrorInfoByType(e) { - var t; - return null != (null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.errorsByType) ? this.rootPlaylistEntity.errorsByType[e] : null - } - getInFlightFragByType(e) { - var t; - return null !== (e = null === (t = null === (t = this.getEntity(this.itemId)) || void 0 === t ? void 0 : t.inFlightFrags) || void 0 === t ? void 0 : t[e]) && void 0 !== e ? e : null - } - getInFlightFragByType$(t) { - return this.selectEntity(this.itemId, e=>{ - return null === (e = null == e ? void 0 : e.inFlightFrags) || void 0 === e ? void 0 : e[t] - } - ) - } - matchAlternates(e, t, i, r) { - t = ne(t) ? this.mediaOptionListQueries[ul.AltAudio].getMatchingAlternateWithPersistentId(t, e, r) : void 0, - r = ne(i) ? this.mediaOptionListQueries[ul.Subtitle].getMatchingAlternateWithPersistentId(i, e, r) : void 0; - return [t || Ol, r || Ol] - } - getLegacyMatchingAlternateWithPersistentId(e, t, i) { - let r = this.mediaOptionListQueries[e].getMatchingAlternateWithPersistentId(t, i, []); - return r = r || this.mediaOptionListQueries[e].getMatchingAlternateWithPersistentId(t, void 0, []), - r - } - isValidMediaOptionTuple(i, e) { - const r = e || this.getEnabledMediaOptionMask(); - return [ul.Variant, ul.AltAudio, ul.Subtitle].reduce((e,t)=>e && r[t] === kl(i[t]), !0) - } - matchGroup(e, t, i, r) { - var n = e.mediaOptionType; - return this.mediaOptionListQueries[n].matchGroup(e, t, i, r) - } - get preferHDR() { - return this.mediaOptionListQueries[ul.Variant].mediaOptionListInfo.preferHDR - } - } - const Iy = { - name: "rps" - }; - class wy { - constructor(e, t) { - this.store = e, - this.logger = t - } - getQuery() { - return new Od(this.store) - } - getQueryForId(e) { - return new Ey(this.store,e) - } - set rootPlaylistEntity(e) { - Co("root.add.rootPlaylist"), - this.store.add(e) - } - removeItems(e) { - Co(`root.add.remove ${JSON.stringify(e)}`), - this.store.remove(e) - } - removeAll() { - Co("root.add.clear"), - this.store.remove() - } - setRootPlaylistEntity(e, t) { - Co("root.set.rootPlaylistEntity"), - this.store.update(e, e=>t) - } - setSessionData(e, t) { - Co("root.set.sessionData"), - this.store.update(e, e=>{ - e.sessionData = t - } - ) - } - setAnchorTime(e, t) { - Co(`root.set.anchorTime: ${t}`), - this.store.update(e, e=>{ - e.anchorTime = t - } - ) - } - setDiscoSeqNum(e, t) { - Co(`root.set.discoSeqNum: ${t}`), - this.store.update(e, e=>{ - e.discoSeqNum = t - } - ) - } - setPendingSeek(e, t) { - Co("root.set.pendingSeek"), - this.store.update(e, e=>{ - e.pendingSeek = t - } - ), - void 0 === t && Xm().setUserSeek(t) - } - setEnabledMediaOptionSwitchContextByType(e, i, r, n) { - this.store.update(e, e=>{ - var t; - if (e.enabledMediaOptionKeys[i].mediaOptionId === r) { - const r = null !== (t = e.mediaOptionSwitchContexts) && void 0 !== t ? t : [null, null, null]; - r[i] = n ? { - userInitiated: n.userInitiated, - switchPosition: n.switchPosition - } : null, - e.mediaOptionSwitchContexts = r - } else - Co(`root.set.mediaOptionSwitchContextByType ${r} doesn't match existing mediaOption ${e.enabledMediaOptionKeys[i].mediaOptionId}`) - } - ) - } - setEnabledMediaOptionByType(r, n, s, a=!1, o) { - s = s || { - itemId: r, - mediaOptionType: n, - mediaOptionId: "Nah" - }, - this.store.update(r, e=>{ - var t; - const i = null !== (t = [...e.enabledMediaOptionKeys]) ? t : [Ol, Ol, Ol]; - if (i[n] = { - itemId: r, - mediaOptionId: s.mediaOptionId - }, - this._updateEnabledMediaOptionKeys(e, i), - a) { - const r = null !== (t = e.mediaOptionSwitchContexts) && void 0 !== t ? t : [null, null, null]; - r[n] = o ? { - userInitiated: o.userInitiated, - switchPosition: o.switchPosition - } : null, - e.mediaOptionSwitchContexts = r - } - } - ) - } - _associateForcedSubtitleWithClosedCaption(e, t, i, r) { - if ((null == i ? void 0 : i.mediaType) === pl.CLOSEDCAPTION) { - t = r.variantMediaOptionById(t), - r = r.mediaOptionListQueries[ul.Subtitle].packageAlternateMediaOption(t, i, !0); - if (r.url !== i.url) { - const n = My(t, r, e.mediaOptionListTuple[ul.Subtitle].mediaOptions, qe()); - e.mediaOptionListTuple[ul.Subtitle].mediaOptions = n - } - } - } - _updateEnabledMediaOptionKeys(t, i) { - var e, r; - const n = null !== (e = t.enabledMediaOptionKeys) && void 0 !== e ? e : [Ol, Ol, Ol]; - let s; - for (let e = 0; e < i.length; ++e) { - var a = i[e] - , o = n[e].mediaOptionId !== a.mediaOptionId; - if (o && (n[e] = Object.assign({}, a)), - e === ul.Variant) { - const i = this.getQueryForId(a.itemId).mediaOptionListQueries[e].mediaOptionList; - o ? t.abrStatus = (r = a.mediaOptionId, - o = i, - o = Lg(r, o), - { - fragDownloadSlow: !1, - fragDownloadTooSlow: !1, - nextMinAutoOptionId: Ol.mediaOptionId, - nextMaxAutoOptionId: Ol.mediaOptionId, - highBWTrigger: o - }) : t.abrStatus.highBWTrigger = Lg(a.mediaOptionId, i), - s = a - } else if (e === ul.Subtitle && kl(a)) { - const i = this.getQueryForId(a.itemId) - , n = i.alternateMediaOptionById(e, a.mediaOptionId); - this._associateForcedSubtitleWithClosedCaption(t, s.mediaOptionId, n, i) - } - } - t.enabledMediaOptionKeys = n, - t.nextMediaOptionKeys = void 0 - } - setManualMode(e, t) { - this.store.update(e, e=>{ - e.manualMode = t - } - ) - } - setEnabledMediaOptions(e, i) { - this.store.update(e, e=>{ - var t = i.map(({mediaOptionId: e, itemId: t})=>({ - mediaOptionId: e, - itemId: t - })); - this._updateEnabledMediaOptionKeys(e, t) - } - ) - } - setEnabledMediaOptionsAndSwitchContexts(e, i, r) { - this.store.update(e, e=>{ - var t = i.map(({mediaOptionId: e, itemId: t})=>({ - mediaOptionId: e, - itemId: t - })); - this._updateEnabledMediaOptionKeys(e, t), - e.mediaOptionSwitchContexts = r - } - ) - } - setNextMediaOptions(e, i) { - Co(`root.set.nextMediaOptions: ${JSON.stringify(null == i ? void 0 : i.map(e=>e.mediaOptionId))}`), - this.store.update(e, e=>{ - var t = i ? i.map(({itemId: e, mediaOptionId: t})=>({ - itemId: e, - mediaOptionId: t - })) : null; - e.nextMediaOptionKeys = t - } - ) - } - updateEnabledMediaOptions(e) { - Co("root.set.updateEnabledMediaOptions"), - this.store.update(e, e=>{ - e.nextMediaOptionKeys && !0 !== e.manualMode && (Co(`root.set.updateEnabledMediaOptions ${JSON.stringify(e.nextMediaOptionKeys)}`), - this._updateEnabledMediaOptionKeys(e, [...e.nextMediaOptionKeys])), - e.nextMediaOptionKeys = void 0 - } - ) - } - setLastLoadedMediaOptionByType(r, n, s) { - Co(`root.set.lastLoadedMediaOptionByType: ${n} ${(s = s || { - itemId: r, - mediaOptionType: n, - mediaOptionId: "Nah" - }).mediaOptionId}`), - this.store.update(r, e=>{ - var t; - const i = null !== (t = e.lastLoadedMediaOptionKeys) && void 0 !== t ? t : [Ol, Ol, Ol]; - i[n] = { - itemId: r, - mediaOptionId: s.mediaOptionId - }, - e.lastLoadedMediaOptionKeys = i - } - ) - } - setPreferredHost(e, t) { - Co(`root.set.preferredHost: ${t}`), - this.store.update(e, e=>{ - e && (e.mediaOptionListTuple[ul.Variant].preferredHost = t) - } - ) - } - setViewportInfo(e, t) { - Co(`root.set.viewportInfo: ${JSON.stringify(t)}`), - this.store.update(e, e=>{ - e && (e.mediaOptionListTuple[ul.Variant].viewportInfo = t) - } - ) - } - static getExistingPersistentIds(e) { - var t; - const i = {} - , r = null === (t = e.enabledMediaOptionKeys[ul.AltAudio]) || void 0 === t ? void 0 : t.mediaOptionId; - if ("Nah" !== r) { - const s = e.mediaOptionListTuple[ul.AltAudio] - , t = wm(s.mediaOptions, Ty.kAllowFilters, s).find(e=>e.mediaOptionId === r); - i.audioPersistentId = null == t ? void 0 : t.persistentID - } - const n = null === (t = e.enabledMediaOptionKeys[ul.Subtitle]) || void 0 === t ? void 0 : t.mediaOptionId; - if ("Nah" !== n) { - const s = e.mediaOptionListTuple[ul.Subtitle] - , t = wm(s.mediaOptions, Ty.kAllowFilters, s).find(e=>e.mediaOptionId === n); - i.subtitlePersistentId = null == t ? void 0 : t.persistentID - } - return i - } - static doUpdateRootHDRSwitch(e, t, i, r) { - const n = e.mediaOptionListTuple.map(e=>Object.assign({}, e)); - n[ul.Variant].preferHDR = t, - n[ul.Variant].hasHdrLevels = i; - const s = Ym() - , a = Hg.getEntity(e.itemId) - , o = Uf(e.itemId) - , d = o.getBandwidthEstimate(s, null == a ? void 0 : a.serviceName) - , l = o.getPlaylistEstimate(s, null == a ? void 0 : a.serviceName) - , u = o.getFragEstimate(s, null == a ? void 0 : a.serviceName) - , c = o.getBufferEstimate(s, null == a ? void 0 : a.serviceName) - , h = { - targetDuration: u.maxDurationSec || (null == s ? void 0 : s.defaultTargetDuration), - targetStartupMs: null == s ? void 0 : s.targetStartupMs - } - , p = wy.getExistingPersistentIds(e); - return Py(Object.assign(Object.assign({}, e), { - mediaOptionListTuple: n, - nextMediaOptionKeys: null - }), p, r, d, h, l, u, c) - } - switchToSDROnly(e) { - Co("root.switchToSDROnly"), - this.store.update(e, e=>{ - var t = wy.doUpdateRootHDRSwitch(e, !1, !1, this.logger)["mediaOptionListTuple"]; - e.mediaOptionListTuple = t - } - ) - } - setHDRPreference(e, i, r) { - Co(`root.set.HDRPreference: ${i}`), - this.store.update(e, e=>{ - var t = e.mediaOptionListTuple[ul.Variant]; - if (t.preferHDR !== i && (!i || t.hasHdrLevels)) { - t = wy.doUpdateRootHDRSwitch(e, i, t.hasHdrLevels, this.logger); - if (r) - return t; - e.mediaOptionListTuple = t.mediaOptionListTuple - } - } - ) - } - setPathwayPriority(e, i) { - Co(`root.set.PathwayPriority: [ ${i.join(", ")} ]`), - this.store.update(e, e=>{ - if (e) { - const t = e.mediaOptionListTuple[ul.Variant]; - t.pathwayPriority = i, - t.preferredHost = null - } - } - ) - } - setCurrentPathwayID(e, t) { - Co(`root.set.currentPathwayID: ${t}`), - this.store.update(e, e=>{ - e && (e.mediaOptionListTuple[ul.Variant].currentPathwayID = t) - } - ) - } - setInitPTS(e, t, i, r, n, s) { - Co(`root.set.initPTS: ${e} ${t} variantDTS:${JSON.stringify(i)} timelineOffset: ${r}`), - this.store.update(e, e=>{ - e.initPtsRecord[t] = { - variantDTS: i, - timelineOffset: r, - offsetTimestamp: n, - iframeMode: s - } - } - ) - } - static prunePenaltyBox(e, t) { - return e.filter(e=>!(e.expiry <= t)) - } - static addToPenaltyBox(e, t, i) { - return e.push({ - mediaOptionId: i, - expiry: t + 12e4 - }) - } - addToPenaltyBox(e, r, n) { - Co(`root.set.penaltyBox: ${r}: ${n}`), - this.store.update(e, ({mediaOptionListTuple: e})=>{ - const t = e[r] - , i = performance.now(); - t.penaltyBoxQueue = wy.prunePenaltyBox(t.penaltyBoxQueue, i), - wy.addToPenaltyBox(t.penaltyBoxQueue, i, n) - } - ) - } - prunePenaltyBox(e, r=null) { - Co(`root.set.prunePenaltyBox: ${r}`), - this.store.update(e, ({mediaOptionListTuple: e})=>{ - var e = r ? [e[r]] : e - , t = performance.now(); - for (const i of e) - i.penaltyBoxQueue = wy.prunePenaltyBox(i.penaltyBoxQueue, t) - } - ) - } - removePermanently(e, r, n) { - Co(`root.set.removePermanently: ${r}: ${n}`), - this.store.update(e, ({mediaOptionListTuple: e})=>{ - const t = e[r] - , i = new Set(t.removed); - i.add(n), - t.removed = Array.from(i) - } - ) - } - moveAllWithMatchingHosts(e, r, n, s) { - Co(`root.set.moveAllMatchingHosts: ${r}:${n} remove:${s}`), - this.store.update(e, ({mediaOptionListTuple: e})=>{ - const t = e[r] - , i = [...t.mediaOptions].filter(e=>yl(n, e.url)).map(e=>e.mediaOptionId); - if (s) { - const e = new Set([...t.removed, ...i]); - t.removed = Array.from(e) - } else { - const e = performance.now(); - t.penaltyBoxQueue = wy.prunePenaltyBox(t.penaltyBoxQueue, e); - for (const r of i) - wy.addToPenaltyBox(t.penaltyBoxQueue, e, r) - } - } - ) - } - setMaxHdcpLevel(e, i, r=!1) { - Co(`root.set.maxHdcpLevel: ${i}`), - this.store.update(e, ({mediaOptionListTuple: e})=>{ - const t = e[ul.Variant]; - (r || Yf(i) < Yf(t.maxHdcpLevel)) && (t.maxHdcpLevel = i) - } - ) - } - updateConsecutiveTimeouts(e, i, r, n) { - this.store.update(e, e=>{ - const t = e.errorsByType || [{ - timeouts: { - load: 0, - append: 0, - key: 0 - } - }, { - timeouts: { - load: 0, - append: 0, - key: 0 - } - }, { - timeouts: { - load: 0, - append: 0, - key: 0 - } - }]; - r ? ++t[i].timeouts[n] : t[i].timeouts[n] = 0, - e.errorsByType = t - } - ) - } - updateInflightFrag(d, l, u, c, h) { - Co("root.set.updateInflightFrag"), - this.store.update(d, r=>{ - if (r.inFlightFrags || (r.inFlightFrags = [null, null]), - !(l === ul.Subtitle || u && u.itemId !== d)) - if (u) { - let {start: e, duration: t} = u; - var {mediaOptionId: n, mediaSeqNum: s, discoSeqNum: a} = u - , o = r.inFlightFrags[l]; - let i = null == o ? void 0 : o.tstart; - c !== (null == o ? void 0 : o.state) && (i = performance.now()), - Fp(o, u) && (e = o.start, - t = o.duration), - r.inFlightFrags[l] = { - itemId: d, - mediaOptionId: n, - mediaSeqNum: s, - discoSeqNum: a, - start: e, - duration: t, - tstart: i, - state: c, - bwSample: Object.assign({}, h) - } - } else - r.inFlightFrags[l] = null - } - ) - } - setNextMaxAutoOptionId(e, t) { - Co(`root.set.nextMaxAutoOptionId: ${t}`), - this.store.update(e, ({abrStatus: e})=>{ - e.nextMaxAutoOptionId = t - } - ) - } - setNextMinAutoOptionId(e, t) { - Co(`root.set.nextMinAutoOptionId: ${t}`), - this.store.update(e, ({abrStatus: e})=>{ - e.nextMinAutoOptionId = t - } - ) - } - setHighBWTrigger(e, t) { - Co(`root.set.setHighBWTrigger: ${t}`), - this.store.update(e, ({abrStatus: e})=>{ - e.highBWTrigger = t - } - ) - } - setFragLoadSlow(e, t) { - Co(`root.set.setFragLoadSlow ${e} ${JSON.stringify(t)}`), - this.store.update(e, ({abrStatus: e})=>{ - e.fragDownloadSlow = t.fragDownloadSlow, - e.fragDownloadTooSlow = t.fragDownloadTooSlow - } - ) - } - pickMediaOptionTupleByPersistentId(e, t, i, r=!1, n=!1) { - var s = e.enabledMediaOptionIdByType(ul.Variant) - , s = e.variantMediaOptionById(s); - let a, o; - if (t === ul.AltAudio) { - const t = e.enabledAlternateMediaOptionByType(ul.Subtitle); - o = null == t ? void 0 : t.persistentID, - a = i - } else { - const t = e.enabledAlternateMediaOptionByType(ul.AltAudio); - a = null == t ? void 0 : t.persistentID, - o = i - } - const d = e.getEnabledMediaOptionMask(); - return d[t] = !!(ne(i) && 0 <= i), - s ? this.getBestMediaOptionTupleFromVariantAndPersistentId(e, s, a, o, d, void 0, r, n, !1) : [Ol, Ol, Ol] - } - getFallbackMediaOptionTupleFromMediaOptionId(e, t, i, r, n=!1, s=!1, a=!1) { - var o = r ? [r] : [i] - , d = e.enabledMediaOptionIdByType(ul.Variant) - , r = e.variantMediaOptionById(d) - , d = t === ul.AltAudio ? e.alternateMediaOptionById(ul.AltAudio, i) : e.enabledAlternateMediaOptionByType(ul.AltAudio) - , d = null == d ? void 0 : d.persistentID - , i = t === ul.Subtitle ? e.alternateMediaOptionById(ul.Subtitle, i) : e.enabledAlternateMediaOptionByType(ul.Subtitle) - , i = null == i ? void 0 : i.persistentID; - return r ? this.getBestMediaOptionTupleFromVariantAndPersistentId(e, r, d, i, void 0, o, n, s, a) : [Ol, Ol, Ol] - } - hasFallbackMediaOptionTuple(e, t, i, r) { - var n = e.mediaOptionListQueries[t].mediaOptionFromId(i); - return e.isValidMediaOptionTuple(this.getFallbackMediaOptionTupleFromMediaOptionId(e, t, i, n.backingMediaOptionId, !1, r)) - } - setLegacyAlternateMediaOption(e, t, i, r, n) { - var s = e.enabledMediaOptionIdByType(ul.Variant) - , s = e.variantMediaOptionById(s) - , s = e.getLegacyMatchingAlternateWithPersistentId(i, r, s); - s ? this.setEnabledMediaOptionByType(t, i, s, !0, n) : this.logger.warn(`${Cl[i]} can't find matching mediaOption for persistent id ${r}`) - } - setEnabledMediaOptionTupleWithMatchedGroups(t, i, e, r) { - const n = ky(t) - , s = this.pickMediaOptionTupleByPersistentId(n, i, e); - if (!n.isValidMediaOptionTuple(s)) - return this.setLegacyAlternateMediaOption(n, t, i, e, r); - sd(()=>{ - this.setEnabledMediaOptionByType(t, i, s[i], !0, r), - s[ul.Variant].mediaOptionId !== n.enabledMediaOptionIdByType(ul.Variant) && this.setPreferredHost(t, gl(s[ul.Variant].url)), - this.setEnabledMediaOptionByType(t, ul.Variant, s[ul.Variant]); - var e = i === ul.AltAudio ? ul.Subtitle : ul.AltAudio; - s[e].mediaOptionId !== n.enabledMediaOptionIdByType(e) && this.setEnabledMediaOptionByType(t, e, s[e], !1) - } - ) - } - canSwitchToSDR(e, t, i, r=!1) { - var n = e.mediaOptionListQueries[ul.Variant].mediaOptionFromId(t) - , r = this.getFallbackMediaOptionTupleFromMediaOptionId(e, ul.Variant, t, n.backingMediaOptionId, !0, i, r); - return e.isValidMediaOptionTuple(r) - } - getBestMediaOptionTupleFromVariantAndPersistentId(t, e, i, r, n, s, a, o, d) { - var l, u = t.mediaOptionListQueries[ul.Variant].listFallbackVariants(e.mediaOptionId, a, o, d, s); - let c = [Ol, Ol, Ol]; - for (let e = 0; e < u.length; ++e) { - const a = u[e]; - if (l = t.matchAlternates(a, i, r, s), - t.isValidMediaOptionTuple([a, ...l], n)) { - c = [a, ...l]; - break - } - } - return c - } - } - const Ay = new class extends pd { - constructor() { - super({}, { - name: "root-playlist-store", - idKey: "itemId", - producerFn: vc - }) - } - akitaPreAddEntity(e) { - return null == e.errorsByType ? Object.assign(Object.assign({}, e), { - errorsByType: [{ - timeouts: { - load: 0, - append: 0, - key: 0 - } - }, { - timeouts: { - load: 0, - append: 0, - key: 0 - } - }, { - timeouts: { - load: 0, - append: 0, - key: 0 - } - }] - }) : e - } - } - ; - new Od(Ay); - let Oy = null; - function ky(e) { - return new Ey(Ay,e) - } - const Cy = (n,e,t,s,i)=>{ - const {rootMediaOptionsTuple: r, sessionKeys: a} = n - , o = Array.from(r[ul.Variant]) - , d = Array.from(r[ul.AltAudio]); - let l = !1 - , u = !1 - , c = o.map(e=>(l = l || Boolean(e.videoCodec), - u = u || Boolean(e.audioCodec) || Boolean(e.audioGroupId), - e)); - return l && u && (c = c.filter(({videoCodec: e})=>Boolean(e))), - Sy(o, d, a, e, t, i).pipe(ur(({hdrMediaOptions: e, sdrMediaOptions: t})=>{ - var i = e.concat(t) - , r = 0 < e.length; - return e.concat(t), - function(e, t, i, r) { - var {itemId: n, itemStartOffset: s, rootMediaOptionsTuple: a, audioMediaSelectionGroup: o, subtitleMediaSelectionGroup: d} = e - , l = Array.from(a[ul.AltAudio]) - , u = Array.from(a[ul.Subtitle]) - , c = t.every(e=>ne(e.score)) - , h = t.some(e=>Dm(!0, e)) - , p = function(e, t) { - const i = [...e]; - return t ? i.sort((e,t)=>e.score - t.score || t.bitrate - e.bitrate) : i.sort((e,t)=>e.bitrate - t.bitrate), - i - }(t, c) - , f = e.baseUrl - , t = null === (a = e.contentSteeringOption) || void 0 === a ? void 0 : a.initPathwayID - , a = e.sessionData; - return { - itemId: n, - baseUrl: f, - mediaOptionListTuple: [{ - mediaOptions: p, - hasHdrLevels: i, - hasIframeLevels: h, - hasScore: c, - preferHDR: r, - compatibleIds: null, - penaltyBoxQueue: [], - removed: [], - currentPathwayID: t - }, { - mediaOptions: l, - compatibleIds: null, - penaltyBoxQueue: [], - removed: [] - }, { - mediaOptions: u, - penaltyBoxQueue: [], - removed: [] - }], - audioMediaSelectionGroup: o, - subtitleMediaSelectionGroup: d, - enabledMediaOptionKeys: [Ol, Ol, Ol], - mediaOptionSwitchContexts: [null, null, null], - anchorTime: 0, - discoSeqNum: NaN, - pendingSeek: void 0, - itemStartOffset: s, - initPtsRecord: {}, - contentSteeringOption: e.contentSteeringOption, - masterVariableList: e.masterVariableList, - loadStats: e.stats, - isMediaPlaylist: e.isMediaPlaylist, - abrStatus: { - fragDownloadSlow: !1, - fragDownloadTooSlow: !1, - nextMinAutoOptionId: Ol.mediaOptionId, - nextMaxAutoOptionId: Ol.mediaOptionId, - highBWTrigger: NaN - }, - sessionData: a - } - }(n, i, r, s) - } - )) - } - ; - function Dy(e, t, i, r, n, s, a) { - var o, d, l, u, c, h, p, f = e.mediaOptionListTuple[ul.Variant], m = wm(f.mediaOptions, xm.kAllowFilters, Object.assign(Object.assign({}, f), { - compatibleIds: null - })), g = Am(f.preferredHost, m); - return { - firstVariant: (o = g, - e = Tg, - f = f.hasScore, - t = t, - i = i, - r = r, - n = n, - s = s, - a = a, - !o || o.length < 1 || o.every(e=>e.iframes) ? void t.warn("no non-iframe media option found") : ((o = f ? Eg(o, i, r, n, s, a) : (d = e, - l = i, - u = r, - c = n, - h = s, - p = a, - o.reduce((e,t)=>{ - if (t.iframes) - return e; - let i = e; - const r = function(e, t, i, r, n, s, a) { - var o, d, l = (o = e.bitrate, - u = e.height, - (d = (e,t,i)=>(e - t) * (e - i) <= 0)(o, t.minValidBitrate, t.maxValidBitrate) && d(u, t.minValidHeight, t.maxValidHeight) ? ll.VALID : ll.INVALID), o = "PQ" === (c = e.videoRange) ? ol.PQ : "HLG" === c ? ol.HLG : "SDR" === c ? ol.SDR : ol.UNKNOWN, {videoCodecRank: u, audioCodecRank: c} = { - videoCodecRank: $p((d = e).videoCodec), - audioCodecRank: Kp(d.audioCodec) - }, d = e.bitrate < t.maxPreferredBitrate ? ll.VALID : ll.INVALID, t = e.audioChannelCount || 1, a = i && r && n && s && !Ig(e, i, r, n, s, a) ? ll.INVALID : ll.VALID; - return new Hp(l,o,u,t,c,a,d,e.height) - }(t, d, l, u, c, h, p); - return (!e || r.isGreaterThan(e.bestRank) || r.isEqualTo(e.bestRank) && t.bitrate > e.selected.bitrate) && (i = { - selected: t, - bestRank: r - }), - i - } - , null).selected)) || t.warn("no valid first media option found"), - o)), - filteredVariants: m, - preferredVariants: g - } - } - function My(e, t, i) { - if ((null == t ? void 0 : t.mediaType) === pl.CLOSEDCAPTION) { - const r = Ty.pairForcedSubtitleMediaOptionWithClosedCaptionInList(e.subtitleGroupId, t, i); - if (r) - return t = Object.assign(Object.assign({}, t), { - url: r.url, - backingMediaOptionId: r.mediaOptionId - }), - i.map(e=>e.mediaOptionId === t.mediaOptionId ? t : e) - } - return i - } - function Py(e, t, i, r, n, s, a, o) { - var d; - const l = e.itemId - , u = e.mediaOptionListTuple[ul.Variant] - , c = e.mediaOptionListTuple[ul.AltAudio] - , h = e.mediaOptionListTuple[ul.Subtitle] - , p = wm(c.mediaOptions, Ty.kAllowFilters, c) - , f = wm(h.mediaOptions, Ty.kAllowFilters, h); - let {firstVariant: m, filteredVariants: g} = Dy(e, i, r, n, s, a, o); - if (!m) { - const U = u.preferHDR; - u.preferHDR = !U && u.hasHdrLevels, - u.preferHDR !== U && (i.warn(`No valid first variant found, toggling hdr preference=${U}->${u.preferHDR}`), - {firstVariant: m, filteredVariants: g} = Dy(e, i, r, n, s, a, o)) - } - if (!m) - throw new V(!0,"No valid first variant found",$.NoValidAlternates); - const y = gl(m.url) - , v = { - itemId: l, - mediaOptionId: null !== (o = null == m ? void 0 : m.mediaOptionId) && void 0 !== o ? o : null - } - , S = null != p && p.length ? null === (o = ((i,r,e,n)=>{ - if (e) { - let t; - return t = ne(i) ? e.MediaSelectionGroupOptions.find(function(e) { - return e.MediaSelectionOptionsPersistentID === i - }) : e.MediaSelectionGroupOptions.find(function(e) { - return e.MediaSelectionOptionsIsDefault - }), - t = t || e.MediaSelectionGroupOptions[0], - n.find(e=>(!r || e.groupId === r) && e.persistentID === (null == t ? void 0 : t.MediaSelectionOptionsPersistentID)) - } - } - )(null == t ? void 0 : t.audioPersistentId, m.audioGroupId, e.audioMediaSelectionGroup, p)) || void 0 === o ? void 0 : o.mediaOptionId : null - , b = S ? { - itemId: l, - mediaOptionId: S - } : Ol - , T = ((i,r,n,s,a,o)=>{ - if (s) { - let t, e; - return t = ne(i) ? s.MediaSelectionGroupOptions.find(function(e) { - return e.MediaSelectionOptionsPersistentID === i - }) : s.MediaSelectionGroupOptions.find(function(e) { - return e.MediaSelectionOptionsIsDefault - }), - t && (e = a.find(e=>e.mediaType === pl.CLOSEDCAPTION ? (!r || e.groupId === r) && e.persistentID === t.MediaSelectionOptionsPersistentID : e.mediaType === pl.SUBTITLE ? (!n || e.groupId === n) && e.persistentID === t.MediaSelectionOptionsPersistentID : void o.warn(Iy, `subtitle media option has unknown type ${e.mediaType}`))), - e - } - } - )(null == t ? void 0 : t.subtitlePersistentId, m.closedcaption, m.subtitleGroupId, e.subtitleMediaSelectionGroup, f, i) - , E = null != f && f.length ? null == T ? void 0 : T.mediaOptionId : null - , I = E ? { - itemId: l, - mediaOptionId: E, - mediaOptionType: ul.Subtitle - } : Ol - , {mediaOptions: w, audioGroups: A, subtitleGroups: O} = (t = g, - d = m, - t.reduce((e,t)=>{ - if (((e,t)=>{ - let i = !0; - e.videoCodec && t.videoCodec && (i = Se.isCompatibleVideoCodec(e.videoCodec, t.videoCodec)); - let r = !1; - e.videoRange && t.videoRange ? r = e.videoRange == t.videoRange : e.videoRange || t.videoRange || (r = !0); - let n = !0; - return e.audioCodec && t.audioCodec && (n = Se.isCompatibleAudioCodec(e.audioCodec, t.audioCodec)), - i && r && n - } - )(d, t)) { - const d = t.audioGroupId; - d && e.audioGroups.add(d), - e.mediaOptions.add(t) - } - var i = t.subtitleGroupId; - i && e.subtitleGroups.add(i); - t = t.closedcaption; - return t && e.closedCaptionGroups.add(t), - e - } - , { - mediaOptions: new Set, - audioGroups: new Set, - subtitleGroups: new Set, - closedCaptionGroups: new Set - })) - , k = Array.from(w).map(e=>e.mediaOptionId) - , C = m.pathwayID - , D = Object.assign(Object.assign({}, u), { - compatibleIds: k, - preferredHost: y, - currentPathwayID: C - }) - , M = [] - , P = c.mediaOptions.reduce((e,t)=>(A.has(t.groupId) && (e.persistentIds.add(t.persistentID), - M.push(t.mediaOptionId), - e.filteredAudioMediaOptions.push(t), - e.altAudio || (e.altAudio = !!t.url)), - e), { - filteredAudioMediaOptions: [], - persistentIds: new Set, - altAudio: !1 - }) - , x = Object.assign(Object.assign({}, c), { - compatibleIds: M - }); - let R = e.audioMediaSelectionGroup; - const L = null == R ? void 0 : R.MediaSelectionGroupOptions; - if (L) { - const e = L.reduce((e,t)=>(P.persistentIds.has(t.MediaSelectionOptionsPersistentID) && e.push(t), - e), new Array); - R = Object.assign(Object.assign({}, R), { - MediaSelectionGroupOptions: e - }) - } - h.mediaOptions = My(m, T, h.mediaOptions); - const _ = h.mediaOptions.reduce((e,t)=>(O.has(t.groupId) && (e.persistentIds.add(t.persistentID), - e.filteredSubtitleMediaOptions.push(t)), - e), { - filteredSubtitleMediaOptions: [], - persistentIds: new Set - }); - let N = e.subtitleMediaSelectionGroup; - const F = null == N ? void 0 : N.MediaSelectionGroupOptions; - if (F) { - const e = F.reduce((e,t)=>(_.persistentIds.has(t.MediaSelectionOptionsPersistentID) && e.push(t), - e), new Array); - N = Object.assign(Object.assign({}, N), { - MediaSelectionGroupOptions: e - }) - } - i = [D, x, h]; - let B = new Map; - Ym().useHighestVideoCodecPrivate && (B = null == D ? void 0 : D.mediaOptions.reduce((e,t)=>{ - const i = t.videoCodecList; - if (i) - for (const t of i) { - const i = Vp(t) - , r = e.get(i); - Se.isHigherCodecByFamily(r, t) && e.set(i, t) - } - return e - } - , B)), - B.size && B.forEach((e,t)=>{} - ); - t = { - fragDownloadSlow: !1, - fragDownloadTooSlow: !1, - nextMinAutoOptionId: Ol.mediaOptionId, - nextMaxAutoOptionId: Ol.mediaOptionId, - highBWTrigger: Lg(v.mediaOptionId, D.mediaOptions) - }; - return Object.assign(Object.assign({}, e), { - enabledMediaOptionKeys: [v, b, I], - mediaOptionListTuple: i, - audioMediaSelectionGroup: R, - abrStatus: t, - highestVideoCodec: B - }) - } - const xy = (o,d,l,u,c,h,p)=>e=>e.pipe(Ql.tag("retrieveRootMediaOptions.input"), Ra(t=>{ - var e; - if (!t) - return Ti; - const {itemId: i, platformInfo: r} = t - , n = ky(i) - , s = d["logger"]; - if (n.hasEntity(i)) - return Bi(n); - Ay.setLoading(!0); - const a = performance.now(); - return function(e, t, u, c, i) { - const {itemId: h, url: p, itemStartOffset: f} = e - , r = xc(e, t); - return bm({ - url: p, - onProgress: { - getData: !0, - cb: dy - }, - xhrSetup: c.xhrSetup - }, r, i).pipe(ur(({responseText: e, stats: t})=>{ - var i = c["keySystemPreference"]; - if (Sm.isMediaPlaylist(e)) { - const c = "media-pl-" + Jd() - , d = Sm.parseMediaOptionPlaylist(e, p, !0, i, {}, h, c, ul.Variant, u, f); - Lc(d.mediaOptionDetails); - var r = { - itemId: h, - mediaOptionId: c, - mediaOptionType: ul.Variant, - url: p, - bandwidth: 0, - bitrate: 0, - iframes: d.mediaOptionDetails.iframesOnly, - pathwayID: "." - }; - return { - itemId: h, - itemStartOffset: f, - rootMediaOptionsTuple: [[r], [], []], - stats: t, - baseUrl: p, - initialDetails: d.mediaOptionDetails, - isMediaPlaylist: !0 - } - } - { - const u = Sm.parseSessionData(e, p) - , c = Sm.parseSessionKeys(e, p, i) - , l = Sm.parseRootPlaylist(h, e, p, !0); - if (l.playlistParsingError) - throw l.playlistParsingError; - var {variantMediaOptions: n, contentSteeringOption: s, masterVariableList: a} = l - , o = Sm.parseRootPlaylistAlternateMediaOptions(h, e, p, l.variantMediaOptions, !0, a); - if (o.playlistParsingError) - throw o.playlistParsingError; - var {audioAlternateOptions: r, subtitleAlternateOptions: i, audioMediaSelectionGroup: e, subtitleMediaSelectionGroup: o} = o.alternateMediaInfo; - return { - itemId: h, - itemStartOffset: f, - rootMediaOptionsTuple: [n, r, i], - stats: t, - baseUrl: p, - audioMediaSelectionGroup: e, - subtitleMediaSelectionGroup: o, - contentSteeringOption: s, - sessionData: u, - sessionKeys: c, - masterVariableList: a - } - } - } - ), e=>e.pipe(Un(e=>{ - if (e instanceof ou) - throw new ru(!1,"Timeout",0,$.ManifestTimeoutError,!0); - if (e instanceof tu) - throw new ru(!1,e.message,e.code,{ - code: e.code, - text: "Manifest network error" - },!1); - throw e - } - ))) - }(t, o, s, l, null === (e = null === (e = Xm()) || void 0 === e ? void 0 : e.getQuery()) || void 0 === e ? void 0 : e.extendMaxTTFB).pipe(Ja(e=>p.triggerManifestLoaded(e)), Ja(({initialDetails: e, stats: t})=>{ - e && (e = e, - t = t, - hg().archiveMediaOptionDetails(e, t, !0)) - } - ), So(u.displaySupportsHdr$), Ra(([e,t])=>Cy(e, r, l, t, s)), ur(e=>(d.rootPlaylistEntity = function(e, t, i, r, n, s) { - const {itemId: a, initialSeekTime: o} = e - , d = Uf(a) - , l = n.enableAdaptiveStartup ? d.getBandwidthEstimate(n, e.serviceName) : void 0 - , u = n.enableAdaptiveStartup ? d.getPlaylistEstimate(n, e.serviceName) : void 0 - , c = n.enableAdaptiveStartup ? d.getFragEstimate(n, e.serviceName) : void 0 - , h = n.enableAdaptiveStartup ? d.getBufferEstimate(n, e.serviceName) : void 0 - , p = n.targetStartupMs - (performance.now() - r) - , f = n.enableAdaptiveStartup ? { - targetDuration: c.maxDurationSec || n.defaultTargetDuration, - targetStartupMs: p - } : void 0 - , m = Py(t, i, s, l, f, u, c, h); - return m.pendingSeek = o, - m - }(t, e, c, a, l, s), - n)), jm(i, null, xc(t, o), 0, !1, n, d, h), $s(()=>{ - Ay.setLoading(!1) - } - )) - } - ), Ql.tag("retrieveRootMediaOptions.emit")); - class Ry { - } - Ry.PlayEnded = 6101, - Ry.Periodic = 6110, - Ry.PlayStalled = 6103, - Ry.KeySessionComplete = 6104, - Ry.PlayLikelyToKeepUp = 6105, - Ry.PlayRateChanged = 6106, - Ry.PlayError = 6107, - Ry.MediaEngineStalled = 6108, - Ry.SwitchComplete = 6109, - Ry.VariantEnded = 6111, - Ry.NwError = 6202; - const Ly = { + class Df { + } + Df.PlayEnded = 6101, + Df.Periodic = 6110, + Df.PlayStalled = 6103, + Df.KeySessionComplete = 6104, + Df.PlayLikelyToKeepUp = 6105, + Df.PlayRateChanged = 6106, + Df.PlayError = 6107, + Df.MediaEngineStalled = 6108, + Df.SwitchComplete = 6109, + Df.VariantEnded = 6111, + Df.NwError = 6202; + const Mf = { avc1: 1, avc3: 1, hvc1: { @@ -28472,7 +21368,7 @@ PQ: 12 } }; - class _y { + class Pf { constructor(e, t) { this.query = e, this.logger = t @@ -28481,51 +21377,51 @@ this.reportingAgent = e } sendPlayEnded(e) { - var t = Ry.PlayEnded; + var t = Df.PlayEnded; this.fillAndFire(t, this.query.playEnded(e)) } sendPlayStalled(e) { - var t = Ry.PlayStalled; + var t = Df.PlayStalled; this.fillAndFire(t, this.query.playStalled(e)) } sendMediaEngineStalled(e) { - var t = Ry.MediaEngineStalled; + var t = Df.MediaEngineStalled; this.fillAndFire(t, this.query.mediaEngineStalled(e)) } sendKeySessionComplete(e) { - var t = Ry.KeySessionComplete; + var t = Df.KeySessionComplete; this.fillAndFire(t, this.query.keySessionComplete(e)) } sendPlayLikelyToKeepUp(e) { - var t = Ry.PlayLikelyToKeepUp; + var t = Df.PlayLikelyToKeepUp; this.fillAndFire(t, this.query.playLikelyToKeepUp(e)) } sendPlayRateChange(e) { - var t = Ry.PlayRateChanged; + var t = Df.PlayRateChanged; this.fillAndFire(t, this.query.playRateChanged(e)) } sendSwitchComplete(e) { - var t = Ry.SwitchComplete; + var t = Df.SwitchComplete; this.fillAndFire(t, this.query.switchComplete(e)) } sendVariantEnded(e) { - var t = Ry.VariantEnded; + var t = Df.VariantEnded; this.fillAndFire(t, this.query.variantEnded(e)) } sendPlayError(e) { - var t = Ry.PlayError; + var t = Df.PlayError; this.fillAndFire(t, this.query.playError(e)) } sendNwError(e) { - var t = Ry.NwError; + var t = Df.NwError; this.fillAndFire(t, this.query.nwError(e)) } sendPeriodic(e) { - var t = Ry.Periodic; + var t = Df.Periodic; this.fillAndFire(t, this.query.periodic(e)) } fillAndFire(e, t) { - var r = e === Ry.PlayEnded || e === Ry.Periodic ? 1 : 0; + var r = e === Df.PlayEnded || e === Df.Periodic ? 1 : 0; if (this.reportingAgent) { let i = {}; Object.entries(t).forEach(([e,t])=>{ @@ -28542,7 +21438,7 @@ } } } - class Ny extends Od { + class xf extends Od { constructor(e, t) { super(e), this.logger = t @@ -28587,7 +21483,7 @@ return null === (e = this.getEntity(e)) || void 0 === e ? void 0 : e.nwErrorRecord } } - class Fy extends pd { + class Rf extends pd { constructor(e) { super({}, { name: "rtc-store", @@ -28825,7 +21721,7 @@ } finalize(e, t) { switch (t) { - case Ry.PlayEnded: + case Df.PlayEnded: this.update(e, ({sessionControlRecord: e})=>{ e.state = "RTC_STATE_STOP", e.oldRate = 0 @@ -28836,7 +21732,7 @@ } ); break; - case Ry.Periodic: + case Df.Periodic: this.update(e, ({sessionControlRecord: t})=>{ t.lastPeriodicTime = Date.now(), t.periodicEventCounter += 1, @@ -28851,7 +21747,7 @@ } ); break; - case Ry.PlayStalled: + case Df.PlayStalled: this.update(e, ({sessionControlRecord: e})=>{ e.state = "RTC_STATE_STALL", e.oldRate = 0 @@ -28862,7 +21758,7 @@ } ); break; - case Ry.KeySessionComplete: + case Df.KeySessionComplete: this.update(e, ({sessionControlRecord: e})=>{ delete e.activeKeySessions[e.finishedKeyUri] } @@ -28872,7 +21768,7 @@ } ); break; - case Ry.PlayLikelyToKeepUp: + case Df.PlayLikelyToKeepUp: this.update(e, ({sessionControlRecord: e})=>{ "RTC_STATE_PLAY" !== e.state && (e.state = "RTC_STATE_CANPLAY", e.lastLikelyToKeepUpTime = Date.now(), @@ -28884,7 +21780,7 @@ } ); break; - case Ry.PlayRateChanged: + case Df.PlayRateChanged: this.update(e, ({sessionControlRecord: e, playEndedRecord: t, playStalledRecord: i, mediaEngineStalledRecord: r, playErrorRecord: n, nwErrorRecord: s})=>{ 0 !== e.rate ? (e.state = "RTC_STATE_PLAY", delete t.LastStall, @@ -28904,7 +21800,7 @@ } ); break; - case Ry.PlayError: + case Df.PlayError: this.update(e, ({sessionControlRecord: e})=>{ e.state = "RTC_STATE_PLAYERROR" } @@ -28914,7 +21810,7 @@ } ); break; - case Ry.MediaEngineStalled: + case Df.MediaEngineStalled: this.update(e, ({sessionControlRecord: e})=>{ e.state = "RTC_STATE_MEDIAENGINESTALL", e.oldRate = 0 @@ -28925,14 +21821,14 @@ } ); break; - case Ry.SwitchComplete: + case Df.SwitchComplete: this.update(e, e=>{ e.switchCompleteRecord = {}, e.sessionControlRecord.prevLevelUrl = e.sessionControlRecord.curLevelUrl } ); break; - case Ry.VariantEnded: + case Df.VariantEnded: this.update(e, ({sessionControlRecord: e})=>{ e.decodedFramesForVariant = 0, e.decodedFramesForVariantSampleCount = 0 @@ -28943,7 +21839,7 @@ } ); break; - case Ry.NwError: + case Df.NwError: this.update(e, ({sessionControlRecord: e})=>{ e.state = "RTC_STATE_NWERROR" } @@ -29473,13 +22369,13 @@ n } _getNormalizedPeak(e, t) { - return "object" == typeof Ly[t] ? 1.5 * e : +e + return "object" == typeof Mf[t] ? 1.5 * e : +e } _getVideoFourCC(e) { - return e && e.split(",").map(e=>e.split(".")[0].trim()).find(e=>!!Ly[e]) + return e && e.split(",").map(e=>e.split(".")[0].trim()).find(e=>!!Mf[e]) } _getVideoQualityIndex(e, t) { - return "object" == typeof Ly[e] ? Ly[e][t] : Ly[e] + return "object" == typeof Mf[e] ? Mf[e][t] : Mf[e] } _getBitrateRank(e, t, i) { t = Math.max(1, this._getNormalizedPeak(e, t)); @@ -29640,10 +22536,10 @@ ) } } - const By = { + const Lf = { name: "rtc-service" }; - class Uy { + class _f { constructor(e, t, i, r) { this.hls = e, this.config = t, @@ -29654,9 +22550,9 @@ this.seekStart = null, this.periodicInterval = t.rtcIntervalTimeout || 3e5, this.intervalFunc = null, - this.rtcStore = new Fy(this.logger), - this.rtcQuery = new Ny(this.rtcStore,this.logger), - this.rtcComponent = new _y(this.rtcQuery,this.logger), + this.rtcStore = new Rf(this.logger), + this.rtcQuery = new xf(this.rtcStore,this.logger), + this.rtcComponent = new Pf(this.rtcQuery,this.logger), i.setRTCQuery(this.rtcQuery), this.subscribeAndUpdateStore(), this.registerForEvents() @@ -29674,13 +22570,13 @@ this.rtcStore.updateVariantEnd(this.rtcEventItemId(!0), { currentTime: e }), - this.sendAndFinalize(this.rtcEventItemId(!0), Ry.VariantEnded), + this.sendAndFinalize(this.rtcEventItemId(!0), Df.VariantEnded), this.rtcStore.updatePeriodic(this.rtcEventItemId(!0), !0), - this.sendAndFinalize(this.rtcEventItemId(!0), Ry.Periodic), + this.sendAndFinalize(this.rtcEventItemId(!0), Df.Periodic), this.rtcStore.updateEnded(this.rtcEventItemId(!0)), - this.sendAndFinalize(this.rtcEventItemId(!0), Ry.PlayEnded) + this.sendAndFinalize(this.rtcEventItemId(!0), Df.PlayEnded) } catch (e) { - this.logger.warn(By, e) + this.logger.warn(Lf, e) } } handleError(e) { @@ -29690,25 +22586,25 @@ mediaDur: this.hls.bufferedDuration, isSeeking: this.isSeeking }), - this.sendAndFinalize(this.rtcEventItemId(), Ry.SwitchComplete)) : t.type === o ? (this.rtcStore.updateNwError(this.rtcEventItemId(), { + this.sendAndFinalize(this.rtcEventItemId(), Df.SwitchComplete)) : t.type === o ? (this.rtcStore.updateNwError(this.rtcEventItemId(), { fatal: t.fatal, details: t.details, code: null === (e = t.response) || void 0 === e ? void 0 : e.code }), - this.sendAndFinalize(this.rtcEventItemId(), Ry.NwError)) : (this.rtcStore.updateMediaError(this.rtcEventItemId(), { + this.sendAndFinalize(this.rtcEventItemId(), Df.NwError)) : (this.rtcStore.updateMediaError(this.rtcEventItemId(), { fatal: t.fatal, details: t.details, code: null === (t = t.response) || void 0 === t ? void 0 : t.code }), - this.sendAndFinalize(this.rtcEventItemId(), Ry.PlayError)) + this.sendAndFinalize(this.rtcEventItemId(), Df.PlayError)) } handleMediaElementError(e) { this.rtcStore.updateMediaElementError(this.rtcEventItemId(), e), - this.sendAndFinalize(this.rtcEventItemId(), Ry.PlayError) + this.sendAndFinalize(this.rtcEventItemId(), Df.PlayError) } handleFragLoaded(e, t) { var i, r, n; - this.checkMediaOptionType(e.mediaOptionType) && (e.itemId !== this.rtcEventItemId() && this.logger.warn(By, `Frag id does not match current item id. Frag Id=${e.itemId}, playing id=${this.rtcEventItemId(!0)}, loading id=${null === (n = this.hls.loadingItem) || void 0 === n ? void 0 : n.itemId}`), + this.checkMediaOptionType(e.mediaOptionType) && (e.itemId !== this.rtcEventItemId() && this.logger.warn(Lf, `Frag id does not match current item id. Frag Id=${e.itemId}, playing id=${this.rtcEventItemId(!0)}, loading id=${null === (n = this.hls.loadingItem) || void 0 === n ? void 0 : n.itemId}`), i = t.tload - t.trequest, r = t.tload - t.tfirst, n = this.serverInfoInstance || {}, @@ -29743,7 +22639,7 @@ } handleLevelLoaded(e, t) { var i; - e ? (e.itemId !== this.rtcEventItemId() && this.logger.warn(By, `media option id does not match current item id. media Id=${e.itemId}, current id=${this.rtcEventItemId}`), + e ? (e.itemId !== this.rtcEventItemId() && this.logger.warn(Lf, `media option id does not match current item id. media Id=${e.itemId}, current id=${this.rtcEventItemId}`), e.mediaOptionType === ul.Variant && (i = t.tload - t.trequest, this.rtcStore.updateLevelLoaded(this.rtcEventItemId(), { url: e.url, @@ -29763,9 +22659,9 @@ e.oldVariant && (this.rtcStore.updateVariantEnd(this.rtcEventItemId(), { currentTime: this.hls.realCurrentTime }), - this.sendAndFinalize(this.rtcEventItemId(), Ry.VariantEnded)), + this.sendAndFinalize(this.rtcEventItemId(), Df.VariantEnded)), this.rtcStore.updateLevelSwitched(this.rtcEventItemId(), t), - this.sendAndFinalize(this.rtcEventItemId(), Ry.SwitchComplete) + this.sendAndFinalize(this.rtcEventItemId(), Df.SwitchComplete) } handleLevelSwitching(e) { this.levelSwitchingUrl = e @@ -29809,7 +22705,7 @@ currentTime: this.hls.realCurrentTime, url: this.levelSwitchingUrl }), - this.sendAndFinalize(this.rtcEventItemId(!0), Ry.PlayRateChanged)) : 1 !== e && 1 === t && (this.playStart = Date.now()), + this.sendAndFinalize(this.rtcEventItemId(!0), Df.PlayRateChanged)) : 1 !== e && 1 === t && (this.playStart = Date.now()), this.oldRate = e, this.newRate = t } @@ -29830,8 +22726,8 @@ } , t = this.rtcQuery.getEntity(this.rtcEventItemId(!0)).sessionControlRecord.state; e.type === Op.LowBuffer || e.type === Op.Seek && e.isLowBufferStall ? "RTC_STATE_PLAY" === t && (this.rtcStore.updateBufferStalled(this.rtcEventItemId(!0), i), - this.sendAndFinalize(this.rtcEventItemId(!0), Ry.PlayStalled)) : "RTC_STATE_PLAY" === t && (this.rtcStore.updateMediaEngineStalled(this.rtcEventItemId(!0), i), - this.sendAndFinalize(this.rtcEventItemId(!0), Ry.MediaEngineStalled)) + this.sendAndFinalize(this.rtcEventItemId(!0), Df.PlayStalled)) : "RTC_STATE_PLAY" === t && (this.rtcStore.updateMediaEngineStalled(this.rtcEventItemId(!0), i), + this.sendAndFinalize(this.rtcEventItemId(!0), Df.MediaEngineStalled)) } handlePlaybackInfo(e, t) { this.rtcStore.updatePlaybackInfo(this.rtcEventItemId(!0), { @@ -29844,7 +22740,7 @@ }) } checkMediaOptionType(e) { - return e === ul.Variant || e === ul.AltAudio || (this.logger.error(By, 'Should not have media option type = "%s" in RTC', Cl[e]), + return e === ul.Variant || e === ul.AltAudio || (this.logger.error(Lf, 'Should not have media option type = "%s" in RTC', Cl[e]), !1) } rtcEventItemId(e=!1) { @@ -29858,7 +22754,7 @@ if (this.hls.userInfo ? this.hls.userInfo.internalBuild ? e = !0 : this.hls.userInfo.diagnosticsAndUsage && (e = this.config.enableRtcReporting) : e = this.config.enableRtcReporting, e) { const i = this.hls.reportingAgent; - i ? this.rtcComponent.setReportingAgent(i) : this.logger.warn(By, "[RTCA] - Reporting is enabled but reportingAgent is null") + i ? this.rtcComponent.setReportingAgent(i) : this.logger.warn(Lf, "[RTCA] - Reporting is enabled but reportingAgent is null") } else this.rtcComponent.setReportingAgent(null); this.serverInfoInstance = null; @@ -29873,11 +22769,11 @@ this.rtcStore.updateVariantEnd(e, { currentTime: this.hls.realCurrentTime }), - this.sendAndFinalize(e, Ry.VariantEnded), + this.sendAndFinalize(e, Df.VariantEnded), this.rtcStore.updatePeriodic(e, !0), - this.sendAndFinalize(e, Ry.Periodic), + this.sendAndFinalize(e, Df.Periodic), this.rtcStore.updateEnded(e), - this.sendAndFinalize(e, Ry.PlayEnded), + this.sendAndFinalize(e, Df.PlayEnded), this.setPeriodic(t) } mediaElementQueryListener(e) { @@ -29888,7 +22784,7 @@ 1 < Math.abs(e) && 1 < Math.abs(t) || (this.rtcStore.updateCanPlay(this.rtcEventItemId(!0), { mediaDur: this.hls.bufferedDuration }), - this.sendAndFinalize(this.rtcEventItemId(!0), Ry.PlayLikelyToKeepUp), + this.sendAndFinalize(this.rtcEventItemId(!0), Df.PlayLikelyToKeepUp), this.rtcStore.updateRateChanged(this.rtcEventItemId(!0), { rate: t, latency: ne(this.playStart) ? Date.now() - this.playStart : 0, @@ -29896,14 +22792,14 @@ currentTime: this.hls.realCurrentTime, url: this.levelSwitchingUrl }), - this.sendAndFinalize(this.rtcEventItemId(!0), Ry.PlayRateChanged)) + this.sendAndFinalize(this.rtcEventItemId(!0), Df.PlayRateChanged)) } } )) } registerForEvents() { const e = wc(this.hls, this); - nn(e.event(P.KEY_REQUEST_STARTED, this.keyRequestStarted, this), e.event(P.KEY_LOADED, this.keyLoaded, this)).pipe($a(this.destroy$)).subscribe() + nn(e.event(x.KEY_REQUEST_STARTED, this.keyRequestStarted, this), e.event(x.KEY_LOADED, this.keyLoaded, this)).pipe($a(this.destroy$)).subscribe() } keyRequestStarted(e) { e.timestamp = Date.now(), @@ -29954,21 +22850,21 @@ keyuri: e.keyuri, currentTime: this.hls.realCurrentTime }), - this.sendAndFinalize(this.rtcEventItemId(), Ry.KeySessionComplete) + this.sendAndFinalize(this.rtcEventItemId(), Df.KeySessionComplete) } licenseChallengeError(e) { this.rtcStore.updateLicenseChallengeError(this.rtcEventItemId(), { timestamp: Date.now(), keyuri: e.keyuri }), - this.sendAndFinalize(this.rtcEventItemId(), Ry.KeySessionComplete) + this.sendAndFinalize(this.rtcEventItemId(), Df.KeySessionComplete) } licenseResponseError(e) { this.rtcStore.updateLicenseResponseError(this.rtcEventItemId(), { timestamp: Date.now(), keyuri: e.keyuri }), - this.sendAndFinalize(this.rtcEventItemId(), Ry.KeySessionComplete) + this.sendAndFinalize(this.rtcEventItemId(), Df.KeySessionComplete) } keyAborted(e) { var t; @@ -29976,7 +22872,7 @@ timestamp: Date.now(), keyuri: e.keyuri }), - this.sendAndFinalize(this.rtcEventItemId(), Ry.KeySessionComplete)) : this.logger.warn(`keyAbort called without active key session ${oe(e.keyuri)}`) + this.sendAndFinalize(this.rtcEventItemId(), Df.KeySessionComplete)) : this.logger.warn(`keyAbort called without active key session ${oe(e.keyuri)}`) } setPeriodic(e) { this.clearPeriodic(), @@ -29984,7 +22880,7 @@ } handlePeriodic(e) { this.rtcStore.updatePeriodic(e, !1), - this.sendAndFinalize(e, Ry.Periodic) + this.sendAndFinalize(e, Df.Periodic) } clearPeriodic() { this.intervalFunc && clearInterval(this.intervalFunc), @@ -29993,58 +22889,7168 @@ sendAndFinalize(e, t) { switch (this.accessLog.addPlayTime(e), t) { - case Ry.PlayEnded: + case Df.PlayEnded: this.rtcComponent.sendPlayEnded(e); break; - case Ry.Periodic: + case Df.Periodic: this.rtcComponent.sendPeriodic(e); break; - case Ry.PlayStalled: + case Df.PlayStalled: this.accessLog.updateStallCount(e), this.rtcComponent.sendPlayStalled(e); break; - case Ry.KeySessionComplete: + case Df.KeySessionComplete: this.rtcComponent.sendKeySessionComplete(e); break; - case Ry.PlayLikelyToKeepUp: + case Df.PlayLikelyToKeepUp: this.accessLog.updateCanPlay(e), this.rtcComponent.sendPlayLikelyToKeepUp(e); break; - case Ry.PlayRateChanged: + case Df.PlayRateChanged: this.rtcComponent.sendPlayRateChange(e); break; - case Ry.PlayError: + case Df.PlayError: this.accessLog.addToErrorLog(e, "mediaError"), this.rtcComponent.sendPlayError(e); break; - case Ry.MediaEngineStalled: + case Df.MediaEngineStalled: this.accessLog.updateMediaEngineStallCount(e), this.rtcComponent.sendMediaEngineStalled(e); break; - case Ry.SwitchComplete: + case Df.SwitchComplete: this.accessLog.addToAccessLog(e), this.rtcComponent.sendSwitchComplete(e); break; - case Ry.VariantEnded: + case Df.VariantEnded: this.rtcComponent.sendVariantEnded(e); break; - case Ry.NwError: + case Df.NwError: this.accessLog.addToErrorLog(e, "networkError"), this.rtcComponent.sendNwError(e); break; default: - return void this.logger.error(By, `Unknown rtc event eventGroupId:${e}`) + return void this.logger.error(Lf, `Unknown rtc event eventGroupId:${e}`) } this.rtcStore.finalize(e, t) } } + const Nf = a=>(e,t)=>{ + let i = 0 + , r = 0; + for (var {timestamp: n, value: s} of e) { + const e = Math.pow(Math.max(0, n - t) / 1e3, a); + i += e * s, + r += e + } + return i / r + } + , Ff = { + "uniform-time-weighted": Nf(0), + "linear-time-weighted": Nf(1), + "quadratic-time-weighted": Nf(2) + }; + class Bf { + constructor(e, t="quadratic-time-weighted", i={ + avgLatencyMs: NaN, + avgBandwidth: NaN + }) { + this.windowSize = e, + this.aggregationMethod = t, + this.latencyEntries = [], + this.bandwidthEntries = [], + this.minEntries = 1, + this.cleanUpExpiredEntries = this.cleanUpExpiredEntries.bind(this), + this.bwSubject = new gi(i) + } + get estimate$() { + return this.bwSubject.asObservable() + } + record(e) { + var {trequest: t, tfirst: i, tload: r, bitsDownloaded: e} = e; + t !== r && (this.recordLatency(t, i), + this.recordBandwidth(t, r, 1e3 * e / (r - t)), + this.bwSubject.closed || (t = this.getEstimate(), + this.bwSubject.next(t))) + } + getEstimate() { + if (this.latencyEntries.length < this.minEntries) + return { + avgLatencyMs: NaN, + avgBandwidth: NaN + }; + const e = performance.now() - this.windowSize + , t = Ff[this.aggregationMethod] + , i = this.latencyEntries.map(({start: e, end: t})=>({ + timestamp: t, + value: t - e, + duration: 1 + })); + this.bandwidthEntries = function(r) { + function n(t, i) { + if (t.length) { + for (let e = 0; e < t.length; e++) + if (t[e].start > i.start || t[e].start === i.start && t[e].end > i.end) { + t.splice(e, 0, i); + break + } + } else + t.push(i) + } + const s = [...r].sort((e,t)=>e.start !== t.start ? e.start - t.start : e.end - t.end) + , t = []; + for (; s.length; ) { + const r = s[0]; + let e; + if (s.shift(), + t.length && (e = t[t.length - 1]), + 0 === t.length || e.end <= r.start) + t.push(r); + else if (r.start === e.start) + r.end === e.end ? e.bitsPerSec += r.bitsPerSec : r.end < e.end || (e.bitsPerSec += r.bitsPerSec, + r.start = e.end, + n(s, r)); + else { + var a = e.end + , o = e.bitsPerSec; + e.end = r.start; + var i = { + start: r.start, + end: Math.min(a, r.end), + bitsPerSec: r.bitsPerSec + o + }; + if (t.push(i), + a !== r.end) { + let e = 0 + , t = 0 + , i = 0; + i = a < r.end ? (e = a, + t = r.end, + r.bitsPerSec) : (e = r.end, + t = a, + o), + n(s, { + start: e, + end: t, + bitsPerSec: i + }) + } + } + } + return t + }(this.bandwidthEntries); + var r = this.bandwidthEntries.map(({end: e, bitsPerSec: t})=>({ + timestamp: e, + duration: 1, + value: t + })); + return { + avgLatencyMs: t(i, e), + avgBandwidth: t(r, e) + } + } + getLatest() { + if (0 === this.latencyEntries.length) + return { + avgLatencyMs: NaN, + avgBandwidth: NaN + }; + var e = this.latencyEntries[this.latencyEntries.length - 1] + , t = this.bandwidthEntries[this.bandwidthEntries.length - 1]; + return { + avgLatencyMs: e.end - e.start, + avgBandwidth: t.bitsPerSec + } + } + recordLatency(e, t) { + this.latencyEntries.push({ + start: e, + end: t + }), + this.updateCleanupTimeout(t) + } + recordBandwidth(e, t, i) { + this.bandwidthEntries.push({ + start: e, + end: t, + bitsPerSec: i + }), + this.updateCleanupTimeout(t) + } + setCleanupTimeout(e) { + this.cleanupTimeout = setTimeout(this.cleanUpExpiredEntries, Math.max(e - performance.now(), 0)), + this.cleanupTimestamp = e + } + clearCleanupTimeout() { + void 0 !== this.cleanupTimeout && (clearTimeout(this.cleanupTimeout), + this.cleanupTimeout = void 0), + this.cleanupTimestamp = void 0 + } + updateCleanupTimeout(e) { + e += this.windowSize; + (!this.cleanupTimestamp || e < this.cleanupTimestamp) && (this.clearCleanupTimeout(), + this.setCleanupTimeout(e)) + } + cleanUpExpiredEntries() { + this.clearCleanupTimeout(); + const t = performance.now() - this.windowSize; + if (this.latencyEntries = this.latencyEntries.filter(e=>e.end >= t), + this.bandwidthEntries = this.bandwidthEntries.filter(e=>e.end >= t), + this.bwSubject.closed || this.bwSubject.next(this.getEstimate()), + 0 < this.latencyEntries.length || 0 < this.bandwidthEntries.length) { + const t = Math.min(...this.latencyEntries.map(e=>e.end), ...this.bandwidthEntries.map(e=>e.end)); + this.updateCleanupTimeout(t) + } + } + destroy() { + this.clearCleanupTimeout() + } + } + const Uf = { + setCombinedEstimate: function(t, i, r) { + const n = qe(); + if (void 0 !== t.storage.set) { + var s = t.bandwidthHistoryStorageKey + , a = { + avgLatencyMs: i.avgLatencyMs, + avgBandwidth: i.avgBandwidth + } + , a = Object.assign({}, a, { + expires: Date.now() + t.bandwidthHistoryTTL + }); + try { + t.storage.set(s, JSON.stringify(a)) + } catch (t) { + n.warn(`Error stringifying! Not persisting bandwidth estimates: ${t.message}`) + } + i = { + maxDuration: i.maxDurationSec, + avgFragParseTimeMs: i.avgParseTimeMs, + avgFragBufferCreationDelayMs: i.avgBufferCreateMs, + avgPlaylistLoadTimeMs: i.avgPlaylistLoadTimeMs, + avgPlaylistParseTimeMs: i.avgPlaylistParseTimeMs, + avgInitFragAppendMs: i.avgInitFragAppendMs, + avgDataFragAppendMs: i.avgDataFragAppendMs + }; + let e = t.storageKeyPrefix; + r && (e += r); + try { + t.storage.set(e, JSON.stringify(i)) + } catch (t) { + n.warn(`Error stringifying! Not persisting bandwidth estimates: ${t.message}`) + } + } else + n.warn("storage.set is not supported! Not persisting bandwidth estimates") + }, + getCombinedEstimate: function(t, e) { + const i = qe(); + let r = {}; + if (void 0 === t.storage.get) + return i.warn("storage.get is not supported! unable to retreive bandwidth estimates"), + this.convertStorageJsonToCombinedEstimate(r); + try { + let e = JSON.parse(t.storage.get(t.bandwidthHistoryStorageKey)); + e = null != e && e.expires && e.expires < Date.now() ? null : { + avgLatencyMs: null == e ? void 0 : e.avgLatencyMs, + avgBandwidth: null == e ? void 0 : e.avgBandwidth + }, + r = Object.assign(Object.assign({}, r), e) + } catch (t) { + i.warn(`Unable to get persisted bandwidth history: ${t.message}`) + } + let n = t.storageKeyPrefix; + e && (n += e); + try { + const e = JSON.parse(t.storage.get(n)); + r = Object.assign(Object.assign({}, r), e) + } catch (t) { + i.warn(`Unable to get persisted bandwidth history: ${t.message}`) + } + return this.convertStorageJsonToCombinedEstimate(r) + }, + convertStorageJsonToCombinedEstimate: function(e) { + return { + avgLatencyMs: (null == e ? void 0 : e.avgLatencyMs) || NaN, + avgBandwidth: (null == e ? void 0 : e.avgBandwidth) || NaN, + maxDurationSec: (null == e ? void 0 : e.maxDuration) || NaN, + avgParseTimeMs: (null == e ? void 0 : e.avgFragParseTimeMs) || NaN, + avgBufferCreateMs: (null == e ? void 0 : e.avgFragBufferCreationDelayMs) || NaN, + avgPlaylistLoadTimeMs: (null == e ? void 0 : e.avgPlaylistLoadTimeMs) || NaN, + avgPlaylistParseTimeMs: (null == e ? void 0 : e.avgPlaylistParseTimeMs) || NaN, + avgInitFragAppendMs: (null == e ? void 0 : e.avgInitFragAppendMs) || NaN, + avgDataFragAppendMs: (null == e ? void 0 : e.avgDataFragAppendMs) || NaN + } + }, + getBandwidthEstimate: function(e, t) { + const i = this.getCombinedEstimate(e, t) + , r = { + avgLatencyMs: null == i ? void 0 : i.avgLatencyMs, + avgBandwidth: null == i ? void 0 : i.avgBandwidth + }; + return ne(r.avgLatencyMs) || (r.avgLatencyMs = NaN), + ne(r.avgBandwidth) || (r.avgBandwidth = NaN), + r + }, + getPlaylistEstimate: function(e, t) { + const i = this.getCombinedEstimate(e, t) + , r = { + avgPlaylistLoadTimeMs: null == i ? void 0 : i.avgPlaylistLoadTimeMs, + avgPlaylistParseTimeMs: null == i ? void 0 : i.avgPlaylistParseTimeMs + }; + return ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = NaN), + ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = NaN), + r + }, + getFragEstimate: function(e, t) { + const i = this.getCombinedEstimate(e, t) + , r = { + maxDurationSec: null == i ? void 0 : i.maxDurationSec, + avgParseTimeMs: null == i ? void 0 : i.avgParseTimeMs + }; + return ne(r.maxDurationSec) || (r.maxDurationSec = NaN), + ne(r.avgParseTimeMs) || (r.avgParseTimeMs = NaN), + r + }, + getBufferEstimate: function(e, t) { + const i = this.getCombinedEstimate(e, t) + , r = { + avgBufferCreateMs: null == i ? void 0 : i.avgBufferCreateMs, + avgInitFragAppendMs: null == i ? void 0 : i.avgInitFragAppendMs, + avgDataFragAppendMs: null == i ? void 0 : i.avgDataFragAppendMs + }; + return ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = NaN), + ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = NaN), + ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = NaN), + r + } + }; + var $f = Uf; + class Vf { + constructor(e=0) { + this._minSamples = e, + this._sum = 0, + this._max = Number.NEGATIVE_INFINITY, + this._numSamples = 0 + } + get avg() { + return this._numSamples < this._minSamples ? NaN : this._sum / this._numSamples + } + get max() { + return 0 < this.count ? this._max : NaN + } + get count() { + return this._numSamples + } + reset() { + this._sum = 0, + this._numSamples = 0, + this._max = Number.NEGATIVE_INFINITY + } + add(e) { + this._sum += e, + this._max = Math.max(this._max, e), + ++this._numSamples + } + } + class Kf extends Od { + constructor(e, t) { + super(e), + this.id = t + } + getBandwidthEstimate(e, t) { + var i; + const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.bandwidthEstimate); + if (ne(r.avgBandwidth) && ne(r.avgLatencyMs)) + return r; + if (e) { + const i = Uf.getBandwidthEstimate(e, t); + ne(r.avgBandwidth) || (r.avgBandwidth = i.avgBandwidth), + ne(r.avgLatencyMs) || (r.avgLatencyMs = i.avgLatencyMs) + } + return r + } + getPlaylistEstimate(e, t) { + var i; + const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.playlistEstimate) + , n = e=>ne(e.avgPlaylistLoadTimeMs) && ne(e.avgPlaylistParseTimeMs); + if (n(r)) + return r; + if (e) { + const i = Uf.getPlaylistEstimate(e, t); + if (ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = i.avgPlaylistLoadTimeMs), + ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = i.avgPlaylistParseTimeMs), + n(r)) + return r; + ne(r.avgPlaylistLoadTimeMs) || (r.avgPlaylistLoadTimeMs = e.statDefaults.playlistLoadTimeMs), + ne(r.avgPlaylistParseTimeMs) || (r.avgPlaylistParseTimeMs = e.statDefaults.playlistParseTimeMs) + } + return r + } + getBufferEstimate(e, t) { + var i; + const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.bufferEstimate) + , n = e=>ne(e.avgBufferCreateMs) && ne(e.avgDataFragAppendMs) && ne(e.avgInitFragAppendMs); + if (n(r)) + return r; + if (e) { + const i = Uf.getBufferEstimate(e, t); + if (ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = i.avgBufferCreateMs), + ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = i.avgDataFragAppendMs), + ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = i.avgInitFragAppendMs), + n(r)) + return r; + ne(r.avgBufferCreateMs) || (r.avgBufferCreateMs = e.statDefaults.fragBufferCreationDelayMs), + ne(r.avgDataFragAppendMs) || (r.avgDataFragAppendMs = e.statDefaults.dataFragAppendMs), + ne(r.avgInitFragAppendMs) || (r.avgInitFragAppendMs = e.statDefaults.initFragAppendMs) + } + return r + } + getFragEstimate(e, t) { + var i; + const r = Object.assign({}, null === (i = this.statsEntity) || void 0 === i ? void 0 : i.fragEstimate) + , n = e=>ne(e.maxDurationSec) && ne(e.avgParseTimeMs); + if (n(r)) + return r; + if (e) { + const i = Uf.getFragEstimate(e, t); + if (ne(r.maxDurationSec) || (r.maxDurationSec = i.maxDurationSec), + ne(r.avgParseTimeMs) || (r.avgParseTimeMs = i.avgParseTimeMs), + n(r)) + return r; + ne(r.maxDurationSec) || (r.maxDurationSec = e.defaultTargetDuration), + ne(r.avgParseTimeMs) || (r.avgParseTimeMs = e.statDefaults.fragParseTimeMs) + } + return r + } + getCombinedEstimate() { + return Object.assign(Object.assign(Object.assign(Object.assign({}, this.getFragEstimate()), this.getPlaylistEstimate()), this.getBufferEstimate()), this.getBandwidthEstimate()) + } + get statsEntity() { + return this.getEntity(this.id) + } + get bandwidthSample() { + var e; + return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.bandwidthSample + } + get bandwidthStatus() { + var e; + return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.bandwidthStatus + } + get fragSample() { + var e; + return null === (e = this.statsEntity) || void 0 === e ? void 0 : e.fragSample + } + get bandwidthEstimate$() { + return this.selectEntity(this.id, "bandwidthEstimate") + } + get fragEstimate$() { + return this.selectEntity(this.id, "fragEstimate") + } + get playlistEstimate$() { + return this.selectEntity(this.id, "playlistEstimate") + } + get bufferEstimate$() { + return this.selectEntity(this.id, "bufferEstimate") + } + get bandwidthSample$() { + return this.selectEntity(this.id, ({bandwidthSample: e})=>e).pipe(Up()) + } + get fragSample$() { + return this.selectEntity(this.id, ({fragSample: e})=>e).pipe(Up()) + } + get playlistSample$() { + return this.selectEntity(this.id, ({playlistSample: e})=>e).pipe(Up()) + } + get bufferMetric$() { + return this.selectEntity(this.id, ({bufferMetric: e})=>e).pipe(Up()) + } + } + class Hf { + constructor(e) { + this.statsStore = e + } + getQuery() { + return new Od(this.statsStore) + } + getQueryForItem(e) { + return new Kf(this.statsStore,e) + } + remove(e) { + this.statsStore.remove(e) + } + removeAll() { + this.statsStore.remove() + } + setBandwidthSample(e) { + this.statsStore.bandwidthSample = e + } + setFragSample(e) { + this.statsStore.fragSample = e + } + setPlaylistSample(e) { + this.statsStore.playlistSample = e + } + setBufferMetric(e) { + this.statsStore.bufferMetric = e + } + setBandwidthEstimate(e) { + this.statsStore.bandwidthEstimate = e + } + setFragEstimate(e) { + this.statsStore.fragEstimate = e + } + setPlaylistEstimate(e) { + this.statsStore.playlistEstimate = e + } + setBufferEstimate(e) { + this.statsStore.bufferEstimate = e + } + } + const jf = new class extends pd { + constructor() { + super({}, { + name: "stats-store", + producerFn: vc + }) + } + set statsEntity(e) { + Co("statsStore.set.stats"), + sd(()=>{ + this.add(e), + this.setActive(e.id) + } + ) + } + set playlistSample(t) { + Co(`stats.set.playlistSample: ${t}`), + this.updateActive(e=>{ + e.playlistSample = t + } + ) + } + set bandwidthSample(t) { + Co(`stats.set.bandwidthSample: ${t}`), + this.updateActive(e=>{ + e.bandwidthSample = t, + e.bandwidthStatus.bandwidthSampleCount += 1, + e.bandwidthStatus.instantBw = 8e3 * t.loaded / (t.tload - t.trequest) + } + ) + } + set fragSample(t) { + Co(`stats.set.fragSample: ${t}`), + this.updateActive(e=>{ + e.fragSample = t + } + ) + } + set bufferMetric(t) { + Co(`stats.set.bufferMetric: ${t}`), + this.updateActive(e=>{ + e.bufferMetric = t + } + ) + } + set bandwidthEstimate(t) { + Co(`stats.set.bandwidthEstimate: ${t}`), + this.updateActive(e=>{ + e.bandwidthEstimate = t + } + ) + } + set fragEstimate(t) { + Co(`stats.set.fragEstimate: ${t}`), + this.updateActive(e=>{ + e.fragEstimate = t + } + ) + } + set playlistEstimate(t) { + Co(`stats.set.playlistEstimate: ${t}`), + this.updateActive(e=>{ + e.playlistEstimate = t + } + ) + } + set bufferEstimate(t) { + Co(`stats.set.bufferEstimate: ${t}`), + this.updateActive(e=>{ + e.bufferEstimate = t + } + ) + } + } + ; + let qf = null; + const Qf = e=>new Kf(jf,e); + function Gf(e, t) { + if (e === t) + return !0; + if (!e || !t) + return !1; + let i = Object.keys(e).length === Object.keys(t).length; + for (const r of Object.keys(e)) + i = i && (isNaN(e[r]) && isNaN(t[r]) || e[r] === t[r]); + return i + } + function Wf(f, m, g) { + return new Ut(e=>{ + (e=>{ + const t = Qf(e); + t.hasEntity(e) ? Bi(t) : (i = jf, + e = e, + Co("stats.loading"), + i.setLoading(!0), + i.statsEntity = { + id: e, + bandwidthEstimate: { + avgLatencyMs: NaN, + avgBandwidth: NaN + }, + bandwidthStatus: { + bandwidthSampleCount: 0, + instantBw: NaN + }, + fragEstimate: { + maxDurationSec: NaN, + avgParseTimeMs: NaN + }, + playlistEstimate: { + avgPlaylistLoadTimeMs: NaN, + avgPlaylistParseTimeMs: NaN + }, + bufferEstimate: { + avgBufferCreateMs: NaN, + avgInitFragAppendMs: NaN, + avgDataFragAppendMs: NaN + } + }, + i.setLoading(!1), + Co("stats.loaded")); + var i + } + )(g.itemId); + const t = Qf(g.itemId) + , {fragSample$: i, playlistSample$: r, bandwidthSample$: n, bufferMetric$: s} = t; + return nn(r.pipe(Hi(Zi), (h = f, + p = m, + e=>e.pipe(Ql.tag("statsPlaylistProcessingEpic.in"), na((e,t)=>(e.playlistLoadTimeMs.add(t.playlistLoadTimeMs), + e.playlistParseTimeMs.add(t.playlistParseTimeMs), + e), { + playlistLoadTimeMs: new Vf(h.minPlaylistCount), + playlistParseTimeMs: new Vf(h.minPlaylistCount) + }), ur(e=>({ + avgPlaylistLoadTimeMs: e.playlistLoadTimeMs.avg, + avgPlaylistParseTimeMs: e.playlistParseTimeMs.avg + })), Es(Gf), Ja(e=>{ + p.setPlaylistEstimate(e) + } + )))), n.pipe(Hi(Zi), (u = f, + c = m, + n=>new Ut(e=>{ + let t = new Bf(u.bandwidthHistoryWindowSize,u.bandwidthHistoryAggregationMethod,{ + avgLatencyMs: NaN, + avgBandwidth: NaN + }); + const i = t.estimate$ + , r = nn(n.pipe(an(e=>e.complete), Ja(e=>{} + ), ur(e=>({ + trequest: e.trequest, + tfirst: e.tfirst, + tload: e.tload, + bitsDownloaded: 8 * e.loaded + })), Ql.tag("statsBandwidthProcessingEpic.in"), Ra(e=>(t.record(e), + Ti))), i.pipe(Es(), Ql.tag("statsBandwidthProcessingEpic.change"), Ja(e=>{ + c && c.setBandwidthEstimate(e) + } + ))).subscribe(e); + return ()=>{ + r.unsubscribe(), + t.destroy(), + t = void 0 + } + } + ))), i.pipe(Hi(Zi), (d = f, + l = m, + e=>e.pipe(Ql.tag("statsFragProcessingEpic.in"), na((e,t)=>(e.durationSec.add(t.durationSec), + e.fragParseMs.add(t.parseTimeMs), + e), { + durationSec: new Vf, + fragParseMs: new Vf(d.minFragmentCount) + }), ur(e=>({ + maxDurationSec: e.durationSec.max, + avgParseTimeMs: e.fragParseMs.avg + })), Es(Gf), Ja(e=>l.setFragEstimate(e))))), s.pipe(Hi(Zi), (a = f, + o = m, + e=>e.pipe(Ql.tag("statsBufferMetricProcessingEpic.in"), na((e,t)=>(ne(t.bufferCreationStart) && ne(t.bufferCreationEnd) && e.bufferCreateMs.add(t.bufferCreationEnd - t.bufferCreationStart), + ne(t.startInitAppend) && ne(t.endInitAppend) && e.initFragAppendMs.add(t.endInitAppend - t.startInitAppend), + ne(t.startDataAppend) && ne(t.endDataAppend) && e.dataFragAppendMs.add(t.endDataAppend - t.startDataAppend), + e), { + bufferCreateMs: new Vf, + initFragAppendMs: new Vf, + dataFragAppendMs: new Vf(a.minFragmentCount) + }), ur(e=>({ + avgBufferCreateMs: e.bufferCreateMs.avg, + avgInitFragAppendMs: e.initFragAppendMs.avg, + avgDataFragAppendMs: e.dataFragAppendMs.avg + })), Es(Gf), Ja(e=>{ + o.setBufferEstimate(e) + } + ))))).pipe(Ua(Ti)).subscribe(e), + ()=>{ + $f.setCombinedEstimate(f, Object.assign(Object.assign(Object.assign(Object.assign({}, t.getFragEstimate()), t.getPlaylistEstimate()), t.getBufferEstimate()), t.getBandwidthEstimate()), g.serviceName), + m.remove(g.itemId) + } + ; + var a, o, d, l, u, c, h, p + } + ) + } + const zf = { + isWebkitMediaElement: e=>"webkitDroppedFrameCount"in e, + isHtmlVideoElement: e=>"getVideoPlaybackQuality"in e, + timeRangeToArray(t) { + const i = []; + for (let e = 0; e < t.length; e++) + i.push([t.start(e), t.end(e)]); + return i + } + }; + class Xf extends Ut { + constructor() { + super(e=>this.works$.pipe(ur(e=>Lr(e)), zr()).subscribe(e)), + this.works$ = new zt + } + addWork(e) { + this.works$.next(e) + } + complete() { + this.works$.complete() + } + } + class Yf { + constructor(e, t) { + this.hls = e, + this.sessionID = t, + this.rtcQuery = null, + this.accessLogData = this.createAccessLogEntry(), + this.accesslog = [], + this.errorlog = [] + } + destroy() { + this.rtcQuery = null, + this.accesslog = [], + this.errorlog = [], + this.accessLogData = void 0, + this.accessLogReporter = void 0 + } + setRTCQuery(e) { + this.rtcQuery = e + } + setupReporter(e) { + this.accessLogReporter = { + SessionID: this.sessionID, + ClientName: null == e ? void 0 : e.clientName, + ServiceName: null == e ? void 0 : e.serviceName + } + } + addPlayTime(e) { + var t, e = null === (t = this.rtcQuery) || void 0 === t ? void 0 : t.getEntity(e); + !e || "RTC_STATE_PLAY" === (e = e.sessionControlRecord).state && (this.accessLogData.PlayTimeWC = (this.accessLogData.PlayTimeWC || 0) + e.eventStartTime) + } + updatePlaybackInfo(e, t) { + this.accessLogData.ViFrDr = this.rtcQuery.getEntity(e).sessionControlRecord.droppedVideoFrames || 0 + } + updateStallCount(e) { + "RTC_STATE_PLAY" === this.rtcQuery.getEntity(e).sessionControlRecord.state && this.accessLogData.StallCount++ + } + updateMediaEngineStallCount(e) { + "RTC_STATE_PLAY" === this.rtcQuery.getEntity(e).sessionControlRecord.state && this.accessLogData.MediaEngineStallCount++ + } + updateCanPlay(e) { + this.accessLogData.StartupTime = this.rtcQuery.getEntity(e).sessionControlRecord.eventStartTime + } + updateFragLoaded(e, t, i) { + var r; + i.fragType === ul.Variant ? (this.accessLogData.NetBytes += i.bytes, + this.accessLogData.ADT += i.adt, + r = this.aggregateFragObserverdBitrate(i, ++this.accessLogData.fragmentCnt, this.accessLogData.NetBytes, this.accessLogData.ADT), + this.accessLogData.OBRLast = r.obrLast, + this.accessLogData.OBRMean = r.obrMean, + this.aggregateFragMinMaxBitrate(this.accessLogData, r.obr), + this.hls.realCurrentTime > i.startPTS && !t && this.accessLogData.overdue++, + this.hasGap(i.startPTS, i.endPTS, this.accessLogData.lastStartPTS, this.accessLogData.lastEndPTS) && this.addToAccessLog(e), + this.accessLogData.startPTS || (this.accessLogData.startPTS = i.startPTS), + this.accessLogData.lastStartPTS = i.startPTS, + this.accessLogData.lastEndPTS = i.endPTS, + this.accessLogData.videoBytes += i.bytes, + this.accessLogData.videoDuration += i.duration) : i.fragType === ul.AltAudio && (this.accessLogData.audioBytes += i.bytes, + this.accessLogData.audioDuration += i.duration) + } + addToAccessLog(e) { + var t = this.getVariantInfo(e) + , i = this.rtcQuery.getEntity(e).sessionControlRecord.curLevelUrl + , r = this.rtcQuery.getEntity(e).playEndedRecord.PlayType; + if (i && "" !== i) { + r = this.translateToAccessLogItem(e, i, t, r); + if (r) { + const n = this.accesslog.length - 20; + 0 < n && this.accesslog.splice(0, n), + this.accesslog.push(r) + } + this.accessLogData = this.createAccessLogEntry(); + e = this.rtcQuery.getEntity(e).switchCompleteRecord.MediaDur; + this.accessLogData.lastMediaDur = e || this.hls.bufferedDuration + } + } + addToErrorLog(e, t) { + var i = null === (r = this.rtcQuery) || void 0 === r ? void 0 : r.getEntity(e); + if (i) { + var r = Number(("mediaError" === t ? i.playErrorRecord : i.nwErrorRecord).ErrCode) + , i = i.sessionControlRecord.curLevelUrl + , r = this.translateToErrorLogItem(e, i, { + domain: t, + code: r + }); + if (r) { + const e = this.errorlog.length - 20; + 0 < e && this.errorlog.splice(0, e), + this.errorlog.push(r) + } + } + } + getAccessLog(e) { + var t; + const i = this.accesslog.slice(0) + , r = null === (t = this.rtcQuery) || void 0 === t ? void 0 : t.getEntity(e); + if (i && r) { + const t = r.sessionControlRecord.curLevelUrl; + if (t && "" !== t) { + const r = this.getVariantInfo(e) + , n = this.translateToAccessLogItem(e, t, r, this.rtcQuery.getEntity(e).playEndedRecord.PlayType); + n && (n["c-provisional-entry"] = !0, + i.push(n)) + } + } + return i + } + get errorLog() { + return this.errorlog + } + createAccessLogEntry() { + return { + fragmentCnt: 0, + overdue: 0, + startPTS: 0, + obrMax: 0, + obrMin: 0, + audioBytes: 0, + audioDuration: 0, + videoBytes: 0, + videoDuration: 0, + svrAddrChanged: 0, + svrAddr: "", + PlayTimeWC: 0, + ViFrDr: 0, + StallCount: 0, + MediaEngineStallCount: 0, + ADT: 0, + NetBytes: 0, + StartupTime: 0, + OBRMean: 0, + OBRLast: 0 + } + } + convertStringObjectToPrimitive(e) { + return e ? "object" == typeof e ? e.toString() : e : "" + } + updateSvrAddrStats(t) { + const i = fl.parseURL(t); + if (i && i.netLoc) { + const t = i.netLoc.indexOf(":"); + let e = 0 <= t ? i.netLoc.slice(0, t) : i.netLoc; + e.startsWith("//") && (e = e.slice(2)), + this.accessLogData.svrAddr ? e !== this.accessLogData.svrAddr && this.accessLogData.svrAddrChanged++ : this.accessLogData.svrAddrChanged = 0, + this.accessLogData.svrAddr = e + } + } + translateToAccessLogItem(e, t, i, r) { + t = this.convertStringObjectToPrimitive(t); + this.updateSvrAddrStats(t); + let n = this.rtcQuery.getEntity(e).switchCompleteRecord.MediaDur; + n = n || this.hls.bufferedDuration, + n = n || 0; + const s = { + uri: t, + "s-ip": this.accessLogData.svrAddr, + "s-ip-changes": this.accessLogData.svrAddrChanged, + "sc-wwan-count": -1, + "c-transfer-duration": this.accessLogData.ADT, + bytes: this.accessLogData.NetBytes, + "c-total-media-requests": this.accessLogData.fragmentCnt, + "cs-guid": this.accessLogReporter.SessionID, + "c-start-time": this.accessLogData.startPTS, + "c-startup-time": this.accessLogData.StartupTime, + "c-duration-watched": this.accessLogData.PlayTimeWC / 1e3, + "c-frames-dropped": this.accessLogData.ViFrDr, + "c-stalls": this.accessLogData.StallCount + this.accessLogData.MediaEngineStallCount, + "c-duration-downloaded": this.accessLogData.lastMediaDur ? n - this.accessLogData.lastMediaDur : n, + "c-overdue": this.accessLogData.overdue, + "c-avg-video-bitrate": 8 * this.accessLogData.videoBytes / (this.accessLogData.videoDuration || 1), + "c-observed-max-bitrate": this.accessLogData.obrMax, + "c-observed-min-bitrate": this.accessLogData.obrMin, + "sc-indicated-bitrate": i.bandwidth || 0, + "sc-indicated-avg-bitrate": i.avgBandwidth || 0, + "c-observed-bitrate": this.accessLogData.OBRMean, + "c-switch-bitrate": this.accessLogData.OBRLast, + "c-provisional-entry": !1 + }; + return s["s-playback-type"] = r, + this.accessLogData.audioBytes && (s["c-avg-audio-bitrate"] = 8 * this.accessLogData.audioBytes / (this.accessLogData.audioDuration || 1)), + s + } + translateToErrorLogItem(e, t, i) { + t = this.convertStringObjectToPrimitive(t); + return this.updateSvrAddrStats(t), + { + date: new Date, + "cs-guid": this.accessLogReporter.SessionID + "-" + e, + uri: t, + "s-ip": this.accessLogData.svrAddr, + status: "" + i.code, + domain: i.domain + } + } + hasGap(e, t, i, r) { + return void 0 !== e && void 0 !== i && (1 < e - r || 1 < i - t) + } + aggregateFragObserverdBitrate(e, t, i, r) { + r = 8 * i / (r / 1e3); + return { + obr: r, + obrLast: 8 * e.bytes / (e.adt / 1e3), + obrMean: r / t + } + } + aggregateFragMinMaxBitrate(e, t) { + (!e.obrMax || t > e.obrMax) && (e.obrMax = t), + (!e.obrMin || t < e.obrMin) && (e.obrMin = t) + } + getVariantInfo(e) { + var t = this.rtcQuery.getEntity(e).sessionControlRecord.curLevelUrl + , e = null === (e = this.rtcQuery.getEntity(e).sessionControlRecord.manifestData) || void 0 === e ? void 0 : e.variantList; + return t && e && e[t] ? e[t] : {} + } + } + const Jf = (r,e,t,i,n,s)=>{ + var a, {absoluteUrl: o, byteRangeOffset: d, keyTagInfo: l, iframe: u, isInitSegment: c} = r, h = o, p = l["method"], {start: o, end: l} = d, t = xc({ + url: h + }, t); + let f, m = o, g = l, y = !1, v = ne(o) || ne(l) ? d : void 0; + if ("AES-128" === p && l && (u || c)) { + const r = l - o; + r % 16 && (g = l + (16 - r % 16)), + 0 !== o && (y = !0, + m = o - 16), + v = { + start: m, + end: g + } + } + return n && ne(r.mediaSeqNum) && r.mediaOptionType === ul.Variant && (f = [], + null === (n = t.reportHTTPResponseHeaders) || void 0 === n || n.forEach(function(e) { + vl.includes(e) ? f.push(e) : qe().warn({ + name: "load-media-fragment" + }, `${e} is not in approved privacy list. Actions required.`) + }), + 0 === f.length && (f = void 0)), + Pc({ + url: h, + byteRangeOffset: v, + checkContentLength: !0, + extendMaxTTFB: s, + collectServerInstanceInfo: f, + onProgress: i, + xhrSetup: e.xhrSetup + }, t).pipe(ur(([e,t,i])=>{ + if (y) { + const t = e; + r.keyTagInfo.iv = new Uint8Array(t.slice(0, 16)), + e = t.slice(16) + } + return [r, e, t, i] + } + ), (a = r, + e=>e.pipe(Un(e=>{ + if (e instanceof ou) + throw new au(!1,"Timeout",0,$.FragmentTimeoutError,!0,a,e.stats); + if (e instanceof tu) + throw new au(!1,e.message,e.code,{ + code: e.code, + text: "Fragment Network Error" + },!1,a); + throw e + } + )))) + } + , Zf = { + clearkey: Zc, + fairplaystreaming: pu, + playready: _c, + widevine: Nc + } + , em = { + getKeySystemFormat(e) { + e = Zf[e]; + return e ? e.keyFormatString : "" + }, + getKeySystemSecurityLevel(e) { + e = Zf[e]; + return e ? e.securityLevels : null + } + } + , tm = { + NONE: "", + "AES-128": "", + "ISO-23001-7": "", + "SAMPLE-AES": "", + "SAMPLE-AES-CTR": "" + } + , im = { + NONE: 0, + "TYPE-0": 1, + "TYPE-1": 2, + "TYPE-2": 3 + }; + function rm(e) { + return e in im + } + function nm(e) { + return null == e ? 4 : im[e] + } + const sm = ["SDR", "PQ", "HLG"] + , am = { + afr: "af", + aka: "ak", + amh: "am", + ara: "ar", + arg: "an", + asm: "as", + ava: "av", + ave: "ae", + aym: "ay", + aze: "az", + bam: "bm", + bel: "be", + ben: "bn", + bih: "bh", + bod: "bo", + bos: "bs", + bre: "br", + bul: "bg", + cat: "ca", + ces: "cs", + cha: "ch", + che: "ce", + chu: "cu", + chv: "cv", + cor: "kw", + cos: "co", + cre: "cr", + cym: "cy", + dan: "da", + deu: "de", + div: "dv", + dzo: "dz", + ell: "el", + eng: "en", + epo: "eo", + est: "et", + eus: "eu", + ewe: "ee", + fao: "fo", + fas: "fa", + fin: "fi", + fra: "fr", + fry: "fy", + ful: "ff", + gla: "gd", + gle: "ga", + glg: "gl", + glv: "gv", + grn: "gn", + guj: "gu", + hat: "ht", + heb: "he", + her: "hz", + hin: "hi", + hmo: "ho", + hrv: "hr", + hun: "hu", + hye: "hy", + ibo: "ig", + ido: "io", + iii: "ii", + iku: "iu", + ile: "ie", + ina: "ia", + ind: "id", + isl: "is", + ita: "it", + jav: "jv", + jpn: "ja", + kal: "kl", + kan: "kn", + kas: "ks", + kat: "ka", + kau: "kr", + kaz: "kk", + khm: "km", + kik: "ki", + kin: "rw", + kir: "ky", + kom: "kv", + kon: "kg", + kor: "ko", + kua: "kj", + kur: "ku", + lao: "lo", + lat: "la", + lav: "lv", + lim: "li", + lit: "lt", + ltz: "lb", + lub: "lu", + lug: "lg", + mah: "mh", + mal: "ml", + mar: "mr", + mkd: "mk", + mlg: "mg", + mlt: "mt", + mol: "mo", + mon: "mn", + mri: "mi", + msa: "ms", + mya: "my", + nav: "nv", + nbl: "nr", + nde: "nd", + ndo: "ng", + nep: "ne", + nld: "nl", + nno: "nn", + nob: "nb", + nya: "ny", + oci: "oc", + oji: "oj", + ori: "or", + orm: "om", + oss: "os", + pan: "pa", + pli: "pi", + pol: "pl", + por: "pt", + pus: "ps", + que: "qu", + roh: "rm", + ron: "ro", + run: "rn", + rus: "ru", + san: "sa", + sin: "si", + slk: "sk", + slv: "sl", + sme: "se", + snd: "sd", + som: "so", + spa: "es", + sqi: "sq", + srd: "sc", + srp: "sr", + sun: "su", + swa: "sw", + swe: "sv", + tah: "ty", + tam: "ta", + tat: "tt", + tel: "te", + tgk: "tg", + tgl: "tl", + tha: "th", + tir: "ti", + ton: "to", + tuk: "tk", + tur: "tr", + uig: "ug", + ukr: "uk", + urd: "ur", + uzb: "uz", + ven: "ve", + vie: "vi", + wln: "wa", + yid: "yi", + zha: "za", + zho: "zh" + } + , om = { + isLanguageCode: e=>e in am, + shortenLanguageCode(e) { + let t; + var i, r; + return e && (r = 0 <= (i = e.indexOf("-")) ? e.slice(0, i) : e, + om.isLanguageCode(r) && (t = am[r]), + t = t || r, + 0 < i && (t += "-" + e.slice(i + 1))), + t + } + } + , dm = { + getRichestVideoCodec(e) { + if (e && e.length) { + e = e.sort((e,t)=>$p(t) - $p(e)); + return e && e.length ? e[0] : void 0 + } + }, + getRichestAudioCodec(e) { + if (e && e.length) { + e = e.sort((e,t)=>Kp(t) - Kp(e)); + return e && e.length ? e[0] : void 0 + } + }, + getRichestChannelLayoutForGroupId(t, i) { + if (t && i && i.length) { + let e; + const r = i.filter(e=>e.groupId === t); + if (r && r.length) { + const t = r.sort((e,t)=>Se.getChannelCount(t.channels) - Se.getChannelCount(e.channels)); + t && t.length && (e = t[0].channels) + } + return e + } + } + }; + function lm(e) { + return new R(L,"steeringManifestParsingError",!1,e,$.FormatError) + } + class um { + constructor(e) { + this._url = null, + this._programDateTime = null, + this._byteRange = null, + this.relurl = null, + this.baseurl = null, + this.isInitSegment = !1, + this.mediaSeqNum = NaN, + this.cc = NaN, + this.iframe = !1, + this.bitrate = NaN, + this.start = NaN, + this.duration = NaN, + this.lastByteRangeEndOffset = NaN, + this.inheritQuery = e, + this.tagList = new Array, + this.iframe = !1 + } + getMediaFragment(e, t, i) { + const r = { + mediaOptionType: i, + absoluteUrl: this.url, + start: this.start, + duration: this.duration, + mediaSeqNum: this.mediaSeqNum, + discoSeqNum: this.cc, + mediaOptionId: t, + itemId: e, + isLastFragment: !1, + isInitSegment: this.isInitSegment + }; + return null !== (e = this.byteRange) && void 0 !== e && e.length && (r.byteRangeOffset = { + start: this.byteRangeStartOffset, + end: this.byteRangeEndOffset + }), + this.iframe && (r.iframe = this.iframe), + this.levelkey && (r.keyTagInfo = this.levelkey), + this.programDateTime && (r.programDateTime = this.programDateTime), + r + } + get url() { + return !this._url && this.relurl && this.baseurl && (this._url = fl.buildAbsoluteURL(this.baseurl, this.relurl, { + alwaysNormalize: !0, + inheritQuery: this.inheritQuery + })), + this._url + } + set url(e) { + this._url = e + } + get programDateTime() { + return !this._programDateTime && this.rawProgramDateTime && (this._programDateTime = new Date(Date.parse(this.rawProgramDateTime))), + this._programDateTime + } + get byteRange() { + if (!this._byteRange) { + const i = new Array(2); + var e, t; + this.rawByteRange && (1 === (e = this.rawByteRange.split("@", 2)).length ? (t = this["lastByteRangeEndOffset"], + i[0] = t || 0) : i[0] = parseInt(e[1]), + i[1] = parseInt(e[0]) + i[0]), + this._byteRange = i + } + return this._byteRange + } + get byteRangeStartOffset() { + return this.byteRange[0] + } + get byteRangeEndOffset() { + return this.byteRange[1] + } + get rangeString() { + return 0 <= this.start && 0 <= this.duration ? `${this.start.toFixed(2)}-${(this.start + this.duration).toFixed(2)}` : "N/A" + } + get fragTag() { + return `sn/cc/levelId: ${this.mediaSeqNum}/${this.cc}` + } + } + const cm = { + parseMediaCharacteristics: e=>e ? e.split(/\s*,\s*/) : new Array, + addMediaToSelectionArray(e, t, i) { + if (void 0 === e) + return -1; + const r = e.MediaSelectionGroupOptions; + let n = r.find(e=>e.MediaSelectionOptionsMediaType === t.mediaType && e.MediaSelectionOptionsName === t.name && e.MediaSelectionOptionsExtendedLanguageTag === t.lang); + return n || (n = { + MediaSelectionOptionsMediaType: t.mediaType, + MediaSelectionOptionsExtendedLanguageTag: t.lang, + MediaSelectionOptionsIsDefault: t.default, + MediaSelectionOptionsName: t.name, + MediaSelectionOptionsPersistentID: i, + MediaSelectionOptionsTaggedMediaCharacteristics: t.characteristics + }, + t.mediaType === pl.SUBTITLE && (n.MediaSelectionOptionsDisplaysNonForcedSubtitles = t.forced ? hl.NO : hl.YES), + i++, + r.push(n)), + t.persistentID = n.MediaSelectionOptionsPersistentID, + i + }, + addDefaultClosedCaptionOption(e, t, i, r) { + e = { + itemId: e, + mediaOptionType: ul.Subtitle, + id: 0, + mediaOptionId: "cc1_" + Jd(), + mediaType: pl.CLOSEDCAPTION, + inStreamID: "CC1", + groupId: "cc", + name: "English-CC", + type: "CLOSED-CAPTIONS", + default: !1, + autoselect: !1, + forced: !1, + lang: "en", + characteristics: ["public.accessibility.transcribes-spoken-dialog", "public.accessibility.describes-music-and-sound"], + persistentID: r + }; + t.push(e), + cm.addMediaToSelectionArray(i, e, r) + } + } + , hm = { + BANDWIDTH: NaN, + "AVERAGE-BANDWIDTH": NaN + } + , pm = { + "TIME-OFFSET": NaN, + "FRAME-RATE": NaN, + SCORE: NaN, + "PLANNED-DURATION": NaN, + DURATION: NaN + } + , fm = /^(\d+)x(\d+)$/ + , mm = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; + class gm { + constructor(e) { + this.validTags = e + } + isKey(e) { + return e in this.validTags + } + trySetValue(e, t, i) { + return !!this.isKey(e) && (i[e] = this.parseFunc(t), + !0) + } + } + class ym { + static parseTags(t) { + let i; + var r = {}; + if (!t) + return r; + for (mm.lastIndex = 0; null !== (i = mm.exec(t)); ) { + const t = i[1].toUpperCase(); + let e = i[2]; + 0 === e.indexOf('"') && e.lastIndexOf('"') === e.length - 1 && (e = e.slice(1, -1)); + for (const i of ym.tagParsers) + if (i.trySetValue(t, e, r)) + break + } + return r + } + } + ym.tagParsers = [new class extends gm { + parseFunc(e) { + return e + } + } + ({ + NAME: "", + TYPE: "", + DEFAULT: "", + AUTOSELECT: "", + FORCED: "", + LANGUAGE: "", + URI: "", + AUDIO: "", + "VIDEO-RANGE": "", + "CLOSED-CAPTIONS": "", + CODECS: "", + BYTERANGE: "", + "INSTREAM-ID": "", + "GROUP-ID": "", + CHANNELS: "", + CHARACTERISTICS: "", + KEYFORMAT: "", + KEYFORMATVERSIONS: "", + "DATA-ID": "", + VALUE: "", + METHOD: "", + "HDCP-LEVEL": "", + "ALLOWED-CPC": "", + SUBTITLES: "", + ID: "", + CLASS: "", + "START-DATE": "", + "END-DATE": "", + "END-ON-NEXT": "", + "SERVER-URI": "", + "PATHWAY-ID": "" + }), new class extends gm { + parseFunc(e) { + e = parseInt(e); + return e > Number.MAX_SAFE_INTEGER ? 1 / 0 : e + } + } + (hm), new class extends gm { + constructor() { + super(...arguments), + this.parseFunc = parseFloat + } + } + (pm), new class extends gm { + parseFunc(e) { + let t = (e || "0x").slice(2); + t = (1 & t.length ? "0" : "") + t; + const i = new Uint8Array(t.length / 2); + for (let e = 0; e < t.length / 2; e++) { + var r = parseInt(t.slice(2 * e, 2 * e + 2), 16); + if (!ne(r)) + return; + i[e] = r + } + return i + } + } + ({ + IV: null + }), new class extends gm { + parseFunc(e) { + e = fm.exec(e); + let t; + return null !== e && (t = { + width: parseInt(e[1], 10), + height: parseInt(e[2], 10) + }), + t + } + } + ({ + RESOLUTION: null + })]; + const vm = { + ExtractVariableParameter: /{\$(.*?)}/g, + LevelPlaylistFast: /#EXTINF:(\d*(?:\.\d+)?)(?:,(.*))?|(?!#)(\S.+)|#EXT-X-BYTERANGE: *(.+)|#EXT-X-PROGRAM-DATE-TIME:(.+)|#EXT-X-BITRATE:(.+)|#EXT-X-DATERANGE:(.+)|#.*/g, + LevelPlaylistSlow: /(?:(?:#(EXTM3U))|(?:#EXT-X-(PLAYLIST-TYPE):(.+))|(?:#EXT-X-(MEDIA-SEQUENCE): *(\d+))|(?:#EXT-X-(TARGETDURATION): *(\d+))|(?:#EXT-X-(KEY):(.+))|(?:#EXT-X-(START):(.+))|(?:#EXT-X-(ENDLIST))|(?:#EXT-X-(DISCONTINUITY-SEQ)UENCE:(\d+))|(?:#EXT-X-(DIS)CONTINUITY))|(?:#EXT-X-(VERSION):(\d+))|(?:#EXT-X-(MAP):(.+))|(?:#EXT-X-(I-FRAMES)-ONLY)|(?:#EXT-X-(DEFINE):(.+))|(?:(#)(.*):(.*))|(?:(#)(.*))(?:.*)\r?\n?/, + MasterPlaylist: /#EXT-X-STREAM-INF:([^\n\r]*)[\r\n]+([^\r\n]+)|#EXT-X-I-FRAME-STREAM-INF:([^\r\n]+)|#EXT-X-DEFINE:([^\n\r]*)|#EXT-X-CONTENT-STEERING:([^\n\r]*)/g, + MasterPlaylistAlternateMedia: /#EXT-X-MEDIA:(.*)/g, + SessionData: /#EXT-X-SESSION-DATA[^:]*:(.*)/g, + SessionKeys: /#EXT-X-SESSION-KEY:([^\n\r]*)/g, + VARIABLE_PLAYLIST_REGEX: /(NAME|VALUE)=\"(.*)\",(NAME|VALUE)=\"(.*)\"|(IMPORT)=\"(.*)\"/ + }; + function Sm(e, t, i) { + return sl.buildAbsoluteURL(t, e, { + alwaysNormalize: !0, + inheritQuery: i + }) + } + class bm { + static isValidPlaylist(e) { + return 0 === e.indexOf("#EXTM3U") + } + static isMediaPlaylist(e) { + return 0 < e.indexOf("#EXTINF:") || 0 < e.indexOf("#EXT-X-PLAYLIST-TYPE:") + } + static replaceVariables(e, t) { + let i, r = !1; + return e && t && (i = e.replace(vm.ExtractVariableParameter, e=>{ + vm.ExtractVariableParameter.lastIndex = 0; + e = vm.ExtractVariableParameter.exec(e)[1]; + if (e && t.hasOwnProperty(e)) + return t[e]; + r = !0 + } + )), + { + updatedString: i, + error: r + } + } + static parseDecryptData(e, t, i) { + const r = ym.parseTags(e) + , n = (e = r.METHOD) && e in tm ? r.METHOD : null; + e = null !== (e = r.KEYFORMAT) && void 0 !== e ? e : null; + if (n && bm.shouldSelectKeyTag(e, n, i)) { + const s = r.URI + , i = r.IV || null; + if (s && r.IV && !i) { + const s = new R(L,_,!0,`Invalid IV: ${r.IV}`,$.PlaylistErrorInvalidEntry); + throw s.url = t, + s + } + const a = s ? sl.buildAbsoluteURL(t, s, { + alwaysNormalize: !0 + }) : t + , o = (r.KEYFORMATVERSIONS || "1").split("/").map(Number).filter(isFinite); + return new Gc(n,a,i,e,o) + } + } + static shouldSelectKeyTag(e, t, i) { + return "AES-128" === t || "NONE" === t || null == i || e === em.getKeySystemFormat(i) + } + static optOutClosedCaption(t) { + let i = !1 + , r = !1; + if (t) + for (let e = 0; e < t.length; ++e) { + const n = t[e]; + if (n.videoCodec && ((r = !0) !== n.iframes && n.closedcaption && "none" === n.closedcaption.toLowerCase())) { + i = !0; + break + } + } + return !r || i + } + static parseRootPlaylistAlternateMediaOptions(a, o, d, l, u, c) { + let h, p; + var f = { + MediaSelectionGroupAllowEmptySelection: 1, + MediaSelectionGroupMediaCharacteristics: ["public.audible"], + MediaSelectionGroupMediaType: pl.AUDIO, + MediaSelectionGroupOptions: [] + } + , m = { + MediaSelectionGroupAllowEmptySelection: 1, + MediaSelectionGroupMediaCharacteristics: ["public.legible"], + MediaSelectionGroupMediaType: pl.SUBTITLE, + MediaSelectionGroupOptions: [] + } + , g = { + videoAlternateOptions: [], + audioAlternateOptions: [], + subtitleAlternateOptions: [], + audioMediaSelectionGroup: f, + subtitleMediaSelectionGroup: m + }; + let y = 0; + for (vm.MasterPlaylistAlternateMedia.lastIndex = 0; null != (h = vm.MasterPlaylistAlternateMedia.exec(o)); ) { + const o = bm.replaceVariables(h[1], c); + if (o.error) { + p = new R(L,N,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); + break + } + var v = ym.parseTags(o.updatedString); + let e, t, i, r = pl.UNKNOWN; + const S = cm.parseMediaCharacteristics(v.CHARACTERISTICS) + , b = v["GROUP-ID"] + , T = v.CHANNELS; + let n, s = null; + switch (v.TYPE) { + case "VIDEO": + r = pl.VIDEO, + t = g.videoAlternateOptions; + break; + case "AUDIO": + r = pl.AUDIO, + s = ul.AltAudio, + t = g.audioAlternateOptions, + i = f; + const a = l.find(e=>e.audioGroupId === b); + n = a ? a.audioCodecList : []; + break; + case "SUBTITLES": + r = pl.SUBTITLE, + s = ul.Subtitle, + t = g.subtitleAlternateOptions, + i = m; + break; + case "CLOSED-CAPTIONS": + r = pl.CLOSEDCAPTION, + s = ul.Subtitle, + e = v["INSTREAM-ID"], + t = g.subtitleAlternateOptions, + i = m + } + const E = { + itemId: a, + mediaOptionType: s, + mediaType: r, + groupId: b, + channels: T, + groupCodecList: n, + name: v.NAME, + type: v.TYPE, + default: "YES" === v.DEFAULT, + autoselect: "YES" === v.AUTOSELECT, + forced: "YES" === v.FORCED, + characteristics: S, + persistentID: y, + id: t ? t.length : 0, + mediaOptionId: `${v.NAME}_${b}_${y}`, + lang: om.shortenLanguageCode(v.LANGUAGE) + }; + v.URI && (E.url = Sm(v.URI, d, u)), + E.name || (E.name = E.lang, + E.mediaType === pl.CLOSEDCAPTION && (E.name += " CC")), + E.mediaType === pl.CLOSEDCAPTION && e && (E.inStreamID = e), + t && (E.id = t.length, + t.push(E)), + y = cm.addMediaToSelectionArray(i, E, y) + } + return 0 !== g.subtitleAlternateOptions.length || bm.optOutClosedCaption(l) || cm.addDefaultClosedCaptionOption(a, g.subtitleAlternateOptions, m, y), + { + alternateMediaInfo: g, + playlistParsingError: p + } + } + static parseMediaOptionPlaylist(e, t, i=!0, r, n, s, a, o, d, l=0) { + var u; + let c = 0 + , h = 0; + const p = { + itemId: s, + mediaOptionId: a, + mediaOptionType: o, + type: "", + version: 0, + url: t, + initSegments: {}, + fragments: [], + liveOrEvent: !0, + startSN: 0, + endSN: 0, + iframesOnly: !1, + targetduration: 0, + totalduration: 0, + averagetargetduration: 0, + ptsKnown: !1 + }; + let f, m, g, y = new Gc("NONE",t,null,null,null), v = !1, S = !1, b = 0, T = null, E = new um(i), I = 0; + const w = {}; + let A, O, k, C = !0, D = !0; + vm.LevelPlaylistFast.lastIndex = 0; + for (var M = ()=>new R(L,_,!0,"Invalid key system preference for the playlist",$.IncompatibleAsset); null !== (f = vm.LevelPlaylistFast.exec(e)); ) { + const e = f[1]; + if (e) { + E.duration = parseFloat(e); + const t = (" " + f[2]).slice(1); + E.title = t || null, + E.tagList.push(t ? ["INF", e, t] : ["INF", e]) + } else if (f[3]) { + if (ne(E.duration)) { + const e = c++; + if (E.start = h + l, + E.levelkey = y, + S && !v) { + O = M(); + break + } + if (v = !1, + S = !1, + E.mediaSeqNum = e, + E.cc = b, + E.iframe = p.iframesOnly, + E.baseurl = t, + (A = bm.replaceVariables((" " + f[3]).slice(1), w)).error) { + O = new R(L,N,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); + break + } + if (E.relurl = A.updatedString, + E.bitrate = ne(E.byteRangeEndOffset) ? 8 * (E.byteRangeEndOffset - E.byteRangeStartOffset) / E.duration : I, + null != g) { + E.rawProgramDateTime = g, + E.tagList.push(["PROGRAM-DATE-TIME", E.rawProgramDateTime]); + const e = E.programDateTime.getTime(); + p.programDateTimeMap = null !== (u = p.programDateTimeMap) && void 0 !== u ? u : {}, + p.programDateTimeMap[e] = E.mediaSeqNum, + p.dateMediaTimePairs = null !== (u = p.dateMediaTimePairs) && void 0 !== u ? u : [], + p.dateMediaTimePairs.push([e, E.start]), + g = void 0 + } + if (p.fragments.push(E.getMediaFragment(s, a, o)), + T = E, + h += E.duration, + C || !p.initSegments[b] || D) + if (p.iframesOnly && 0 < E.byteRangeStartOffset && !p.initSegments[b] && !D) { + const e = new um(i); + if (e.url = E.url, + e.rawByteRange = Math.min(E.byteRangeStartOffset, 1316) + "@0", + e.baseurl = t, + e.isInitSegment = !0, + e.cc = b, + e.levelkey = y, + e.iframe = !0, + S && !v) { + O = M(); + break + } + v = !1, + S = !1, + p.initSegments[b] = e.getMediaFragment(s, a, o) + } else + k && (k.discoSeqNum = b, + p.initSegments[b] = k); + C = !1, + D = !1, + E = new um(i) + } + } else if (f[4]) { + if (E.rawByteRange = (" " + f[4]).slice(1), + T) { + const e = T.byteRangeEndOffset; + e && (E.lastByteRangeEndOffset = e) + } + } else if (f[5]) + g = (" " + f[5]).slice(1); + else if (f[6]) { + const e = parseInt(f[6]); + ne(e) && (I = 1e3 * e) + } else if (f[7]) { + const e = f[7] + , t = ym.parseTags(e); + t.ID && (p.daterangeTags || (p.daterangeTags = {}), + p.daterangeTags[t.ID] = t) + } else { + for (f = f[0].match(vm.LevelPlaylistSlow), + m = 1; m < f.length && void 0 === f[m]; m++) + ; + const e = bm.replaceVariables((" " + f[m + 1]).slice(1), w) + , d = bm.replaceVariables((" " + f[m + 2]).slice(1), w); + if (e.error || d.error) { + O = new R(L,N,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); + break + } + const l = e.updatedString + , P = d.updatedString; + switch (f[m]) { + case "#": + E.tagList.push(P ? [l, P] : [l]); + break; + case "PLAYLIST-TYPE": + p.type = l.toUpperCase(), + "VOD" === p.type && (p.liveOrEvent = !1); + break; + case "MEDIA-SEQUENCE": + 0 === p.fragments.length && (c = p.startSN = parseInt(l)); + break; + case "TARGETDURATION": + p.targetduration = parseFloat(l); + break; + case "VERSION": + p.version = parseInt(l); + break; + case "EXTM3U": + break; + case "ENDLIST": + p.liveOrEvent = !1; + break; + case "DIS": + b++, + E.tagList.push(["DIS"]), + C = !0; + break; + case "DISCONTINUITY-SEQ": + b = parseInt(l); + break; + case "KEY": + const e = l; + if (S = !0, + !v) { + try { + y = bm.parseDecryptData(e, t, r) + } catch (e) { + O = e + } + y && (v = !0) + } + break; + case "START": + const d = l + , u = ym.parseTags(d)["TIME-OFFSET"]; + ne(u) && (p.startTimeOffset = u); + break; + case "I-FRAMES": + p.iframesOnly = !0; + break; + case "MAP": + const h = ym.parseTags(l); + if (E.relurl = h.URI, + E.rawByteRange = h.BYTERANGE, + E.baseurl = t, + E.isInitSegment = !0, + E.levelkey = y, + S && !v) { + O = M(); + break + } + v = !1, + S = !1, + k = E.getMediaFragment(s, a, o), + D = !0, + E = new um(i); + break; + case "DEFINE": + const f = vm.VARIABLE_PLAYLIST_REGEX.exec(l) + , m = "NAME" === f[1] ? f[2] : f[4] + , g = "VALUE" === f[1] ? f[2] : f[4] + , N = f[5] + , T = f[6]; + if (m || g || "IMPORT" !== N || !n.hasOwnProperty(T)) { + if (!m || N || f[1] === f[3] || w.hasOwnProperty(m)) { + O = new R(L,_,!0,$.PlaylistErrorMissingImportReference.text,$.PlaylistErrorMissingImportReference); + break + } + w[m] = g + } else + w[T] = n[T] + } + } + } + return E = T, + E && !E.relurl && (p.fragments.pop(), + h -= E.duration), + !p.liveOrEvent && 0 < p.fragments.length && (p.fragments[p.fragments.length - 1].isLastFragment = !0), + p.totalduration = h, + p.averagetargetduration = h / p.fragments.length, + p.endSN = c - 1, + { + mediaOptionDetails: p, + playlistParsingError: O + } + } + static parseRootPlaylist(t, e, i, r) { + const n = [] + , s = {}; + let a, o, d, l, u = null, c = !0; + for (vm.MasterPlaylist.lastIndex = 0; null != (a = vm.MasterPlaylist.exec(e)); ) + if (a[4]) { + a = vm.VARIABLE_PLAYLIST_REGEX.exec(a[4]); + const t = "NAME" === a[1] ? a[2] : a[4] + , e = "VALUE" === a[1] ? a[2] : a[4] + , i = a[5]; + if (!t || s.hasOwnProperty(t) || i || a[1] === a[3]) { + l = new R(L,_,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); + break + } + s[t] = e + } else if (a[5]) { + const t = bm.replaceVariables(a[5], s); + if (t.error) { + l = new R(L,_,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); + break + } + const e = ym.parseTags(t.updatedString); + if ("string" != typeof e["SERVER-URI"]) { + l = new R(L,_,!0,$.PlaylistErrorInvalidSERVERURI.text,$.PlaylistErrorInvalidSERVERURI); + break + } + if (null != e["PATHWAY-ID"] && "string" != typeof e["PATHWAY-ID"]) { + l = new R(L,_,!0,$.PlaylistErrorInvalidPATHWAYID.text,$.PlaylistErrorInvalidPATHWAYID); + break + } + u = { + serverURI: Sm(e["SERVER-URI"], i, !1), + initPathwayID: e["PATHWAY-ID"] || "." + } + } else { + d = bm.replaceVariables(a[1] || a[3], s); + const e = ym.parseTags(d.updatedString); + if (o = bm.replaceVariables(a[2] || e.URI, s), + d.error || o.error) { + l = new R(L,_,!0,$.PlaylistErrorInvalidEXTXDEFINE.text,$.PlaylistErrorInvalidEXTXDEFINE); + break + } + if (void 0 !== e.SCORE && !ne(e.SCORE) || e.SCORE < 0) { + l = new R(L,_,!0,$.PlaylistErrorInvalidSCORE.text,$.PlaylistErrorInvalidSCORE), + c = !1; + break + } + c && void 0 === e.SCORE && (c = !1); + const u = e.BANDWIDTH + , p = e["AVERAGE-BANDWIDTH"] + , f = p || u + , m = null !== (h = e["VIDEO-RANGE"]) && void 0 !== h ? h : "SDR"; + if (null == (h = m) || !sm.includes(h)) + continue; + const g = { + itemId: t, + mediaOptionId: `level_${(f || 0) + n.length % 1e3 / 1e3}`, + mediaOptionType: ul.Variant, + attrs: e, + url: Sm(o.updatedString, i, r), + name: e.NAME, + audioGroupId: e.AUDIO, + subtitleGroupId: e.SUBTITLES, + iframes: !!a[3], + bandwidth: u, + avgBandwidth: p, + bitrate: f, + videoRange: m, + frameRate: e["FRAME-RATE"], + allowedCPCMap: bm.parseAllowedCPC(e["ALLOWED-CPC"]), + closedcaption: e["CLOSED-CAPTIONS"], + levelCodec: e.CODECS, + score: e.SCORE, + pathwayID: e["PATHWAY-ID"] || "." + } + , y = e["HDCP-LEVEL"]; + rm(y) && (g.hdcpLevel = y); + var h = e.RESOLUTION; + if (h && (g.width = h.width, + g.height = h.height), + e.CODECS) { + g.videoCodecList = new Array, + g.audioCodecList = new Array; + const t = e.CODECS.split(/[ ,]+/) + , i = t["length"]; + for (let e = 0; e < i; e++) { + const i = t[e]; + switch (i.slice(0, 4)) { + case "avc1": + g.videoCodec = Se.avc1toavcoti(i), + g.videoCodecList.push(g.videoCodec); + break; + case "avc3": + case "dvav": + case "dva1": + case "hev1": + case "hvc1": + case "dvh1": + case "dvhe": + case "vp09": + g.videoCodec = i, + g.videoCodecList.push(g.videoCodec); + break; + default: + g.audioCodec = i, + g.audioCodecList.push(g.audioCodec) + } + } + 1 < g.audioCodecList.length && (g.audioCodec = dm.getRichestAudioCodec(g.audioCodecList)), + 1 < g.videoCodecList.length && (g.videoCodec = dm.getRichestVideoCodec(g.videoCodecList)) + } + if (null != (l = "string" != typeof (h = g.pathwayID) ? lm("invalid steering manifest PATHWAY-PRIORITY list item data type") : /^[\w\-\.]+$/.test(h) ? void 0 : lm("steering manifest contains invalid pathway ID: " + h))) + break; + let cpc = g.allowedCPCMap ? JSON.stringify(g.allowedCPCMap) : "null"; + if (!cpc.includes("WIDEVINE_HARDWARE") && !g.url.includes('trickPlay') && !g.videoCodec.includes("hvc1")) + n.push(g) + } + + try{ + // console.log(n, window.screen.width) + let ok = (n.map( function(item){return{height : item.height, content: item}})); + let screenHeight = (app.cfg.visual.videoRes ?? window.screen.height) ; + ok.sort(function (a, b) { + return a.height - b.height; + }); + for (var i = 0; i < ok.length; i++){ + if (ok[i].height > screenHeight){ + if (i == 0){n.splice(0,n.length);n.push(ok[i].content)} + else{n.splice(0,n.length);n.push(ok[i-1].content)} + console.log('selected' , n[0].height) + break; + + } + + } + if (n.length > 1){ + n.splice(0,n.length - 1); + } + // console.log(n) + // console.log(ok) + } catch (e){ console.log(e)} + return { + variantMediaOptions: n, + contentSteeringOption: u, + masterVariableList: s, + playlistParsingError: l, + scoreAvailable: c + } + } + static parseAllowedCPC(e) { + if ("string" != typeof e) + return null; + const n = {}; + return e.split(",").forEach(e=>{ + const t = e.split(":"); + let i, r; + if (2 === t.length) + i = t[0].trim(), + r = t[1].trim(); + else { + if (!(2 < t.length)) + return; + r = t[t.length - 1].trim(), + t.pop(), + i = t.join(":") + } + if (!(i in n)) { + let e = new Array; + "" !== r && (e = r.split("/").map(e=>e.trim())), + n[i] = e + } + } + ), + n + } + static parseSessionKeys(e, t, i) { + var r; + const n = []; + for (vm.SessionData.lastIndex = 0; r = vm.SessionKeys.exec(e); ) + try { + const e = bm.parseDecryptData(r[1], t, i); + e && e.isEncrypted && n.push(e) + } catch (e) {} + return n + } + static parseSessionData(e, t) { + var i; + const r = [] + , n = new Set; + for (vm.SessionData.lastIndex = 0; null != (i = vm.SessionData.exec(e)); ) { + const e = ym.parseTags(i[1]); + e.LANGUAGE = om.shortenLanguageCode(e.LANGUAGE); + const t = e.LANGUAGE ? e["DATA-ID"] + "|" + e.LANGUAGE : void 0; + "DATA-ID"in e ? t && n.has(t) || ("com.apple.hls.other-tags" === e["DATA-ID"] && (e.VALUE = function(t) { + let i; + try { + i = JSON.parse(Vc.base64DecodeToStr(t)) + } catch (e) { + i = t + } + return i + }(e.VALUE)), + r.push(e), + t && n.add(t)) : qe().error(`Error processing DATA-ID ${e["DATA-ID"]} and LANGUAGE ${e.LANGUAGE}`) + } + return { + itemList: r, + baseUrl: t + } + } + } + var Tm, Em, Im, wm, Am, Om = bm; + const km = (e,t,i)=>{ + i = Object.assign(Object.assign({}, e), { + method: "GET", + responseType: "text", + extendMaxTTFB: i + }); + return ml(i.url) ? Mc().load(i, t).pipe(ur(e=>({ + responseText: e.data.response.data, + responseURL: e.data.response.uri, + stats: e.stats + }))) : Oc(i, t).pipe(ur(([e,t])=>({ + responseText: e.responseText, + responseURL: e.responseURL, + stats: t + }))) + } + , Cm = (e,n,t,i,s,a,o,d,r)=>{ + const {url: l, itemId: u, mediaOptionId: c, mediaOptionType: h} = e + , p = xc(e, i); + return km({ + url: l, + xhrSetup: t.xhrSetup + }, p, r).pipe(ur(({responseText: e, stats: t})=>{ + var i = performance.now() + , r = bm.parseMediaOptionPlaylist(e, l, !0, a, d, u, c, h, s, n); + Lc(r.mediaOptionDetails); + var e = performance.now() + , r = r["mediaOptionDetails"] + , i = { + playlistLoadTimeMs: t.tload - t.trequest, + playlistParseTimeMs: e - i + }; + return o.setPlaylistSample(i), + { + mediaOptionDetails: r, + stats: t + } + } + ), (f = h, + m = c, + g = l, + e=>e.pipe(Un(e=>{ + if (e instanceof ou) + throw new nu(!1,"Timeout",0,$.PlaylistTimeoutError,!0,f,m,g); + if (e instanceof tu) + throw new nu(!1,e.message,e.code,{ + code: e.code, + text: "Playlist Network Error" + },!1,f,m,g); + throw e + } + )))); + var f, m, g + } + , Dm = (f,e,m,t,g)=>Bi(e).pipe(Ra(e=>{ + const {keyTagInfo: t, isInitSegment: i, iframe: r, byteRangeOffset: n} = f + , s = t["method"] + , {start: a, end: o} = n; + if ("AES-128" !== s) + return Bi(e); + { + !t.uri || t.iv || t.format && "identity" !== t.format || (t.iv = function(t) { + const i = new Uint8Array(16); + for (let e = 12; e < 16; e++) + i[e] = t >> 8 * (15 - e) & 255; + return i + }(f.mediaSeqNum)); + const n = e + , s = t.key.buffer + , d = t.iv.buffer + , l = o && (r || i) ? o - a : void 0 + , u = !m.enableWebCrypto || !!l + , c = s.slice(0) + , h = d.slice(0) + , p = { + useJSCrypto: u, + plainTextLength: l + }; + return g.decrypt(c, h, "AES-CBC", n, p) + } + } + )); + class Mm { + constructor(e) { + this.option = e + } + get name() { + return this.option.name + } + get priority() { + return this.option.priority + } + get expiry() { + return this.option.expiry + } + filter(i, e) { + const r = this.option.initFn && this.option.initFn(i, e) || (e ? Object.assign({}, e) : {}); + let t = i; + return this.option.firstPassFn && i.forEach((e,t)=>this.option.firstPassFn(e, t, r, i)), + this.option.filterFn && (t = i.filter((e,t)=>this.option.filterFn(e, t, r, i))), + null != this.option.filterFn && 0 !== t.length || !this.option.minSortingFn || (t = i.sort((e,t)=>this.option.minSortingFn(e, t, r, i))), + this.option.finalFn && this.option.finalFn(t, r, i), + t + } + } + function Pm(e, t, i) { + return (t || []).reduce((e,t)=>t.filter(e, i), Array.from(e)) + } + function xm(t, e) { + return e.filter(e=>{ + return yl(t, null !== (e = e.url) && void 0 !== e ? e : null) + } + ) + } + function Rm() { + return [new Mm({ + name: "Remove Filter", + priority: 0, + filterFn: (t,e,i)=>!i || i.removed.every(e=>t.mediaOptionId !== e) + }), new Mm({ + name: "Penalty Box Filter", + priority: 1, + filterFn: (t,e,i)=>{ + const r = performance.now(); + return !i || i.penaltyBoxQueue.every(e=>e.expiry <= r || t.mediaOptionId !== e.mediaOptionId) + } + }), new Mm({ + name: "Compatible IDs Filter", + priority: 1, + filterFn: (t,e,i)=>!i || null == i.compatibleIds || i.compatibleIds.some(e=>e === t.mediaOptionId) + })] + } + class Lm extends Od { + constructor(e, t, i) { + super(e), + this.itemId = t, + this.mediaOptionType = i, + this.allowFilters = this._initFilters() + } + get mediaOptionList() { + var e; + return (null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.mediaOptions) || null + } + get mediaOptionList$() { + return this.mediaOptionListInfo$.pipe(ur(({mediaOptions: e})=>e)) + } + mediaOptionFromId(t) { + var e; + return null !== (e = (null !== (e = this.mediaOptionList) && void 0 !== e ? e : []).find(e=>e.mediaOptionId === t)) && void 0 !== e ? e : null + } + _getFilteredList(e) { + return Pm(e.mediaOptions, this.allowFilters, e) + } + get filteredMediaOptionList() { + return this.mediaOptionListInfo ? this._getFilteredList(this.mediaOptionListInfo) : null + } + get filteredMediaOptionList$() { + return this.mediaOptionListInfo$.pipe(Ra(e=>{ + const t = [Ul] + , i = performance.now(); + for (const r of e.penaltyBoxQueue) + ne(r.expiry) && r.expiry > i && t.push(vn(r.expiry - i)); + return nn(...t).pipe(ur(()=>this._getFilteredList(e))) + } + ), yd()) + } + get preferredMediaOptionList() { + return this.filteredMediaOptionList ? xm(this.preferredHost, this.filteredMediaOptionList) : [] + } + get preferredMediaOptionList$() { + return Zd([this.preferredHost$, this.filteredMediaOptionList$]).pipe(ur(([e,t])=>xm(e, t))) + } + getNewHost(e) { + e = this.getFallbackVariant(e, !1, !0); + return null != e && e.url ? gl(e.url) : this.preferredHost + } + } + function _m(e) { + return "PQ" === e.videoRange || "HLG" === e.videoRange + } + function Nm(e, t) { + return t.iframes === e + } + function Fm(e, t, i, r) { + return !r || i.bitrate > r.bitrate && i.bitrate <= e.bitrate ? Tm.Better : i.bitrate === r.bitrate ? Tm.Same : Tm.Worse + } + function Bm(e, t) { + return e && !t ? -1 : !e && t ? 1 : 0 + } + (dd = Tm = Tm || {})[dd.Better = 1] = "Better", + dd[dd.Same = 0] = "Same", + dd[dd.Worse = -1] = "Worse"; + class Um extends Lm { + constructor(e, t) { + super(e, t, ul.Variant) + } + static makeFilters() { + return [...Rm().concat([new Mm({ + name: "HDR Filter", + priority: 1, + filterFn: (e,t,i)=>!i || (i.hasHdrLevels && i.preferHDR) === _m(e) + }), new Mm({ + name: "Viewport Filter", + priority: 1, + firstPassFn: (e,t,i)=>{ + if (i && e && !e.iframes && e.videoCodec) { + const t = !i.lowestBitrate || e.bitrate < i.lowestBitrate ? e.bitrate : i.lowestBitrate; + i.lowestBitrate = t + } + } + , + filterFn: (e,t,i)=>!(e && i && i.viewportInfo && e.videoCodec && i.lowestBitrate) || function(e, t) { + return e.width < 1.35 * t.width && e.height < 1.35 * t.height && e.width * e.height < t.width * t.height * 1.35 + }({ + width: e.width, + height: e.height + }, i.viewportInfo) || e.bitrate === i.lowestBitrate + }), new Mm({ + name: "HDCP Filter", + priority: 2, + filterFn: (e,t,i)=>!i || !rm(i.maxHdcpLevel) || nm(e.hdcpLevel) < nm(i.maxHdcpLevel) + })])].sort((e,t)=>{ + return (null !== (e = e.priority) && void 0 !== e ? e : Number.MAX_SAFE_INTEGER) - (null !== (t = t.priority) && void 0 !== t ? t : Number.MAX_SAFE_INTEGER) + } + ) + } + _initFilters() { + return Um.kAllowFilters + } + get preferredHost() { + var e; + return null !== (e = null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.preferredHost) && void 0 !== e ? e : null + } + get preferredHost$() { + return this.selectEntity(this.itemId, e=>{ + return null !== (e = null == e ? void 0 : e.mediaOptionListTuple[ul.Variant].preferredHost) && void 0 !== e ? e : null + } + ) + } + get mediaOptionListInfo() { + var e; + return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionListTuple[ul.Variant]) && void 0 !== e ? e : null + } + get mediaOptionListInfo$() { + return this.selectEntity(this.itemId, e=>{ + return null === (e = null == e ? void 0 : e.mediaOptionListTuple) || void 0 === e ? void 0 : e[ul.Variant] + } + ).pipe(Up()) + } + get hdrMode$() { + return this.mediaOptionListInfo$.pipe(ur(e=>!0 === e.preferHDR && e.hasHdrLevels), Es()) + } + get maxHdcpLevel$() { + return this.selectEntity(this.itemId, e=>{ + e = null === (e = null == e ? void 0 : e.mediaOptionListTuple) || void 0 === e ? void 0 : e[ul.Variant]; + return null == e ? void 0 : e.maxHdcpLevel + } + ).pipe(Es()) + } + listFallbackVariants(t, e, i, r, n) { + var s = this.mediaOptionListInfo + , a = null === (o = this.mediaOptionList) || void 0 === o ? void 0 : o.find(e=>e.mediaOptionId === t); + if (!a || !s) + return null; + var o = this.makeFilteredListFromVariant(a, e, n); + if (!o) + return null; + e = gl(a.url), + s = s.hasScore; + return Um._listFallbackVariants(o, a, e, s, i, r, n) + } + getFallbackVariant(t, e, i, r) { + var n = this.mediaOptionListInfo + , s = null === (s = this.mediaOptionList) || void 0 === s ? void 0 : s.find(e=>e.mediaOptionId === t); + if (!s || !n) + return null; + e = this.makeFilteredListFromVariant(s, e, r); + if (!e) + return null; + r = gl(s.url), + n = n.hasScore; + return Um._getFallbackVariant(e, s, r, n, i) + } + makeFilteredListFromVariant(e, t, i) { + let r = this.mediaOptionListInfo; + if (!e || !this.mediaOptionList || !r) + return null; + r = Object.assign(Object.assign({}, r), { + includeAllEligiblePathways: !0 + }); + e = Array.from(this.mediaOptionList); + let n = t ? Pm(e, this.allowFilters, Object.assign(Object.assign({}, r), { + preferHDR: !1, + compatibleIds: null + })) : this._getFilteredList(r); + return n ? (i && 0 < i.length && (n = n.filter(e=>!i.includes(e.mediaOptionId))), + n) : null + } + get hasIframes() { + var e; + return null !== (e = null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.hasIframeLevels) && void 0 !== e && e + } + canSwitchToSDR(e, t, i=!1) { + var r = this.mediaOptionListInfo; + if (!this.mediaOptionList || !r) + return !1; + var n = this.mediaOptionFromId(e); + if (!n) + return !1; + if (!_m(n)) + return !1; + var s = gl(n.url) + , e = Pm(Array.from(this.mediaOptionList), this.allowFilters, Object.assign(Object.assign({}, r), { + preferHDR: !1, + compatibleIds: null + })) + , r = r.hasScore; + return null != Um._getFallbackVariant(e, n, s, r, t, i) + } + static _listFallbackVariants(e, r, n, t, s, a=!1, i=null) { + let o = !1; + const d = function(e, s, a) { + const t = [...e] + , o = gl(s.url) + , d = s.audioGroupId; + return t.sort((e,t)=>{ + let i = 0; + var r = a && ne(e.score) && ne(t.score) + , n = r ? e.score > t.score && e.score <= s.score : e.bitrate > t.bitrate && e.bitrate <= s.bitrate + , r = r ? e.score === t.score : e.bitrate === t.bitrate; + return n ? i = -1 : r ? (i = Bm(yl(o, e.url), yl(o, t.url)), + 0 === i && (i = Bm(!d || e.audioGroupId === d, !d || t.audioGroupId === d))) : i = 1, + i + } + ), + t + }(e.filter(e=>{ + var t = !(e.iframes !== r.iframes || s && yl(n, e.url)) + , i = a ? e.bitrate < r.bitrate : e.bitrate <= r.bitrate + , i = t && i; + return r.mediaOptionId === e.mediaOptionId ? (o = i, + !1) : i + } + ), r, t); + return !o || i && i.includes(r.mediaOptionId) || d.unshift(r), + d + } + static _getFallbackVariant(e, t, i, r, n, s=!1) { + let a = null; + e = (e = s ? e.filter(e=>e.bitrate < t.bitrate) : e).filter(e=>e.mediaOptionId !== t.mediaOptionId && e.iframes === t.iframes); + if (n && null != i) + for (const o of e) + Fm(t, 0, o, a) !== Tm.Better || yl(i, o.url) || (a = o); + else + for (const o of e) { + const r = Fm(t, 0, o, a); + r !== Tm.Better && (r !== Tm.Same || !yl(i, o.url) || yl(i, a.url) && o.audioGroupId !== t.audioGroupId) || (a = o) + } + return a + } + getMatchingVariant(e, t) { + var i = this.mediaOptionFromId(e) + , r = gl(null == i ? void 0 : i.url) + , n = t.mediaOptionType === ul.AltAudio ? "audioGroupId" : "subtitleGroupId"; + let s = null; + this.mediaOptionListInfo.hasScore; + for (const e of this.filteredMediaOptionList) + if (e[n] === t.groupId) { + if (!i) { + s = e; + break + } + var a = Fm(i, 0, e, s); + a !== Tm.Better && (a !== Tm.Same || s.mediaOptionId === i.mediaOptionId || e.mediaOptionId !== i.mediaOptionId && !yl(r, e.url)) || (s = e) + } + return s + } + get currentPathwayID() { + var e; + return null === (e = this.mediaOptionListInfo) || void 0 === e ? void 0 : e.currentPathwayID + } + } + function $m(e, t) { + switch (e) { + case Em.SendAlternateToPenaltyBox: + e = Em.RetryRequest, + 401 !== t && 403 !== t && 407 !== t && t !== $.CorruptStream.code && t !== $.LivePlaylistUpdateError.code || (e = Em.SendEndCallback); + break; + case Em.RemoveAlternatePermanently: + e = Em.SendEndCallback + } + return e + } + function Vm(e, t, i, r, n, s, a, o=!1) { + const d = s.mediaOptionListQueries[n] + , l = 0 != (e.errorActionFlags & Im.MoveAllAlternatesMatchingHost) + , u = s.mediaOptionListQueries[n].mediaOptionFromId(r) + , c = a.getFallbackMediaOptionTupleFromMediaOptionId(s, n, r, u.backingMediaOptionId, !1, l, o); + let {errorAction: h, errorActionFlags: p} = e; + return s.isValidMediaOptionTuple(c) ? yl(d.preferredHost, c[n].url) && (p &= ~Im.MoveAllAlternatesMatchingHost) : (t || (h = $m(h, i), + p = 0), + d instanceof Um && (!0 === d.mediaOptionFromId(r).iframes ? (h = Em.DoNothing, + p = 0) : !t && a.canSwitchToSDR(s, r, l, o) && (h = e.errorAction, + p = Im.SwitchToSDR))), + { + errorAction: h, + errorActionFlags: p + } + } + function Km(e) { + let t, i = 0; + switch (e) { + case 0: + t = Em.SendAlternateToPenaltyBox, + i = Im.MoveAllAlternatesMatchingHost; + break; + case 410: + t = Em.RemoveAlternatePermanently; + break; + case 500: + case 502: + case 503: + case 504: + case 404: + case 409: + case 401: + case 403: + case 407: + case $.LivePlaylistUpdateError.code: + case $.PlaylistNotReceived.code: + default: + t = Em.SendAlternateToPenaltyBox, + i = 0 + } + return { + errorAction: t, + errorActionFlags: i + } + } + function Hm(i, r, n, s, a, o, d) { + var {errorAction: l, errorActionFlags: u} = i; + let e = !0; + switch (l) { + case Em.RemoveAlternatePermanently: + case Em.SendAlternateToPenaltyBox: + { + if (null == a || null == o) + return r.handled = !1; + const i = n.itemId; + let e = o + , t = n.mediaOptionListQueries[a].mediaOptionFromId(o); + t.backingMediaOptionId && (e = t.backingMediaOptionId, + t = n.mediaOptionListQueries[a].mediaOptionFromId(e)); + var c = 0 != (u & Im.MoveAllAlternatesMatchingHost) + , h = 0 != (u & Im.MoveAllAlternatesMatchingHDCP) + , p = 0 != (u & Im.SwitchToSDR) + , f = l === Em.RemoveAlternatePermanently; + if (h && "hdcpLevel"in t) { + const r = t.hdcpLevel; + s.setMaxHdcpLevel(i, r) + } + if (p && s.switchToSDROnly(i), + c) { + const r = gl(t.url); + s.moveAllWithMatchingHosts(i, a, r, f) + } else + f ? s.removePermanently(i, a, e) : s.addToPenaltyBox(i, a, e); + if (n.enabledMediaOptionIdByType(a) === o) { + let e = [Ol, Ol, Ol]; + e = s.getFallbackMediaOptionTupleFromMediaOptionId(n, a, o, null, !1, c, d), + n.isValidMediaOptionTuple(e) ? s.setPreferredHost(i, gl(e[ul.Variant].url)) : r.fatal = !0, + r.fatal && (e = [Ol, Ol, Ol]), + s.setNextMediaOptions(n.itemId, e) + } + break + } + case Em.SendEndCallback: + r.fatal = !0; + break; + case Em.RetryRequest: + case Em.DoNothing: + default: + e = !1 + } + return r.handled = e, + e + } + function jm(e, t) { + t instanceof ru || t instanceof nu || t instanceof au || (t instanceof uu || t instanceof lu) && oe(t.keyuri) + } + function qm(t, i, r) { + if (t.handled = !0, + r && i < r.maxNumRetry && ne(r.retryDelayMs)) { + let e; + return e = "linear" === r.backoff ? (i + 1) * r.retryDelayMs : Math.pow(2, i) * r.retryDelayMs, + e = Math.min(r.maxRetryDelayMs, e), + jm(0, t), + vn(e) + } + return t.fatal = !0, + jm(0, t), + Ui(t) + } + function Qm(e, t, i, r, n, s, a, o, d=!1) { + return (null == r ? void 0 : r.errorAction) === Em.RetryRequest ? qm(e, t, i, s.logger) : Gm(e, 0, r, n, s, a, o, d) + } + function Gm(e, t, i, r, n, s, a, o=!1) { + const d = new Ji; + return sd(()=>{ + i && (jm(n.logger, e), + Hm(i, e, r, n, s, a, o)), + d.error(e) + } + ), + d + } + function Wm(t, i, r, n) { + return e=>e.pipe(Un(e=>{ + if (t.logger.error(`Got demux error ${e.message}`), + e instanceof D || e instanceof F) { + Em.SendAlternateToPenaltyBox; + return Gm(e, 0, { + errorAction: e.fatal ? Em.SendEndCallback : e instanceof F ? Em.SendAlternateToPenaltyBox : Em.RemoveAlternatePermanently, + errorActionFlags: 0 + }, i, t, r, n) + } + throw e + } + )) + } + function zm(e, t, i, r, n) { + e = null !== (e = null === (e = n.getKeyInfo(e)) || void 0 === e ? void 0 : e.mediaOptionIds) && void 0 !== e ? e : []; + for (const s of e) + for (const n of i.mediaOptionListQueries) + null != n.mediaOptionFromId(s) && r.updateConsecutiveTimeouts(i.itemId, n.mediaOptionType, t, "key") + } + function Xm(r, t, e, n, s, a) { + const o = n.logger + , i = s.enabledMediaOptionKeys + , d = []; + for (const t of r.mediaOptionIds) { + const r = i.some(e=>e.mediaOptionId === t) + , e = s.mediaOptionListQueries.find(e=>null != e.mediaOptionFromId(t)); + if (e) { + const n = e.mediaOptionType + , a = { + mediaOptionId: t, + mediaOptionType: n + }; + r ? d.push(a) : d.unshift(a) + } else + o.warn(`Couldn't find query for ${t}`) + } + const l = new Ji; + return sd(()=>{ + const e = r instanceof lu; + zm(r.keyuri, e, s, n, a); + let t, i = !1; + for (const {mediaOptionId: e, mediaOptionType: a} of d) + t = function(e, t, i, r, n) { + let s = { + errorAction: Em.SendAlternateToPenaltyBox, + errorActionFlags: 0 + }; + if (e instanceof lu) + s.errorAction = Em.SendAlternateToPenaltyBox; + else { + const t = e.isOkToRetry; + e.keyErrorReason === Xl.OutputRestricted ? (s.errorAction = Em.RemoveAlternatePermanently, + s.errorActionFlags |= Im.MoveAllAlternatesMatchingHDCP) : t ? s = Km(e.code) : s.errorAction = Em.RemoveAlternatePermanently + } + s.errorActionFlags &= ~Im.MoveAllAlternatesMatchingHost; + var a = r.enabledMediaOptionIdByType(i); + return t === a ? Vm(s, !1, e.code, a, i, r, n, e.isTimeout) : s + }(r, e, a, s, n), + o.error(`[Keys] handleNetworkError uri=${oe(r.keyuri)} mediaOptionId=${e} mediaOptionType=${a} action=${JSON.stringify(t)}`), + t.errorAction === Em.RetryRequest && (i = !0), + Hm(t, r, s, n, a, e); + i ? (l.next(), + l.complete()) : (jm(0, r), + l.error(r)) + } + ), + l.pipe(Ra(()=>qm(r, t, e, n.logger))) + } + function Ym(t, i, r, n, s, a, o, d) { + return n = Math.max(0, n), + e=>e.pipe(Ja(()=>{ + null != i && o.updateConsecutiveTimeouts(t, i, !1, "load") + } + ), ya(e=>e.pipe(Kr((e,t)=>function(e, t, i, r, n, s, a, o) { + var d; + if (!(e instanceof p)) + return Ui(e); + let l, u, c, h = !1; + if (e instanceof ru) + c = { + errorAction: $m(Km((d = e).response.code).errorAction, d.response.code), + errorActionFlags: 0 + }; + else if (e instanceof nu || e instanceof au) { + ({mediaOptionType: u, mediaOptionId: l, isTimeout: h} = e); + const t = null === (d = s.mediaOptionListQueries[u]) || void 0 === d ? void 0 : d.mediaOptionFromId(l); + if (!r && e.isTimeout && null != t && (!("iframes"in t) || !0 !== t.iframes) && (a.updateConsecutiveTimeouts(s.itemId, e.mediaOptionType, !0, "load"), + e instanceof au && e.stats)) { + const t = performance.now(); + o.setBandwidthSample(Object.assign(Object.assign({}, e.stats), { + tfirst: e.stats.tfirst || t, + tload: e.stats.tload || t, + complete: !0, + mediaOptionType: u + })) + } + c = function(e, t, i, r, n) { + var s = e.response.code; + let a = Km(s); + var {mediaOptionId: o, mediaOptionType: d} = e; + return t ? a.errorActionFlags &= ~Im.MoveAllAlternatesMatchingHost : a = function(e, t, i, r, n) { + let {errorAction: s, errorActionFlags: a} = t; + if (e.isTimeout) { + const t = e["mediaOptionType"] + , o = null !== (n = null === (n = n.getErrorInfoByType(t)) || void 0 === n ? void 0 : n.timeouts.load) && void 0 !== n ? n : 0; + !i && r <= o && (s = Em.DoNothing, + a = 0) + } + return { + errorAction: s, + errorActionFlags: a + } + }(e, a, t, i, r), + a = Vm(a, t, s, o, d, r, n, e.isTimeout), + a + }(e, r, n, s, a) + } + return Qm(e, t, i, c, s, a, u, l, h) + }(e, t, Rc(e, r), s, n, a, o, d))))) + } + Um.kAllowFilters = Um.makeFilters(), + (dd = Em = Em || {})[dd.DoNothing = 0] = "DoNothing", + dd[dd.SendEndCallback = 1] = "SendEndCallback", + dd[dd.SendAlternateToPenaltyBox = 2] = "SendAlternateToPenaltyBox", + dd[dd.RemoveAlternatePermanently = 3] = "RemoveAlternatePermanently", + dd[dd.InsertDiscontinuity = 4] = "InsertDiscontinuity", + dd[dd.RetryRequest = 5] = "RetryRequest", + (dd = Im = Im || {})[dd.MoveAllAlternatesMatchingHost = 1] = "MoveAllAlternatesMatchingHost", + dd[dd.MoveAllAlternatesMatchingHDCP = 2] = "MoveAllAlternatesMatchingHDCP", + dd[dd.SwitchToSDR = 4] = "SwitchToSDR"; + class Jm extends Od { + constructor(e) { + super(e) + } + get currentConfig() { + var e; + return null === (e = this.getActive()) || void 0 === e ? void 0 : e.config + } + get extendMaxTTFB() { + var e; + return null === (e = this.getActive()) || void 0 === e ? void 0 : e.extendMaxTTFB + } + get config$() { + return this.selectActive(e=>null == e ? void 0 : e.config) + } + get userSeek$() { + return this.selectActive(e=>null == e ? void 0 : e.userSeek) + } + } + w(); + class Zm extends pd { + constructor() { + super({}, { + name: "hls-store", + producerFn: vc + }) + } + } + class eg { + constructor(e) { + this.store = e + } + getQuery() { + return new Jm(this.store) + } + setHlsEntity(e) { + const t = e.id; + Co(`hls.set.entity ${t}`), + sd(()=>{ + this.store.add(de(e)), + this.store.setActive(t) + } + ) + } + removeEntity(e) { + Co(`hls.remove ${e}`), + this.store.remove(e) + } + setStartTime(t) { + this.store.updateActive(e=>{ + e.config.startPosition = t + } + ) + } + setUserSeek(t) { + this.store.updateActive(e=>{ + e.userSeek = t + } + ) + } + setExtendMaxTTFB(t) { + this.store.updateActive(e=>{ + e.extendMaxTTFB = t + } + ) + } + } + let tg, ig; + function rg() { + return tg = tg || new eg(new Zm), + tg + } + function ng() { + return rg().getQuery().currentConfig + } + function sg(e, t, i, r) { + var n = t.mediaSeqNum - e.startSN; + if (n < 0 || n >= e.fragments.length) + return e; + const s = Object.assign(Object.assign({}, e), { + fragments: e.fragments.map(e=>Object.assign({}, e)) + }) + , a = s.fragments + , o = a[n]; + if (!Fp(t, a[n])) + return null == r || r.warn("Parsed and existing fragments don't match"), + e; + var {startDtsTs: d, startPts: e, endPts: t} = t; + o.startDtsTs = d, + o.startPts = e, + o.endPts = t, + o.start = i, + o.duration = b(o.endPts, o.startPts); + for (let e = n; 0 < e; e--) + ag(a, e, e - 1, r); + for (let e = n; e < a.length - 1; e++) + ag(a, e, e + 1, r); + s.totalduration = 0; + for (const l of a) + s.totalduration += l.duration; + return s.ptsKnown = !0, + og(s), + s + } + function ag(e, t, i, r) { + const n = e[t] + , s = e[i]; + s.startPts ? (t < i && n.start + n.duration > s.start || i < t && s.start + s.duration > n.start) && (null == r || r.warn(`overlapping segments found ${n.mediaSeqNum}->${s.mediaSeqNum}`)) : s.start = t < i ? n.start + n.duration : Math.max(n.start - s.duration, 0) + } + function og(e) { + if (e.programDateTimeMap) { + e.dateMediaTimePairs = []; + for (var [t,i] of Object.entries(e.programDateTimeMap)) { + t = Number(t), + i = e.fragments[i - e.startSN]; + i && (i = i.start, + e.dateMediaTimePairs.push([t, i])) + } + e.dateMediaTimePairs.sort((e,t)=>e[0] - t[0]) + } + } + function dg(t, i) { + if ("VOD" === t.type || "VOD" === i.type || t.iframesOnly !== i.iframesOnly) + return i; + var r = t.mediaOptionId === i.mediaOptionId; + let n = Object.assign(Object.assign({}, i), { + initSegments: {}, + fragments: [], + ptsKnown: !1 + }); + const s = Math.max(t.startSN, n.startSN) - n.startSN + , a = Math.min(t.endSN, n.endSN) - n.startSN + , o = n.startSN - t.startSN + , d = t.fragments + , l = i.fragments; + let u = 0; + for (let e = s; e <= a; ++e) + if (d[o + e] && l[e]) { + u = d[o + e].discoSeqNum - l[e].discoSeqNum; + break + } + const c = n.initSegments; + let h = null; + for (let e = 0; e < l.length; e++) { + const p = d[o + e] + , s = l[e] + , a = Object.assign({}, s) + , f = s.discoSeqNum + u; + i.initSegments[s.discoSeqNum] && (c[f] = Object.assign(Object.assign({}, i.initSegments[s.discoSeqNum]), { + discoSeqNum: f + })), + a.discoSeqNum = f, + r && a.mediaSeqNum === (null == p ? void 0 : p.mediaSeqNum) && null != p.startPts && (a.start = p.start, + a.duration = p.duration, + a.startDtsTs = p.startDtsTs, + a.endDtsTs = p.endDtsTs, + a.startPts = p.startPts, + a.endPts = p.endPts, + h = a), + n.fragments.push(a) + } + if (h) + n = sg(n, h, h.start); + else if (0 <= o && o < d.length) { + const t = d[o].start + , i = n.fragments; + for (let e = 0; e < l.length; e++) + i[e].start += t + } + return n.ptsKnown = n.ptsKnown || r && !0 === t.ptsKnown && t.endSN >= i.startSN, + og(n), + n + } + function lg(e, t, i) { + let r = t.targetduration; + return ne(i.liveSyncDuration) ? r = i.liveSyncDuration : ne(i.liveSyncDurationCount) && (r = i.liveSyncDurationCount * t.targetduration), + e + Math.max(0, t.totalduration - r) + } + function ug(e, t, i, r, n) { + if (!t.ptsKnown) + return 0; + var s = t.targetduration + , a = t.fragments[0].start + , r = n.canContinuePlaybackWithoutGap(t, i, { + avgPlaylistLoadTimeMs: 0, + avgPlaylistParseTimeMs: 0 + }, r); + let o = Math.max(0, e - s); + return e < a && !r && (o = a), + o + } + function cg(e) { + return 1e3 * (e.averagetargetduration || e.targetduration) + } + function hg(e, t) { + var i = cg(e) + , t = performance.now() - t; + return e.liveOrEvent && i <= t + } + function pg(e, t) { + return function(e) { + const t = [] + , i = e.fragments; + for (const e of i) { + const {discoSeqNum: i, start: r} = e; + t.push({ + timelineOffset: r, + mediaFragment: e + }) + } + return t + }(e).find(e=>t(e.mediaFragment)) + } + function fg(s, e, a, t, o) { + var i; + const d = !t.liveOrEvent || t.ptsKnown; + let r = null !== (i = pg(t, t=>{ + var e = t.mediaSeqNum >= a + , i = 0 < t.duration + , r = t.start + t.duration + , n = !d || s < r || s - r < 1 && t.isLastFragment + , r = o.every(e=>!Fp(e.frag, t)); + return e && i && n && r + } + )) && void 0 !== i ? i : null + , n = NaN; + null != r && ne(e) && r.mediaFragment.discoSeqNum !== e && (n = r.mediaFragment.discoSeqNum, + r = null); + e = o.some(e=>0 < e.frag.framesWithoutIDR); + return r && e && o[o.length - 1].frag.mediaOptionId !== t.mediaOptionId && (r = null !== (t = pg(t, e=>e.mediaSeqNum === r.mediaFragment.mediaSeqNum - 1)) && void 0 !== t ? t : r), + { + foundFrag: r, + nextDisco: n + } + } + function mg(e) { + const t = e.fragments; + return t.map(e=>e.duration).reduce((e,t)=>e + t, null !== (e = t[0].start) && void 0 !== e ? e : 0) + } + class gg extends Od { + constructor(e, t) { + super(e), + this.mediaOption = t + } + get itemId() { + return this.mediaOption.itemId + } + get mediaOptionId() { + return this.mediaOption.mediaOptionId + } + get initSegmentEntities() { + var e; + return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.initSegmentCacheEntities + } + get mediaLibraryEntity() { + return this.getEntity(this.itemId) + } + get mediaOptionDetailsEntityRecord() { + var e; + return null === (e = this.mediaLibraryEntity) || void 0 === e ? void 0 : e.mediaOptionDetailsEntityRecord + } + get mediaOptionDetailsEntity() { + return this.mediaOptionDetailsEntityRecord ? this.mediaOptionDetailsEntityRecord[this.mediaOptionId] : null + } + get mediaOptionDetails() { + var e; + return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.mediaOptionDetails + } + get playlistDuration() { + var e; + return null === (e = this.mediaOptionDetailsEntity) || void 0 === e ? void 0 : e.playlistDuration + } + get mediaOptionDetailsEntity$() { + const {itemId: e, mediaOptionId: t} = this; + return this.selectEntity(e, e=>{ + if (null != e && e.mediaOptionDetailsEntityRecord) + return null == e ? void 0 : e.mediaOptionDetailsEntityRecord[t] + } + ) + } + get mediaOptionDetails$() { + return this.selectEntity(this.itemId, e=>{ + return null === (e = null == e ? void 0 : e.mediaOptionDetailsEntityRecord[this.mediaOptionId]) || void 0 === e ? void 0 : e.mediaOptionDetails + } + ).pipe(Up()) + } + get playlistDuration$() { + return this.mediaOptionDetailsEntity$.pipe(ur(e=>null == e ? void 0 : e.playlistDuration), Up(), Es()) + } + get live$() { + return this.mediaOptionDetails$.pipe(ur(e=>null == e ? void 0 : e.liveOrEvent), Es()) + } + } + class yg extends pd { + constructor() { + super({}, { + name: "media-library-store", + idKey: "itemId", + producerFn: vc + }) + } + } + class vg { + constructor(e) { + this.store = e + } + getQuery() { + return new Od(this.store) + } + getQueryForOption(e) { + return new gg(this.store,e) + } + createMediaLibraryEntity(e) { + var t = { + itemId: e, + mediaOptionDetailsEntityRecord: {} + }; + Co(`library.entity.create: ${e}`), + this.store.add(t) + } + setDetailsLoading(e) { + const {itemId: t, mediaOptionId: i} = e; + Co(`library.details.loading: ${i}`), + this.store.update(t, ({mediaOptionDetailsEntityRecord: e})=>{ + e[i] || (e[i] = { + initSegmentCacheEntities: {}, + unchangedCount: 0 + }), + e[i].detailsLoading = !0 + } + ) + } + archiveMediaOptionDetails(i, r, n) { + const {itemId: e, mediaOptionId: s} = i + , a = performance.now() + , o = mg(i); + Co(`library.details.loaded: ${s}`), + this.store.update(e, e=>{ + const t = e.mediaOptionDetailsEntityRecord[s]; + t.detailsLoading = !1, + t.mediaOptionDetails = i, + t.lastUpdateMillis = a, + n ? t.unchangedCount = 0 : ++t.unchangedCount, + t.playlistDuration = o, + t.stats = r, + e.liveOrEvent = i.liveOrEvent + } + ) + } + setInitSegmentLoading(e) { + const {itemId: t, mediaOptionId: i, discoSeqNum: r} = e; + Co(`library.initsegs.loading: ${i}/${r}`), + this.store.update(t, e=>{ + e.mediaOptionDetailsEntityRecord[i].initSegLoading = r + } + ) + } + archiveInitSegmentEntity(i, r) { + const {itemId: e, mediaOptionId: n, discoSeqNum: s} = i; + Co(`library.initseg.loaded: ${n}/${s}`), + this.store.update(e, ({mediaOptionDetailsEntityRecord: e})=>{ + const t = e[n]; + t.initSegmentCacheEntities[s] = [i, r], + t.initSegLoading = null + } + ) + } + updatePTSDTS(e, r, n, s) { + this.store.update(e, ({mediaOptionDetailsEntityRecord: e})=>{ + const t = e[r]; + var i; + null != t && t.mediaOptionDetails && ({variantDTS: i, timelineOffset: e} = n, + e = S(s.startDtsTs) - S(i) + e, + e = sg(t.mediaOptionDetails, s, e), + t.mediaOptionDetails = e, + t.playlistDuration = mg(e)) + } + ) + } + remove(e) { + this.store.remove(e) + } + clear() { + this.store.remove() + } + } + function Sg() { + return ig = ig || new vg(new yg), + ig + } + const bg = e=>Sg().getQueryForOption(e) + , Tg = (d,e,t=!1)=>{ + if (!kl(e)) + return Bi(null); + const i = e["itemId"] + , r = d["mediaLibraryService"] + , n = r.getQueryForOption(e); + n.hasEntity(i) || r.createMediaLibraryEntity(i); + var s = n.mediaOptionDetailsEntity + , a = n.mediaOptionDetails; + return null == a || t || "VOD" !== a.type && (!a.liveOrEvent || hg(a, s.lastUpdateMillis)) ? (r.setDetailsLoading(e), + function(l) { + var e; + const {logger: t, config: u, rootPlaylistQuery: c, rootPlaylistService: h, statsService: i, mediaLibraryService: p, mediaSink: r} = d + , f = r.mediaQuery + , n = u.playlistLoadPolicy + , s = u.keySystemPreference + , a = c.masterVariableList + , o = null === (e = null === (e = rg()) || void 0 === e ? void 0 : e.getQuery()) || void 0 === e ? void 0 : e.extendMaxTTFB; + return Cm(l, c.itemStartOffset, u, n, t, s, i, a, o).pipe(Hi(Zi), ur(t=>{ + const i = p.getQueryForOption(l) + , r = i.mediaOptionDetails; + let n = t["mediaOptionDetails"]; + var e = t["stats"]; + let s = !0; + if (n.liveOrEvent) { + const d = n["mediaOptionType"]; + t = n, + s = null == r || t.endSN !== r.endSN || t.liveOrEvent !== r.liveOrEvent; + let e = n; + r && (e = dg(r, n)); + const i = c.lastLoadedMediaOptionByType(d) + , u = i ? null === (t = p.getQueryForOption(i)) || void 0 === t ? void 0 : t.mediaOptionDetails : null; + !e.ptsKnown && u && u.mediaOptionId !== (null == r ? void 0 : r.mediaOptionId) && (e = dg(u, n)), + n = e + } + n && (p.archiveMediaOptionDetails(n, e, s), + h.setLastLoadedMediaOptionByType(c.itemId, l.mediaOptionType, l)); + const a = !s && i.mediaOptionDetailsEntity.unchangedCount >= u.liveMaxUnchangedPlaylistRefresh + , o = function(e, t, i, r) { + t = ug(r.currentTime, e, t, i, r), + i = e.fragments[e.fragments.length - 1], + r = i.start + i.duration; + return { + expired: null != i && e.liveOrEvent && e.ptsKnown && r < t, + windowEnd: r, + minPosition: t + } + }(n, e.tload, u.maxBufferHole, f); + if (a || o.expired) { + e = a ? $.LivePlaylistUpdateError : { + text: `Live window too far in the past end:${o.windowEnd.toFixed(3)} minPosition:${o.minPosition}`, + code: 0 + }; + throw new nu(!1,e.text,e.code,e,!1,l.mediaOptionType,l.mediaOptionId,l.url) + } + return n + } + ), Ql.tag("getMediaOptionDetailsCommon.emit.loaded"), Ym(l.itemId, l.mediaOptionType, xc(l, n), u.maxNumAddLevelToPenaltyBox, !1, c, h, i)).pipe(Cs(1)) + }(e)) : Bi(a).pipe(Ql.tag("retrieveMediaOptionDetails.emit.cached")).pipe(Cs(1)) + } + ; + const Eg = (t,i)=>{ + if (!i) + return Bi(null); + const {mediaLibraryService: r, mediaParser: n} = t + , e = r.getQueryForOption(i) + , {mediaOption: s, mediaOptionDetailsEntityRecord: a, mediaOptionDetails: o} = e + , d = s["mediaOptionId"]; + if (null == a || !a[d]) + throw new Error("retrieveInitSegmentCacheEntity no details entity"); + if (!o) + throw new Error("retrieveInitSegmentCacheEntity no details"); + var l = a[d]["initSegmentCacheEntities"] + , u = o["initSegments"] + , c = i["discoSeqNum"]; + if (l[c]) { + const [t,r] = l[c]; + let e = t; + return r && (e = n.willBeTrackSwitch(i) ? t : r), + Bi(e) + } + const h = u[c]; + return h ? (r.setInitSegmentLoading(h), + wg(t, h, !1, !1).pipe(Hi(Zi), Ra(e=>Ig(e, h, t)), Ql.tag("retrieveInitSegmentCacheEntity.emit"))) : Bi(null) + } + ; + function Ig(e, n, t) { + const {logger: s, mediaSink: i, rootPlaylistService: r, rootPlaylistQuery: a, mediaParser: o, mediaLibraryService: d, gaplessInstance: l} = t + , u = i["mediaQuery"] + , c = d.getQueryForOption(n) + , {mediaOption: h, mediaOptionDetails: p} = c + , {itemId: f, mediaOptionId: m} = h + , {keyTagInfo: g, discoSeqNum: y, mediaOptionType: v} = n + , S = u.seeking + , b = p.liveOrEvent + , T = v === ul.Variant && p.ptsKnown; + let E, I; + n.isInitSegment ? I = new Uint8Array(e) : E = new Uint8Array(e); + var e = { + segment: E, + initSegment: I, + frag: n, + ptsKnown: T, + seeking: S, + live: b, + totalDuration: p.totalduration + }; + return o.parseInitSegment(e, null !== (e = null === navigator || void 0 === navigator ? void 0 : navigator.vendor) && void 0 !== e ? e : "").pipe(ur(e=>{ + var {track: t, moovData: i, mimeType: r} = e + , e = t["initSegment"]; + l.inGaplessMode && Se.isVideoCodec(t.codec) && (s.warn(`Video codec discovered in gapless mode codec:${t.codec}`), + l.dequeueSource("InvalidFormat")); + r = { + itemId: f, + mediaOptionId: m, + discoSeqNum: y, + initParsedData: i, + data: e, + mimeType: r, + keyTagInfo: g, + fragment: n + }; + return d.archiveInitSegmentEntity(r), + r + } + ), Wm(r, a, v, m)) + } + function wg(n, s, i, r) { + var e; + const {rootPlaylistQuery: t, rootPlaylistService: a, config: o, rtcService: d, statsService: l} = n + , {itemId: u, mediaOptionType: c} = s + , h = o.fragLoadPolicy + , p = ne(s.mediaSeqNum); + let f; + p && (f = { + getData: !1, + cb: (e,t,i,r)=>(a.updateInflightFrag(u, s.mediaOptionType, s, "loading", i), + !1) + }); + let m = !1; + return r && null === d.serverInfoInstance && (m = !0), + Jr([Og(n, s.keyTagInfo, { + itemId: s.itemId, + mediaOptionId: s.mediaOptionId + }), Jf(s, o, h, f, m, null === (e = null === (e = rg()) || void 0 === e ? void 0 : e.getQuery()) || void 0 === e ? void 0 : e.extendMaxTTFB).pipe(Ja(([,,e,t])=>{ + i && l.setBandwidthSample(Object.assign(Object.assign({}, e), { + mediaOptionType: s.mediaOptionType + })), + r && m && (d.serverInfoInstance = t), + p && a.updateInflightFrag(u, s.mediaOptionType, s, "loaded", e) + } + ), Ym(u, c, xc(s, h), o.maxNumAddLevelToPenaltyBox, !1, t, a, l))]).pipe(Cs(1), Ja(([,e])=>{ + var t; + r && ([t,,e] = e, + d.handleFragLoaded(t, e)) + } + ), Ra(([e,t])=>{ + const [i,r] = t; + return i.keyTagInfo.key = e.key, + Dm(i, r, o, n.logger, n.rpcClients.crypto) + } + ), Ql.tag("getMediaFragmentCommon.emit")) + } + const Ag = (i,e,t)=>{ + const {rootPlaylistService: r, rootPlaylistQuery: n} = i + , {timelineOffset: s, mediaFragment: a} = t.foundFrag + , {itemId: o, discoSeqNum: d} = a; + return r.updateInflightFrag(o, a.mediaOptionType, a, "loading", null), + Jr([Og(i, a.keyTagInfo, { + itemId: a.itemId, + mediaOptionId: a.mediaOptionId + }), Eg(i, a).pipe(Ra(t=>wg(i, a, !0, !0).pipe(Ra(e=>{ + return function(e, t, i, y, v, S) { + const r = new Uint8Array(e) + , {rootPlaylistService: n, mediaSink: s, mediaParser: a, rootPlaylistQuery: o, mediaLibraryService: b} = S + , d = s["mediaQuery"] + , l = b.getQueryForOption(y) + , {mediaOption: u, mediaOptionDetails: c} = l + , {itemId: T, mediaOptionId: E} = u + , {discoSeqNum: I, mediaSeqNum: w, mediaOptionType: h, isLastFragment: A} = y + , p = d.seeking + , f = c.liveOrEvent + , m = h === ul.Variant && c.ptsKnown + , O = { + segment: r, + frag: y, + seeking: p, + live: f, + ptsKnown: m, + totalDuration: c.totalduration, + defaultInitPTS: t, + iframeMediaStart: Np(y) ? y.iframeMediaStart : void 0, + iframeDuration: Np(y) ? y.iframeMediaDuration : void 0 + }; + let g; + if (null != i && (null === (t = y.keyTagInfo) || void 0 === t ? void 0 : t.uri) === (null === (t = i.keyTagInfo) || void 0 === t ? void 0 : t.uri)) + g = Bi(i); + else if (null != i) { + const e = Object.assign(Object.assign({}, i.fragment), { + keyTagInfo: y.keyTagInfo + }); + g = Ig(i.data, e, S) + } else + g = Ig(e, y, S); + return g.pipe(Ra(m=>{ + const g = performance.now(); + if (null != m) { + const g = m["data"] + , e = new Uint8Array(g); + O.initSegment = e + } + return a.parseSegment(O, "").pipe(ur(e=>{ + var t = performance.now() + , {startPTS: i, startDTS: r, endPTS: n, endDTS: s, firstKeyframePts: a, framesWithoutIDR: o, dropped: d, data1: l, data2: u, captionData: c, id3Samples: h, parsedInitSegment: e} = e + , t = { + durationSec: n.baseTime / n.timescale - i.baseTime / i.timescale, + parseTimeMs: t - g + }; + S.statsService.setFragSample(t); + let p = Object.assign({}, m); + if (e) { + const {track: g, moovData: f, mimeType: v} = e + , S = g["initSegment"]; + p = { + itemId: T, + mediaOptionId: E, + discoSeqNum: I, + initParsedData: f, + data: S, + mimeType: v, + keyTagInfo: y.keyTagInfo, + fragment: y + }, + b.archiveInitSegmentEntity(m, p) + } + e = y.keyTagInfo; + return [p, { + itemId: T, + mediaOptionId: E, + mediaSeqNum: w, + discoSeqNum: I, + startDtsTs: r, + endDtsTs: s, + timelineOffset: v, + firstKeyframePts: a, + framesWithoutIDR: o, + dropped: d, + data1: l, + data2: u, + startPts: i, + endPts: n, + keyTagInfo: e, + isLastFragment: A, + iframe: null !== (e = y.iframe) && void 0 !== e && e, + duration: y.duration, + iframeMediaDuration: Np(y) ? y.iframeMediaDuration : void 0, + captionData: c, + id3Samples: h + }] + } + )) + } + ), Wm(n, o, h, E)) + }(e, null === (e = n.getInitPTS(d)) || void 0 === e ? void 0 : e.offsetTimestamp, t, a, s, i) + } + ), Ja(e=>{} + ), Ql.tag(`retrieveMediaFragmentCacheEntity.${e}.emit`)))).pipe(Cs(1))]).pipe(Ra(([,e])=>Bi(e))) + } + ; + function Og(e, t, i) { + const {keySystemAdapter: r, rootPlaylistQuery: n, rootPlaylistService: s, config: a} = e; + return r.getKeyFromDecryptData(t, i).pipe((o = t.uri, + d = xc({ + url: t.uri + }, a.keyLoadPolicy), + l = n, + u = s, + c = r.ksQuery, + e=>e.pipe(od(()=>{ + zm(o, !1, l, u, c) + } + ), ya(e=>e.pipe(Kr((e,t)=>{ + if (e instanceof lu || e instanceof uu) + return Xm(e, t, Rc(e, d), u, l, c); + throw e + } + )))))); + var o, d, l, u, c + } + class kg { + constructor(e, t, i) { + this.hls = e, + this.destroy$ = new zt, + this.iframeSwitchStart = 0, + this.logger = t.child({ + name: "hls-player-events" + }), + this.rtc = i, + this.subscribeAndEmit() + } + destroy() { + this.destroy$.next() + } + subscribeAndEmit() { + var e = this.loaderQueryListener(new fu(bc)) + , t = this.hls.publicQueries$.pipe(Ra(([e,t])=>nn(this.rootPlaylistQueryListener(e, t), this.mediaElementQueryListener(t, e)))); + nn(e, t, this.activeItemListener(this.hls.itemQueue)).pipe(Un(e=>{ + var t = e.message; + return this.logger.error(`Got error in HlsPlayerEvents ${t}`, e), + Ti + } + ), $a(this.destroy$), $s(()=>{} + )).subscribe() + } + activeItemListener(e) { + return e.activeItemById$.pipe(Up(), Ra(e=>{ + e = e.url; + return this.hls.trigger(x.MANIFEST_LOADING, { + url: e + }), + Ti + } + )) + } + rootPlaylistQueryListener(t, e) { + var i = t.enabledMediaOptionByType$(ul.Variant).pipe(an(e=>!!e), Ra(e=>{ + var t; + return this.hls.trigger(x.LEVEL_SWITCHING, e), + null === (t = this.rtc) || void 0 === t || t.handleLevelSwitching(e.url), + Ti + } + )) + , r = t.enabledMediaOptionByType$(ul.Variant).pipe(Ra(i=>bg(i).mediaOptionDetailsEntity$.pipe(an(e=>!0 === (null == e ? void 0 : e.detailsLoading)), Ja(e=>{ + var t = { + url: oe(null == i ? void 0 : i.url), + level: i.mediaOptionId, + type: Cl[i.mediaOptionType] + }; + return this.hls.trigger(x.LEVEL_LOADING, t), + Ti + } + )))) + , n = t.enabledMediaOptionByType$(ul.Variant).pipe(Ra(e=>{ + const t = bg(e); + let i = 0; + return t.mediaOptionDetailsEntity$.pipe(Up(), an(e=>{ + var t = null !== e.stats && !1 === e.detailsLoading && e.lastUpdateMillis > i; + return i = null !== (e = e.lastUpdateMillis) && void 0 !== e ? e : 0, + t + } + )) + } + ), Ra(e=>{ + var t = e.mediaOptionDetails + , i = e.stats + , r = { + mediaOptionId: t.mediaOptionId, + details: t, + playlistType: t.type, + stats: i + }; + if (null === (i = this.rtc) || void 0 === i || i.handleLevelLoaded(t, r.stats), + this.hls.trigger(x.LEVEL_LOADED, r), + 0 === e.unchangedCount) { + const e = { + level: 0, + details: t + }; + this.hls.trigger(x.LEVEL_UPDATED, e) + } + if (null != t && t.daterangeTags) { + const e = { + daterangeTags: t.daterangeTags + }; + this.hls.trigger(x.DATERANGE_UPDATED, e) + } + return Ti + } + )) + , s = t.enableMediaOptionSwitchedForType$(ul.AltAudio).pipe(Ra(e=>{ + e = t.alternateMediaOptionById(ul.AltAudio, e.mediaOptionId); + return e && this.triggerAudioSwitch(e), + Ti + } + )) + , a = t.rootPlaylistEntity$.pipe(an(e=>null !== e.enabledMediaOptionKeys[ul.AltAudio].mediaOptionId), Cs(1), Ra(e=>{ + const t = e.enabledMediaOptionKeys[ul.AltAudio].mediaOptionId; + return t && (e = e.mediaOptionListTuple[ul.AltAudio].mediaOptions.find(e=>e.mediaOptionId === t), + this.triggerAudioSwitch(e)), + Ti + } + )); + return nn(i, s, $l(e.textTracksCreated$, e=>e).pipe(Ra(()=>t.enabledMediaOptionByType$(ul.Subtitle).pipe(Ra(e=>{ + e = t.alternateMediaOptionById(ul.Subtitle, e.mediaOptionId); + return e ? this.hls.trigger(x.SUBTITLE_TRACK_SWITCH, { + track: Object.assign({}, e), + hidden: !1 + }) : this.hls.trigger(x.SUBTITLE_TRACK_SWITCH, { + track: void 0, + hidden: !1 + }), + Ti + } + )))), t.sessionData$.pipe(an(e=>null != e.complete), Cs(1), Ja(e=>{} + ), ur(e=>{ + this.hls.trigger(x.SESSION_DATA_COMPLETE, e) + } + )), t.getPreferredMediaOptionsByType$(ul.Variant).pipe(Oa(1), ur(e=>{ + const t = e; + null === (e = this.rtc) || void 0 === e || e.handleLevelsChanged(t), + t.forEach(e=>{} + ), + this.hls.trigger(x.LEVELS_CHANGED, { + requiresReset: !1, + levels: t + }) + } + )), t.getPreferredMediaOptionsByType$(ul.AltAudio).pipe(ur(e=>{ + this.hls.trigger(x.AUDIO_TRACKS_UPDATED, { + audioTracks: e + }) + } + )), $l(e.textTracksCreated$, e=>e).pipe(Ra(()=>t.getPreferredMediaOptionsByType$(ul.Subtitle).pipe(Cs(1), ur(e=>{ + this.hls.trigger(x.SUBTITLE_TRACKS_UPDATED, { + subtitleTracks: e + }), + this.hls.trigger(x.SUBTITLE_TRACKS_CREATED) + } + )))), n, r, a) + } + mediaElementQueryListener(s, e) { + return nn(s.seekTo$.pipe(ur(e=>{ + var t; + e && ne(e.pos) ? (null === (t = this.rtc) || void 0 === t || t.handleSeek("SEEKING"), + this.hls.trigger(x.SEEKING, { + seekToPos: e.pos + })) : null === e && (null === (e = this.rtc) || void 0 === e || e.handleSeek("SEEKED"), + this.hls.trigger(x.SEEKED)) + } + )), s.desiredRate$.pipe(xa(0), ca(), ur(e=>{ + var t = e[0] + , i = e[1]; + jp(i) ? 0 == this.iframeSwitchStart && (this.iframeSwitchStart = performance.now()) : this.iframeSwitchStart = 0, + this.hls.trigger(x.DESIRED_RATE_CHANGED, { + oldRate: t, + newRate: i + }), + null === (e = this.rtc) || void 0 === e || e.handleDesiredRateChanged(t, i) + } + )), s.sourceBufferEntityByType$(cl.AltAudio).pipe(an(e=>!!e), Es((e,t)=>e.totalBytes === t.totalBytes), ur(e=>{ + this.hls.trigger(x.BUFFER_APPENDED) + } + )), s.sourceBufferEntityByType$(cl.Variant).pipe(an(e=>!!e), Es((e,t)=>e.totalBytes === t.totalBytes), ur(e=>{ + var t; + null === (t = this.rtc) || void 0 === t || t.handleVariantBufferAppended(e.timestampOffset, e.totalBytes), + this.hls.trigger(x.BUFFER_APPENDED) + } + )), s.stallInfo$.pipe(Up(), So(s.combinedBuffer$), ur(([e])=>{ + var t; + null === (t = this.rtc) || void 0 === t || t.handleStalled(e, s.getCombinedBufferInfo(e.currentTime, 0).len), + this.hls.trigger(x.STALLED, e) + } + )), Cr([Bi(e), Zd([s.timeupdate$, s.bufferedSegmentsByType$(cl.Variant)]).pipe(so(1e3), ur(([t,e])=>null == e ? void 0 : e.find(e=>e.startPTS <= t && e.endPTS > t)), an(e=>!!e), xa(null), ca())]).pipe(Ra(([e,[t,i]])=>{ + var r = null == i ? void 0 : i.frag + , t = null == t ? void 0 : t.frag; + if (r && !Fp(t, r) && (this.hls.trigger(x.FRAG_CHANGED, i), + this.hls.inGaplessMode && this.checkAndTriggerReadyForNext(s, i), + !t || r.mediaOptionId !== t.mediaOptionId)) { + const s = e.mediaOptionListQueries[ul.Variant].mediaOptionFromId(r.mediaOptionId); + if (!s) + return this.logger.warn("variantInfo is undefined in fragChangeMonitor"), + Ti; + const n = t ? t.mediaOptionId : "" + , i = r.mediaOptionId; + s.iframes && (performance.now(), + this.iframeSwitchStart), + null === (r = this.rtc) || void 0 === r || r.handleLevelSwitched({ + url: s.url, + mediaOptionId: s.mediaOptionId, + oldVariant: "" !== n ? n : void 0, + newVariant: i + }), + this.hls.trigger(x.LEVEL_SWITCHED, s) + } + return Ti + } + )), s.isBufferedToEnd$(this.hls.config.maxBufferHole, !1).pipe(an(e=>!0 === e), Hi(Zi), ur(e=>{ + if (e && !this.hls.itemQueue.isPreloading() && this.hls.inGaplessMode) { + const i = s.getCombinedBufferInfo(s.currentTime, 0); + var t = 0; + i && (t = i.end, + e = s.mediaElementDuration, + 0 < t && e - s.currentTime < 10 && this.hls.trigger(x.READY_FOR_NEXT_ITEM, { + duration: t + })) + } + } + ))) + } + checkAndTriggerReadyForNext(e, t) { + var i, r; + t && t.frag && (i = e.currentTime, + (r = e.getCombinedBufferInfo(i, 0)) && (i = r.end, + r = e.mediaElementDuration, + e = e.bufferMonitorInfo, + e = Math.max(e.almostDryWaterLevelSeconds, e.lowWaterLevelSeconds / 2), + (r - t.endPTS <= e || t.frag.isLastFragment) && this.hls.inGaplessMode && !this.hls.isPreloading && this.hls.trigger(x.READY_FOR_NEXT_ITEM, { + duration: i + }))) + } + loaderQueryListener(e) { + return nn(e.unresolvedUriLoading$.pipe(ur(e=>e.map(e=>{ + e = { + uri: e.uri, + responseType: e.responseType, + userAgent: e.userAgent + }; + this.hls.trigger(x.UNRESOLVED_URI_LOADING, e) + } + )))) + } + triggerAudioSwitch(e) { + e && this.hls.trigger(x.AUDIO_TRACK_SWITCHED, { + id: e.id + }) + } + triggerManifestLoaded(e) { + e = { + levels: e.rootMediaOptionsTuple[ul.Variant], + audioTracks: e.rootMediaOptionsTuple[ul.AltAudio], + subtitleTracks: e.rootMediaOptionsTuple[ul.Subtitle], + url: e.baseUrl, + audioMediaSelectionGroup: e.audioMediaSelectionGroup, + subtitleMediaSelectionGroup: e.subtitleMediaSelectionGroup, + stats: e.stats, + isMediaPlaylist: e.isMediaPlaylist + }; + this.hls.trigger(x.MANIFEST_LOADED, e) + } + triggerManifestParsed(e) { + var t = { + levels: e.mediaOptionListQueries[ul.Variant].filteredMediaOptionList, + firstLevel: 0, + audio: !1, + video: !0, + altAudio: !1, + audioTracks: e.mediaOptionListQueries[ul.AltAudio].filteredMediaOptionList, + audioMediaSelectionGroup: e.audioMediaSelectionGroup, + subtitleMediaSelectionGroup: e.subtitleMediaSelectionGroup, + stats: e.loadStats + }; + null === (e = this.rtc) || void 0 === e || e.handleManifestParsed(t), + this.hls.trigger(x.MANIFEST_PARSED, t) + } + urlRedactedManifestLoaded(e) { + const t = Object.assign({}, e); + return t.url = oe(t.url), + t.levels = le(t.levels), + t.audioTracks = ue(t.audioTracks), + t.subtitleTracks = ue(t.subtitleTracks), + t + } + urlRedactedManifestParsed(e) { + const t = Object.assign({}, e); + return t.levels = le(t.levels), + t.audioTracks = ue(t.audioTracks), + t + } + } + (w = wm = wm || {}).LowBandwidth = "LowBandwidth", + w.HighBandwidth = "HighBandwidth", + w.PreferredListChanged = "PreferredListChanged", + w.IframeModeChange = "IframeModeChange", + w.None = ""; + const Cg = { + minValidBitrate: 2e6, + maxValidBitrate: 5e6, + maxPreferredBitrate: 3e6, + minValidHeight: 480, + maxValidHeight: 720 + }; + function Dg(e, a, o, d, l, u) { + return e.reduce((e,t)=>{ + if (t.iframes) + return e; + let i = e; + const r = (n = t.score, + s = a && o && d && l && !Mg(t, a, o, d, l, u) ? ll.INVALID : ll.VALID, + new Hp(s,n)); + var n, s; + return (!e || r.isGreaterThan(e.bestRank) || r.isEqualTo(e.bestRank) && t.bandwidth < e.selected.bandwidth) && (i = { + selected: t, + bestRank: r + }), + i + } + , null).selected + } + function Mg(e, t, i, r, n, s) { + var {targetDuration: a, targetStartupMs: o} = i + , d = r["avgPlaylistLoadTimeMs"] + , l = n["avgParseTimeMs"] + , {avgBufferCreateMs: i, avgInitFragAppendMs: r, avgDataFragAppendMs: n} = s + , {avgBandwidth: s, avgLatencyMs: t} = t; + return e.bandwidth <= s && (e.avgBandwidth || e.bandwidth) * a / s * 1e3 + d + i + +(t + l + (r + n)) <= o + } + const Pg = { + name: "abr" + }; + function xg(e, t) { + return ne(e) ? Math.min(e, t) : t + } + function Rg(e) { + return ne(null == e ? void 0 : e.avgBandwidth) + } + function Lg(e, t) { + return e.getCurrentWaterLevelByType(cl.Variant, t) / (0 !== e.playbackRate ? Math.abs(e.playbackRate) : 1) + } + function _g(t, i, e, r) { + if (e) + return t; + let n = -1; + if (t < 0) + return n; + for (let e = t; e < i.length; ++e) { + const t = Fg(i[e], r); + if (t.altAudio && t.subtitle) { + n = e; + break + } + } + return n + } + function Ng(t, e, i, r, n, s, a) { + const o = i.preferredMediaOptions[ul.Variant].filter(e=>e.iframes === t); + if (!o.length) + return { + variantMediaOption: Ol.mediaOptionId, + holdOffDuration: 0, + lowestCandidate: null + }; + let d = 0; + const l = i.nextMinAutoOptionId; + if (l !== Ol.mediaOptionId) { + const t = o.findIndex(e=>e.mediaOptionId === l); + 0 <= t && (d = t) + } + if (d = _g(d, o, t, i), + d < 0) + return { + variantMediaOption: Ol.mediaOptionId, + holdOffDuration: 0, + lowestCandidate: null + }; + let u = o.length - 1; + const c = i.nextMaxAutoOptionId; + if (c !== Ol.mediaOptionId) { + const t = o.findIndex(e=>e.mediaOptionId === c); + 0 <= t && (u = t) + } + var h = i.variantMediaOptionById(r.mediaOptionId) + , p = r.mediaOptionDetails + , f = (null == h ? void 0 : h.iframes) !== t ? 0 : Lg(n, e.maxBufferHole); + let m, g; + if (t) { + const t = e.desiredIframeFPS; + g = p ? p.targetduration / t : 0, + g = Math.max(1 / t, g) + } else + g = p ? p.targetduration : 0; + h = e.abrBandWidthUpFactor, + p = e.abrBandWidthFactor; + return m = Bg(o, g, d, u, f, t, s.getCombinedEstimate(), s.bandwidthStatus, p, h, e, i, r, n, a), + m.variantMediaOption === Ol.mediaOptionId && (m = Bg(o, g, d, u, f + xg(g, e.maxStarvationDelay), t, s.getCombinedEstimate(), s.bandwidthStatus, p, h, e, i, r, n, a), + m.variantMediaOption === Ol.mediaOptionId && 0 <= d && (m.variantMediaOption = o[d].mediaOptionId, + m.alternates = t ? null : Fg(o[d], i))), + m + } + function Fg(e, t) { + var i = t.enabledMediaOptionKeys + , r = i[ul.AltAudio] + , r = kl(r) ? t.mediaOptionListQueries[ul.AltAudio].getMatchingAlternate(r.mediaOptionId, e) : Ol + , i = i[ul.Subtitle]; + return { + altAudio: r, + subtitle: kl(i) ? t.mediaOptionListQueries[ul.Subtitle].getMatchingAlternate(i.mediaOptionId, e) : Ol + } + } + function Bg(i, r, n, e, s, a, o, d, t, l, u, c, h, p, f) { + "bandwidth-history-controller" !== u.abrBandwidthEstimator && f.warn(`Unsupported configuration: ${u.abrBandwidthEstimator} for ABR bandwidth estimator`); + const m = d.bandwidthSampleCount + , g = c.abrStatus + , y = p.maxBufferSize + , v = u.minTargetDurations || 1 + , S = c.mediaOptionListQueries[ul.Variant].mediaOptionListInfo.hasScore; + if (!i.length) + return { + variantMediaOption: Ol.mediaOptionId, + holdOffDuration: -1, + lowestCandidate: null + }; + const b = c.enabledMediaOptionIdByType(ul.Variant) + , T = c.variantMediaOptionById(b) + , E = null != i.find(e=>e.mediaOptionId === b) + , I = T && T.iframes === a + , w = T && I ? T.score : void 0 + , A = T && I ? T.frameRate : void 0 + , O = T && I ? T.height : void 0 + , k = I ? Lg(p, u.maxBufferHole) : 0; + e = Math.max(0, Math.min(i.length - 1, e)), + n = Math.max(0, Math.min(i.length - 1, n)); + var C = h.mediaOptionDetailsEntityRecord + , D = Ug(o.avgBandwidth, l, t, m); + let M; + for (let t = e; t >= n; t--) { + const n = i[t]; + let e = n.mediaOptionId; + const l = n.score + , u = C && C[e] ? C[e].mediaOptionDetails : void 0 + , h = C && C[e] ? C[e].lastUpdateMillis : null + , p = u ? u.totalduration / u.fragments.length : r + , f = null != T && n.bitrate > T.bitrate + , B = null != T && n.bitrate < T.bitrate + , m = !(null != A && (f && n.frameRate < A || B && n.frameRate > A)) + , U = !(f && null != O && O > n.height) + , $ = !(B && (n.bitrate === T.bitrate - 1 || n.bitrate === T.bitrate + 1)) + , V = !(S && f && null != w && (l < w || l === w && T && n.bitrate >= T.bitrate)) + , K = n.iframes === a; + if (ne(p) && K && m && U && $ && V) { + var {adjustedbw: P, bitrate: x, fetchDuration: R, rejectLevelDueToPeakBW: L, canFitMultipleSegments: _, requireAlternates: N, alternates: F} = function(e, t, i, r, n, s, a, o, d, l, u, c) { + var h = n ? a.bwUp : a.bwDown + , n = e.bitrate + , a = t ? t.totalduration / t.fragments.length : o + , s = $g(e, t, o, h, ne(s.avgPlaylistLoadTimeMs) ? s.avgPlaylistLoadTimeMs : s.avgLatencyMs, l) + , l = e.bandwidth + , i = n < h && h < l && i <= 2 * a + , d = r * ((l || n || 0) * ((null == t ? void 0 : t.targetduration) || a)) / 8 <= d; + let p = null; + u = !u; + return u && (p = Fg(e, c), + p.altAudio && p.subtitle || (p = null)), + { + adjustedbw: h, + bitrate: n, + fetchDuration: s, + rejectLevelDueToPeakBW: i, + canFitMultipleSegments: d, + requireAlternates: u, + alternates: p + } + }(n, u, k, v, f, o, D, r, y, h, a, c); + if (N && Boolean(F) && (M = e), + x < P && _ && !L && (!N || Boolean(F)) && (a || !R || R < s)) + return L = P, + N = g, + P = (P = d).instantBw, + (N.fragDownloadSlow || N.fragDownloadTooSlow || ne(P) && P < L) && E && I && k <= 2 * p && f && (e = b), + { + variantMediaOption: e, + holdOffDuration: R, + alternates: F, + lowestCandidate: M + } + } + } + return { + variantMediaOption: Ol.mediaOptionId, + holdOffDuration: -1, + lowestCandidate: M + } + } + function Ug(e, t, i, r) { + let n, s; + return 4 <= r ? (n = e * t, + s = e * i) : n = s = e / 1.8, + { + bwUp: n, + bwDown: s + } + } + function $g(e, t, i, r, n, s) { + let a = e.bitrate * (t ? t.totalduration / t.fragments.length : i) / r; + return null == t || !t.liveOrEvent || t.ptsKnown && !Kg(t.totalduration, n, s) || (a *= 2), + ne(n) && (!ne(s) || null != t && t.liveOrEvent) && (a += n / 1e3), + a + } + function Vg(t, e) { + let i = 1 / 0; + if (t === Ol.mediaOptionId) + return i; + var r = e.find(e=>e.mediaOptionId === t); + if (!r) + return 1 / 0; + const n = r.iframes + , s = r.bitrate + , a = r.frameRate + , o = e.find(e=>e.iframes === n && (void 0 === a || e.frameRate >= a) && e.bitrate > s); + return o && (i = o.bitrate), + i + } + function Kg(e, t, i) { + return t = ne(t) ? t : 0, + !ne(i) || performance.now() - i + t > 1e3 * e + } + function Hg(e, t) { + return (null == e ? void 0 : e.fragDownloadSlow) === (null == t ? void 0 : t.fragDownloadSlow) && e.fragDownloadTooSlow === (null == t ? void 0 : t.fragDownloadTooSlow) + } + function jg(e) { + return "loading" === (null == e ? void 0 : e.state) && ne(null === (e = e.bwSample) || void 0 === e ? void 0 : e.trequest) + } + const qg = 2e3; + function Qg(e, t, i, r) { + let {fragDownloadSlow: n, fragDownloadTooSlow: s} = t; + var a = i.variantMediaOptionById(e.mediaOptionId).bitrate + , t = e.bwSample; + r = r.child(Pg); + i = t.total || Math.max(t.loaded, Math.round(e.duration * a / 8)), + a = performance.now() - t.tfirst, + i = t.loaded * e.duration * 1e3 / i; + return a >= qg && 1e3 <= a - i && (n || r.warn(`flow indicates low bandwidth, after time/duration behind real time: ${a}/${a - i}`), + n = !0), + a >= 1e3 * e.duration && (s || r.warn(`too much time spent downloading fragment, likely to switch down ${a} > ${1e3 * e.duration}`), + s = !0), + { + fragDownloadSlow: n, + fragDownloadTooSlow: s + } + } + function Gg(e, t, i, r, n) { + var s; + const a = n.logger.child(Pg) + , o = r.isIframeRate + , d = i.mediaOptionListQueries[ul.Variant].preferredMediaOptionList + , l = i.enabledMediaOptionKeys[ul.Variant]; + let u = e; + if (u !== wm.None || d.some(e=>e.mediaOptionId === l.mediaOptionId) || (u = wm.PreferredListChanged), + u !== wm.None && !(o && u !== wm.IframeModeChange && r.getBufferedSegmentsByType(cl.Variant).filter(e=>e.frag.iframe).length < t.minFramesBeforeSwitchingLevel)) { + const c = Qf(i.itemId) + , h = bg(l) + , p = [Ol, Ol, Ol] + , f = function(e, t, i, r, n, s, a) { + let o = t.nextMaxAutoOptionId; + if (o === Ol.mediaOptionId || Rg(s.getBandwidthEstimate())) + return d = e, + l = t, + u = r, + e = n, + r = s, + s = a.child({ + name: "abr" + }), + a = e.isIframeRate, + l.enabledMediaOptionIdByType(ul.Variant), + Ng(a, d, l, u, e, r, s); + if (n.isIframeRate) + return { + variantMediaOption: o, + holdOffDuration: 0, + lowestCandidate: null + }; + { + const c = t.variantMediaOptionById(o) + , h = t.enabledAlternateMediaOptionByType(ul.Subtitle) + , n = t.enabledAlternateMediaOptionByType(ul.AltAudio) + , p = null == n ? void 0 : n.persistentID + , f = null == h ? void 0 : h.persistentID + , m = !t.preferHDR + , g = i.getBestMediaOptionTupleFromVariantAndPersistentId(t, c, p, f, void 0, [], m, !1, !1); + return t.isValidMediaOptionTuple(g) ? (o = g[ul.Variant].mediaOptionId, + { + variantMediaOption: o, + holdOffDuration: 0, + alternates: { + altAudio: g[ul.AltAudio], + subtitle: g[ul.Subtitle] + }, + lowestCandidate: null + }) : { + variantMediaOption: t.enabledMediaOptionKeys[ul.Variant].mediaOptionId, + holdOffDuration: 0, + lowestCandidate: null + } + } + var d, l, u + }(t, i, n, h, r, c, a); + if (f.variantMediaOption !== l.mediaOptionId) { + p[ul.Variant] = { + itemId: i.itemId, + mediaOptionId: f.variantMediaOption + }; + for (const e of [ul.AltAudio, ul.Subtitle]) { + const t = i.enabledMediaOptionIdByType(e); + if (t !== Ol.mediaOptionId) { + const r = e === ul.AltAudio ? null === (s = f.alternates) || void 0 === s ? void 0 : s.altAudio : null === (s = f.alternates) || void 0 === s ? void 0 : s.subtitle; + p[e] = r || { + itemId: i.itemId, + mediaOptionId: t + } + } + } + return n.setEnabledMediaOptions(i.itemId, p), + 1 + } + } + } + const Wg = { + name: "iframes" + } + , zg = new pd({},{ + name: "item-queue", + producerFn: vc, + idKey: "itemId", + resettable: !0 + }) + , Xg = new class extends Od { + } + (zg); + class Yg { + constructor() { + this.firstItem = !0, + this.playingEntity = null, + this.loadingEntity = null + } + static createItem(e, t, i, r, n) { + const s = new Date + , a = `${s.getHours()}:${s.getMinutes()}:${s.getSeconds()}`; + qe(); + var o = function(e) { + e = sl.parseURL(e).fragment.substr(1); + if (0 === e.length) + return null; + const t = new URLSearchParams(e); + if (!t.has("t")) + return null; + e = Number(t.get("t")); + return ne(e) ? e : null + }(t); + if (o) + i = o; + else { + const e = ng(); + ne(null == e ? void 0 : e.startPosition) && (i = e.startPosition) + } + return { + itemId: `${e}_${a}`, + name: e, + url: t, + serviceName: n, + createTime: a, + initialSeekTime: i, + itemStartOffset: 0, + platformInfo: r, + config: {} + } + } + get activeItemById$() { + return Xg.selectActiveId().pipe(ur(e=>Xg.getActive())) + } + get removedItems$() { + return Xg.selectEntityAction(To.Remove).pipe(ur(e=>e)) + } + get activeItem() { + return Xg.getActive() + } + get queueItems$() { + return Xg.selectAll().pipe(ur(e=>null != e ? e : [])) + } + get isFirstItem() { + return this.firstItem + } + get playingItem() { + return this.playingEntity + } + get loadingItem() { + return this.loadingEntity + } + addQueueItem(e, t, i, r, n, s) { + Xg.getCount(); + const a = Yg.createItem(e, t, i, r, s); + null != this.playingEntity && (a.initialSeekTime = void 0), + n && (a.itemStartOffset = n, + this.firstItem = !1, + this.playingEntity = this.activeItem, + this.loadingEntity = a), + Co(`queue.add.item: ${e}`), + sd(()=>{ + zg.add(a), + zg.setActive(a.itemId) + } + ) + } + updatePlayingItemId() { + this.playingEntity = this.loadingEntity, + this.loadingEntity = null, + this.clearAllButActive() + } + resetLoadingItem() { + this.removeQueueItem(this.loadingEntity.itemId), + this.loadingEntity = null, + sd(()=>{ + zg.setActive(this.playingEntity.itemId) + } + ) + } + isPreloading() { + return null !== this.playingEntity && null !== this.loadingEntity + } + setQueueItem(t, i, r, n, s) { + Co("queue.set.item"), + this.loadingEntity = null, + sd(()=>{ + zg.reset(); + var e = Yg.createItem(t, i, r, n, s); + zg.add(e), + zg.setActive(e.itemId) + } + ), + this.playingEntity = this.activeItem + } + removeQueueItem(e) { + zg.remove(e) + } + clearQueue() { + zg.reset() + } + clearAllButActive() { + var e; + const t = null === (e = this.activeItem) || void 0 === e ? void 0 : e.itemId; + sd(()=>{ + Xg.getAll().forEach(e=>{ + e.itemId !== t && zg.remove(e.itemId) + } + ) + } + ) + } + set earlyAudioSelection(t) { + zg.updateActive(e=>{ + e.earlySelection || (e.earlySelection = {}), + e.earlySelection.audioPersistentId = t + } + ) + } + get earlyAudioSelection() { + var e; + return null === (e = this.activeItem.earlySelection) || void 0 === e ? void 0 : e.audioPersistentId + } + set earlySubtitleSelection(t) { + zg.updateActive(e=>{ + e.earlySelection || (e.earlySelection = {}), + e.earlySelection.subtitlePersistentId = t + } + ) + } + get earlySubtitleSelection() { + var e; + return null === (e = this.activeItem.earlySelection) || void 0 === e ? void 0 : e.subtitlePersistentId + } + } + function Jg(e, t, i, r, n, s) { + return Gm(e, 0, Vm({ + errorAction: Em.RemoveAlternatePermanently, + errorActionFlags: 0 + }, !1, e.response.code, i, t, s, n), s, n, t, i).pipe(Un(e=>{ + throw !1 === e.fatal && r.resetMediaSource(), + e + } + )) + } + function Zg(e, t) { + if (!e || 0 === e.length) + return 0; + const i = [...e].sort((e,t)=>t[0] - e[0]) + , r = t.getTime() + , n = null !== (t = i.find(([e])=>r >= e)) && void 0 !== t ? t : i[i.length - 1] + , [s,a] = n + , o = a + (r - s) / 1e3; + return Math.max(0, o) + } + function ey(e, t) { + if (e && 0 !== e.length) { + const i = [...e].sort((e,t)=>t[1] - e[1]) + , r = null !== (e = i.find(([,e])=>e <= t)) && void 0 !== e ? e : i[i.length - 1] + , [n,s] = r; + return new Date(n + 1e3 * (t - s)) + } + } + function ty(l, e, u, c, h, p) { + return e.child({ + name: "seek" + }), + e=>e.pipe(Ra((e,t)=>{ + var i, r, n, s, a, o, d = u.mediaQuery.seekTo$.pipe(Up()); + return i = 0 === t, + r = l, + n = h, + s = p, + (null == (t = e) ? Ti : t instanceof Date ? (a = t, + o = s, + n.enabledMediaOptionByType$(ul.Variant).pipe(Ra(e=>o.getQueryForOption(e).mediaOptionDetails$), ur(e=>Zg(e.dateMediaTimePairs, a)), Cs(1))) : function(n, e, s, a, t) { + let i = a.enabledMediaOptionByType$(ul.Variant).pipe(Ra(e=>t.getQueryForOption(e).mediaOptionDetails$), an(e=>ne(null == e ? void 0 : e.totalduration)), Cs(1), ur(e=>{ + var t = !e.liveOrEvent + , i = e.totalduration + , r = a.itemStartOffset; + return t ? ne(n) ? 0 <= n ? n : r + (i + n) : r + (ne(e.startTimeOffset) ? e.startTimeOffset : 0) : !ne(n) || n < 0 || 0 === n && s.liveEdgeForZeroStartPositon ? lg(0, e, s) : n + } + )); + return e && (i = i.pipe(Ja(e=>{} + ))), + i + }(t, i, r, n, s)).pipe($s(()=>{ + null != e && c.setPendingSeek(h.itemId, void 0) + } + ), $a(d)) + } + ), Ja(e=>{ + ne(e) && (u.seekTo = e) + } + )) + } + class iy { + constructor(e, t, i, r, n, s) { + this.logger = e, + this._rootPlaylistService = t, + this._rootQuery = i, + this._mediaQuery = r, + this._iframeMachine = n, + this._anchorMSNs = [NaN, NaN], + this._avDetails = [null, null], + this.logger = e.child({ + name: "fpicker" + }), + this._discoSeqNum = NaN, + this.lookUpTolerance = Math.max(s.maxBufferHole, s.maxFragLookUpTolerance) + } + destroy() { + this._anchorMSNs = [NaN, NaN], + this._avDetails = [null, null], + this._rootQuery = null, + this._mediaQuery = null, + this._rootPlaylistService = null, + this._iframeMachine = null + } + get discoSeqNum() { + return this._discoSeqNum + } + get _discoSeqNum() { + return this._rootQuery.discoSeqNum + } + set _discoSeqNum(e) { + this._rootPlaylistService.setDiscoSeqNum(this._rootQuery.itemId, e) + } + get anchorMSNs() { + return this._anchorMSNs + } + _resolvePosition(e, t, i) { + let r = e; + t = this._avDetails[t]; + if ((null == t ? void 0 : t.mediaOptionId) !== (null == i ? void 0 : i.mediaOptionId) && i.liveOrEvent && !1 === i.ptsKnown) + if (null != (null == t ? void 0 : t.dateMediaTimePairs) && i.dateMediaTimePairs) { + const n = ey(t.dateMediaTimePairs, e); + r = Zg(i.dateMediaTimePairs, n) + } else { + const e = 3 * i.targetduration + , n = i.fragments[0].start + i.totalduration; + r = Math.max(0, n - e) + } + return r + } + _updateAnchorByPosition(e, t) { + let i = NaN; + const r = t[cl.Variant]; + if (r) { + const t = r.fragments + , n = this._resolvePosition(e, cl.Variant, r); + if (i = Bl.ccForTime(t, n), + !ne(i)) { + const r = t[0] + , s = t[t.length - 1] + , a = r.start + , o = s.start + s.duration; + this.logger.warn(`${e.toFixed(3)} out of range [${a.toFixed(3)},${o.toFixed(3)}]`), + e <= a ? i = r.discoSeqNum : e >= o && (i = s.discoSeqNum) + } + } else + this.logger.warn("No variant details for anchoring"); + this._updateAnchor(i, t) + } + _updateAnchor(e, n) { + const s = e !== this._discoSeqNum; + s && (this._discoSeqNum = e), + Ml.forEach(e=>{ + const t = this._avDetails[e] + , i = n[e] + , r = (null == t ? void 0 : t.mediaOptionId) !== (null == i ? void 0 : i.mediaOptionId); + if (s || r) + this._updateAnchorForType(xl(e), i); + else if (i) { + const {mediaOptionId: n, ptsKnown: s, dateMediaTimePairs: t} = i; + this._avDetails[e] = { + mediaOptionId: n, + ptsKnown: s, + dateMediaTimePairs: t + } + } + } + ) + } + getNextFragments(e, i) { + const {position: r, bufferInfoTuple: t, switchContexts: n} = e + , s = t.map((e,t)=>ry(r, i[t], n[t], null == e ? void 0 : e.buffered, this.lookUpTolerance)).reduce((e,t)=>Math.min(t, e), Number.POSITIVE_INFINITY); + return this._updateAnchorByPosition(s, i), + this._getNextFragmentsInternal(e, i) + } + _getNextFragmentsInternal(i, r) { + const n = [null, null]; + r.forEach((e,t)=>{ + n[t] = this._getNextFragmentForType(i, r, t) + } + ); + var e = n[cl.Variant] + , t = n[cl.AltAudio] + , s = null === (a = null == e ? void 0 : e.foundFrag) || void 0 === a ? void 0 : a.mediaFragment + , a = null === (a = null == t ? void 0 : t.foundFrag) || void 0 === a ? void 0 : a.mediaFragment; + if (s && a && (a.start > s.start + s.duration ? (this.logger.warn("Audio too far ahead"), + n[cl.AltAudio] = iy.noopResult) : s.start > a.start + a.duration && !this._mediaQuery.isIframeRate && (this.logger.warn("Video too far ahead"), + n[cl.Variant] = iy.noopResult)), + !isFinite(null == e ? void 0 : e.nextDisco) || null != t && !ne(t.nextDisco)) + return n; + { + const o = n[cl.Variant].nextDisco; + return this._updateAnchor(o, r), + this._getNextFragmentsInternal(i, r) + } + } + _getNextFragmentForType(e, t, i) { + var {position: r, bufferInfoTuple: n, switchContexts: s} = e + , a = t[i] + , o = null !== (l = null === (c = n[i]) || void 0 === c ? void 0 : c.buffered) && void 0 !== l ? l : { + start: r, + end: r, + len: 0 + } + , d = this._mediaQuery.getBufferedSegmentsByType(i) + , l = null !== (c = null === (e = s[i]) || void 0 === e ? void 0 : e.userInitiated) && void 0 !== c && c + , u = ry(r, a, s[i], o, this.lookUpTolerance); + if (!a) + return null; + var {highWaterLevelSeconds: e, lowWaterLevelSeconds: c} = this._mediaQuery.bufferMonitorInfo + , r = o.len; + if (!l && e <= r) + return iy.noopResult; + var e = i === cl.Variant ? cl.AltAudio : cl.Variant + , n = null === (n = n[e]) || void 0 === n ? void 0 : n.buffered + , e = null !== (e = null === (e = s[e]) || void 0 === e ? void 0 : e.userInitiated) && void 0 !== e && e; + let h = !1; + i === cl.Variant && c <= r && 1 < this._mediaQuery.expectedSbCount && null != n && n.end < o.end && (e || n.end - n.start < c) && (h = !0); + let p, f = null, m = NaN; + if (this._mediaQuery.isIframeRate && i === cl.Variant && a.iframesOnly) { + const g = function(e, t, i) { + e = i.nextFragment(a.fragments, (null == e ? void 0 : e.fragments) || [], t, u); + if (!e) + return null; + var {frag: t, newMediaRootTime: e} = e; + return { + foundFrag: { + timelineOffset: t.iframeMediaStart, + mediaFragment: t + }, + nextDisco: NaN, + newMediaRootTime: e + } + }(t[cl.AltAudio], this._mediaQuery.desiredRate, this._iframeMachine); + if (g) { + ({foundFrag: f, nextDisco: m, newMediaRootTime: p} = g); + const i = f.mediaFragment; + i.discoSeqNum !== this._discoSeqNum && this._updateAnchor(i.discoSeqNum, t) + } + } else { + const g = this._anchorMSNs[i]; + ({foundFrag: f, nextDisco: m, newMediaRootTime: p} = fg(u, this._discoSeqNum, g, a, d)) + } + return h && this._rootQuery.getInitPTS(null == f ? void 0 : f.mediaFragment.discoSeqNum) ? iy.noopResult : { + foundFrag: f, + nextDisco: m, + newMediaRootTime: p + } + } + _updateAnchorForType(e, t) { + var i, r, n; + if (!t) + return this._anchorMSNs[e] = NaN, + void (this._avDetails[e] = null); + ne(this._discoSeqNum) ? (n = this._discoSeqNum, + n = null !== (r = null == (n = (r = t.fragments, + i = n, + r.find(e=>e.discoSeqNum === i))) ? void 0 : n.mediaSeqNum) && void 0 !== r ? r : t.startSN, + this._anchorMSNs[e] = n, + {mediaOptionId: r, ptsKnown: n, dateMediaTimePairs: t} = t, + this._avDetails[e] = { + mediaOptionId: r, + ptsKnown: n, + dateMediaTimePairs: t + }) : this.logger.warn("Trying to anchor with non-finite discoSeqNum") + } + } + function ry(e, t, i, r, n) { + r = null != r ? r : { + start: e, + end: e, + len: 0 + }; + i = null !== (i = null == i ? void 0 : i.userInitiated) && void 0 !== i && i, + n = null != t && t.iframesOnly ? 0 : n; + return i || 0 === r.len ? e : r.end + n + } + iy.noopResult = { + foundFrag: null, + nextDisco: NaN + }; + const ny = { + name: "avpipe" + }; + function sy(r) { + const {config: o, rootPlaylistService: d, rootPlaylistQuery: l, mediaSink: e, gaplessInstance: t} = r + , u = e.mediaQuery + , i = Zd(Ml.map(e=>l.enabledMediaOptionSwitchForType$(e).pipe(Ja(e=>{} + )))).pipe(Ra(e=>{ + if (!kl({ + itemId: l.itemId, + mediaOptionId: e[ul.Variant].toId + })) + throw new V(!0,`No valid variant enabled id:${e[ul.Variant].toId}`,$.NoValidAlternates); + e = e.map(({fromId: e, toId: t},i)=>function(t, i, r, n, s) { + var e, a, o; + const {rootPlaylistQuery: d, rootPlaylistService: l, mediaSink: u, mediaParser: c, config: h, iframeMachine: p} = t + , f = u.mediaQuery; + if (!n || !s || n === s) + return Ul; + switch (r) { + case ul.Variant: + { + c.reset(ul.Variant); + const t = xl(r) + , l = d.variantMediaOptionById(n) + , g = d.variantMediaOptionById(s); + if (null == g || null == l) + return Ul; + let e = NaN; + if (l.iframes !== g.iframes || !g.iframes && p.isStarted) { + if (u.toggleTrickPlaybackMode(g.iframes), + !g.iframes && p.isStarted) { + const t = u.mediaQuery.autoPausedRestartTime + , i = t || p.iframeClockTimeSeconds; + u.autoPausedRestartTime = void 0, + e = i, + p.stop() + } + return u.pause(), + u.flushData(t, 0, 1 / 0, !0).pipe(Ja(()=>{ + isFinite(e) && (u.seekTo = e) + } + )) + } + if (!h.allowFastSwitchUp || g.iframes) + return Ul; + var m = bg(l).mediaOptionDetails; + if (null != m && null != g && l.bitrate < g.bitrate) { + const r = m.targetduration + , n = bg(g) + , s = n.mediaOptionDetails + , c = n.mediaOptionDetailsEntity.lastUpdateMillis + , p = f.getCurrentWaterLevelByType(t, h.maxBufferHole) + , y = function(e, t, i, r, n, s, a, o) { + if (n.nextMaxAutoOptionId !== Ol.mediaOptionId && !Rg(s.getBandwidthEstimate())) + return Number.POSITIVE_INFINITY; + a = Ug(s.getBandwidthEstimate().avgBandwidth, a.abrBandWidthUpFactor, a.abrBandWidthFactor, s.bandwidthStatus.bandwidthSampleCount), + s = ne(s.getPlaylistEstimate().avgPlaylistLoadTimeMs) ? s.getPlaylistEstimate().avgPlaylistLoadTimeMs : s.getBandwidthEstimate().avgLatencyMs, + a = t.bitrate > e.bitrate ? a.bwUp : a.bwDown; + return null == i || !i.liveOrEvent || i.ptsKnown && !Kg(i.totalduration, s, o) ? $g(t, i, r, a, s, o) : Number.POSITIVE_INFINITY + }(l, g, s, r, d.abrStatus, i, h, c) + h.maxStarvationDelay + , v = f.currentTime + y + , S = null === (o = null === (a = f.sourceBufferEntityByType(t)) || void 0 === a ? void 0 : a.bufferedSegments) || void 0 === o ? void 0 : o.find(e=>e.startPTS >= v); + let e; + if (S) { + const t = S.endPTS - S.startPTS; + e = S.startPTS + Math.min(Math.max(t - h.maxFragLookUpTolerance, .5 * t), .75 * t) + } + if (ne(e) && p >= y) + return u.flushData(t, e, 1 / 0) + } + } + break; + case ul.AltAudio: + e = d, + m = s, + o = "Nah" === (a = n) ? null : e.alternateMediaOptionById(ul.AltAudio, a), + o = Boolean(o && o.url), + m = "Nah" === a ? null : e.alternateMediaOptionById(ul.AltAudio, m), + m = Boolean(m && m.url), + o && !m && (l.setEnabledMediaOptionSwitchContextByType(d.itemId, ul.AltAudio, s, void 0), + u.resetMediaSource(f.currentTime)), + c.reset(ul.AltAudio) + } + return Ul + }(r, n, i, e, t)); + return Xr(Bi(!0), Jr(e).pipe(Js(!1))) + } + ), Ql.tag("mediaOptionSwitch.audiovideo.out")) + , n = Qf(l.itemId) + , s = r.logger.child(ny) + , a = new iy(s,d,l,u,r.iframeMachine,o); + return Zd([l.anchorTime$.pipe(Ql.tag("anchorTime.audiovideo.in")), i]).pipe(Ra(([i,e])=>e ? Ti : u.needData$(o.maxBufferHole, t.inGaplessMode, t.isPreloading).pipe(ur(e=>{ + var t = [l.enabledMediaOptionSwitchContexts[ul.Variant], l.enabledMediaOptionSwitchContexts[ul.AltAudio]]; + return u.getSourceBufferInfoAction(e, i, t, o.maxBufferHole) + } + ), Ls(e=>{ + if (!e) + return Ti; + e = Bi(e).pipe(ay(r, a), dy(r)); + return hn($l(function(e) { + const {mediaSink: t, rootPlaylistQuery: i, rootPlaylistService: r} = e + , n = t.mediaQuery + , s = e.logger.child(Pg); + return nn((a = i, + o = s, + Zd([n.fellBelowLowWater$, a.getInFlightFragByType$(ul.Variant)]).pipe(Ra(e=>{ + var [,t] = e; + if (!jg(t)) + return Ti; + const i = performance.now() - t.bwSample.trequest + , r = qg - i + , n = 1e3 * t.duration - i + , s = [Ul]; + return 0 < r && s.push(vn(r)), + 0 < n && s.push(vn(n)), + nn(...s).pipe(Js(e)) + } + ), na((e,[t,i])=>{ + const r = Object.assign({}, e); + return t && (r.fragDownloadSlow = !0), + Qg(i, r, a, o) + } + , { + fragDownloadSlow: !1, + fragDownloadTooSlow: !1 + }), xa({ + fragDownloadSlow: !1, + fragDownloadTooSlow: !1 + }), Es(Hg))), function(r) { + const s = r.mediaSink.mediaQuery + , {rootPlaylistQuery: e, config: a} = r; + return s.desiredRate$.pipe(Ra(t=>0 === t ? Ti : Zd([e.getInFlightFragByType$(ul.Variant), e.mediaOptionListQueries[ul.Variant].preferredMediaOptionList$.pipe(ur(e=>e.filter(Nm.bind(null, jp(t)))))])), so(100), Ra(e=>{ + const [t,i] = e; + if (!jg(t) || i.findIndex(e=>e.mediaOptionId === t.mediaOptionId) <= 0) + return Ti; + var r = performance.now() - t.bwSample.trequest + , n = xg(t.duration, a.maxStarvationDelay) + , n = Math.min(1e3 * n, 500 * t.duration / s.playbackRate); + return vn(Math.max(0, n - r), 100).pipe(Js(e)) + } + )).pipe(na((e,[t,i])=>function(t, i, r, e) { + let {fragDownloadSlow: n, fragDownloadTooSlow: s} = t; + const {config: a, rootPlaylistService: o, rootPlaylistQuery: d, mediaSink: l, statsService: u, mediaLibraryService: c} = e + , h = e.logger.child(Pg) + , p = l.mediaQuery; + if (p.paused) + return t; + e = i.bwSample; + if (!ne(e.tfirst)) + return t; + const f = performance.now() + , m = f - e.trequest + , g = xg(i.duration, a.maxStarvationDelay) + , y = ul.Variant + , v = i.mediaOptionId + , S = d.variantMediaOptionById(v) + , b = c.getQueryForOption(S) + , T = S.bitrate + , E = Math.max(1, 8e3 * e.loaded / m) + , I = 8 * ((ne(e.total) ? e.total : Math.max(e.loaded, Math.round(i.duration * T / 8))) - e.loaded) / E + , w = Lg(p, a.maxBufferHole); + let A; + if (ne(w) && 0 < w && !ne(null === (O = p.seekTo) || void 0 === O ? void 0 : O.pos)) + A = w; + else { + const _ = m / 1e3; + A = _ < g ? g - _ : g + } + var O = n; + ({fragDownloadSlow: n, fragDownloadTooSlow: s} = Qg(i, t, d, h)); + t = 2 * ((null === (t = b.mediaOptionDetails) || void 0 === t ? void 0 : t.targetduration) || i.duration); + if (!(w <= t && (I >= A || n))) + return rg().getQuery().extendMaxTTFB && rg().setExtendMaxTTFB(0), + { + fragDownloadSlow: n, + fragDownloadTooSlow: s + }; + O || h.warn(`likely to stall ${se({ + maxTimeToLoadSec: A, + minSwitchDuration: t, + stats: e, + elapsedMs: m, + remainingTimeSec: I, + instantBw: E, + bufferAheadSec: w, + fragDownloadSlow: n + })}`), + n = !0, + rg().getQuery().extendMaxTTFB || rg().setExtendMaxTTFB(6e5); + O = I >= A; + let k; + const C = i.itemId + , D = u.getQueryForItem(C) + , M = D.getCombinedEstimate() + , P = Object.assign(Object.assign({}, M), { + avgBandwidth: E + }) + , x = D.bandwidthStatus + , R = S.iframes + , L = _g(0, r, R, d); + if (L < 0) + return { + fragDownloadSlow: n, + fragDownloadTooSlow: s + }; + t = Math.max(L, r.findIndex(e=>e && e.mediaOptionId === S.mediaOptionId)); + if (O) { + let e = Bg(r, i.duration, L, t, A, R, P, x, 1, 1, a, d, b, p, h); + const N = Ol.mediaOptionId; + k = e.variantMediaOption !== N || (e = Bg(r, i.duration, L, t, I, R, P, x, 1, 1, a, d, b, p, h)).variantMediaOption !== N ? e.variantMediaOption : e.lowestCandidate + } else { + const _ = _g(0, r.slice(L, t).reverse(), R, d) + , i = t - 1 - _; + (0 <= _ || t === L) && (k = r[i].mediaOptionId) + } + if (null != k && k !== d.abrStatus.nextMaxAutoOptionId && o.setNextMaxAutoOptionId(C, k), + O) + throw h.warn(`loading too slow, abort fragment loading and switch to level ${k}`), + u.setBandwidthSample(Object.assign(Object.assign({}, e), { + tfirst: e.tfirst || f, + tload: e.tload || f, + complete: !0, + mediaOptionType: y + })), + s = !0, + new du({ + mediaOptionType: y, + mediaOptionId: v + },k,$.FragmentAbortError); + return { + fragDownloadSlow: n, + fragDownloadTooSlow: s + } + }(e, t, i, r), { + fragDownloadSlow: !1, + fragDownloadTooSlow: !1 + }), xa({ + fragDownloadSlow: !1, + fragDownloadTooSlow: !1 + }), Es(Hg)) + }(e)).pipe(xa({ + fragDownloadSlow: !1, + fragDownloadTooSlow: !1 + }), na((e,t)=>({ + fragDownloadSlow: e.fragDownloadSlow || t.fragDownloadSlow, + fragDownloadTooSlow: e.fragDownloadTooSlow || t.fragDownloadTooSlow + })), Es(Hg), ur(e=>(r.setFragLoadSlow(i.itemId, e), + !1)), Un(e=>{ + if (e instanceof du) { + const e = { + fragDownloadSlow: !0, + fragDownloadTooSlow: !0 + }; + return r.setFragLoadSlow(i.itemId, e), + Bi(!0) + } + return Ui(e) + } + )); + var a, o + }(r), e=>e), e).pipe(Cs(1), $s(()=>{ + Ml.forEach(e=>{ + d.updateInflightFrag(l.itemId, e, null, null, null) + } + ) + } + )) + } + ))), ur(()=>{ + if (!l.getEntity(l.itemId).manualMode) { + let e = wm.None; + var i, r, n, s; + i = bf(), + r = u, + n = o, + s = null == r ? void 0 : r.clientWidth, + a = null == r ? void 0 : r.clientHeight, + r = "object" == typeof window && window.devicePixelRatio ? window.devicePixelRatio : 1, + a = s && a ? { + width: s * r, + height: a * r + } : void 0, + r = (r = (null === (r = i.getQuery()) || void 0 === r ? void 0 : r.viewportInfo) || {}) && a && (r.width !== a.width || r.height !== a.height), + n.useViewportSizeForLevelCap && r && (i.updateViewportInfo(a), + 1) && (e = wm.PreferredListChanged); + let t = !1; + var a = l.enabledVariantMediaOption; + !function(e, t) { + const i = d.logger.child(Pg) + , r = e.abrStatus + , n = r.fragDownloadSlow || r.fragDownloadTooSlow + , s = ne(null === (t = t.seekTo) || void 0 === t ? void 0 : t.pos); + return n && !r.fragDownloadTooSlow && s ? (i.warn("could be ignoring low bandwidth due to seek"), + 0) : n + }(l, u) ? function(e, t) { + const i = Qf(t.itemId) + , r = i.getBandwidthEstimate() + , n = t.abrStatus; + if (Rg(r)) { + var t = (null === (t = i.bandwidthStatus) || void 0 === t ? void 0 : t.bandwidthSampleCount) || 0 + , t = Ug(r.avgBandwidth, e.abrBandWidthUpFactor, e.abrBandWidthFactor, t)["bwUp"]; + return t > n.highBWTrigger + } + }(o, l) && (e = wm.HighBandwidth, + d.setNextMinAutoOptionId(a.itemId, a.mediaOptionId)) : (e = wm.LowBandwidth, + l.nextMaxAutoOptionId === Ol.mediaOptionId && (d.setNextMaxAutoOptionId(a.itemId, a.mediaOptionId), + t = !0)), + Gg(e, o, l, u, d), + t ? d.setNextMaxAutoOptionId(a.itemId, Ol.mediaOptionId) : e === wm.HighBandwidth && d.setNextMinAutoOptionId(a.itemId, Ol.mediaOptionId) + } + } + ), $s(()=>{} + )) + } + const ay = (r,n)=>e=>{ + const {rootPlaylistQuery: t, mediaSink: a} = r + , i = r.logger.child(ny); + return e.pipe(Hi(Zi), So(t.enabledMediaOptionKeys$), Ra(([s,e])=>bn(oy(s, ul.Variant, r, e).pipe(Ja(e=>{ + var e = e.detailsEntity; + if (!e.mediaOptionDetails.liveOrEvent || e.mediaOptionDetails.ptsKnown) { + const t = e.playlistDuration + , i = (null === (e = s.bufferInfoTuple[0]) || void 0 === e ? void 0 : e.buffered.end) || 0 + , r = (null === (e = s.bufferInfoTuple[1]) || void 0 === e ? void 0 : e.buffered.end) || 0 + , n = Math.max(i, r); + a.msDuration = ne(a.msDuration) ? Math.max(a.msDuration, t, n) : t + } + } + )), oy(s, ul.AltAudio, r, e)).pipe(ur(e=>({ + action: s, + detailsAndContext: e + })))), Ra(({action: e, detailsAndContext: t})=>function t(i, r, n, s, l) { + var e; + const {mediaSink: u, iframeMachine: c, rootPlaylistQuery: a} = n + , o = [l[ul.Variant].detailsEntity.mediaOptionDetails, null === (e = null === (e = l[ul.AltAudio]) || void 0 === e ? void 0 : e.detailsEntity) || void 0 === e ? void 0 : e.mediaOptionDetails]; + let d = r.getNextFragments(s, o); + const h = d.reduce((e,t)=>Math.max(e, ne(null == t ? void 0 : t.newMediaRootTime) ? t.newMediaRootTime : -1 / 0), -1 / 0); + return ne(h) && (u.seekTo = h, + d = [null, null]), + d.every(e=>null == (null == e ? void 0 : e.foundFrag)) ? Bi(null) : bn(...d.map((e,d)=>e && null != e.foundFrag ? Ag(n, d, e).pipe(Ja(e=>{ + const t = e[1] + , i = l[d].switchContext; + t.switchPosition = null == i ? void 0 : i.switchPosition; + const r = null !== (e = null == i ? void 0 : i.userInitiated) && void 0 !== e && e + , n = u["mediaQuery"] + , {desiredRate: s, isIframeRate: a} = n + , o = a && c.isStarted && s && s < 0 && s !== c.iframeRate; + (r || o) && (t.flushBeforeAppend = { + start: 0, + end: Number.POSITIVE_INFINITY + }) + } + )) : Bi(null))).pipe(ur(e=>function(g, e, t, i) { + const {rootPlaylistService: r, rootPlaylistQuery: n, mediaSink: s, mediaLibraryService: a, config: y} = e + , v = s.mediaQuery + , o = n.itemId + , d = v.isIframeRate; + let l = n.getInitPTS(t); + if (null == l || !d && l.iframeMode !== d) { + const c = null !== (e = null === (e = i[ul.Variant]) || void 0 === e ? void 0 : e[1].startDtsTs) && void 0 !== e ? e : null; + if (null == c) + return g.warn("updatePTSInfo: Variant data missing."), + null; + const n = null !== (e = null === (e = i[ul.Variant]) || void 0 === e ? void 0 : e[1].timelineOffset) && void 0 !== e ? e : 0 + , s = B(n, c.timescale) + , a = { + baseTime: c.baseTime - s.baseTime, + timescale: c.timescale + }; + r.setInitPTS(o, t, c, n, a, d), + l = { + variantDTS: c, + timelineOffset: n, + offsetTimestamp: a, + iframeMode: d + } + } + i.forEach(e=>{ + e && !ne(e[1].iframeMediaDuration) && a.updatePTSDTS(o, e[1].mediaOptionId, l, e[1]) + } + ); + const S = [null, null]; + if (i[ul.Variant]) { + const [g,c] = i[ul.Variant]; + let e = l.offsetTimestamp; + if (d) { + const g = c.startDtsTs + , i = B(c.timelineOffset, g.timescale); + e = { + baseTime: g.baseTime - i.baseTime, + timescale: g.timescale + } + } + S[cl.Variant] = { + initSeg: g, + dataSeg: c, + offsetTimestamp: e + } + } + if (i[ul.AltAudio]) { + const [g,c] = i[ul.AltAudio]; + S[cl.AltAudio] = { + initSeg: g, + dataSeg: c, + offsetTimestamp: l.offsetTimestamp + } + } + const u = S.map((e,t)=>{ + const i = null == e ? void 0 : e.dataSeg; + if (i) { + const {itemId: r, mediaOptionId: n, mediaSeqNum: s, discoSeqNum: a, startPts: o, endPts: d, duration: l, iframe: u} = i + , c = e["offsetTimestamp"] + , h = b(o, c) + , p = b(d, c) + , f = bg(i) + , m = S[0]; + return m && m.dataSeg.dropped || i.flushBeforeAppend || !((null === (e = null === (e = v.getBufferInfo(h, y.maxBufferHole)[t]) || void 0 === e ? void 0 : e.buffered) || void 0 === e ? void 0 : e.len) >= p - h) ? { + start: h, + duration: u ? l : p - h, + itemId: r, + mediaOptionId: n, + mediaSeqNum: s, + discoSeqNum: a, + targetDuration: f.mediaOptionDetails.targetduration + } : (g.warn(`${Cl[t]} Discarding append due to complete overlap with existing buffer`), + S[t] = null) + } + return null + } + ); + return u.every(e=>!e) ? null : { + appendDataTuple: S, + inFlightFrags: u, + initPTSInfo: l + } + }(i, n, r.discoSeqNum, e)), Ra(e=>{ + if (e) + return Bi(e); + { + const e = function(e, r) { + const n = e.enabledMediaOptionKeys + , s = [null, null] + , a = [null, null]; + return Ml.map(e=>{ + var t; + if (kl(n[e])) { + const i = bg(n[e]).mediaOptionDetailsEntity; + a[e] = null === (t = i.mediaOptionDetails) || void 0 === t ? void 0 : t.ptsKnown, + s[e] = { + detailsEntity: i, + switchContext: null === (e = r[e]) || void 0 === e ? void 0 : e.switchContext + } + } + } + ), + s + }(a, l); + return t(i, r, n, s, e) + } + } + )) + }(i, n, r, e, t)), Ql.tag("mediaProducerEpic.emit")) + } + ; + function oy(e, i, t, r) { + const {rootPlaylistQuery: n, mediaLibraryService: s} = t + , a = r[i]; + if (t.logger.child({ + name: Cl[i] + }), + !a || "Nah" === a.mediaOptionId) + return Bi({ + detailsEntity: null, + switchContext: null + }); + const o = s.getQueryForOption(a); + return Cr([Bi(e), o.mediaOptionDetailsEntity$.pipe(Es((e,t)=>(null == e ? void 0 : e.lastUpdateMillis) === (null == t ? void 0 : t.lastUpdateMillis)))]).pipe(an(([,e])=>{ + if (i === ul.AltAudio && !n.altMediaOptionHasValidUrl(i, a.mediaOptionId)) + return !0; + var t = null == e ? void 0 : e.mediaOptionDetails; + return null != t && (e = null !== (e = e.lastUpdateMillis) && void 0 !== e ? e : 0, + !t.liveOrEvent || !t.ptsKnown || !Kg(null == t ? void 0 : t.totalduration, 0, e)) + } + ), Cs(1), So(n.enabledMediaOptionSwitchContextsByType$(i)), ur(([[,e],t])=>({ + detailsEntity: e, + switchContext: t + }))) + } + const dy = t=>e=>{ + const {rootPlaylistQuery: g, rootPlaylistService: y, mediaSink: v, legibleSystemAdapter: o, statsService: d, rtcService: l} = t; + return e.pipe(Ql.tag("mediaConsumerEpic.in"), Ra(e=>{ + if (!e) + return Bi(!1); + const {appendDataTuple: r, inFlightFrags: m, initPTSInfo: t} = e + , i = t["offsetTimestamp"]; + return m.forEach((e,t)=>{ + e && y.updateInflightFrag(e.itemId, t, e, "appending", null) + } + ), + r.forEach(e=>{ + e && (e = e.dataSeg, + o.addLegibleSamples(i, e.captionData, e.id3Samples, e.endPts)) + } + ), + v.appendData(r, (e,t,i,r,n)=>{ + var s, a, o, d, l, u, c, h, p, f = null !== (f = m[t].targetDuration) && void 0 !== f ? f : 10; + return s = v, + a = e, + o = t, + d = i, + l = f, + u = r, + c = g, + h = y, + p = n, + e=>e.pipe(Ja(()=>{ + h.updateConsecutiveTimeouts(c.itemId, o, !1, "append") + } + ), ya(e=>e.pipe(Kr((e,t)=>{ + var i = e instanceof rf && e.isTimeout; + if (h.updateConsecutiveTimeouts(c.itemId, o, i, "append"), + i) + return function(e, t, i, r, n, s, a, o) { + let d = { + errorAction: Em.SendAlternateToPenaltyBox, + errorActionFlags: 0 + }; + var l = s.getCurrentWaterLevel(i.maxBufferHole) + , u = l < i.almostDryBufferSec; + let c = NaN; + s = i.appendErrorMaxRetry, + i = a.rootPlaylistEntity.errorsByType[r].timeouts.append; + u && s <= i || s <= t ? d.errorAction = Em.SendEndCallback : c = 1e3 * l; + s = { + retryDelayMs: c, + maxNumRetry: s, + maxRetryDelayMs: c + }; + return d = Vm(d, !1, e.response.code, n, r, a, o), + Qm(e, t, s, d, a, o, r, n).pipe() + }(e, t, u, o, d, p, c, h); + if (e instanceof nf) + return function(e, t, i, r, n, s, a, o, d, l) { + var u = t.type + , u = o.getCurrentWaterLevelByType(u, n.maxBufferHole); + if (u >= n.almostDryBufferSec) { + const t = 1e3 * r + , n = { + errorAction: Em.RetryRequest, + errorActionFlags: 0 + }; + return 1e3 * u < t && (l.hasFallbackMediaOptionTuple(d, s, a, !1) ? n.errorAction = Em.SendAlternateToPenaltyBox : n.errorAction = Em.SendEndCallback), + Qm(e, i, { + retryDelayMs: t, + maxNumRetry: 1 / 0, + maxRetryDelayMs: t + }, n, d, l, s, a) + } + return i < n.appendErrorMaxRetry ? t.remove(0, Number.POSITIVE_INFINITY) : (e.fatal = !0, + Ui(e)) + }(e, a, t, l, u, o, d, p, c, h); + if (e instanceof af) { + const {mediaOptionType: a, mediaOptionId: o} = e; + return Jg(e, a, o, s, h, c) + } + throw e + } + )))) + } + , g.highestVideoCodec).pipe(ur(e=>{ + m.forEach((e,t)=>{ + e && y.updateInflightFrag(e.itemId, t, e, "appended", null) + } + ); + var t = e.filter(e=>(null == e ? void 0 : e.fragmentType) === ul.Variant); + t.length && (d.setBufferMetric(t[0]), + null == l || l.handleFragBuffered(t[0])); + e = r[cl.AltAudio]; + if (null !== (t = null == e ? void 0 : e.dataSeg) && void 0 !== t && t.flushBeforeAppend || ne(null === (t = null == e ? void 0 : e.dataSeg) || void 0 === t ? void 0 : t.switchPosition)) { + const {itemId: i, mediaOptionId: r} = e.dataSeg; + y.setEnabledMediaOptionSwitchContextByType(i, ul.AltAudio, r, void 0) + } + return !0 + } + ), (n = v, + s = y, + a = g, + e=>e.pipe(Un(e=>{ + if (e instanceof tf) { + var {mediaOptionType: t, mediaOptionId: i} = e; + return Jg(e, t, i, n, s, a) + } + throw e + } + )))); + var n, s, a + } + )) + } + ; + function ly(e) { + const {logger: r, rootPlaylistService: n, rootPlaylistQuery: t} = e + , s = t.itemId; + return e=>e.pipe(ya(e=>e.pipe(Kr(e=>{ + if (r.error(`Got error in pipeline ${e.message} fatal:${null == e ? void 0 : e.fatal} handled:${null == e ? void 0 : e.handled}`), + !(e instanceof p) || e.fatal) + throw e; + return e.handled ? (t = n, + i = s, + vn(0).pipe(ur(()=>{ + t.updateEnabledMediaOptions(i) + } + ))) : Ti; + var t, i + } + )))) + } + const uy = ()=>e=>e.pipe(Ql.tag("mediaFragmentPipelineEpic.in"), Ra(i=>{ + if (!i) + return Ti; + const {logger: e, config: t, platformService: r, rootPlaylistService: n, rootPlaylistQuery: s, keySystemAdapter: a, mediaSink: o, mediaParser: d, gaplessInstance: l, mediaLibraryService: u} = i + , c = s["itemId"] + , h = o["mediaQuery"] + , p = a.keyStatusChange$.pipe((f = i, + e=>e.pipe(Ra(e=>{ + const {decryptdata: t, status: i, error: r} = e + , n = f["rootPlaylistQuery"]; + if ("needs-renewal" === i) + return Og(f, t, null); + if ("error" !== i || !(r instanceof uu || r instanceof lu) || r.handled) + return Ti; + { + const {rootPlaylistService: e, keySystemAdapter: t} = f; + return Xm(r, 0, null, e, n, t.ksQuery) + } + } + ), Ra(()=>Ti)))); + var f; + const m = r.getQuery() + , g = m.displaySupportsHdr$.pipe(Es(), Ra(e=>(n.setHDRPreference(c, e, !0), + Ti))) + , y = m.viewportInfo$.pipe(Es((e,t)=>e && t && e.width === t.width && e.height === t.height), Ja(e=>{ + t.useViewportSizeForLevelCap && n.setViewportInfo(c, e) + } + ), Ua(Ti)) + , v = Zd([s.hdrMode$.pipe(Es()), s.maxHdcpLevel$.pipe(Es())]).pipe(Ra(([])=>(l.inGaplessMode || 0 !== s.itemStartOffset || (o.resetMediaSource(), + d.reset()), + Ti))) + , S = nn(function(i) { + const {rootPlaylistQuery: t, mediaSink: r} = i + , e = t.enabledMediaOptions$.pipe(Up(), Ja(e=>{ + e = e[ul.AltAudio], + e = kl(e) && null != (null == e ? void 0 : e.url) ? 2 : 1; + r.setExpectedSbCount(e) + } + )) + , n = t.enabledMediaOptionByType$(ul.Variant).pipe(an(e=>kl(e)), Ra(e=>bg(e).mediaOptionDetails$), Cs(1), Ja(e=>{ + r.bufferMonitorTargetDuration = e.targetduration + } + )) + , s = Dl.map(e=>t.enabledMediaOptionByType$(e).pipe(Ql.tag("mediaOptionRetrieve.switch"), Ra(t=>{ + if (!t || !t.url || !kl(t)) + return Ti; + var e = r.mediaQuery.desiredRate$.pipe(ur(e=>0 !== e), Es()); + return Tg(i, t).pipe(Ql.tag("mediaOptionRetrieve.first"), Ua(e), Ra(e=>e ? function e(t, i) { + const r = t.mediaLibraryService; + return function(e) { + if (!e) + return Ti; + var {mediaOptionDetails: t, lastUpdateMillis: i, unchangedCount: e} = e; + if (null == t || !t.liveOrEvent) + return Ti; + if (hg(t, i)) + return vn(0).pipe(Ja(()=>{} + )); + let r = cg(t); + return 0 < e && (r /= 2, + r = Math.max(r, 5e3)), + r -= performance.now() - i, + r += 0, + r = Math.max(1e3, Math.round(r)), + vn(r).pipe(Ja(()=>{} + )) + }(r.getQueryForOption(i).mediaOptionDetailsEntity).pipe(Ra(()=>Tg(t, i, !0)), Ra(()=>e(t, i))) + }(i, t) : Ti)) + } + ))); + return nn(e, n, nn(...s)).pipe(Ua(Ti)) + }(i), sy(i), function(t) { + const {rootPlaylistQuery: i, mediaSink: e} = t; + return $l(e.mediaQuery.mediaElementEntity$, e=>!!e).pipe(Ra(e=>i.anchorTime$.pipe(Up(), Ql.tag("anchorTime.subtitle.in"), (s=>e=>{ + const {rootPlaylistQuery: i, rootPlaylistService: t, legibleSystemAdapter: r} = s + , n = i.enabledAlternateMediaOptionByType(ul.Subtitle); + if (r.gotTracks) + r.selectedTrack = n; + else { + const s = i.preferredMediaOptions[ul.Subtitle]; + r.setTracks(s, n, i.getDisabledMediaOption(ul.Subtitle)) + } + return e.pipe(Ql.tag("subtitleEpic.select.in"), Ra(()=>(r.anchorTimeChanged(), + nn(r.nativeSubtitleTrackChange$.pipe(Ra(e=>(e.mediaOptionId !== r.selectedMediaOption.mediaOptionId && t.setEnabledMediaOptionByType(e.itemId, ul.Subtitle, e), + Ti))), i.enabledMediaOptionByType$(ul.Subtitle).pipe(ur(e=>{ + const t = kl(e) ? i.alternateMediaOptionById(ul.Subtitle, e.mediaOptionId) : e; + return r.selectedMediaOption = t, + t + } + )).pipe(Es((e,t)=>(null == e ? void 0 : e.mediaOptionId) === (null == t ? void 0 : t.mediaOptionId)))))), Ql.tag("subtitleEpic.select.emit")) + } + )(t), (s=>e=>{ + const {mediaSink: t, rootPlaylistQuery: i, legibleSystemAdapter: r, logger: n} = s; + return e.pipe(Ql.tag("subtitleEpic.process.in"), Ra(e=>{ + if (!e || !e.url || !kl(e)) + return Bi([null, null, null]); + return Zd([bg(e).mediaOptionDetails$, i.discoSeqNum$.pipe(an(e=>ne(e)))]).pipe(Ra(([e,t])=>((i,r,e)=>{ + const {legibleSystemAdapter: n, rootPlaylistQuery: t} = i; + return t.initPTS$(e).pipe(Ra(t=>t ? n.findFrags$(r, e).pipe(Ra(e=>r && (null == e ? void 0 : e.foundFrags) ? cy(i, t.offsetTimestamp, e, r) : Ul)) : sn)) + } + )(s, e, t))) + } + ), Ql.tag("subtitleEpic.process.emit")) + } + )(t)))) + }(i), p).pipe(Js(void 0), ly(i)) + , b = h.seekTo$.pipe(ur(e=>null == e ? void 0 : e.pos), an(e=>ne(e)), Es((e,t)=>Math.abs(e - t) < Number.EPSILON), Ra(e=>(n.setAnchorTime(c, e), + Ti))) + , T = h.gotPlaying$.pipe(an(e=>e), Ja(e=>{ + s.mediaOptionListQueries[ul.Variant].filteredMediaOptionList.forEach(e=>{} + ) + } + ), Cs(1), Ua(Ti)); + return nn(s.pendingSeek$.pipe(ty(t, e, o, n, s, u)), function() { + const {config: s, mediaSink: a, rootPlaylistQuery: e, mediaLibraryService: t} = i + , o = i.logger.child({ + name: "live" + }) + , d = a.mediaQuery; + return e.enabledMediaOptionByType$(ul.Variant).pipe(an(kl), Ra(e=>t.getQueryForOption(e).mediaOptionDetailsEntity$.pipe(an(e=>{ + var t; + return (null === (t = null == e ? void 0 : e.mediaOptionDetails) || void 0 === t ? void 0 : t.ptsKnown) && e.mediaOptionDetails.liveOrEvent + } + ), Es((e,t)=>(null == e ? void 0 : e.lastUpdateMillis) === (null == t ? void 0 : t.lastUpdateMillis)))), ur(e=>{ + var t = e.mediaOptionDetails + , i = d.currentTime + , r = d.msDuration; + let n = NaN; + return i < ug(i, t, e.lastUpdateMillis, s.maxBufferHole, d) && (n = lg(t.fragments[0].start, t, s), + n >= r && (o.warn(`seekTo position > duration, updating ${a.msDuration}->${e.playlistDuration}`), + a.msDuration = e.playlistDuration), + a.seekTo = n), + n + } + )) + }(), b, S, g, y, v, function() { + const e = i.mediaSink.mediaQuery; + return Cr([Bi(i), e.desiredRate$.pipe(ca())]).pipe(Ra(([e,[t,i]])=>{ + const {rootPlaylistQuery: s, rootPlaylistService: r, config: a, mediaSink: n, mediaLibraryService: o, statsService: d} = e + , l = n.mediaQuery; + if (jp(t) !== jp(i)) + Gg(wm.IframeModeChange, a, s, l, r); + else if (0 === t && 1 === i && !Ml.every(e=>{ + const t = s.enabledMediaOptionKeys[e] + , i = o.getQueryForOption(t) + , r = d.getQueryForItem(s.itemId) + , n = i.mediaOptionDetailsEntity; + return !(null !== (e = null == n ? void 0 : n.mediaOptionDetails) && void 0 !== e && e.ptsKnown) || l.canContinuePlaybackWithoutGap(n.mediaOptionDetails, n.lastUpdateMillis, r.getPlaylistEstimate(), a.maxBufferHole) + } + )) + return n.pause(), + n.flushAll(0, 1 / 0, !0); + return Ti + } + ), Ua(Ti)) + }(), function(e) { + const s = e.rootPlaylistQuery + , t = e.mediaSink.mediaQuery + , i = s.enabledMediaOptionByType$(ul.Variant); + return Cr([Bi(e), t.desiredRate$.pipe(ca()), i]).pipe(Es((e,t)=>e[1] === t[1]), Ra(([e,[t,i],r])=>{ + t = jp(t), + i = jp(i); + if (t === i) + return Ti; + const n = e["rootPlaylistService"]; + return i ? e.rootPlaylistQuery.nextMaxAutoOptionId === Ol.mediaOptionId && n.setNextMaxAutoOptionId(e.rootPlaylistQuery.itemId, r.mediaOptionId) : n.setNextMaxAutoOptionId(s.itemId, Ol.mediaOptionId), + Ti + } + )) + }(i), T).pipe(Ql.tag("mediaFragmentPiplineEpic.emit"), Js(void 0)) + } + )) + , cy = (r,e,t,i)=>{ + const n = r.legibleSystemAdapter + , s = t.foundFrags; + return Lr(s).pipe(ur(t=>{ + return ((e,t,i)=>{ + const {rootPlaylistQuery: r, legibleSystemAdapter: n} = e; + return Yr(()=>((t,i)=>wg(e, i, !1, !1).pipe(ur(e=>({ + initPTS: t, + data: e, + mediaFragment: i + })), Ql.tag("retrieveSubtitleFragmentCacheEntity.emit")))(t, i).pipe(ur(({initPTS: e, data: t, mediaFragment: i})=>({ + frag: i, + cueRange: function(e, t, i, r, n) { + if (e) + return n.processSubtitleFrag(e, t, i, r) + }(r.enabledAlternateMediaOptionByType(ul.Subtitle), i, e, t, n) + })))) + } + )(r, e, t).pipe((i = e=>n.checkReadyToLoadNextSubtitleFragment$(t, s).pipe(an(e=>e)), + function(e) { + return e.lift(new ms(i)) + } + )); + var i + } + ), Wr(r.config.vttConcurrentLoadCount), Ja(e=>{ + n.reviewParsedFrag(e, t, i) !== Ap.CloseEnough && r.legibleSystemAdapter.tryAgain$.next(!0) + } + )) + } + , hy = (e,t)=>{ + let i, r = ""; + return i = e.videoCodec && e.audioCodec ? (r = `${e.videoCodec}, ${e.audioCodec}`, + t = null != t ? t : "video/mp4", + "audiovideo") : e.videoCodec ? (r = `${e.videoCodec}`, + t = null != t ? t : "video/mp4", + "video") : (r = `${null !== (e = e.audioCodec) && void 0 !== e ? e : ""}`, + t = null != t ? t : "audio/mp4", + "audio"), + { + mimeType: `${t};codecs=${r}`, + codec: r, + container: t, + type: i + } + } + ; + class py { + constructor(e, t, i) { + this.config = e, + this.logger = t, + this.demuxClient = i, + this.typeSupported = { + mp4: MediaSource.isTypeSupported("video/mp4"), + mpeg: MediaSource.isTypeSupported("audio/mpeg"), + mp3: MediaSource.isTypeSupported('audio/mp4; codecs="mp3"'), + ac3: MediaSource.isTypeSupported('audio/mp4; codecs="ac-3"'), + ec3: MediaSource.isTypeSupported('audio/mp4; codecs="ec-3"') + }, + this.demuxers = [], + this.lastInitFrags = [], + this.lastFrags = [] + } + parseInitSegment(h, e) { + return this.getDemuxerInfo(h, this.lastInitFrags, e, this.demuxClient).pipe(Ra(({demuxer: e, contiguous: t, trackSwitch: i, discontinuity: r, accurateTimeOffset: n})=>{ + const s = h["frag"] + , {keyTagInfo: a, start: o, mediaOptionType: d} = s; + if (this.lastInitFrags[d] = s, + h.initSegment) { + const e = We.remuxInitSegment(new Uint8Array(h.initSegment), this.logger, a) + , t = Je.parseInitSegment(e) + , {mimeType: i, type: r, codec: n, container: s} = hy(t); + return Bi({ + moovData: t, + mimeType: i, + track: { + type: r, + codec: n, + initSegment: e, + container: s + } + }) + } + const l = h.segment || h.initSegment + , u = l ? h.initSegment : void 0 + , c = wc(e.observer); + return Bi(c.event(v.FRAG_PARSING_INIT_SEGMENT).pipe(ur(this.handleInitSegmentData)), c.event(P.INTERNAL_ERROR).pipe(Ra(this.handleError)), e.pushWithoutTransfer(l, a, u, o, r, i, t, h.totalDuration, n, void 0, h.iframeMediaStart, h.iframeDuration).pipe(Ua(Ti))).pipe(Wr(), Cs(1)) + } + )) + } + parseSegment(y, e) { + return this.getDemuxerInfo(y, this.lastFrags, e, this.demuxClient).pipe(Ra(({demuxer: e, contiguous: t, trackSwitch: i, discontinuity: r, accurateTimeOffset: n})=>{ + const {frag: h, defaultInitPTS: p} = y + , {keyTagInfo: s, start: a, duration: f, mediaOptionType: m} = h; + let g; + this.lastFrags[m] = h; + const o = wc(e.observer); + return Bi(o.event(v.FRAG_PARSING_INIT_SEGMENT).pipe(Ra(e=>{ + var t; + return e.track.initSegment.byteLength !== (null === (t = y.initSegment) || void 0 === t ? void 0 : t.byteLength) && (g = this.handleInitSegmentData(e)), + Ti + } + )), o.event(v.FRAG_PARSING_DATA).pipe(ur(e=>{ + var {startPTS: t, startDTS: i, firstKeyframePts: r, framesWithoutIDR: n, dropped: s, data1: a, data2: o, captionData: d, id3Samples: l} = e; + let {endPTS: u, endDTS: c} = e; + return null == u && (this.logger.warn(`${Cl[m]} ${Bp(h)}: null endPTS parsed, using duration ${f}`), + u = Object.assign(Object.assign({}, t), { + baseTime: t.baseTime + B(f, t.timescale).baseTime + })), + null == c && (this.logger.warn(`${Cl[m]} ${Bp(h)}: null endDTS parsed, using duration ${f}`), + c = Object.assign(Object.assign({}, i), { + baseTime: i.baseTime + B(f, i.timescale).baseTime + })), + ne(y.iframeMediaStart) || function(e, t, i, r) { + let n = NaN + , s = NaN; + if (ne(i)) + s = i, + n = .01, + isFinite(s) && isFinite(r) && (s += r); + else { + { + const o = void 0 + } + } + var {startPTS: a, startDTS: i, endPTS: r, endDTS: t} = t; + if (!(0 <= a.baseTime && 0 <= i.baseTime && 0 < e.duration && (null == r || 0 < b(r, a)) && (null == t || 0 < b(t, i)) && (!ne(n) || !ne(s) || Math.abs(S(i) - s) <= n))) + throw new D(!1,`Failed demuxer sanity check frag=${Bp(e)} parsed=${JSON.stringify({ + startPTS: a, + endPTS: r, + startDTS: i, + endDTS: t + })} ${se({ + expectedStartDTS: s, + fudge: n + })}`,$.FailedDemuxerSanityCheck) + }(h, e, (p, + y.iframeMediaStart), this.config.audioPrimingDelay), + { + startPTS: t, + endPTS: u, + startDTS: i, + endDTS: c, + firstKeyframePts: r, + framesWithoutIDR: n, + dropped: s, + data1: a, + data2: o, + captionData: d, + id3Samples: l, + parsedInitSegment: g + } + } + )), o.event(P.INTERNAL_ERROR).pipe(Ra(this.handleError)), e.push(y.segment, s, y.initSegment, a, r, i, t, y.totalDuration, n, p, y.iframeMediaStart, y.iframeDuration).pipe(Ua(Ti))).pipe(Wr(), Cs(1)) + } + )) + } + reset(e) { + if (null == e) + return this.demuxers.forEach(e=>{ + e && e.destroy() + } + ), + void (this.demuxers = []); + const t = this.demuxers[e]; + null == t || t.destroy(), + this.demuxers[e] = null + } + destroy(e) { + null != e ? this.reset(e) : this.reset() + } + willBeTrackSwitch(e, t) { + var {mediaOptionType: i, mediaOptionId: e} = e + , i = (t || this.lastFrags)[i]; + return !(i && i.mediaOptionId === e) + } + getDemuxerInfo(e, r, t, i) { + const {frag: n, ptsKnown: s, seeking: a, live: o} = e + , {discoSeqNum: d, mediaSeqNum: l, mediaOptionType: u} = n; + return Yr(()=>{ + var e = this.demuxers[u]; + return e ? Bi(e) : i.init(this.typeSupported, this.config, t).pipe(Ja(e=>this.demuxers[u] = e)) + } + ).pipe(ur(e=>{ + var t = r[u] + , i = this.willBeTrackSwitch(n, r); + return { + demuxer: e, + trackSwitch: i, + discontinuity: !(t && d === t.discoSeqNum), + contiguous: !!t && !i && t.mediaSeqNum + 1 === l, + accurateTimeOffset: !a && (s || !o) + } + } + )) + } + handleInitSegmentData(e) { + var t = e["track"] + , i = t["initSegment"] + , r = Je.parseInitSegment(i) + , {mimeType: n, type: s, codec: a, container: e} = hy(r, t.container); + return { + moovData: r, + mimeType: n, + track: Object.assign(Object.assign({}, t), { + type: s, + codec: a, + initSegment: i, + container: e + }) + } + } + handleError(e) { + return Ui(e) + } + } + function fy(e) { + return Math.min(e.targetduration, 15) + } + function my(e, t, i, r) { + if (200 === t && r && 10 < r.length) { + if (Om.isValidPlaylist(r)) + return !0; + { + const t = new R(o,_,!0,"response doesnt have #EXTM3U tag",$.PlaylistErrorMissingEXTM3U); + throw t.url = e, + t + } + } + return !1 + } + const gy = { + name: "pltfrm" + }; + function yy(e, t) { + t = Ih.getKeySystemSecurityLevel(t); + return null != e && void 0 !== t[e] + } + function vy(e) { + return e.every(e=>e.iframes) + } + function Sy(e, t) { + return !ne(e) || !ne(t) || e <= t + } + function by() { + const n = new Set + , s = new Set; + return e=>{ + const i = (e,t)=>{ + t = t ? "audio" : "video"; + n.has(e) || s.has(e) || (((e,t)=>{ + let i = MediaSource.isTypeSupported(`${e}/mp4;codecs=${t}`); + return "mp4a.40.34" !== t || i || (i = MediaSource.isTypeSupported(`${e}/mpeg`)), + i + } + )(t, e) ? n : s).add(e) + } + , t = (e,t)=>(i(e, t), + s.has(e)); + let r = !1; + return e.audioCodecList && (r = e.audioCodecList.some(e=>t(e, !0))), + !r && e.videoCodecList && (r = e.videoCodecList.some(e=>t(e, !1))), + !r + } + } + function Ty(e, t) { + for (const i in e) + if (e[i].type === t) + return e[i]; + return {} + } + function Ey(e, t, i) { + t.filter(e=>!i.includes(e)).map(e=>e.mediaOptionId) + } + function Iy(e, i, s) { + const a = new Map + , r = new Array; + return e.forEach(t=>{ + var e = Array(); + !function(e, t, i) { + var r = qc.getCapabilities(t.videoCodecList, t.audioCodecList) + , t = JSON.stringify(r); + let n; + a.has(t) ? n = a.get(t) : (n = Ih.requestKeySystemAccess(e, r, void 0, s).pipe(ur(()=>!0), Un(e=>(s.warn(`Request key system error: ${e.message}`), + Bi(!1))), Aa({ + bufferSize: 1, + refCount: !0 + })), + a.set(t, n)), + i.push(n) + }(i, t, e); + e = Jr(e).pipe(ur(e=>{ + if (void 0 === e.find(e=>!1 === e)) + return t + } + )); + r.push(e) + } + ), + Jr(r).pipe(ur(e=>e.filter(e=>Boolean(e)))) + } + function wy(e, r) { + const o = new Set + , d = new Set + , l = !MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.2"; channels="-1"') + , u = l && !MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.2"; channels="2"; features="INVALID"') + , t = e.filter(e=>{ + let t = !1; + var i; + return e.audioCodecList && e.audioGroupId && (i = dm.getRichestChannelLayoutForGroupId(e.audioGroupId, r), + 0 < e.audioCodecList.length && i && (t = ((e,t)=>{ + var i, r, n, s = Se.isDolbyAtmos(e, t); + if (u || l && !s) { + n = `${i = e}/${r = t}`, + o.has(n) || d.has(n) || (((e,t)=>{ + const i = t.split("/") + , r = parseInt(i[0]); + let n, s; + if (1 < i.length) { + const t = i[1].split(",")[0]; + n = `audio/mp4;codecs="${e}";channels="${r}";features="${t}"`, + s = `audio/mp4;codecs="${e}";channels="8";features="${t}"` + } else + n = `audio/mp4;codecs="${e}";channels="${r}"`; + let a = MediaSource.isTypeSupported(n); + return !a && s && (a = MediaSource.isTypeSupported(s)), + a + } + )(i, r) ? o : d).add(n); + const a = `${e}/${t}`; + return d.has(a) + } + return !!s + } + )(dm.getRichestAudioCodec(e.audioCodecList), i))), + !t + } + ); + return Ey(0, e, t), + t + } + function Ay(e, t, d) { + const n = 0 < (null == t ? void 0 : t.length) + , i = e.filter(o=>{ + var e = function() { + if (!d) + return { + highestPlayableAverageBitRate: void 0, + highestPlayablePeakBitRate: void 0, + highestPlayableWidth: void 0, + highestPlayableHeight: void 0, + highestPlayableFrameRate: void 0 + }; + const e = o.videoCodec + , t = o.videoRange + , i = d.videoDynamicRangeFormats + , r = d.videoCodecs + , n = Se.getDynamicRangeType(t, e) + , s = Se.getCompressionType(e) + , a = function(e, t, i, r) { + if (!r && !i) + return {}; + var n, s, t = i ? Ty(i, t) : {}, r = r ? Ty(r, e) : {}; + let a, o; + return o = e === pe.SDR ? (a = t, + r) : (a = r, + t), + n = Object.assign({}, a), + s = o, + Object.keys(s).forEach(e=>{ + n[e] || (n[e] = s[e]) + } + ), + n + }(n, s, r, i); + return s !== fe.VP09 && (a.highestPlayablePeakBitRateForClearContent = void 0), + a + }() + , t = e["highestPlayablePeakBitRateForClearContent"] + , i = o.allowedCPCMap || n + , r = Sy(o.bandwidth, e.highestPlayablePeakBitRate); + return (i || !t ? r : r || Sy(o.bandwidth, t)) && Sy(o.avgBandwidth, e.highestPlayableAverageBitRate) && Sy(o.width, e.highestPlayableWidth) && Sy(o.height, e.highestPlayableHeight) && Sy(o.frameRate, e.highestPlayableFrameRate) + } + ); + return Ey(0, e, i), + i + } + function Oy(e, a, o, d, l, u) { + var r = (null == d ? void 0 : d.maxHdcpLevel) || void 0; + let c = [...e]; + (0 < l.disableVideoCodecList.size || 0 < l.disableAudioCodecList.size) && (c = function(e, t, i) { + let r = e.filter(e=>!e.videoCodec || e.videoCodecList.every(e=>{ + e = $p(e); + return !t.has(e) + } + )); + return r = r.filter(e=>!(!e.iframes && e.audioCodec) || e.audioCodecList.every(e=>{ + e = Kp(e); + return !i.has(e) + } + )), + Ey(0, e, r), + r + }(c, l.disableVideoCodecList, l.disableAudioCodecList)), + r && rm(r) && (c = function(e) { + const t = nm(r) + , i = e.filter(e=>{ + e = e.hdcpLevel; + return !e || nm(e) <= t + } + ); + return Ey(0, e, i), + i + }(c)); + var t = null == d ? void 0 : d.maxSecurityLevel + , e = null == l ? void 0 : l.keySystemPreference; + t && e && yy(t, e) && (c = function(e, t, i) { + function r(e) { + return yy(e, i) ? n[e] : -1 + } + const n = Ih.getKeySystemSecurityLevel(i) + , s = Ih.getKeySystemFormat(i) + , a = r(t) + , o = e.filter(e=>{ + e = null !== (e = null === (e = e.allowedCPCMap) || void 0 === e ? void 0 : e[s]) && void 0 !== e ? e : []; + let t = !0; + for (const i of e) + if (t = r(i) <= a, + !t) + break; + return t + } + ); + return Ey(0, e, o), + [...o] + }(c, t, e)), + c = c.map(t=>{ + var e; + return t.audioCodecList && t.audioGroupId && ((e = null == (e = a.find(e=>e.groupId === t.audioGroupId)) ? void 0 : e.channels) && (t.audioChannelCount = parseInt(e))), + t + } + ); + const h = !(null == l || !l.useMediaKeySystemAccessFilter) && e && navigator && "function" == typeof navigator.requestMediaKeySystemAccess; + return (h ? Iy(c, e, u) : Bi(c)).pipe(Ra(e=>{ + if (0 === e.length || vy(e)) + throw new R(L,f,void 0,"no media option with compatible codecs found in playlist",void 0); + h && Ey(0, c, e); + const t = navigator && navigator.mediaCapabilities + , n = !(null == l || !l.useMediaCapabilities) && t && "function" == typeof t.decodingInfo; + let i; + return i = n ? function(e, n, s) { + const a = [] + , o = by() + , d = function(o) { + const d = new Map + , l = navigator && navigator.mediaCapabilities; + return (i,e,t,n,r)=>{ + const s = { + type: "media-source" + }; + n ? s.video = function(e) { + const t = { + contentType: `video/mp4;codecs=${e}`, + width: i.width, + height: i.height, + bitrate: i.bandwidth || i.avgBandwidth, + framerate: i.iframes ? 8 : i.frameRate + }; + if (i.videoRange) + switch (i.videoRange) { + case "PQ": + Se.isDolby(e) ? (t.hdrMetadataType = Am.DoVi, + t.colorGamut = "rec2020") : (Se.isHEVC(e) || Se.isVP09(e)) && (t.hdrMetadataType = Am.HDR10, + t.colorGamut = "rec2020"), + t.transferFunction = "pq"; + break; + case "HLG": + t.colorGamut = "rec2020", + t.transferFunction = "hlg" + } + return t + }(t) : s.audio = function(e, t, i) { + const r = { + contentType: `audio/mp4;codecs=${e}` + } + , n = dm.getRichestChannelLayoutForGroupId(t.audioGroupId, i); + return n && (r.channels = Se.getChannelCount(n).toString(), + r.spatialRendering = Se.isDolbyAtmos(e, n)), + r + }(t, i, e); + e = JSON.stringify(s); + let a; + return d.has(e) ? a = d.get(e) : (a = Lr(l.decodingInfo(s)).pipe(ur(e=>{ + const t = e.configuration || e.supportedConfiguration + , i = t instanceof Object && (!s.video || null == Object.keys(s.video).find(e=>!(e in t.video))) && (!s.audio || null == Object.keys(s.audio).find(e=>!(e in t.audio))) + , r = e.supported && (!n || e.powerEfficient) && i; + return r || o.warn(gy, `Unsupported config ${e.supported}/${e.powerEfficient}/${i} ${JSON.stringify(s)} supportedConfig=${JSON.stringify(t)}`), + r + } + )), + d.set(e, a)), + [...r, a] + } + }(s); + return e.forEach(t=>{ + var e; + let i = []; + if (null === (e = t.videoCodecList) || void 0 === e || e.forEach(e=>{ + i = d(t, n, e, !0, i) + } + ), + 0 < (null === (e = t.audioCodecList) || void 0 === e ? void 0 : e.length)) { + const s = dm.getRichestAudioCodec(t.audioCodecList); + i = d(t, n, s, !1, i) + } + let r = Bi(t); + 0 < i.length && (r = Jr(i).pipe(ur(e=>null == e.find(e=>!1 === e) ? t : null), Un(e=>(s.warn(gy, `decodingInfo errror: ${e.message}`), + Bi(o(t) ? t : null))))), + a.push(r) + } + ), + Jr(a).pipe(ur(e=>e.filter(e=>Boolean(e)))) + }(e, a, u) : Bi(e = wy((r = e, + s = by(), + s = r.filter(s), + Ey(0, r, s), + e = s), a)), + i.pipe(ur(e=>{ + if (0 === e.length || vy(e)) + throw new R(L,f,void 0,"no media option with compatible codecs found in manifest",void 0); + if (0 === (t = e = Ay(e, o, d), + r = t.filter(e=>!e.iframes || !e.width || !e.height || e.width * e.height <= 2488320), + Ey(0, t, r), + (e = r).length) || vy(e)) + throw new R(L,f,void 0,"no media option with compatible codecs found in manifest",void 0); + var t; + let i = (null == d ? void 0 : d.videoDynamicRangeFormats) || []; + n && 0 === i.length && (i = [{ + type: pe.SDR + }, { + type: pe.HDR + }, { + type: pe.HDR10 + }, { + type: pe.DolbyVision + }, { + type: pe.HLG + }]); + var {hdrMediaOptions: r, sdrMediaOptions: e} = function(e, t) { + const i = t.reduce((e,t)=>{ + switch (t.type) { + case pe.DolbyVision: + e.doViSupported = !0; + break; + case pe.HDR10: + e.hdr10Supported = !0; + break; + case pe.HLG: + e.hlgSupported = !0 + } + return e + } + , { + doViSupported: !1, + hdr10Supported: !1, + hlgSupported: !1 + }) + , {doViSupported: r, hdr10Supported: n, hlgSupported: s} = i; + return e.reduce((e,t)=>{ + var i; + switch (Se.getDynamicRangeType(t.videoRange, null !== (i = t.videoCodec) && void 0 !== i ? i : "")) { + case pe.HDR: + case pe.HDR10: + n && e.hdrMediaOptions.push(t); + break; + case pe.DolbyVision: + r && e.hdrMediaOptions.push(t); + break; + case pe.HLG: + s && e.hdrMediaOptions.push(t); + break; + default: + "SDR" !== t.videoRange && null != t.videoRange || e.sdrMediaOptions.push(t) + } + return e + } + , { + hdrMediaOptions: new Array, + sdrMediaOptions: new Array + }) + }(e, i); + if (0 === r.length && 0 === e.length || vy(r) && vy(e)) + throw new R(L,"manifestIncompatibleVideoRangeError",void 0,"mediaOption with compatible VIDEO-RANGE not found in manifest",void 0); + return { + hdrMediaOptions: r, + sdrMediaOptions: e + } + } + ), Un(e=>{ + throw e instanceof R && (e.fatal = !0, + e.response = $.IncompatibleAsset), + e + } + )); + var r, s + } + )) + } + function ky(e, t) { + return t.mediaOptionId !== e.mediaOptionId && t.persistentID === e.persistentID && t.groupId !== e.groupId + } + (w = Am = Am || {}).HDR10 = "smpteSt2086", + w.DoVi = "smpteSt2094-10", + w.HDR10Plus = "smpteSt2094-40"; + class Cy extends Lm { + constructor(e, t, i) { + super(e, t, i) + } + static makeFilters() { + return Rm() + } + _initFilters() { + return Cy.kAllowFilters + } + get _mediaOptionType() { + return this.mediaOptionType + } + get preferredHost() { + return null + } + get preferredHost$() { + return Bi(null) + } + get mediaOptionListInfo() { + var e; + return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionListTuple[this._mediaOptionType]) && void 0 !== e ? e : null + } + get mediaOptionListInfo$() { + return this.selectEntity(this.itemId, e=>e && e.mediaOptionListTuple ? e.mediaOptionListTuple[this._mediaOptionType] : null).pipe(Up()) + } + getFallbackVariant(t, e, i, r) { + var n; + const s = null === (n = this.mediaOptionList) || void 0 === n ? void 0 : n.find(e=>e.mediaOptionId === t); + if (!s) + return null; + const a = this.filteredMediaOptionList; + if (!a) + return null; + const o = gl(s.url); + if (i) + return null !== (i = a.find(e=>ky(s, e) && !yl(o, e.url))) && void 0 !== i ? i : null; + let d = null; + for (const t of a) + !ky(s, t) || d && !yl(o, t.url) || (d = t); + return d + } + getMatchingAlternateWithPersistentId(t, i, r) { + var e; + return null !== (e = this.preferredMediaOptionList.find(e=>!(0 < (null == r ? void 0 : r.length) && r.includes(e.mediaOptionId)) && (!ne(t) || e.persistentID === t) && (!i || this.matchGroup(e, i.audioGroupId, i.subtitleGroupId, i.closedcaption)))) && void 0 !== e ? e : null + } + matchGroup(e, t, i, r) { + let n = !1; + switch (e.type) { + case "CLOSED-CAPTIONS": + n = !r || e.groupId === r; + break; + case "SUBTITLES": + n = !i || e.groupId === i; + break; + case "AUDIO": + n = !t || e.groupId === t + } + return n + } + getMatchingAlternate(e, t) { + e = this.mediaOptionFromId(e); + return this.getMatchingAlternateWithPersistentId(null == e ? void 0 : e.persistentID, t, []) + } + packageAlternateMediaOption(e, t, i) { + return t.mediaType === pl.CLOSEDCAPTION ? this.augmentClosedCaptionsWithForcedSubtitles(null == e ? void 0 : e.subtitleGroupId, t, i) : t + } + augmentClosedCaptionsWithForcedSubtitles(e, t, i) { + i = this.pairForcedSubtitleMediaOptionWithClosedCaption(e, t, i); + return i ? Object.assign(Object.assign({}, t), { + url: i.url, + backingMediaOptionId: i.mediaOptionId + }) : t + } + pairForcedSubtitleMediaOptionWithClosedCaption(t, i, r) { + let n; + if (i && i.mediaType === pl.CLOSEDCAPTION) { + let e = this.mediaOptionList; + r && (e = this.preferredMediaOptionList), + n = Cy.pairForcedSubtitleMediaOptionWithClosedCaptionInList(t, i, e) + } + return n + } + static pairForcedSubtitleMediaOptionWithClosedCaptionInList(t, i, e) { + return e.find(function(e) { + return e.mediaType === pl.SUBTITLE && e.lang === i.lang && e.forced && e.autoselect && (!t || e.groupId === t) + }) + } + } + Cy.kAllowFilters = Cy.makeFilters(); + class Dy extends Od { + constructor(e, t) { + super(e), + this.itemId = t, + this.mediaOptionListQueries = [new Um(e,this.itemId), new Cy(e,this.itemId,ul.AltAudio), new Cy(e,this.itemId,ul.Subtitle)] + } + get rootPlaylistEntity() { + return this.getEntity(this.itemId) + } + get rootMediaOptionsTuple() { + var e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.mediaOptionListTuple; + return e ? [e[0].mediaOptions, e[1].mediaOptions, e[2].mediaOptions] : [[], [], []] + } + get itemStartOffset() { + var e, t; + return null !== (e = this.rootPlaylistEntity) && void 0 !== e && e.itemStartOffset && ne(null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.itemStartOffset) ? null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.itemStartOffset : 0 + } + get highestVideoCodec() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.highestVideoCodec + } + get baseUrl() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.baseUrl + } + get anchorTime() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.anchorTime + } + get discoSeqNum() { + var e; + return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.discoSeqNum) && void 0 !== e ? e : NaN + } + get discoSeqNum$() { + return this.selectEntity(this.itemId, "discoSeqNum") + } + get audioMediaSelectionGroup() { + var e; + return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.audioMediaSelectionGroup) && void 0 !== e ? e : null + } + get subtitleMediaSelectionGroup() { + var e; + return null !== (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.subtitleMediaSelectionGroup) && void 0 !== e ? e : null + } + get audioMediaSelectionOptions() { + var e; + return null !== (e = null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.audioMediaSelectionGroup) || void 0 === e ? void 0 : e.MediaSelectionGroupOptions) && void 0 !== e ? e : [] + } + get subtitleMediaSelectionOptions() { + var e; + return null !== (e = null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.subtitleMediaSelectionGroup) || void 0 === e ? void 0 : e.MediaSelectionGroupOptions) && void 0 !== e ? e : [] + } + get contentSteeringOption() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.contentSteeringOption + } + get masterVariableList() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.masterVariableList + } + get loadStats() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.loadStats + } + get isMediaPlaylist() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.isMediaPlaylist + } + getInitPTS(e) { + var t; + return null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.initPtsRecord[e] + } + get abrStatus$() { + return this.selectEntity(this.itemId, e=>null == e ? void 0 : e.abrStatus) + } + get abrStatus() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus + } + get nextMaxAutoOptionId() { + var e; + return null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus) || void 0 === e ? void 0 : e.nextMaxAutoOptionId + } + get nextMinAutoOptionId() { + var e; + return null === (e = null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.abrStatus) || void 0 === e ? void 0 : e.nextMinAutoOptionId + } + initPTS$(t) { + return this.selectEntity(this.itemId, ({initPtsRecord: e})=>e[t]) + } + get rootPlaylistEntity$() { + return this.selectEntity(this.itemId).pipe(an(e=>Boolean(e)), ur(e=>e)) + } + get rootPlaylistEntityAdded$() { + return this.selectEntityAction(To.Add).pipe(ur(e=>e.map(e=>this.getEntity(e)))) + } + get rootMediaOptionsTuple$() { + return Zd([this.selectEntity(this.itemId, e=>e.mediaOptionListTuple[0].mediaOptions), this.selectEntity(this.itemId, e=>e.mediaOptionListTuple[1].mediaOptions), this.selectEntity(this.itemId, e=>e.mediaOptionListTuple[2].mediaOptions)]) + } + get sessionData() { + var e; + return null === (e = this.rootPlaylistEntity) || void 0 === e ? void 0 : e.sessionData + } + get sessionData$() { + return this.selectEntity(this.itemId, ({sessionData: e})=>e).pipe(Up()) + } + get anchorTime$() { + return this.selectEntity(this.itemId, "anchorTime").pipe(Ra(e=>ne(e) ? e !== this.anchorTime ? (qe().warn(`anchorTime doesn't match stored value! ${e} !== ${this.anchorTime}`), + Ti) : Bi(e) : Ti)) + } + get pendingSeek$() { + return this.selectEntity(this.itemId, ({pendingSeek: e})=>e).pipe(Es((e,t)=>e === t || "number" == typeof e && "number" == typeof t && isNaN(e) && isNaN(t))) + } + get enabledMediaOptionKeys$() { + return this.selectEntity(this.itemId, "enabledMediaOptionKeys").pipe(an(e=>Boolean(e))) + } + get enabledMediaOptionKeys() { + var e; + return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.enabledMediaOptionKeys) && void 0 !== e ? e : [Ol, Ol, Ol] + } + get enabledMediaOptionSwitchContexts() { + var e; + return null !== (e = null === (e = this.getEntity(this.itemId)) || void 0 === e ? void 0 : e.mediaOptionSwitchContexts) && void 0 !== e ? e : [null, null, null] + } + enabledMediaOptionSwitchContextsByType$(t) { + return this.selectEntity(this.itemId, "mediaOptionSwitchContexts").pipe(ur(e=>null == e ? void 0 : e[t])) + } + get enabledMediaOptions$() { + return Zd([this.enabledMediaOptionByType$(ul.Variant), this.enabledMediaOptionByType$(ul.AltAudio), this.enabledMediaOptionByType$(ul.Subtitle)]) + } + get enabledAVOptions$() { + return Zd([this.enabledMediaOptionByType$(ul.Variant), this.enabledMediaOptionByType$(ul.AltAudio)]) + } + rawEnabledMediaOptionByType$(t) { + return this.enabledMediaOptionKeys$.pipe(ur(e=>{ + const i = e[t]; + return kl(i) && this.rootMediaOptionsTuple[t].find(e=>{ + return t = i, + e.itemId === t.itemId && e.mediaOptionId === t.mediaOptionId; + var t + } + ) || Ol + } + )) + } + enabledMediaOptionByType$(e) { + return this.rawEnabledMediaOptionByType$(e).pipe(Es((e,t)=>e.mediaOptionId === t.mediaOptionId && e.url === t.url)) + } + enabledMediaOptionSwitchForType$(e) { + return this.rawEnabledMediaOptionByType$(e).pipe(So(this.enabledMediaOptionSwitchContextsByType$(e)), xa(null), ca(), ur(([e,t])=>({ + fromId: null == e ? void 0 : e[0].mediaOptionId, + toId: null == t ? void 0 : t[0].mediaOptionId, + switchContext: null == t ? void 0 : t[1] + })), Es((e,t)=>e.fromId === t.fromId && e.toId === t.toId)) + } + enableMediaOptionSwitchedForType$(t) { + return this.enabledMediaOptionByType$(t).pipe(Ra(e=>$l(Cr([Bi(e), this.enabledMediaOptionSwitchContextsByType$(t).pipe(ca())]), ([,e])=>e[0] && !e[1])), ur(([e])=>e)) + } + enabledMediaOptionIdByType(e) { + return this.getEntity(this.itemId).enabledMediaOptionKeys[e].mediaOptionId + } + variantMediaOptionById(e) { + return this.mediaOptionListQueries[ul.Variant].mediaOptionFromId(e) + } + alternateMediaOptionById(e, t) { + return this.mediaOptionListQueries[e].mediaOptionFromId(t) + } + enabledAlternateMediaOptionByType(e) { + var t = this.enabledMediaOptionIdByType(e); + return this.alternateMediaOptionById(e, t) + } + get enabledVariantMediaOption() { + var e = this.enabledMediaOptionIdByType(ul.Variant); + return this.variantMediaOptionById(e) + } + lastLoadedMediaOptionByType(e) { + var t; + return null === (t = this.getEntity(this.itemId).lastLoadedMediaOptionKeys) || void 0 === t ? void 0 : t[e] + } + get nextMediaOptionsKeys$() { + return this.selectEntity(this.itemId, "nextMediaOptionKeys") + } + get preferredMediaOptions() { + return [this.mediaOptionListQueries[0].preferredMediaOptionList, this.mediaOptionListQueries[1].preferredMediaOptionList, this.mediaOptionListQueries[2].preferredMediaOptionList] + } + get preferredMediaOptions$() { + return Zd([this.mediaOptionListQueries[0].preferredMediaOptionList$, this.mediaOptionListQueries[1].preferredMediaOptionList$, this.mediaOptionListQueries[2].preferredMediaOptionList$]) + } + get filteredMediaOptions() { + return [this.mediaOptionListQueries[0].filteredMediaOptionList, this.mediaOptionListQueries[1].filteredMediaOptionList, this.mediaOptionListQueries[2].filteredMediaOptionList] + } + getDisabledMediaOption(e) { + return { + itemId: this.itemId, + mediaOptionType: e, + mediaOptionId: "Nah" + } + } + getEnabledMediaOptionMask() { + return this.enabledMediaOptionKeys.map(e=>kl(e)) + } + getPreferredMediaOptionsByType$(e) { + return this.mediaOptionListQueries[e].preferredMediaOptionList$ + } + altMediaOptionHasValidUrl(e, t) { + t = this.alternateMediaOptionById(e, t); + return Boolean(null == t ? void 0 : t.url) + } + get hdrMode$() { + return this.mediaOptionListQueries[ul.Variant].hdrMode$ + } + get maxHdcpLevel$() { + return this.mediaOptionListQueries[ul.Variant].maxHdcpLevel$ + } + get currentPathwayID() { + return this.mediaOptionListQueries[ul.Variant].currentPathwayID + } + get preferredHost() { + return this.mediaOptionListQueries[ul.Variant].preferredHost + } + getErrorInfoByType(e) { + var t; + return null != (null === (t = this.rootPlaylistEntity) || void 0 === t ? void 0 : t.errorsByType) ? this.rootPlaylistEntity.errorsByType[e] : null + } + getInFlightFragByType(e) { + var t; + return null !== (e = null === (t = null === (t = this.getEntity(this.itemId)) || void 0 === t ? void 0 : t.inFlightFrags) || void 0 === t ? void 0 : t[e]) && void 0 !== e ? e : null + } + getInFlightFragByType$(t) { + return this.selectEntity(this.itemId, e=>{ + return null === (e = null == e ? void 0 : e.inFlightFrags) || void 0 === e ? void 0 : e[t] + } + ) + } + matchAlternates(e, t, i, r) { + t = ne(t) ? this.mediaOptionListQueries[ul.AltAudio].getMatchingAlternateWithPersistentId(t, e, r) : void 0, + r = ne(i) ? this.mediaOptionListQueries[ul.Subtitle].getMatchingAlternateWithPersistentId(i, e, r) : void 0; + return [t || Ol, r || Ol] + } + getLegacyMatchingAlternateWithPersistentId(e, t, i) { + let r = this.mediaOptionListQueries[e].getMatchingAlternateWithPersistentId(t, i, []); + return r = r || this.mediaOptionListQueries[e].getMatchingAlternateWithPersistentId(t, void 0, []), + r + } + isValidMediaOptionTuple(i, e) { + const r = e || this.getEnabledMediaOptionMask(); + return [ul.Variant, ul.AltAudio, ul.Subtitle].reduce((e,t)=>e && r[t] === kl(i[t]), !0) + } + matchGroup(e, t, i, r) { + var n = e.mediaOptionType; + return this.mediaOptionListQueries[n].matchGroup(e, t, i, r) + } + get preferHDR() { + return this.mediaOptionListQueries[ul.Variant].mediaOptionListInfo.preferHDR + } + } + const My = { + name: "rps" + }; + class Py { + constructor(e, t) { + this.store = e, + this.logger = t + } + getQuery() { + return new Od(this.store) + } + getQueryForId(e) { + return new Dy(this.store,e) + } + set rootPlaylistEntity(e) { + Co("root.add.rootPlaylist"), + this.store.add(e) + } + removeItems(e) { + Co(`root.add.remove ${JSON.stringify(e)}`), + this.store.remove(e) + } + removeAll() { + Co("root.add.clear"), + this.store.remove() + } + setRootPlaylistEntity(e, t) { + Co("root.set.rootPlaylistEntity"), + this.store.update(e, e=>t) + } + setSessionData(e, t) { + Co("root.set.sessionData"), + this.store.update(e, e=>{ + e.sessionData = t + } + ) + } + setAnchorTime(e, t) { + Co(`root.set.anchorTime: ${t}`), + this.store.update(e, e=>{ + e.anchorTime = t + } + ) + } + setDiscoSeqNum(e, t) { + Co(`root.set.discoSeqNum: ${t}`), + this.store.update(e, e=>{ + e.discoSeqNum = t + } + ) + } + setPendingSeek(e, t) { + Co("root.set.pendingSeek"), + this.store.update(e, e=>{ + e.pendingSeek = t + } + ), + void 0 === t && rg().setUserSeek(t) + } + setEnabledMediaOptionSwitchContextByType(e, i, r, n) { + this.store.update(e, e=>{ + var t; + if (e.enabledMediaOptionKeys[i].mediaOptionId === r) { + const r = null !== (t = e.mediaOptionSwitchContexts) && void 0 !== t ? t : [null, null, null]; + r[i] = n ? { + userInitiated: n.userInitiated, + switchPosition: n.switchPosition + } : null, + e.mediaOptionSwitchContexts = r + } else + Co(`root.set.mediaOptionSwitchContextByType ${r} doesn't match existing mediaOption ${e.enabledMediaOptionKeys[i].mediaOptionId}`) + } + ) + } + setEnabledMediaOptionByType(r, n, s, a=!1, o) { + s = s || { + itemId: r, + mediaOptionType: n, + mediaOptionId: "Nah" + }, + this.store.update(r, e=>{ + var t; + const i = null !== (t = [...e.enabledMediaOptionKeys]) ? t : [Ol, Ol, Ol]; + if (i[n] = { + itemId: r, + mediaOptionId: s.mediaOptionId + }, + this._updateEnabledMediaOptionKeys(e, i), + a) { + const r = null !== (t = e.mediaOptionSwitchContexts) && void 0 !== t ? t : [null, null, null]; + r[n] = o ? { + userInitiated: o.userInitiated, + switchPosition: o.switchPosition + } : null, + e.mediaOptionSwitchContexts = r + } + } + ) + } + _associateForcedSubtitleWithClosedCaption(e, t, i, r) { + if ((null == i ? void 0 : i.mediaType) === pl.CLOSEDCAPTION) { + t = r.variantMediaOptionById(t), + r = r.mediaOptionListQueries[ul.Subtitle].packageAlternateMediaOption(t, i, !0); + if (r.url !== i.url) { + const n = Fy(t, r, e.mediaOptionListTuple[ul.Subtitle].mediaOptions, qe()); + e.mediaOptionListTuple[ul.Subtitle].mediaOptions = n + } + } + } + _updateEnabledMediaOptionKeys(t, i) { + var e, r; + const n = null !== (e = t.enabledMediaOptionKeys) && void 0 !== e ? e : [Ol, Ol, Ol]; + let s; + for (let e = 0; e < i.length; ++e) { + var a = i[e] + , o = n[e].mediaOptionId !== a.mediaOptionId; + if (o && (n[e] = Object.assign({}, a)), + e === ul.Variant) { + const i = this.getQueryForId(a.itemId).mediaOptionListQueries[e].mediaOptionList; + o ? t.abrStatus = (r = a.mediaOptionId, + o = i, + o = Vg(r, o), + { + fragDownloadSlow: !1, + fragDownloadTooSlow: !1, + nextMinAutoOptionId: Ol.mediaOptionId, + nextMaxAutoOptionId: Ol.mediaOptionId, + highBWTrigger: o + }) : t.abrStatus.highBWTrigger = Vg(a.mediaOptionId, i), + s = a + } else if (e === ul.Subtitle && kl(a)) { + const i = this.getQueryForId(a.itemId) + , n = i.alternateMediaOptionById(e, a.mediaOptionId); + this._associateForcedSubtitleWithClosedCaption(t, s.mediaOptionId, n, i) + } + } + t.enabledMediaOptionKeys = n, + t.nextMediaOptionKeys = void 0 + } + setManualMode(e, t) { + this.store.update(e, e=>{ + e.manualMode = t + } + ) + } + setEnabledMediaOptions(e, i) { + this.store.update(e, e=>{ + var t = i.map(({mediaOptionId: e, itemId: t})=>({ + mediaOptionId: e, + itemId: t + })); + this._updateEnabledMediaOptionKeys(e, t) + } + ) + } + setEnabledMediaOptionsAndSwitchContexts(e, i, r) { + this.store.update(e, e=>{ + var t = i.map(({mediaOptionId: e, itemId: t})=>({ + mediaOptionId: e, + itemId: t + })); + this._updateEnabledMediaOptionKeys(e, t), + e.mediaOptionSwitchContexts = r + } + ) + } + setNextMediaOptions(e, i) { + Co(`root.set.nextMediaOptions: ${JSON.stringify(null == i ? void 0 : i.map(e=>e.mediaOptionId))}`), + this.store.update(e, e=>{ + var t = i ? i.map(({itemId: e, mediaOptionId: t})=>({ + itemId: e, + mediaOptionId: t + })) : null; + e.nextMediaOptionKeys = t + } + ) + } + updateEnabledMediaOptions(e) { + Co("root.set.updateEnabledMediaOptions"), + this.store.update(e, e=>{ + e.nextMediaOptionKeys && !0 !== e.manualMode && (Co(`root.set.updateEnabledMediaOptions ${JSON.stringify(e.nextMediaOptionKeys)}`), + this._updateEnabledMediaOptionKeys(e, [...e.nextMediaOptionKeys])), + e.nextMediaOptionKeys = void 0 + } + ) + } + setLastLoadedMediaOptionByType(r, n, s) { + Co(`root.set.lastLoadedMediaOptionByType: ${n} ${(s = s || { + itemId: r, + mediaOptionType: n, + mediaOptionId: "Nah" + }).mediaOptionId}`), + this.store.update(r, e=>{ + var t; + const i = null !== (t = e.lastLoadedMediaOptionKeys) && void 0 !== t ? t : [Ol, Ol, Ol]; + i[n] = { + itemId: r, + mediaOptionId: s.mediaOptionId + }, + e.lastLoadedMediaOptionKeys = i + } + ) + } + setPreferredHost(e, t) { + Co(`root.set.preferredHost: ${t}`), + this.store.update(e, e=>{ + e && (e.mediaOptionListTuple[ul.Variant].preferredHost = t) + } + ) + } + setViewportInfo(e, t) { + Co(`root.set.viewportInfo: ${JSON.stringify(t)}`), + this.store.update(e, e=>{ + e && (e.mediaOptionListTuple[ul.Variant].viewportInfo = t) + } + ) + } + static getExistingPersistentIds(e) { + var t; + const i = {} + , r = null === (t = e.enabledMediaOptionKeys[ul.AltAudio]) || void 0 === t ? void 0 : t.mediaOptionId; + if ("Nah" !== r) { + const s = e.mediaOptionListTuple[ul.AltAudio] + , t = Pm(s.mediaOptions, Cy.kAllowFilters, s).find(e=>e.mediaOptionId === r); + i.audioPersistentId = null == t ? void 0 : t.persistentID + } + const n = null === (t = e.enabledMediaOptionKeys[ul.Subtitle]) || void 0 === t ? void 0 : t.mediaOptionId; + if ("Nah" !== n) { + const s = e.mediaOptionListTuple[ul.Subtitle] + , t = Pm(s.mediaOptions, Cy.kAllowFilters, s).find(e=>e.mediaOptionId === n); + i.subtitlePersistentId = null == t ? void 0 : t.persistentID + } + return i + } + static doUpdateRootHDRSwitch(e, t, i, r) { + const n = e.mediaOptionListTuple.map(e=>Object.assign({}, e)); + n[ul.Variant].preferHDR = t, + n[ul.Variant].hasHdrLevels = i; + const s = ng() + , a = Xg.getEntity(e.itemId) + , o = Qf(e.itemId) + , d = o.getBandwidthEstimate(s, null == a ? void 0 : a.serviceName) + , l = o.getPlaylistEstimate(s, null == a ? void 0 : a.serviceName) + , u = o.getFragEstimate(s, null == a ? void 0 : a.serviceName) + , c = o.getBufferEstimate(s, null == a ? void 0 : a.serviceName) + , h = { + targetDuration: u.maxDurationSec || (null == s ? void 0 : s.defaultTargetDuration), + targetStartupMs: null == s ? void 0 : s.targetStartupMs + } + , p = Py.getExistingPersistentIds(e); + return By(Object.assign(Object.assign({}, e), { + mediaOptionListTuple: n, + nextMediaOptionKeys: null + }), p, r, d, h, l, u, c) + } + switchToSDROnly(e) { + Co("root.switchToSDROnly"), + this.store.update(e, e=>{ + var t = Py.doUpdateRootHDRSwitch(e, !1, !1, this.logger)["mediaOptionListTuple"]; + e.mediaOptionListTuple = t + } + ) + } + setHDRPreference(e, i, r) { + Co(`root.set.HDRPreference: ${i}`), + this.store.update(e, e=>{ + var t = e.mediaOptionListTuple[ul.Variant]; + if (t.preferHDR !== i && (!i || t.hasHdrLevels)) { + t = Py.doUpdateRootHDRSwitch(e, i, t.hasHdrLevels, this.logger); + if (r) + return t; + e.mediaOptionListTuple = t.mediaOptionListTuple + } + } + ) + } + setPathwayPriority(e, i) { + Co(`root.set.PathwayPriority: [ ${i.join(", ")} ]`), + this.store.update(e, e=>{ + if (e) { + const t = e.mediaOptionListTuple[ul.Variant]; + t.pathwayPriority = i, + t.preferredHost = null + } + } + ) + } + setCurrentPathwayID(e, t) { + Co(`root.set.currentPathwayID: ${t}`), + this.store.update(e, e=>{ + e && (e.mediaOptionListTuple[ul.Variant].currentPathwayID = t) + } + ) + } + setInitPTS(e, t, i, r, n, s) { + Co(`root.set.initPTS: ${e} ${t} variantDTS:${JSON.stringify(i)} timelineOffset: ${r}`), + this.store.update(e, e=>{ + e.initPtsRecord[t] = { + variantDTS: i, + timelineOffset: r, + offsetTimestamp: n, + iframeMode: s + } + } + ) + } + static prunePenaltyBox(e, t) { + return e.filter(e=>!(e.expiry <= t)) + } + static addToPenaltyBox(e, t, i) { + return e.push({ + mediaOptionId: i, + expiry: t + 12e4 + }) + } + addToPenaltyBox(e, r, n) { + Co(`root.set.penaltyBox: ${r}: ${n}`), + this.store.update(e, ({mediaOptionListTuple: e})=>{ + const t = e[r] + , i = performance.now(); + t.penaltyBoxQueue = Py.prunePenaltyBox(t.penaltyBoxQueue, i), + Py.addToPenaltyBox(t.penaltyBoxQueue, i, n) + } + ) + } + prunePenaltyBox(e, r=null) { + Co(`root.set.prunePenaltyBox: ${r}`), + this.store.update(e, ({mediaOptionListTuple: e})=>{ + var e = r ? [e[r]] : e + , t = performance.now(); + for (const i of e) + i.penaltyBoxQueue = Py.prunePenaltyBox(i.penaltyBoxQueue, t) + } + ) + } + removePermanently(e, r, n) { + Co(`root.set.removePermanently: ${r}: ${n}`), + this.store.update(e, ({mediaOptionListTuple: e})=>{ + const t = e[r] + , i = new Set(t.removed); + i.add(n), + t.removed = Array.from(i) + } + ) + } + moveAllWithMatchingHosts(e, r, n, s) { + Co(`root.set.moveAllMatchingHosts: ${r}:${n} remove:${s}`), + this.store.update(e, ({mediaOptionListTuple: e})=>{ + const t = e[r] + , i = [...t.mediaOptions].filter(e=>yl(n, e.url)).map(e=>e.mediaOptionId); + if (s) { + const e = new Set([...t.removed, ...i]); + t.removed = Array.from(e) + } else { + const e = performance.now(); + t.penaltyBoxQueue = Py.prunePenaltyBox(t.penaltyBoxQueue, e); + for (const r of i) + Py.addToPenaltyBox(t.penaltyBoxQueue, e, r) + } + } + ) + } + setMaxHdcpLevel(e, i, r=!1) { + Co(`root.set.maxHdcpLevel: ${i}`), + this.store.update(e, ({mediaOptionListTuple: e})=>{ + const t = e[ul.Variant]; + (r || nm(i) < nm(t.maxHdcpLevel)) && (t.maxHdcpLevel = i) + } + ) + } + updateConsecutiveTimeouts(e, i, r, n) { + this.store.update(e, e=>{ + const t = e.errorsByType || [{ + timeouts: { + load: 0, + append: 0, + key: 0 + } + }, { + timeouts: { + load: 0, + append: 0, + key: 0 + } + }, { + timeouts: { + load: 0, + append: 0, + key: 0 + } + }]; + r ? ++t[i].timeouts[n] : t[i].timeouts[n] = 0, + e.errorsByType = t + } + ) + } + updateInflightFrag(d, l, u, c, h) { + Co("root.set.updateInflightFrag"), + this.store.update(d, r=>{ + if (r.inFlightFrags || (r.inFlightFrags = [null, null]), + !(l === ul.Subtitle || u && u.itemId !== d)) + if (u) { + let {start: e, duration: t} = u; + var {mediaOptionId: n, mediaSeqNum: s, discoSeqNum: a} = u + , o = r.inFlightFrags[l]; + let i = null == o ? void 0 : o.tstart; + c !== (null == o ? void 0 : o.state) && (i = performance.now()), + Fp(o, u) && (e = o.start, + t = o.duration), + r.inFlightFrags[l] = { + itemId: d, + mediaOptionId: n, + mediaSeqNum: s, + discoSeqNum: a, + start: e, + duration: t, + tstart: i, + state: c, + bwSample: Object.assign({}, h) + } + } else + r.inFlightFrags[l] = null + } + ) + } + setNextMaxAutoOptionId(e, t) { + Co(`root.set.nextMaxAutoOptionId: ${t}`), + this.store.update(e, ({abrStatus: e})=>{ + e.nextMaxAutoOptionId = t + } + ) + } + setNextMinAutoOptionId(e, t) { + Co(`root.set.nextMinAutoOptionId: ${t}`), + this.store.update(e, ({abrStatus: e})=>{ + e.nextMinAutoOptionId = t + } + ) + } + setHighBWTrigger(e, t) { + Co(`root.set.setHighBWTrigger: ${t}`), + this.store.update(e, ({abrStatus: e})=>{ + e.highBWTrigger = t + } + ) + } + setFragLoadSlow(e, t) { + Co(`root.set.setFragLoadSlow ${e} ${JSON.stringify(t)}`), + this.store.update(e, ({abrStatus: e})=>{ + e.fragDownloadSlow = t.fragDownloadSlow, + e.fragDownloadTooSlow = t.fragDownloadTooSlow + } + ) + } + pickMediaOptionTupleByPersistentId(e, t, i, r=!1, n=!1) { + var s = e.enabledMediaOptionIdByType(ul.Variant) + , s = e.variantMediaOptionById(s); + let a, o; + if (t === ul.AltAudio) { + const t = e.enabledAlternateMediaOptionByType(ul.Subtitle); + o = null == t ? void 0 : t.persistentID, + a = i + } else { + const t = e.enabledAlternateMediaOptionByType(ul.AltAudio); + a = null == t ? void 0 : t.persistentID, + o = i + } + const d = e.getEnabledMediaOptionMask(); + return d[t] = !!(ne(i) && 0 <= i), + s ? this.getBestMediaOptionTupleFromVariantAndPersistentId(e, s, a, o, d, void 0, r, n, !1) : [Ol, Ol, Ol] + } + getFallbackMediaOptionTupleFromMediaOptionId(e, t, i, r, n=!1, s=!1, a=!1) { + var o = r ? [r] : [i] + , d = e.enabledMediaOptionIdByType(ul.Variant) + , r = e.variantMediaOptionById(d) + , d = t === ul.AltAudio ? e.alternateMediaOptionById(ul.AltAudio, i) : e.enabledAlternateMediaOptionByType(ul.AltAudio) + , d = null == d ? void 0 : d.persistentID + , i = t === ul.Subtitle ? e.alternateMediaOptionById(ul.Subtitle, i) : e.enabledAlternateMediaOptionByType(ul.Subtitle) + , i = null == i ? void 0 : i.persistentID; + return r ? this.getBestMediaOptionTupleFromVariantAndPersistentId(e, r, d, i, void 0, o, n, s, a) : [Ol, Ol, Ol] + } + hasFallbackMediaOptionTuple(e, t, i, r) { + var n = e.mediaOptionListQueries[t].mediaOptionFromId(i); + return e.isValidMediaOptionTuple(this.getFallbackMediaOptionTupleFromMediaOptionId(e, t, i, n.backingMediaOptionId, !1, r)) + } + setLegacyAlternateMediaOption(e, t, i, r, n) { + var s = e.enabledMediaOptionIdByType(ul.Variant) + , s = e.variantMediaOptionById(s) + , s = e.getLegacyMatchingAlternateWithPersistentId(i, r, s); + s ? this.setEnabledMediaOptionByType(t, i, s, !0, n) : this.logger.warn(`${Cl[i]} can't find matching mediaOption for persistent id ${r}`) + } + setEnabledMediaOptionTupleWithMatchedGroups(t, i, e, r) { + const n = Ly(t) + , s = this.pickMediaOptionTupleByPersistentId(n, i, e); + if (!n.isValidMediaOptionTuple(s)) + return this.setLegacyAlternateMediaOption(n, t, i, e, r); + sd(()=>{ + this.setEnabledMediaOptionByType(t, i, s[i], !0, r), + s[ul.Variant].mediaOptionId !== n.enabledMediaOptionIdByType(ul.Variant) && this.setPreferredHost(t, gl(s[ul.Variant].url)), + this.setEnabledMediaOptionByType(t, ul.Variant, s[ul.Variant]); + var e = i === ul.AltAudio ? ul.Subtitle : ul.AltAudio; + s[e].mediaOptionId !== n.enabledMediaOptionIdByType(e) && this.setEnabledMediaOptionByType(t, e, s[e], !1) + } + ) + } + canSwitchToSDR(e, t, i, r=!1) { + var n = e.mediaOptionListQueries[ul.Variant].mediaOptionFromId(t) + , r = this.getFallbackMediaOptionTupleFromMediaOptionId(e, ul.Variant, t, n.backingMediaOptionId, !0, i, r); + return e.isValidMediaOptionTuple(r) + } + getBestMediaOptionTupleFromVariantAndPersistentId(t, e, i, r, n, s, a, o, d) { + var l, u = t.mediaOptionListQueries[ul.Variant].listFallbackVariants(e.mediaOptionId, a, o, d, s); + let c = [Ol, Ol, Ol]; + for (let e = 0; e < u.length; ++e) { + const a = u[e]; + if (l = t.matchAlternates(a, i, r, s), + t.isValidMediaOptionTuple([a, ...l], n)) { + c = [a, ...l]; + break + } + } + return c + } + } + const xy = new class extends pd { + constructor() { + super({}, { + name: "root-playlist-store", + idKey: "itemId", + producerFn: vc + }) + } + akitaPreAddEntity(e) { + return null == e.errorsByType ? Object.assign(Object.assign({}, e), { + errorsByType: [{ + timeouts: { + load: 0, + append: 0, + key: 0 + } + }, { + timeouts: { + load: 0, + append: 0, + key: 0 + } + }, { + timeouts: { + load: 0, + append: 0, + key: 0 + } + }] + }) : e + } + } + ; + new Od(xy); + let Ry = null; + function Ly(e) { + return new Dy(xy,e) + } + const _y = (n,e,t,s,i)=>{ + const {rootMediaOptionsTuple: r, sessionKeys: a} = n + , o = Array.from(r[ul.Variant]) + , d = Array.from(r[ul.AltAudio]); + let l = !1 + , u = !1 + , c = o.map(e=>(l = l || Boolean(e.videoCodec), + u = u || Boolean(e.audioCodec) || Boolean(e.audioGroupId), + e)); + return l && u && (c = c.filter(({videoCodec: e})=>Boolean(e))), + Oy(o, d, a, e, t, i).pipe(ur(({hdrMediaOptions: e, sdrMediaOptions: t})=>{ + var i = e.concat(t) + , r = 0 < e.length; + return e.concat(t), + function(e, t, i, r) { + var {itemId: n, itemStartOffset: s, rootMediaOptionsTuple: a, audioMediaSelectionGroup: o, subtitleMediaSelectionGroup: d} = e + , l = Array.from(a[ul.AltAudio]) + , u = Array.from(a[ul.Subtitle]) + , c = t.every(e=>ne(e.score)) + , h = t.some(e=>Nm(!0, e)) + , p = function(e, t) { + const i = [...e]; + return t ? i.sort((e,t)=>e.score - t.score || t.bitrate - e.bitrate) : i.sort((e,t)=>e.bitrate - t.bitrate), + i + }(t, c) + , f = e.baseUrl + , t = null === (a = e.contentSteeringOption) || void 0 === a ? void 0 : a.initPathwayID + , a = e.sessionData; + return { + itemId: n, + baseUrl: f, + mediaOptionListTuple: [{ + mediaOptions: p, + hasHdrLevels: i, + hasIframeLevels: h, + hasScore: c, + preferHDR: r, + compatibleIds: null, + penaltyBoxQueue: [], + removed: [], + currentPathwayID: t + }, { + mediaOptions: l, + compatibleIds: null, + penaltyBoxQueue: [], + removed: [] + }, { + mediaOptions: u, + penaltyBoxQueue: [], + removed: [] + }], + audioMediaSelectionGroup: o, + subtitleMediaSelectionGroup: d, + enabledMediaOptionKeys: [Ol, Ol, Ol], + mediaOptionSwitchContexts: [null, null, null], + anchorTime: 0, + discoSeqNum: NaN, + pendingSeek: void 0, + itemStartOffset: s, + initPtsRecord: {}, + contentSteeringOption: e.contentSteeringOption, + masterVariableList: e.masterVariableList, + loadStats: e.stats, + isMediaPlaylist: e.isMediaPlaylist, + abrStatus: { + fragDownloadSlow: !1, + fragDownloadTooSlow: !1, + nextMinAutoOptionId: Ol.mediaOptionId, + nextMaxAutoOptionId: Ol.mediaOptionId, + highBWTrigger: NaN + }, + sessionData: a + } + }(n, i, r, s) + } + )) + } + ; + function Ny(e, t, i, r, n, s, a) { + var o, d, l, u, c, h, p, f = e.mediaOptionListTuple[ul.Variant], m = Pm(f.mediaOptions, Um.kAllowFilters, Object.assign(Object.assign({}, f), { + compatibleIds: null + })), g = xm(f.preferredHost, m); + return { + firstVariant: (o = g, + e = Cg, + f = f.hasScore, + t = t, + i = i, + r = r, + n = n, + s = s, + a = a, + !o || o.length < 1 || o.every(e=>e.iframes) ? void t.warn("no non-iframe media option found") : ((o = f ? Dg(o, i, r, n, s, a) : (d = e, + l = i, + u = r, + c = n, + h = s, + p = a, + o.reduce((e,t)=>{ + if (t.iframes) + return e; + let i = e; + const r = function(e, t, i, r, n, s, a) { + var o, d, l = (o = e.bitrate, + u = e.height, + (d = (e,t,i)=>(e - t) * (e - i) <= 0)(o, t.minValidBitrate, t.maxValidBitrate) && d(u, t.minValidHeight, t.maxValidHeight) ? ll.VALID : ll.INVALID), o = "PQ" === (c = e.videoRange) ? ol.PQ : "HLG" === c ? ol.HLG : "SDR" === c ? ol.SDR : ol.UNKNOWN, {videoCodecRank: u, audioCodecRank: c} = { + videoCodecRank: $p((d = e).videoCodec), + audioCodecRank: Kp(d.audioCodec) + }, d = e.bitrate < t.maxPreferredBitrate ? ll.VALID : ll.INVALID, t = e.audioChannelCount || 1, a = i && r && n && s && !Mg(e, i, r, n, s, a) ? ll.INVALID : ll.VALID; + return new Hp(l,o,u,t,c,a,d,e.height) + }(t, d, l, u, c, h, p); + return (!e || r.isGreaterThan(e.bestRank) || r.isEqualTo(e.bestRank) && t.bitrate > e.selected.bitrate) && (i = { + selected: t, + bestRank: r + }), + i + } + , null).selected)) || t.warn("no valid first media option found"), + o)), + filteredVariants: m, + preferredVariants: g + } + } + function Fy(e, t, i) { + if ((null == t ? void 0 : t.mediaType) === pl.CLOSEDCAPTION) { + const r = Cy.pairForcedSubtitleMediaOptionWithClosedCaptionInList(e.subtitleGroupId, t, i); + if (r) + return t = Object.assign(Object.assign({}, t), { + url: r.url, + backingMediaOptionId: r.mediaOptionId + }), + i.map(e=>e.mediaOptionId === t.mediaOptionId ? t : e) + } + return i + } + function By(e, t, i, r, n, s, a, o) { + var d; + const l = e.itemId + , u = e.mediaOptionListTuple[ul.Variant] + , c = e.mediaOptionListTuple[ul.AltAudio] + , h = e.mediaOptionListTuple[ul.Subtitle] + , p = Pm(c.mediaOptions, Cy.kAllowFilters, c) + , f = Pm(h.mediaOptions, Cy.kAllowFilters, h); + let {firstVariant: m, filteredVariants: g} = Ny(e, i, r, n, s, a, o); + if (!m) { + const U = u.preferHDR; + u.preferHDR = !U && u.hasHdrLevels, + u.preferHDR !== U && (i.warn(`No valid first variant found, toggling hdr preference=${U}->${u.preferHDR}`), + {firstVariant: m, filteredVariants: g} = Ny(e, i, r, n, s, a, o)) + } + if (!m) + throw new V(!0,"No valid first variant found",$.NoValidAlternates); + const y = gl(m.url) + , v = { + itemId: l, + mediaOptionId: null !== (o = null == m ? void 0 : m.mediaOptionId) && void 0 !== o ? o : null + } + , S = null != p && p.length ? null === (o = ((i,r,e,n)=>{ + if (e) { + let t; + return t = ne(i) ? e.MediaSelectionGroupOptions.find(function(e) { + return e.MediaSelectionOptionsPersistentID === i + }) : e.MediaSelectionGroupOptions.find(function(e) { + return e.MediaSelectionOptionsIsDefault + }), + t = t || e.MediaSelectionGroupOptions[0], + n.find(e=>(!r || e.groupId === r) && e.persistentID === (null == t ? void 0 : t.MediaSelectionOptionsPersistentID)) + } + } + )(null == t ? void 0 : t.audioPersistentId, m.audioGroupId, e.audioMediaSelectionGroup, p)) || void 0 === o ? void 0 : o.mediaOptionId : null + , b = S ? { + itemId: l, + mediaOptionId: S + } : Ol + , T = ((i,r,n,s,a,o)=>{ + if (s) { + let t, e; + return t = ne(i) ? s.MediaSelectionGroupOptions.find(function(e) { + return e.MediaSelectionOptionsPersistentID === i + }) : s.MediaSelectionGroupOptions.find(function(e) { + return e.MediaSelectionOptionsIsDefault + }), + t && (e = a.find(e=>e.mediaType === pl.CLOSEDCAPTION ? (!r || e.groupId === r) && e.persistentID === t.MediaSelectionOptionsPersistentID : e.mediaType === pl.SUBTITLE ? (!n || e.groupId === n) && e.persistentID === t.MediaSelectionOptionsPersistentID : void o.warn(My, `subtitle media option has unknown type ${e.mediaType}`))), + e + } + } + )(null == t ? void 0 : t.subtitlePersistentId, m.closedcaption, m.subtitleGroupId, e.subtitleMediaSelectionGroup, f, i) + , E = null != f && f.length ? null == T ? void 0 : T.mediaOptionId : null + , I = E ? { + itemId: l, + mediaOptionId: E, + mediaOptionType: ul.Subtitle + } : Ol + , {mediaOptions: w, audioGroups: A, subtitleGroups: O} = (t = g, + d = m, + t.reduce((e,t)=>{ + if (((e,t)=>{ + let i = !0; + e.videoCodec && t.videoCodec && (i = Se.isCompatibleVideoCodec(e.videoCodec, t.videoCodec)); + let r = !1; + e.videoRange && t.videoRange ? r = e.videoRange == t.videoRange : e.videoRange || t.videoRange || (r = !0); + let n = !0; + return e.audioCodec && t.audioCodec && (n = Se.isCompatibleAudioCodec(e.audioCodec, t.audioCodec)), + i && r && n + } + )(d, t)) { + const d = t.audioGroupId; + d && e.audioGroups.add(d), + e.mediaOptions.add(t) + } + var i = t.subtitleGroupId; + i && e.subtitleGroups.add(i); + t = t.closedcaption; + return t && e.closedCaptionGroups.add(t), + e + } + , { + mediaOptions: new Set, + audioGroups: new Set, + subtitleGroups: new Set, + closedCaptionGroups: new Set + })) + , k = Array.from(w).map(e=>e.mediaOptionId) + , C = m.pathwayID + , D = Object.assign(Object.assign({}, u), { + compatibleIds: k, + preferredHost: y, + currentPathwayID: C + }) + , M = [] + , P = c.mediaOptions.reduce((e,t)=>(A.has(t.groupId) && (e.persistentIds.add(t.persistentID), + M.push(t.mediaOptionId), + e.filteredAudioMediaOptions.push(t), + e.altAudio || (e.altAudio = !!t.url)), + e), { + filteredAudioMediaOptions: [], + persistentIds: new Set, + altAudio: !1 + }) + , x = Object.assign(Object.assign({}, c), { + compatibleIds: M + }); + let R = e.audioMediaSelectionGroup; + const L = null == R ? void 0 : R.MediaSelectionGroupOptions; + if (L) { + const e = L.reduce((e,t)=>(P.persistentIds.has(t.MediaSelectionOptionsPersistentID) && e.push(t), + e), new Array); + R = Object.assign(Object.assign({}, R), { + MediaSelectionGroupOptions: e + }) + } + h.mediaOptions = Fy(m, T, h.mediaOptions); + const _ = h.mediaOptions.reduce((e,t)=>(O.has(t.groupId) && (e.persistentIds.add(t.persistentID), + e.filteredSubtitleMediaOptions.push(t)), + e), { + filteredSubtitleMediaOptions: [], + persistentIds: new Set + }); + let N = e.subtitleMediaSelectionGroup; + const F = null == N ? void 0 : N.MediaSelectionGroupOptions; + if (F) { + const e = F.reduce((e,t)=>(_.persistentIds.has(t.MediaSelectionOptionsPersistentID) && e.push(t), + e), new Array); + N = Object.assign(Object.assign({}, N), { + MediaSelectionGroupOptions: e + }) + } + i = [D, x, h]; + let B = new Map; + ng().useHighestVideoCodecPrivate && (B = null == D ? void 0 : D.mediaOptions.reduce((e,t)=>{ + const i = t.videoCodecList; + if (i) + for (const t of i) { + const i = Vp(t) + , r = e.get(i); + Se.isHigherCodecByFamily(r, t) && e.set(i, t) + } + return e + } + , B)), + B.size && B.forEach((e,t)=>{} + ); + t = { + fragDownloadSlow: !1, + fragDownloadTooSlow: !1, + nextMinAutoOptionId: Ol.mediaOptionId, + nextMaxAutoOptionId: Ol.mediaOptionId, + highBWTrigger: Vg(v.mediaOptionId, D.mediaOptions) + }; + return Object.assign(Object.assign({}, e), { + enabledMediaOptionKeys: [v, b, I], + mediaOptionListTuple: i, + audioMediaSelectionGroup: R, + abrStatus: t, + highestVideoCodec: B + }) + } + const Uy = (o,d,l,u,c,h,p)=>e=>e.pipe(Ql.tag("retrieveRootMediaOptions.input"), Ra(t=>{ + var e; + if (!t) + return Ti; + const {itemId: i, platformInfo: r} = t + , n = Ly(i) + , s = d["logger"]; + if (n.hasEntity(i)) + return Bi(n); + xy.setLoading(!0); + const a = performance.now(); + return function(e, t, u, c, i) { + const {itemId: h, url: p, itemStartOffset: f} = e + , r = xc(e, t); + return km({ + url: p, + onProgress: { + getData: !0, + cb: my + }, + xhrSetup: c.xhrSetup + }, r, i).pipe(ur(({responseText: e, stats: t})=>{ + var i = c["keySystemPreference"]; + if (Om.isMediaPlaylist(e)) { + const c = "media-pl-" + Jd() + , d = Om.parseMediaOptionPlaylist(e, p, !0, i, {}, h, c, ul.Variant, u, f); + Lc(d.mediaOptionDetails); + var r = { + itemId: h, + mediaOptionId: c, + mediaOptionType: ul.Variant, + url: p, + bandwidth: 0, + bitrate: 0, + iframes: d.mediaOptionDetails.iframesOnly, + pathwayID: "." + }; + return { + itemId: h, + itemStartOffset: f, + rootMediaOptionsTuple: [[r], [], []], + stats: t, + baseUrl: p, + initialDetails: d.mediaOptionDetails, + isMediaPlaylist: !0 + } + } + { + const u = Om.parseSessionData(e, p) + , c = Om.parseSessionKeys(e, p, i) + , l = Om.parseRootPlaylist(h, e, p, !0); + if (l.playlistParsingError) + throw l.playlistParsingError; + var {variantMediaOptions: n, contentSteeringOption: s, masterVariableList: a} = l + , o = Om.parseRootPlaylistAlternateMediaOptions(h, e, p, l.variantMediaOptions, !0, a); + if (o.playlistParsingError) + throw o.playlistParsingError; + var {audioAlternateOptions: r, subtitleAlternateOptions: i, audioMediaSelectionGroup: e, subtitleMediaSelectionGroup: o} = o.alternateMediaInfo; + return { + itemId: h, + itemStartOffset: f, + rootMediaOptionsTuple: [n, r, i], + stats: t, + baseUrl: p, + audioMediaSelectionGroup: e, + subtitleMediaSelectionGroup: o, + contentSteeringOption: s, + sessionData: u, + sessionKeys: c, + masterVariableList: a + } + } + } + ), e=>e.pipe(Un(e=>{ + if (e instanceof ou) + throw new ru(!1,"Timeout",0,$.ManifestTimeoutError,!0); + if (e instanceof tu) + throw new ru(!1,e.message,e.code,{ + code: e.code, + text: "Manifest network error" + },!1); + throw e + } + ))) + }(t, o, s, l, null === (e = null === (e = rg()) || void 0 === e ? void 0 : e.getQuery()) || void 0 === e ? void 0 : e.extendMaxTTFB).pipe(Ja(e=>p.triggerManifestLoaded(e)), Ja(({initialDetails: e, stats: t})=>{ + e && (e = e, + t = t, + Sg().archiveMediaOptionDetails(e, t, !0)) + } + ), So(u.displaySupportsHdr$), Ra(([e,t])=>_y(e, r, l, t, s)), ur(e=>(d.rootPlaylistEntity = function(e, t, i, r, n, s) { + const {itemId: a, initialSeekTime: o} = e + , d = Qf(a) + , l = n.enableAdaptiveStartup ? d.getBandwidthEstimate(n, e.serviceName) : void 0 + , u = n.enableAdaptiveStartup ? d.getPlaylistEstimate(n, e.serviceName) : void 0 + , c = n.enableAdaptiveStartup ? d.getFragEstimate(n, e.serviceName) : void 0 + , h = n.enableAdaptiveStartup ? d.getBufferEstimate(n, e.serviceName) : void 0 + , p = n.targetStartupMs - (performance.now() - r) + , f = n.enableAdaptiveStartup ? { + targetDuration: c.maxDurationSec || n.defaultTargetDuration, + targetStartupMs: p + } : void 0 + , m = By(t, i, s, l, f, u, c, h); + return m.pendingSeek = o, + m + }(t, e, c, a, l, s), + n)), Ym(i, null, xc(t, o), 0, !1, n, d, h), $s(()=>{ + xy.setLoading(!1) + } + )) + } + ), Ql.tag("retrieveRootMediaOptions.emit")); function $y(t, o, d, l, u, c, h) { return e=>e.pipe(Up(), Ra(e=>{ - return e ? Cr([Bi(e).pipe(xy(t.manifestLoadPolicy, d, t, l, null, u, c)), (n = t, + return e ? Cr([Bi(e).pipe(Uy(t.manifestLoadPolicy, d, t, l, null, u, c)), (n = t, s = o, a = h.mux, new Ut(e=>{ - const t = new ay(n,s,a); + const t = new py(n,s,a); return e.next(t), ()=>{ t.destroy() @@ -30082,11 +30088,11 @@ this.keySystemAdapter = null, this.legibleSystemAdapter = null, this.sessionID = Jd(), - this.statsService = (Bf = Bf || new Nf(Ff), - Bf), + this.statsService = (qf = qf || new Hf(jf), + qf), this.gaplessCapable = !0, - this.teardownWorker$ = new Hf, - this.itemQueue = new jg, + this.teardownWorker$ = new Xf, + this.itemQueue = new Yg, (e.liveSyncDurationCount || e.liveMaxLatencyDurationCount) && (e.liveSyncDuration || e.liveMaxLatencyDuration)) throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration"); const f = Object.assign(Object.assign({}, Al), e); @@ -30095,16 +30101,16 @@ const r = this.sessionID; let n = "silent"; e.debug && (n = f.debugLevel), - this.logger = null !== (i = this.logger) && void 0 !== i ? i : ([D,c={}] = [r, (u = { + this.logger = null !== (i = this.logger) && void 0 !== i ? i : ([M,h={}] = [r, (c = { sendLogs: e.sendLogs, level: "log" === n ? "debug" : n, consoleOverride: "boolean" != typeof e.debug ? e.debug : void 0, buildType: f.buildType }, - M = u.consoleOverride, + P = c.consoleOverride, Object.assign({ name: "hls", - timestamp: u.sendLogs ? Ae.stdTimeFunctions.epochTime : Ae.stdTimeFunctions.isoTime, + timestamp: c.sendLogs ? Ae.stdTimeFunctions.epochTime : Ae.stdTimeFunctions.isoTime, browser: { asObject: !0, serialize: !0, @@ -30112,49 +30118,49 @@ send: (e,t)=>{} }, write: { - debug: Ke.bind(null, Ve(M || console, "debug"), "debug"), - info: Ke.bind(null, Ve(M || console, "info"), "info"), - warn: Ke.bind(null, Ve(M || console, "warn"), "warn"), - error: Ke.bind(null, Ve(M || console, "error"), "error"), - fatal: Ke.bind(null, Ve(M || console, "error"), "fatal") + debug: Ke.bind(null, Ve(P || console, "debug"), "debug"), + info: Ke.bind(null, Ve(P || console, "info"), "info"), + warn: Ke.bind(null, Ve(P || console, "warn"), "warn"), + error: Ke.bind(null, Ve(P || console, "error"), "error"), + fatal: Ke.bind(null, Ve(P || console, "error"), "fatal") } } - }, u))], - Be && Be.sessionId === D ? Be.warn("Logger Singleton already setup, returning existing singleton") : (Be = Ae(Ue(c)).child({ - sessionId: D, + }, c))], + Be && Be.sessionId === M ? Be.warn("Logger Singleton already setup, returning existing singleton") : (Be = Ae(Ue(h)).child({ + sessionId: M, name: "hls" }), Be.qe = e=>Be.info(e), - Be.sessionId = D), + Be.sessionId = M), Be), Lo = !1, Ro && (delete window.$$stores, delete window.$$queries), this.hlsConfig.audioPrimingDelay = 0, - this.rootPlaylistService = (M = this.logger, - Oy = new wy(Ay,M), - Oy), + this.rootPlaylistService = (P = this.logger, + Ry = new Py(xy,P), + Ry), this.customUrlLoader = Mc(), this.sessionDataLoader = new _p(f,Oc,this.customUrlLoader.load,this.logger); - var s, a, o, d, l, u = f.liveMaxLatencyDurationCount, c = f.liveSyncDurationCount; - if (ne(u) && ne(c) && u <= c) + var s, a, o, d, l, u, c = f.liveMaxLatencyDurationCount, h = f.liveSyncDurationCount; + if (ne(c) && ne(h) && c <= h) throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be gt "liveSyncDurationCount"'); if (ne(f.liveMaxLatencyDuration) && (f.liveMaxLatencyDuration <= f.liveSyncDuration || !ne(f.liveSyncDuration))) throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be gt "liveSyncDuration"'); - const h = Xm(); - h.setHlsEntity({ + const p = rg(); + p.setHlsEntity({ id: r, config: f }); - const p = hg() - , m = new gf(vf) - , g = (Ph = Ph || new Dh(Mh), + const m = Sg() + , g = new gf(vf) + , y = (Ph = Ph || new Dh(Mh), Ph); - this.accessLogInstance = new jf(this,r), - this.rtcService = new Uy(this,f,this.accessLogInstance,this.logger), - this.playerEvents = new bg(this,this.logger,this.rtcService); - const y = (D = this.platformService, - l = D, + this.accessLogInstance = new Yf(this,r), + this.rtcService = new _f(this,f,this.accessLogInstance,this.logger), + this.playerEvents = new kg(this,this.logger,this.rtcService); + const v = (M = this.platformService, + u = M, (()=>{ if ("function" == typeof matchMedia) { var e = matchMedia("(dynamic-range: high)") @@ -30165,21 +30171,22 @@ return Bi(!0) } )().pipe(Ja(e=>{ - l.updateSupportsHdr(e) + u.updateSupportsHdr(e) } )).pipe(Ua(Ti))) - , v = this.mediaElement$.pipe((s = f, + , S = this.mediaElement$.pipe((s = f, o = (a = this).logger, d = this.teardownWorker$, + l = this.rtcService, e=>e.pipe(Ql.tag("playback.mediaElementServiceEpic.in"), Ra(e=>{ if (!e) return Bi(null); - const t = new hf(e,mf,s,a,o,d); + const t = new hf(e,mf,s,a,o,d,l); return t.openMediaSource(new MediaSource), nn(Bi(t), t) } ), Ql.tag("playback.mediaElementServiceEpic.emit"))), wa()) - , S = this.itemQueue.activeItemById$.pipe(Ra(e=>e ? Vf(f, this.statsService, e, this.logger) : Ti)); + , b = this.itemQueue.activeItemById$.pipe(Ra(e=>e ? Wf(f, this.statsService, e, this.logger) : Ti)); this.rpcService = (()=>{ let e = f.createRPCService; return f.enableWorker && null == e && (e = Cf), @@ -30187,23 +30194,23 @@ e(this.logger) } )(), - this.rpcClients = (M = this.rpcService, + this.rpcClients = (P = this.rpcService, { - crypto: new Ef(M), - mux: new If(M) + crypto: new Ef(P), + mux: new If(P) }); - var b, T, E, I, w, A, O, k, C, u = Cr([this.itemQueue.activeItemById$.pipe($y(f, this.logger, this.rootPlaylistService, m, this.statsService, this.playerEvents, this.rpcClients), Ja(e=>{ + var T, E, I, w, A, O, k, C, D, c = Cr([this.itemQueue.activeItemById$.pipe($y(f, this.logger, this.rootPlaylistService, g, this.statsService, this.playerEvents, this.rpcClients), Ja(e=>{ var t = null == e ? void 0 : e.rootPlaylistQuery; this.publicQueriesInternal$.next([t, null]), this.iframeMachine = null == e ? void 0 : e.iframeMachine, t && this.playerEvents.triggerManifestParsed(t) } - )), v.pipe((E = this.itemQueue.removedItems$, - I = g, - w = f, - A = m, - k = (O = this).rtcService, - C = this.logger, + )), S.pipe((I = this.itemQueue.removedItems$, + w = y, + A = f, + O = g, + C = (k = this).rtcService, + D = this.logger, e=>Cr([((n,s,a,o,d,l,u)=>e.pipe(Ql.tag("[Keys] playback.keySystemServiceEpic.in"), Ra(r=>r ? new Ut(e=>{ let t = new kh(n,r,a,o,d,l,u); const i = nn(Bi(t), s.pipe(Kr(e=>t.removeKeysForItems(e)), Ua(Ti))).subscribe(e); @@ -30214,7 +30221,7 @@ t = void 0 } } - ) : Bi(null)), Ql.tag("[Keys] playback.keySystemServiceEpic.emit")))(I, E, w, A, O, k, C), ((t,i,r)=>e.pipe(Ql.tag("playback.legibleServiceEpic.in"), Ra(e=>e ? nn(Bi(e = new Rp(e,t,i,r)), e) : Bi(null)), Ql.tag("playback.legibleServiceEpic.emit")))(w, O, C), e]).pipe(ur(([e,t,i])=>({ + ) : Bi(null)), Ql.tag("[Keys] playback.keySystemServiceEpic.emit")))(w, I, A, O, k, C, D), ((t,i,r)=>e.pipe(Ql.tag("playback.legibleServiceEpic.in"), Ra(e=>e ? nn(Bi(e = new Rp(e,t,i,r)), e) : Bi(null)), Ql.tag("playback.legibleServiceEpic.emit")))(A, k, D), e]).pipe(ur(([e,t,i])=>({ keySystemAdapter: e, legibleSystemAdapter: t, mediaSink: i @@ -30237,7 +30244,7 @@ rpcClients: this.rpcClients, rootPlaylistService: this.rootPlaylistService, rootPlaylistQuery: s, - mediaLibraryService: p, + mediaLibraryService: m, keySystemAdapter: i, legibleSystemAdapter: r, mediaSink: n, @@ -30253,7 +30260,7 @@ const {rootPlaylistQuery: t, mediaSink: e, mediaLibraryService: i} = a; this.publicQueriesInternal$.next([t, e.mediaQuery]); const n = e.mediaQuery - , r = Bi(a).pipe(ry()) + , r = Bi(a).pipe(uy()) , s = t.rootPlaylistEntity$.pipe(Up(), Cs(1), Ja(()=>{ this.commitEarlySelection(a.logger) } @@ -30263,7 +30270,7 @@ } ), Un(e=>(this.logger.error(e.message), Ti))) - , d = Uf(t.itemId) + , d = Qf(t.itemId) , l = function(l, e, u, r, t) { const a = u.mediaQuery , i = Zd([a.seekTo$, a.bufferedSegmentsByType$(cl.Variant)]).pipe(ur(([e,t])=>{ @@ -30310,7 +30317,7 @@ var a = 0 != p && 1 != p , o = t.details , d = o.fragments - , t = oy(o) + , t = fy(o) , i = Math.max(1, t * i); let l = a || n.len >= t || n.len >= i; a = d[o.fragments.length - 1], @@ -30326,7 +30333,7 @@ }(t, i, e.startTargetDurationFactor); var o = h.combined; if (!a && 0 < o.len) { - const p = oy(i.details); + const p = fy(i.details); a = function(n, e, t, i, r, s, a) { var o = null === (o = h.sbTuple[ul.Variant]) || void 0 === o ? void 0 : o.buffered; if ((null == o ? void 0 : o.len) >= t) @@ -30423,22 +30430,22 @@ return d.waterLevelChangedForType$(cl.Variant).pipe(an(e=>e === kp.AboveHighWater), Ls(()=>n.enabledMediaOptionByType$(ul.Variant).pipe(Ra(e=>{ var t = n.mediaOptionListQueries[ul.Variant].hasIframes , i = null !== (i = null === (i = s.getQuery().getEntity(n.itemId)) || void 0 === i ? void 0 : i.liveOrEvent) && void 0 !== i && i; - return !t || i ? Ti : (i = Uf(n.itemId), - e = pg(e), - i = Dg(!0, o, n, e, d, i, a), + return !t || i ? Ti : (i = Qf(n.itemId), + e = bg(e), + i = Ng(!0, o, n, e, d, i, a), i = n.variantMediaOptionById(i.variantMediaOption), - fg(r, i)) + Tg(r, i)) } ), Ra(e=>{ - var t = og(d.currentTime, n.discoSeqNum, 0, e, []); + var t = fg(d.currentTime, n.discoSeqNum, 0, e, []); return null !== (e = null == t ? void 0 : t.foundFrag) && void 0 !== e && e.mediaFragment ? (t = t.foundFrag.mediaFragment, - nn(Sg(r, t.keyTagInfo, { + nn(Og(r, t.keyTagInfo, { itemId: t.itemId, mediaOptionId: t.mediaOptionId - }), mg(r, t))) : (a.warn(Vg, "Unable to find fragment for iframe prefetch"), + }), Eg(r, t))) : (a.warn(Wg, "Unable to find fragment for iframe prefetch"), Ti) } - ), Cs(1), Ua(Ti), Un(e=>(a.error(Vg, `got error ${e.message} in prefetch`), + ), Cs(1), Ua(Ti), Un(e=>(a.error(Wg, `got error ${e.message} in prefetch`), Ti)), $s(()=>{} )))) }(t))) @@ -30458,7 +30465,7 @@ nextDuration: n.msDuration - this.loadingItem.itemStartOffset }; this.itemQueue.updatePlayingItemId(), - this.trigger(P.ITEM_TRANSITIONED, i), + this.trigger(x.ITEM_TRANSITIONED, i), this.rtcService.itemTransitioned(e, t) } } @@ -30476,41 +30483,36 @@ } return nn(...p) } - )), c = this.itemQueue.removedItems$.pipe(od(e=>{ + )), h = this.itemQueue.removedItems$.pipe(od(e=>{ var t; t = e, - hg().remove(t), + Sg().remove(t), this.rootPlaylistService.removeItems(e) } - )), D = h.getQuery().userSeek$.pipe((b = this.itemQueue, - T = this.rootPlaylistService, - e=>e.pipe(Up(), Ra(e=>Jr([Bi(e), b.activeItemById$.pipe(Up(), Ra(e=>T.getQueryForId(e.itemId).rootPlaylistEntity$), Cs(1))])), ur(([e,t])=>(T.setPendingSeek(t.itemId, e), - e))))), M = h.getQuery().selectEntityAction(To.Add).pipe(Ja(()=>{ + )), M = p.getQuery().userSeek$.pipe((T = this.itemQueue, + E = this.rootPlaylistService, + e=>e.pipe(Up(), Ra(e=>Jr([Bi(e), T.activeItemById$.pipe(Up(), Ra(e=>E.getQueryForId(e.itemId).rootPlaylistEntity$), Cs(1))])), ur(([e,t])=>(E.setPendingSeek(t.itemId, e), + e))))), P = p.getQuery().selectEntityAction(To.Add).pipe(Ja(()=>{ this.logger.warn(`new Hls instance added while old one still active sessionId:${r}`) } )); - nn(v.pipe(Un(e=>{ - var t; - return e instanceof MediaError && (null === (t = this.rtcService) || void 0 === t || t.handleMediaElementError(e)), - Ti - } - )), nn(y, D, S, c, u, this.teardownWorker$).pipe(Un(e=>this._handleError(e)))).pipe($s(()=>{ + nn(S.pipe(Un(()=>Ti)), nn(v, M, b, h, c, this.teardownWorker$).pipe(Un(e=>this._handleError(e)))).pipe($s(()=>{ var e, t; try { this.detachMedia(), - this.trigger(P.DESTROYING), + this.trigger(x.DESTROYING), this.playerEvents.destroy(), null === (e = this.accessLogInstance) || void 0 === e || e.destroy(), null === (t = this.rtcService) || void 0 === t || t.destroy(), - hg().clear(), + Sg().clear(), this.rootPlaylistService.removeAll(), this.itemQueue.clearQueue(), - h.removeEntity(this.sessionID) + p.removeEntity(this.sessionID) } catch (e) { this.logger.error(`Got error in finalize ${e.message}`) } } - ), $a(hn(this.destroy$, M))).subscribe() + ), $a(hn(this.destroy$, P))).subscribe() } get publicQueries$() { return this.publicQueriesInternal$.pipe(an(e=>Boolean(e) && Boolean(e[0]) && Boolean(e[1]))) @@ -30524,10 +30526,10 @@ return null !== (e = null == e ? void 0 : e[1]) && void 0 !== e ? e : null } static get version() { - return "2.141.0" + return "2.141.1" } static get Events() { - return P + return x } get Events() { return Vy.Events @@ -30573,10 +30575,10 @@ 0 < (null == n ? void 0 : n.len) && (e = $l(this.mediaElementAdapter.mediaQuery.stallInfo$, e=>null != e).pipe(ur(()=>{} ))) } - return e.pipe(Ra(()=>(this.trigger(P.ERROR, t), + return e.pipe(Ra(()=>(this.trigger(x.ERROR, t), Ti))) } - this.trigger(P.ERROR, t) + this.trigger(x.ERROR, t) } catch (i) { throw this.logger.error(`Error thrown inside _handleError ${i.message}`, i), i @@ -30585,7 +30587,7 @@ } updateLiveSeekableRange(e, t) { return e.enabledMediaOptionByType$(ul.Variant).pipe(Ra(e=>{ - const t = pg(e); + const t = bg(e); let i = 0; return t.mediaOptionDetailsEntity$.pipe(Up(), an(e=>{ var t = null !== e.stats && !1 === e.detailsLoading && e.lastUpdateMillis > i; @@ -30608,12 +30610,12 @@ paused: n.paused, position: n.currentTime, duration: n.duration, - seekableTimeRanges: Kf.timeRangeToArray(n.seekable), - loadedTimeRanges: Kf.timeRangeToArray(n.buffered) + seekableTimeRanges: zf.timeRangeToArray(n.seekable), + loadedTimeRanges: zf.timeRangeToArray(n.buffered) }; let e = 0 , t = 0; - if (Kf.isHtmlVideoElement(n)) { + if (zf.isHtmlVideoElement(n)) { const o = n.getVideoPlaybackQuality; if (o && typeof o == typeof Function) { const o = n.getVideoPlaybackQuality(); @@ -30623,7 +30625,7 @@ t = a.totalVideoFrames - e } } else - Kf.isWebkitMediaElement(n) && (e = a.droppedVideoFrames = n.webkitDroppedFrameCount, + zf.isWebkitMediaElement(n) && (e = a.droppedVideoFrames = n.webkitDroppedFrameCount, t = a.decodedFrameCount = n.webkitDecodedFrameCount); i.enablePerformanceLogging && r.getCombinedMediaSourceBufferInfo(i.maxBufferHole), null === (i = this.rtcService) || void 0 === i || i.handlePlaybackInfo(e, t) @@ -30661,7 +30663,7 @@ const e = this.hlsConfig.trickPlaybackConfig.enabled , t = [0, 1] , i = this._activeRootQuery - , r = hg().getQuery(); + , r = Sg().getQuery(); return e && i && r.getEntity(i.itemId) && !1 === r.getEntity(i.itemId).liveOrEvent && t.push(8, 24, 48, 96), t } @@ -30682,7 +30684,7 @@ null === (r = this.accessLogInstance) || void 0 === r || r.setupReporter(i.appData), null != i && i.platformInfo && this.platformService.updatePlatformInfo(i.platformInfo), this.itemQueue.setQueueItem(`item:${null !== (r = null == i ? void 0 : i.itemId) && void 0 !== r ? r : Jd()}`, e, t, null == i ? void 0 : i.platformInfo, null === (t = null == i ? void 0 : i.appData) || void 0 === t ? void 0 : t.serviceName), - Xm().setStartTime(void 0) + rg().setStartTime(void 0) } queueSource(e, t, i) { var r; @@ -30717,7 +30719,7 @@ Object.assign(Object.assign({}, t), { url: oe(e.url) }), - this.trigger(P.ITEM_EVICTED, t)) : this.logger.error("dequeueSource called with no playing or loading item") + this.trigger(x.ITEM_EVICTED, t)) : this.logger.error("dequeueSource called with no playing or loading item") } endSource() { this.gaplessCapable = !1, @@ -30755,21 +30757,21 @@ this.teardownWorker$) } attachMedia(e) { - this.trigger(P.MEDIA_ATTACHING, { + this.trigger(x.MEDIA_ATTACHING, { media: e }), this.mediaElement$.next(e), this.encryptedMediaElement$.next(e), - this.trigger(P.MEDIA_ATTACHED, { + this.trigger(x.MEDIA_ATTACHED, { media: e }) } detachMedia() { var e; - this.mediaElement$.getValue() && (this.trigger(P.MEDIA_DETACHING), + this.mediaElement$.getValue() && (this.trigger(x.MEDIA_DETACHING), null === (e = this.rtcService) || void 0 === e || e.detachMedia(), this.mediaElement$.next(null), - this.trigger(P.MEDIA_DETACHED)) + this.trigger(x.MEDIA_DETACHED)) } handleResolvedUri(e, t) { this.customUrlLoader.setCustomUrlResponse(e, { @@ -30909,14 +30911,14 @@ this.isPreloading && (e > this.loadingItem.itemStartOffset && (this.logger.warn(`[Gapless] Seeking past track boundary oldSeek=${e}, adjustedSeek=${this.loadingItem.itemStartOffset}`), e = this.loadingItem.itemStartOffset), e < this._mediaElementQuery.getBufferInfo(this._mediaElementQuery.currentTime, this.config.maxBufferHole)[0].buffered.start && this.dequeueSource("SeekToUnbufferedTimeRanges")), - Xm().setUserSeek(e) + rg().setUserSeek(e) } set seekTo(e) { var t = Number(e); - ne(t) ? this.inGaplessMode ? this.gaplessSeekTo(t) : Xm().setUserSeek(t) : this.logger.error(`[seek] got invalid seek value ${e}`) + ne(t) ? this.inGaplessMode ? this.gaplessSeekTo(t) : rg().setUserSeek(t) : this.logger.error(`[seek] got invalid seek value ${e}`) } seekToDate(e) { - Xm().setUserSeek(e) + rg().setUserSeek(e) } get availableProgramDateTime() { return new Map(this._currentDateToMediaTimeTuple) @@ -30925,10 +30927,10 @@ if (!this._activeRootQuery) return []; var e = this._activeRootQuery.enabledMediaOptionKeys[ul.Variant]; - return kl(e) && null !== (e = null === (e = hg().getQueryForOption(e).mediaOptionDetails) || void 0 === e ? void 0 : e.dateMediaTimePairs) && void 0 !== e ? e : [] + return kl(e) && null !== (e = null === (e = Sg().getQueryForOption(e).mediaOptionDetails) || void 0 === e ? void 0 : e.dateMediaTimePairs) && void 0 !== e ? e : [] } get playingDate() { - return Gg(this._currentDateToMediaTimeTuple, this.realCurrentTime) + return ey(this._currentDateToMediaTimeTuple, this.realCurrentTime) } set variantId(e) {} set audioSelectedPersistentID(e) { @@ -31009,7 +31011,7 @@ get bufferInfo$() { return this.publicQueries$.pipe(Ra(e=>{ const [,t] = e - , i = Xm().getQuery().currentConfig; + , i = rg().getQuery().currentConfig; return nn(t.timeupdate$, t.bufferedRangeTuple$).pipe(so(1e3), ur(()=>{ var e = t.currentTime; return { @@ -31034,10 +31036,10 @@ } stopLoad() {} get config() { - return Object.assign(Object.assign({}, de(Ym())), { + return Object.assign(Object.assign({}, de(ng())), { set startPosition(e) { qe().warn(`Setting start position ${null == e ? void 0 : e.toFixed(3)} using deprecated method`), - Xm().setStartTime(e) + rg().setStartTime(e) } }) } @@ -31053,4 +31055,3 @@ "object" == typeof exports && "undefined" != typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define(t) : (e = "undefined" != typeof globalThis ? globalThis : e || jy).Hls = t() }(!1); //# sourceMappingURL=hls.js.map - diff --git a/src/renderer/assets/feather/mic.svg b/src/renderer/assets/feather/mic.svg new file mode 100644 index 00000000..dc5f780c --- /dev/null +++ b/src/renderer/assets/feather/mic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/plus-circle-white.svg b/src/renderer/assets/feather/plus-circle-white.svg new file mode 100644 index 00000000..bd6a25ec --- /dev/null +++ b/src/renderer/assets/feather/plus-circle-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/video.svg b/src/renderer/assets/feather/video.svg new file mode 100644 index 00000000..8ff156aa --- /dev/null +++ b/src/renderer/assets/feather/video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/volume-2.svg b/src/renderer/assets/feather/volume-2.svg new file mode 100644 index 00000000..eaf07b56 --- /dev/null +++ b/src/renderer/assets/feather/volume-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/volume.svg b/src/renderer/assets/feather/volume.svg new file mode 100644 index 00000000..a6282072 --- /dev/null +++ b/src/renderer/assets/feather/volume.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/x-circle-white.svg b/src/renderer/assets/feather/x-circle-white.svg new file mode 100644 index 00000000..4ad16a6a --- /dev/null +++ b/src/renderer/assets/feather/x-circle-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/feather/x-circlePng.png b/src/renderer/assets/feather/x-circlePng.png new file mode 100644 index 00000000..9b0f9ca2 Binary files /dev/null and b/src/renderer/assets/feather/x-circlePng.png differ diff --git a/src/renderer/assets/infinity.svg b/src/renderer/assets/infinity.svg new file mode 100644 index 00000000..4d06c7b8 --- /dev/null +++ b/src/renderer/assets/infinity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/assets/logocut.png b/src/renderer/assets/logocut.png index 3f1e9b8b..29e744c4 100644 Binary files a/src/renderer/assets/logocut.png and b/src/renderer/assets/logocut.png differ diff --git a/src/renderer/assets/pip.svg b/src/renderer/assets/pip.svg new file mode 100644 index 00000000..76253ddc --- /dev/null +++ b/src/renderer/assets/pip.svg @@ -0,0 +1,8 @@ + + + + + diff --git a/src/renderer/assets/repeatOne.svg b/src/renderer/assets/repeatOne.svg new file mode 100644 index 00000000..3b5bba82 --- /dev/null +++ b/src/renderer/assets/repeatOne.svg @@ -0,0 +1,33 @@ + + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + \ No newline at end of file diff --git a/src/renderer/audio/audio.js b/src/renderer/audio/audio.js index 64118b7c..948a4d7a 100644 --- a/src/renderer/audio/audio.js +++ b/src/renderer/audio/audio.js @@ -5,6 +5,8 @@ var CiderAudio = { gainNode : null, spatialNode : null, spatialInput: null, + audioBands : null, + preampNode : null, }, init: function (cb = function () { }) { //AudioOutputs.fInit = true; @@ -21,8 +23,14 @@ var CiderAudio = { }, off: function(){ try{ - CiderAudio.audioNodes.gainNode.disconnect(); - CiderAudio.audioNodes.spatialNode.disconnect(); + try{ + CiderAudio.audioNodes.gainNode.disconnect(); } catch(e){} + try{ CiderAudio.audioNodes.spatialNode.disconnect();} catch(e){} + try{ + CiderAudio.audioNodes.preampNode.disconnect(); + CiderAudio.audioNodes.audioBands[0].disconnect(); + CiderAudio.audioNodes.audioBands[9].disconnect(); + } catch(e){} CiderAudio.source.connect(CiderAudio.context.destination);} catch(e){} }, connectContext: function (mediaElem){ @@ -42,6 +50,7 @@ var CiderAudio = { if (app.cfg.audio.spatial){ CiderAudio.spatialOn() } + CiderAudio.equalizer() }, normalizerOn: function (){}, normalizerOff: function (){ @@ -49,7 +58,7 @@ var CiderAudio = { }, spatialOn: function (){ try{ - CiderAudio.audioNodes.gainNode.connect(CiderAudio.context.destination);} catch(e){} + CiderAudio.audioNodes.gainNode.disconnect(CiderAudio.context.destination);} catch(e){} CiderAudio.audioNodes.spatialNode = new ResonanceAudio(CiderAudio.context); CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.context.destination); let roomDimensions = { @@ -90,6 +99,42 @@ var CiderAudio = { } ); } + }, + equalizer: function (){ + let BANDS = app.cfg.audio.equalizer.frequencies; + let GAIN = app.cfg.audio.equalizer.gain; + let Q = app.cfg.audio.equalizer.Q; + CiderAudio.audioNodes.audioBands = []; + + for (i = 0; i < BANDS.length; i++) { + CiderAudio.audioNodes.audioBands[i] = CiderAudio.context.createBiquadFilter(); + CiderAudio.audioNodes.audioBands[i].type = 'peaking'; // 'peaking'; + CiderAudio.audioNodes.audioBands[i].frequency.value = BANDS[i]; + CiderAudio.audioNodes.audioBands[i].Q.value = Q[i]; + CiderAudio.audioNodes.audioBands[i].gain.value = GAIN[i] * app.cfg.audio.equalizer.mix; + } + + CiderAudio.audioNodes.preampNode = CiderAudio.context.createBiquadFilter(); + CiderAudio.audioNodes.preampNode.type = 'highshelf'; + CiderAudio.audioNodes.preampNode.frequency.value = 0; // allow all + CiderAudio.audioNodes.preampNode.gain.value = app.cfg.audio.equalizer.preamp; + + if (app.cfg.audio.spatial) { + try{ + CiderAudio.audioNodes.spatialNode.output.disconnect(CiderAudio.context.destination); } catch(e){} + CiderAudio.audioNodes.spatialNode.output.connect(CiderAudio.audioNodes.preampNode); + } else { + try{ + CiderAudio.audioNodes.gainNode.disconnect(CiderAudio.context.destination);} catch(e){} + CiderAudio.audioNodes.gainNode.connect(CiderAudio.audioNodes.preampNode); + } + + CiderAudio.audioNodes.preampNode.connect(CiderAudio.audioNodes.audioBands[0]); + + for (i = 1; i < BANDS.length; i ++) { + CiderAudio.audioNodes.audioBands[i-1].connect(CiderAudio.audioNodes.audioBands[i]); + } + CiderAudio.audioNodes.audioBands[BANDS.length-1].connect(CiderAudio.context.destination); } } diff --git a/src/renderer/index.js b/src/renderer/index.js index 69ce0b26..2979fd4c 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -1,8 +1,8 @@ Vue.use(VueObserveVisibility); - +var notyf = new Notyf(); // This is going to suck to code var CiderContextMenu = { - Menu: function (event) { + Menu: function(event) { this.items = [] }, async Create(event, menudata) { @@ -15,17 +15,17 @@ var CiderContextMenu = { menu.style.top = 0 + "px"; menu.style.position = "absolute"; menu.style.zIndex = "99909"; - menu.addEventListener("animationend", function () { + menu.addEventListener("animationend", function() { menu.classList.remove("context-menu-open"); - }, {once: true}); + }, { once: true }); function close() { menuBackground.style.pointerEvents = "none"; menu.classList.add("context-menu-close"); - menu.addEventListener("animationend", function () { + menu.addEventListener("animationend", function() { menuBackground.remove(); menu.remove(); - }, {once: true}); + }, { once: true }); } // when menubackground is clicked, remove it @@ -75,7 +75,7 @@ var CiderContextMenu = { } const MusicKitObjects = { - LibraryPlaylist: function () { + LibraryPlaylist: function() { this.id = "" this.type = "library-playlist-folders" this.href = "" @@ -99,7 +99,7 @@ const MusicKitTools = { } // limit an array to a certain number of items -Array.prototype.limit = function (n) { +Array.prototype.limit = function(n) { return this.slice(0, n); }; @@ -134,6 +134,8 @@ const app = new Vue({ platform: "", mk: {}, quickPlayQuery: "", + lz: ipcRenderer.sendSync("get-i18n", "en_US"), + lzListing: ipcRenderer.sendSync("get-i18n-listing"), search: { term: "", hints: [], @@ -169,57 +171,57 @@ const app = new Vue({ data: {}, }, library: { - downloadNotification: { + backgroundNotification: { show: false, message: "", total: 0, progress: 0 }, songs: { - sortingOptions: { - "albumName": "Album", - "artistName": "Artist", - "name": "Name", - "genre": "Genre", - "releaseDate": "Release Date", - "durationInMillis": "Duration" + sortingOptions: { + "albumName": "0", + "artistName": "0", + "name": "0", + "genre": "0", + "releaseDate": "0", + "durationInMillis": "0" }, sorting: "name", sortOrder: "asc", listing: [], - meta: {total: 0, progress: 0}, + meta: { total: 0, progress: 0 }, search: "", displayListing: [], downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library }, albums: { sortingOptions: { - "artistName": "Artist", - "name": "Name", - "genre": "Genre", - "releaseDate": "Release Date" + "albumName": "0", + "artistName": "0", + "name": "0", + "genre": "0" }, viewAs: 'covers', sorting: ["dateAdded", "name"], // [0] = recentlyadded page, [1] = albums page sortOrder: ["desc", "asc"], // [0] = recentlyadded page, [1] = albums page listing: [], - meta: {total: 0, progress: 0}, + meta: { total: 0, progress: 0 }, search: "", displayListing: [], downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library }, artists: { sortingOptions: { - "artistName": "Artist", - "name": "Name", - "genre": "Genre", - "releaseDate": "Release Date" + "artistName": "0", + "name": "0", + "genre": "0", + "releaseDate": "0" }, viewAs: 'covers', sorting: ["dateAdded", "name"], // [0] = recentlyadded page, [1] = albums page sortOrder: ["desc", "asc"], // [0] = recentlyadded page, [1] = albums page listing: [], - meta: {total: 0, progress: 0}, + meta: { total: 0, progress: 0 }, search: "", displayListing: [], downloadState: 0 // 0 = not started, 1 = in progress, 2 = complete, 3 = empty library @@ -231,6 +233,8 @@ const app = new Vue({ loadingState: 0, // 0 loading, 1 loaded, 2 error id: "" }, + webremoteurl : "", + webremoteqr: "", mxmtoken: "", mkIsReady: false, playerReady: false, @@ -249,17 +253,24 @@ const app = new Vue({ start: 0, end: 0 }, + v3: { + requestBody: { + platform: "web" + } + }, + tmpHeight : '', + tmpWidth : '', tmpVar: [], notification: false, chrome: { - hideUserInfo: ipcRenderer.sendSync("is-dev"), + hideUserInfo: ipcRenderer.sendSync("is-dev") || false, artworkReady: false, userinfo: { "id": "", "attributes": { "name": "Cider User", "handle": "CiderUser", - "artwork": {"url": "./assets/logocut.png"} + "artwork": { "url": "./assets/logocut.png" } } }, menuOpened: false, @@ -286,7 +297,9 @@ const app = new Vue({ musicBaseUrl: "https://api.music.apple.com/", modals: { addToPlaylist: false, - spatialProperties: false + spatialProperties: false, + qrcode: false, + equalizer: false, }, socialBadges: { badgeMap: {}, @@ -306,7 +319,7 @@ const app = new Vue({ }, watch: { cfg: { - handler: function (val, oldVal) { + handler: function(val, oldVal) { console.log(`cfg changed from ${oldVal} to ${val}`); ipcRenderer.send("setStore", val); }, @@ -326,25 +339,62 @@ const app = new Vue({ }, }, methods: { + setLz(lang) { + if(lang == "") { + lang = this.cfg.general.language + } + this.lz = ipcRenderer.sendSync("get-i18n", lang) + }, + getLz(message) { + if(this.lz[message]) { + return this.lz[message] + }else{ + return message + } + }, + setLzManual() { + app.$data.library.songs.sortingOptions = { + "albumName": app.getLz('term.sortBy.album'), + "artistName": app.getLz('term.sortBy.artist'), + "name": app.getLz('term.sortBy.name'), + "genre": app.getLz('term.sortBy.genre'), + "releaseDate": app.getLz('term.sortBy.releaseDate'), + "durationInMillis": app.getLz('term.sortBy.duration') + } + + app.$data.library.albums.sortingOptions = { + "albumName": app.getLz('term.sortBy.album'), + "artistName": app.getLz('term.sortBy.artist'), + "name": app.getLz('term.sortBy.name'), + "genre": app.getLz('term.sortBy.genre') + } + + app.$data.library.artists.sortingOptions = { + "artistName": app.getLz('term.sortBy.artist'), + "name": app.getLz('term.sortBy.name'), + "genre": app.getLz('term.sortBy.genre'), + "releaseDate": app.getLz('term.sortBy.releaseDate') + } + }, async showSocialListeningTo() { let contentIds = Object.keys(app.socialBadges.badgeMap) - app.showCollection({data: this.socialBadges.mediaItems}, "Friends Listening To", "albums") - if(this.socialBadges.mediaItemDLState == 1 || this.socialBadges.mediaItemDLState == 2) { + app.showCollection({ data: this.socialBadges.mediaItems }, "Friends Listening To", "albums") + if (this.socialBadges.mediaItemDLState == 1 || this.socialBadges.mediaItemDLState == 2) { return } this.socialBadges.mediaItemDLState = 2 - await asyncForEach(contentIds, async (item)=>{ + await asyncForEach(contentIds, async(item) => { try { let type = "albums" - if(item.includes("pl.")) { + if (item.includes("pl.")) { type = "playlists" } - if(item.includes("ra.")) { + if (item.includes("ra.")) { type = "stations" } let found = await app.mk.api.v3.music(`/v1/catalog/us/${type}/${item}`) this.socialBadges.mediaItems.push(found.data.data[0]) - }catch(e){ + } catch (e) { } }) @@ -369,7 +419,7 @@ const app = new Vue({ app.menuPanel.content.name = data.name ?? ""; app.menuPanel.content.items = data.items ?? {}; app.menuPanel.content.headerItems = data.headerItems ?? {}; - if(event) { + if (event) { app.menuPanel.event = event; } }, @@ -378,13 +428,12 @@ const app = new Vue({ let data = await response.text(); return data; }, - getSocialBadges(cb = () => { - }) { + getSocialBadges(cb = () => {}) { let self = this try { - app.mk.api.socialBadgingMap().then(data => { - self.socialBadges.badgeMap = data.badgingMap - cb(data.badgingMap) + app.mk.api.v3.music("/v1/social/badging-map").then(data => { + self.socialBadges.badgeMap = data.data.results.badgingMap + cb(data.data.results.badgingMap) }) } catch (ex) { this.socialBadges.badgeMap = {} @@ -476,9 +525,9 @@ const app = new Vue({ }) } else if ((self.selectedMediaItems[i].kind == "album" || self.selectedMediaItems[i].kind == "albums") && self.selectedMediaItems[i].isLibrary != true) { self.selectedMediaItems[i].kind = "albums" - let res = await self.mk.api.albumRelationship(self.selectedMediaItems[i].id, "tracks"); - let ids = res.map(function (i) { - return {id: i.id, type: i.type} + let res = await self.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/albums/${self.selectedMediaItems[i].id}/tracks`); + let ids = res.data.data.map(function(i) { + return { id: i.id, type: i.type } }) pl_items = pl_items.concat(ids) } else if (self.selectedMediaItems[i].kind == "library-song" || self.selectedMediaItems[i].kind == "library-songs") { @@ -489,9 +538,9 @@ const app = new Vue({ }) } else if ((self.selectedMediaItems[i].kind == "library-album" || self.selectedMediaItems[i].kind == "library-albums") || (self.selectedMediaItems[i].kind == "album" && self.selectedMediaItems[i].isLibrary == true)) { self.selectedMediaItems[i].kind = "library-albums" - let res = await self.mk.api.library.albumRelationship(self.selectedMediaItems[i].id, "tracks"); - let ids = res.map(function (i) { - return {id: i.id, type: i.type} + let res = await self.mk.api.v3.music(`/v1/me/library/albums/${self.selectedMediaItems[i].id}/tracks`); + let ids = res.data.data.map(function(i) { + return { id: i.id, type: i.type } }) pl_items = pl_items.concat(ids) } else { @@ -503,7 +552,16 @@ const app = new Vue({ } this.modals.addToPlaylist = false - this.mk.api.library.appendTracksToPlaylist(playlist_id, pl_items).then(() => { + await app.mk.api.v3.music( + `/v1/me/library/playlists/${playlist_id}/tracks`, {}, { + fetchOptions: { + method: "POST", + body: JSON.stringify({ + data: pl_items + }) + } + } + ).then(() => { if (this.page == 'playlist_' + this.showingPlaylist.id) { this.getPlaylistFromID(this.showingPlaylist.id) } @@ -511,22 +569,37 @@ const app = new Vue({ }, async init() { let self = this + this.setLz(this.cfg.general.language) + this.setLzManual() clearTimeout(this.hangtimer) this.mk = MusicKit.getInstance() + let needsReload = (typeof localStorage["music.ampwebplay.media-user-token"] == "undefined") this.mk.authorize().then(() => { self.mkIsReady = true + if(needsReload) { + document.location.reload() + } }) this.$forceUpdate() if (this.isDev) { this.mk.privateEnabled = true + // Hide UserInfo if Dev mode + this.chrome.hideUserInfo = true + } else { + // Get Hide User from Settings + this.chrome.hideUserInfo = !this.cfg.visual.showuserinfo } if (this.cfg.visual.hw_acceleration == "disabled") { document.body.classList.add("no-gpu") } this.mk._services.timing.mode = 0 this.platform = ipcRenderer.sendSync('cider-platform'); - // Set profile name - this.chrome.userinfo = await this.mkapi("personalSocialProfile", false, "") + + try { + // Set profile name + this.chrome.userinfo = (await app.mk.api.v3.music(`/v1/me/social-profile`)).data.data[0] + } catch (err) {} + // API Fallback if (!this.chrome.userinfo) { this.chrome.userinfo = { @@ -534,16 +607,25 @@ const app = new Vue({ "attributes": { "name": "Cider User", "handle": "CiderUser", - "artwork": {"url": "./assets/logocut.png"} + "artwork": { "url": "./assets/logocut.png" } } } } MusicKitInterop.init() // Set the volume - this.mk.volume = this.cfg.general.volume - // ipcRenderer.invoke('getStoreValue', 'general.volume').then((value) => { - // self.mk.volume = value - // }) + + // Check the value of this.cfg.audio.muted + if( !this.cfg.audio.muted ) + { + // Set the mk.volume to the last stored volume data + this.mk.volume = this.cfg.audio.volume + } else if( this.cfg.audio.muted ) { + // Set mk.volume to -1 (setting to 0 wont work, so temp solution setting to -1) + this.mk.volume = -1; + } + // ipcRenderer.invoke('getStoreValue', 'audio.volume').then((value) => { + // self.mk.volume = value + // }) // load cached library if (localStorage.getItem("librarySongs") != null) { @@ -555,7 +637,7 @@ const app = new Vue({ this.library.albums.displayListing = this.library.albums.listing } - window.onbeforeunload = function (e) { + window.onbeforeunload = function(e) { window.localStorage.setItem("currentTrack", JSON.stringify(app.mk.nowPlayingItem)) window.localStorage.setItem("currentTime", JSON.stringify(app.mk.currentPlaybackTime)) window.localStorage.setItem("currentQueue", JSON.stringify(app.mk.queue.items)) @@ -563,9 +645,9 @@ const app = new Vue({ // Load saved quality switch (app.cfg.audio.quality) { - case "extreme": + /** case "extreme": app.mk.bitrate = app.cfg.audio.quality = 990 - break; + break; **/ case "high": app.mk.bitrate = app.cfg.audio.quality = 256 break; @@ -573,7 +655,8 @@ const app = new Vue({ app.mk.bitrate = app.cfg.audio.quality = 64 break; default: - app.mk.bitrate = app.cfg.audio.quality + // app.mk.bitrate = app.cfg.audio.quality + break; } @@ -586,7 +669,9 @@ const app = new Vue({ lastItem = JSON.parse(lastItem) let kind = lastItem.attributes.playParams.kind; let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind; - app.mk.setQueue({[truekind]: [lastItem.attributes.playParams.id]}) + app.mk.setQueue({ + [truekind]: [lastItem.attributes.playParams.id] + }) app.mk.mute() setTimeout(() => { app.mk.play().then(() => { @@ -604,9 +689,8 @@ const app = new Vue({ for (id of ids) { if (!(i == 0 && ids[0] == lastItem.attributes.playParams.id)) { try { - app.mk.playLater({songs: [id]}) - } catch (err) { - } + app.mk.playLater({ songs: [id] }) + } catch (err) {} } i++; } @@ -636,10 +720,26 @@ const app = new Vue({ } }) + ipcRenderer.on('play', function(_event, mode, id) { + if (mode !== 'url'){ + self.mk.setQueue({[mode]: id}).then(() => { + app.mk.play() + }) + } else { + app.openAppleMusicURL(id) + } + }); + + this.mk.addEventListener(MusicKit.Events.playbackStateDidChange, ()=>{ + ipcRenderer.send('wsapi-updatePlaybackState', wsapi.getAttributes()); + }) + this.mk.addEventListener(MusicKit.Events.playbackTimeDidChange, (a) => { self.lyriccurrenttime = self.mk.currentPlaybackTime this.currentSongInfo = a self.playerLCD.playbackDuration = (self.mk.currentPlaybackTime) + // wsapi + ipcRenderer.send('wsapi-updatePlaybackState', wsapi.getAttributes()); }) this.mk.addEventListener(MusicKit.Events.nowPlayingItemDidChange, (a) => { @@ -655,11 +755,10 @@ const app = new Vue({ let previewURL = null try { previewURL = app.mk.nowPlayingItem.previewURL - } catch (e) { - } + } catch (e) {} if (!previewURL) { - app.mk.api.song(app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.relationships.catalog.data[0].id).then((response) => { - previewURL = response.attributes.previews[0].url + app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/songs/${app.mk.nowPlayingItem._songId ?? app.mk.nowPlayingItem.relationships.catalog.data[0].id}`).then((response) => { + previewURL = response.data.data[0].attributes.previews[0].url if (previewURL) ipcRenderer.send('getPreviewURL', previewURL) }) @@ -668,14 +767,12 @@ const app = new Vue({ ipcRenderer.send('getPreviewURL', previewURL) } - } catch (e) { - } + } catch (e) {} } try { a = a.item.attributes; - } catch (_) { - } + } catch (_) {} let type = (self.mk.nowPlayingItem != null) ? self.mk.nowPlayingItem["type"] ?? '' : ''; if (type.includes("musicVideo") || type.includes("uploadedVideo") || type.includes("music-movie")) { @@ -694,7 +791,7 @@ const app = new Vue({ app.loadLyrics(); // Playback Notifications - if ((app.platform === "darwin" || app.platform === "linux") && !document.hasFocus() && a.artistName && a.artwork && a.name) { + if (this.cfg.general.playbackNotifications && !document.hasFocus() && a.artistName && a.artwork && a.name) { if (this.notification) { this.notification.close() } @@ -709,7 +806,7 @@ const app = new Vue({ this.mk.addEventListener(MusicKit.Events.playbackVolumeDidChange, (_a) => { - this.cfg.general.volume = this.mk.volume + this.cfg.audio.volume = this.mk.volume }) this.refreshPlaylists() @@ -726,10 +823,19 @@ const app = new Vue({ this.$forceUpdate() }, 500) }, + unauthorize() { + this.mk.unauthorize() + document.location.reload() + }, getAppClasses() { + let classes = {} if (this.cfg.advanced.experiments.includes('compactui')) { - return {compact: true} + classes.compact = true } + if(this.cfg.visual.window_background_style == "none") { + classes.simplebg = true + } + return classes }, invokeDrawer(panel) { if (this.drawer.panel == panel && this.drawer.open) { @@ -802,8 +908,7 @@ const app = new Vue({ }, playlistHeaderContextMenu(event) { let menu = { - items: [ - { + items: [{ name: "New Playlist", action: () => { this.newPlaylist() @@ -822,13 +927,11 @@ const app = new Vue({ async editPlaylistFolder(id, name = "New Playlist") { let self = this this.mk.api.v3.music( - `/v1/me/library/playlist-folders/${id}`, - {}, - { + `/v1/me/library/playlist-folders/${id}`, {}, { fetchOptions: { method: "PATCH", body: JSON.stringify({ - attributes: {name: name} + attributes: { name: name } }) } } @@ -839,13 +942,11 @@ const app = new Vue({ async editPlaylist(id, name = "New Playlist") { let self = this this.mk.api.v3.music( - `/v1/me/library/playlists/${id}`, - {}, - { + `/v1/me/library/playlists/${id}`, {}, { fetchOptions: { method: "PATCH", body: JSON.stringify({ - attributes: {name: name} + attributes: { name: name } }) } } @@ -864,7 +965,18 @@ const app = new Vue({ if (tracks.length > 0) { request.tracks = tracks } - app.mk.api.library.createPlaylist(request).then(res => { + app.mk.api.v3.music(`/v1/me/library/playlists`, {}, { + fetchOptions: { + method: "POST", + body: JSON.stringify({ + "attributes": { "name": name }, + "relationships": { + "tracks": { "data": tracks }, + } + }) + } + }).then(res => { + res = res.data.data[0] console.log(res) self.appRoute(`playlist_` + res.id); self.showingPlaylist = []; @@ -885,7 +997,11 @@ const app = new Vue({ deletePlaylist(id) { let self = this if (confirm(`Are you sure you want to delete this playlist?`)) { - app.mk.api.library.deletePlaylist(id).then(res => { + app.mk.api.v3.music(`/v1/me/library/playlists/${id}`, {}, { + fetchOptions: { + method: "DELETE" + } + }).then(res => { // remove this playlist from playlists.listing if it exists let found = self.playlists.listing.find(item => item.id == id) if (found) { @@ -894,23 +1010,28 @@ const app = new Vue({ }) } }, - async showCollection(response, title, type) { + async showCollection(response, title, type, requestBody = {}) { let self = this + console.log(response) + this.collectionList.requestBody = {} this.collectionList.response = response this.collectionList.title = title this.collectionList.type = type + this.collectionList.requestBody = requestBody app.appRoute("collection-list") }, async showArtistView(artist, title, view) { - let response = await this.mk.api.artistView(artist, view, {}, {view: view, includeResponseMeta: !0}) + let response = (await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/artists/${artist}/view/${view}`,{}, {includeResponseMeta: !0})).data + console.log(response) await this.showCollection(response, title, "artists") }, async showRecordLabelView(label, title, view) { - let response = await this.mk.api.recordLabelView(label, view, {}, {view: view, includeResponseMeta: !0}) + let response = (await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/record-labels/${label}/view/${view}`)).data await this.showCollection(response, title, "record-labels") }, async showSearchView(term, group, title) { - let response = await this.mk.api.search(term, { + + let requestBody = { platform: "web", groups: group, types: "activities,albums,apple-curators,artists,curators,editorial-items,music-movies,music-videos,playlists,songs,stations,tv-episodes,uploaded-videos,record-labels", @@ -934,17 +1055,23 @@ const app = new Vue({ }, omit: { resource: ["autos"] - } - }, {groups: group, includeResponseMeta: !0}) - console.log(response) - let responseFormat = { - data: response[group].data.data, - next: response[group].next, + }, groups: group } - await this.showCollection(responseFormat, title, "search") + let response = await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/search?term=${term}`, requestBody , { + includeResponseMeta: !0 + }) + + console.log('searchres', response) + let responseFormat = { + data: response.data.results[group].data, + next: response.data.results[group].next, + groups: group + } + await this.showCollection(responseFormat, title, "search", requestBody) }, async getPlaylistContinuous(response, transient = false) { + response = response.data.data[0] let self = this let playlistId = response.id if (!transient) this.playlists.loadingState = 0 @@ -977,33 +1104,30 @@ const app = new Vue({ include: "tracks", platform: "web", "include[library-playlists]": "catalog,tracks", - "fields[playlists]": "curatorName,playlistType,name,artwork,url", - "include[library-songs]": "catalog,artists,albums", - "fields[catalog]": "artistUrl,albumUrl", - "fields[songs]": "artistUrl,albumUrl" + "fields[playlists]": "curatorName,playlistType,name,artwork,url,playParams", + "include[library-songs]": "catalog,artists,albums,playParams,name,artwork,url", + "fields[catalog]": "artistUrl,albumUrl,url", + "fields[songs]": "artistUrl,albumUrl,playParams,name,artwork,url,artistName,albumName,durationInMillis" } if (!transient) { this.playlists.loadingState = 0; } - let playlistId = '' - - try { - app.mk.api.library.playlist(id, params).then(res => { - self.getPlaylistContinuous(res, transient) - }) - } catch (e) { + app.mk.api.v3.music(`/v1/me/library/playlists/${id}`, params).then(res => { + self.getPlaylistContinuous(res, transient) + }).catch((e) => { console.log(e); try { - app.mk.api.library.playlist(id, params).then(res => { + app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/playlists/${id}`, params).then(res => { self.getPlaylistContinuous(res, transient) }) } catch (err) { console.log(err) } - } + }) }, async getArtistFromID(id) { + this.page = "" const artistData = await this.mkapi("artists", false, id, { "views": "featured-release,full-albums,appears-on-albums,featured-albums,featured-on-albums,singles,compilation-albums,live-albums,latest-release,top-music-videos,similar-artists,top-songs,playlists,more-to-hear,more-to-see", "extend": "artistBio,bornOrFormed,editorialArtwork,editorialVideo,isGroup,origin,hero", @@ -1012,9 +1136,9 @@ const app = new Vue({ "fields[albums]": "artistName,artistUrl,artwork,contentRating,editorialArtwork,editorialVideo,name,playParams,releaseDate,url,trackCount", "limit[artists:top-songs]": 20, "art[url]": "f" - }, {includeResponseMeta: !0}) - console.log(artistData) - this.artistPage.data = artistData.data[0] + }, { includeResponseMeta: !0 }) + console.log(artistData.data.data[0]) + this.artistPage.data = artistData.data.data[0] this.page = "artist-page" }, progressBarStyle() { @@ -1063,7 +1187,7 @@ const app = new Vue({ this.search.hints = [] return } - let hints = await app.mkapi("searchHints", false, this.search.term) + let hints = await (await app.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/search/hints?term=${this.search.term}`)).data.results this.search.hints = hints ? hints.terms : [] }, getSongProgress() { @@ -1079,7 +1203,8 @@ const app = new Vue({ return `${mins}:${seconds.replace("0.", "")}` }, hashCode(str) { - let hash = 0, i, chr; + let hash = 0, + i, chr; if (str.length === 0) return hash; for (i = 0; i < str.length; i++) { chr = str.charCodeAt(i); @@ -1094,7 +1219,7 @@ const app = new Vue({ return; } route = route.replace(/#/g, "") - // if the route contains does not include a / then route to the page directly + // if the route contains does not include a / then route to the page directly if (route.indexOf("/") == -1) { this.page = route window.location.hash = this.page @@ -1109,14 +1234,13 @@ const app = new Vue({ kind: page, id: id, attributes: { - playParams: {kind: page, id: id, isLibrary: isLibrary} + playParams: { kind: page, id: id, isLibrary: isLibrary } } }) }, routeView(item) { let kind = (item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')) : (item.type ?? '')); - let id = (item.attributes.playParams ? (item.attributes.playParams.id ?? (item.id ?? '')) : (item.id ?? '')); - ; + let id = (item.attributes.playParams ? (item.attributes.playParams.id ?? (item.id ?? '')) : (item.id ?? ''));; let isLibrary = item.attributes.playParams ? (item.attributes.playParams.isLibrary ?? false) : false; console.log(kind, id, isLibrary) @@ -1154,7 +1278,10 @@ const app = new Vue({ window.location.hash = `${kind}/${id}` document.querySelector("#app-content").scrollTop = 0 } else if (!kind.toString().includes("radioStation") && !kind.toString().includes("song") && !kind.toString().includes("musicVideo") && !kind.toString().includes("uploadedVideo") && !kind.toString().includes("music-movie")) { - let params = {extend: "editorialVideo"} + let params = { + extend: "offers,editorialVideo", + "views": "appears-on,more-by-artist,related-videos,other-versions,you-might-also-like,video-extras,audio-extras", + } app.page = (kind) + "_" + (id); app.getTypeFromID((kind), (id), (isLibrary), params); window.location.hash = `${kind}/${id}${isLibrary ? "/" + isLibrary : ''}` @@ -1176,8 +1303,8 @@ const app = new Vue({ } }, async getNowPlayingItemDetailed(target) { - let u = await app.mkapi(app.mk.nowPlayingItem.playParams.kind, (app.mk.nowPlayingItem.songId == -1), (app.mk.nowPlayingItem.songId != -1) ? app.mk.nowPlayingItem.songId : app.mk.nowPlayingItem["id"], {"include[songs]": "albums,artists"}); - app.searchAndNavigate(u, target) + let u = await app.mkapi(app.mk.nowPlayingItem.playParams.kind, (app.mk.nowPlayingItem.songId == -1), (app.mk.nowPlayingItem.songId != -1) ? app.mk.nowPlayingItem.songId : app.mk.nowPlayingItem["id"], { "include[songs]": "albums,artists" }); + app.searchAndNavigate(u.data.data[0], target) }, async searchAndNavigate(item, target) { let self = this @@ -1198,21 +1325,19 @@ const app = new Vue({ artistId = artistId.substring(artistId.lastIndexOf('ids=') + 4, artistId.lastIndexOf('-')) } } - } catch (_) { - } + } catch (_) {} if (artistId == "") { - let artistQuery = await app.mk.api.search(item.attributes.artistName, { + let artistQuery = (await app.mk.api.v3.music(`v1/catalog/${app.mk.storefrontId}/search?term=${item.attributes.artistName}`, { limit: 1, types: 'artists' - }) + })).data.results; try { if (artistQuery.artists.data.length > 0) { artistId = artistQuery.artists.data[0].id; console.log(artistId) } - } catch (e) { - } + } catch (e) {} } console.log(artistId); if (artistId != "") @@ -1233,21 +1358,19 @@ const app = new Vue({ albumId = albumId.substring(0, albumId.indexOf("?i=")) } } - } catch (_) { - } + } catch (_) {} if (albumId == "") { try { - let albumQuery = await app.mk.api.search(item.attributes.albumName + " " + (item.attributes.artistName ?? ""), { + let albumQuery = (await app.mk.api.v3.music(`v1/catalog/${app.mk.storefrontId}/search?term=${item.attributes.albumName + " " + (item.attributes.artistName ?? "")}`, { limit: 1, types: 'albums' - }) + })).data.results; if (albumQuery.albums.data.length > 0) { albumId = albumQuery.albums.data[0].id; console.log(albumId) } - } catch (e) { - } + } catch (e) {} } if (albumId != "") { self.appRoute(`album/${albumId}`) @@ -1257,25 +1380,23 @@ const app = new Vue({ let labelId = ''; try { labelId = item.relationships['record-labels'].data[0].id - } catch (_) { - } + } catch (_) {} if (labelId == "") { try { - let labelQuery = await app.mk.api.search(item.attributes.recordLabel, { + let labelQuery = (await app.mk.api.v3.music(`v1/catalog/${app.mk.storefrontId}/search?term=${item.attributes.recordLabel}`, { limit: 1, types: 'record-labels' - }) + })).data.results; if (labelQuery["record-labels"].data.length > 0) { labelId = labelQuery["record-labels"].data[0].id; console.log(labelId) } - } catch (e) { - } + } catch (e) {} } if (labelId != "") { app.showingPlaylist = [] - await app.getTypeFromID("recordLabel", labelId, false, {views: 'top-releases,latest-releases,top-artists'}); + await app.getTypeFromID("recordLabel", labelId, false, { views: 'top-releases,latest-releases,top-artists' }); app.page = "recordLabel_" + labelId; } @@ -1288,86 +1409,85 @@ const app = new Vue({ }, getArtistInfo(id, isLibrary) { this.getArtistFromID(id) - //this.getTypeFromID("artist",id,isLibrary,query) + //this.getTypeFromID("artist",id,isLibrary,query) }, playMediaItem(item) { let kind = (item.attributes.playParams ? (item.attributes.playParams.kind ?? (item.type ?? '')) : (item.type ?? '')); - let id = (item.attributes.playParams ? (item.attributes.playParams.id ?? (item.id ?? '')) : (item.id ?? '')); - ; + let id = (item.attributes.playParams ? (item.attributes.playParams.id ?? (item.id ?? '')) : (item.id ?? ''));; let isLibrary = item.attributes.playParams ? (item.attributes.playParams.isLibrary ?? false) : false; let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind; console.log(kind, id, isLibrary) app.mk.stop().then(() => { if (kind.includes("artist")) { - app.mk.setStationQueue({artist: 'a-' + id}).then(() => { + app.mk.setStationQueue({ artist: 'a-' + id }).then(() => { app.mk.play() }) } - // else if (kind.includes("playlist") && (id.startsWith("p.") || id.startsWith("pl."))){ - // /* Randomize array in-place using Durstenfeld shuffle algorithm */ - // function shuffleArray(array) { - // for (var i = array.length - 1; i > 0; i--) { - // var j = Math.floor(Math.random() * (i + 1)); - // var temp = array[i]; - // array[i] = array[j]; - // array[j] = temp; - // } - // } - // app.mk.clearQueue().then(function () { { - // app.mk.setQueue({[truekind]: [item.attributes.playParams.id ?? item.id]}).then(function () { - // app.mk.play().then(function (){ - // app.mk.clearQueue().then(function (){ - // var playlistId = id - // const params = { - // include: "tracks", - // platform: "web", - // "include[library-playlists]": "catalog,tracks", - // "fields[playlists]": "curatorName,playlistType,name,artwork,url", - // "include[library-songs]": "catalog,artists,albums", - // "fields[catalog]": "artistUrl,albumUrl", - // "fields[songs]": "artistUrl,albumUrl" - // } - // var playlistId = '' + // else if (kind.includes("playlist") && (id.startsWith("p.") || id.startsWith("pl."))){ + // /* Randomize array in-place using Durstenfeld shuffle algorithm */ + // function shuffleArray(array) { + // for (var i = array.length - 1; i > 0; i--) { + // var j = Math.floor(Math.random() * (i + 1)); + // var temp = array[i]; + // array[i] = array[j]; + // array[j] = temp; + // } + // } + // app.mk.clearQueue().then(function () { { + // app.mk.setQueue({[truekind]: [item.attributes.playParams.id ?? item.id]}).then(function () { + // app.mk.play().then(function (){ + // app.mk.clearQueue().then(function (){ + // var playlistId = id + // const params = { + // include: "tracks", + // platform: "web", + // "include[library-playlists]": "catalog,tracks", + // "fields[playlists]": "curatorName,playlistType,name,artwork,url", + // "include[library-songs]": "catalog,artists,albums", + // "fields[catalog]": "artistUrl,albumUrl", + // "fields[songs]": "artistUrl,albumUrl" + // } + // var playlistId = '' - // try { - // function getPlaylist(id, params, isLibrary){ - // if (isLibrary){ - // return app.mk.api.library.playlist(id, params) - // } else { return app.mk.api.playlist(id, params)} - // } - // getPlaylist(id, params, isLibrary).then(res => { - // let query = res.relationships.tracks.data.map(item => new MusicKit.MediaItem(item)); - // if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')} - // app.mk.queue.append(query) - // if (!res.relationships.tracks.next) { - // return - // } else { - // getPlaylistTracks(res.relationships.tracks.next) - // } + // try { + // function getPlaylist(id, params, isLibrary){ + // if (isLibrary){ + // return app.mk.api.library.playlist(id, params) + // } else { return app.mk.api.playlist(id, params)} + // } + // getPlaylist(id, params, isLibrary).then(res => { + // let query = res.relationships.tracks.data.map(item => new MusicKit.MediaItem(item)); + // if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')} + // app.mk.queue.append(query) + // if (!res.relationships.tracks.next) { + // return + // } else { + // getPlaylistTracks(res.relationships.tracks.next) + // } - // function getPlaylistTracks(next) { - // app.apiCall(app.musicBaseUrl + next, res => { - // if (res.id != playlistId) { - // return - // } - // let query = res.data.map(item => new MusicKit.MediaItem(item)) - // if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')} - // app.mk.queue.append(query) + // function getPlaylistTracks(next) { + // app.apiCall(app.musicBaseUrl + next, res => { + // if (res.id != playlistId) { + // return + // } + // let query = res.data.map(item => new MusicKit.MediaItem(item)) + // if (app.mk.shuffleMode == 1){shuffleArray(query); console.log('shf')} + // app.mk.queue.append(query) - // if (res.next) { - // getPlaylistTracks(res.next) - // } - // }) - // } - // }) - // } catch (e) {} + // if (res.next) { + // getPlaylistTracks(res.next) + // } + // }) + // } + // }) + // } catch (e) {} - // }) - // }) - // }) - // } - // }) + // }) + // }) + // }) + // } + // }) // } else { app.playMediaItemById((id), (kind), (isLibrary), item.attributes.url ?? '') @@ -1377,7 +1497,7 @@ const app = new Vue({ async getTypeFromID(kind, id, isLibrary = false, params = {}, params2 = {}) { let a; if (kind == "album" | kind == "albums") { - params["include"] = "tracks,artists,record-labels"; + params["include"] = "tracks,artists,record-labels,catalog"; } try { a = await this.mkapi(kind.toString(), isLibrary, id.toString(), params, params2); @@ -1390,19 +1510,18 @@ const app = new Vue({ a = [] } finally { if (kind == "appleCurator") { - app.appleCurator = a + app.appleCurator = a.data.data[0] } else { this.getPlaylistContinuous(a) } } } finally { if (kind == "appleCurator") { - app.appleCurator = a + app.appleCurator = a.data.data[0] } else { this.getPlaylistContinuous(a) } - } - ; + }; }, searchLibrarySongs() { let self = this @@ -1579,12 +1698,12 @@ const app = new Vue({ let searchTerm = this.library.artists.search.toLowerCase() let artistName = "" let albumName = "" - // if (item.attributes.artistName != null) { - // artistName = item.attributes.artistName.toLowerCase() - // } - // if (item.attributes.albumName != null) { - // albumName = item.attributes.albumName.toLowerCase() - // } + // if (item.attributes.artistName != null) { + // artistName = item.attributes.artistName.toLowerCase() + // } + // if (item.attributes.albumName != null) { + // albumName = item.attributes.albumName.toLowerCase() + // } // remove any non-alphanumeric characters and spaces from search term and item name searchTerm = searchTerm.replace(/[^a-z0-9 ]/gi, "") @@ -1606,14 +1725,17 @@ const app = new Vue({ } }, async mkapi(method, library = false, term, params = {}, params2 = {}, attempts = 0) { + if (method.includes(`recordLabel`)) { method = `record-labels` } + if (method.includes(`appleCurator`)) { method = `apple-curators` } if (attempts > 3) { return } + let truemethod = (!method.endsWith("s")) ? (method + "s") : method; try { if (library) { - return await this.mk.api.library[method](term, params, params2) + return await this.mk.api.v3.music(`v1/me/library/${truemethod}/${term.toString()}`, params, params2) } else { - return await this.mk.api[method](term, params, params2) + return await this.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/${truemethod}/${term.toString()}`, params, params2) } } catch (e) { console.log(e) @@ -1650,8 +1772,8 @@ const app = new Vue({ return } this.library.songs.downloadState = 1 - this.library.downloadNotification.show = true - this.library.downloadNotification.message = "Updating library songs..." + this.library.backgroundNotification.show = true + this.library.backgroundNotification.message = app.getLz('notification.updatingLibrarySongs') function downloadChunk() { const params = { @@ -1665,14 +1787,14 @@ const app = new Vue({ } self.library.songs.downloadState = 1 if (downloaded == null) { - app.mk.api.library.songs("", params, {includeResponseMeta: !0}).then((response) => { - processChunk(response) + app.mk.api.v3.music(`/v1/me/library/songs/`, params).then((response) => { + processChunk(response.data) }) } else { - if (downloaded.next != null && typeof downloaded.next === "function") { - downloaded.next("", params, {includeResponseMeta: !0}).then((response) => { - processChunk(response) + if (downloaded.next != null) { + app.mk.api.v3.music(downloaded.next, params).then((response) => { + processChunk(response.data) }) } else { console.log("Download next", downloaded.next) @@ -1683,10 +1805,10 @@ const app = new Vue({ function processChunk(response) { downloaded = response library = library.concat(downloaded.data) - self.library.downloadNotification.show = true - self.library.downloadNotification.message = "Updating library songs..." - self.library.downloadNotification.total = downloaded.meta.total - self.library.downloadNotification.progress = library.length + self.library.backgroundNotification.show = true + self.library.backgroundNotification.message = app.getLz('notification.updatingLibrarySongs') + self.library.backgroundNotification.total = downloaded.meta.total + self.library.backgroundNotification.progress = library.length if (downloaded.meta.total == 0) { self.library.songs.downloadState = 3 @@ -1696,7 +1818,7 @@ const app = new Vue({ console.log("downloaded.next is undefined") self.library.songs.listing = library self.library.songs.downloadState = 2 - self.library.downloadNotification.show = false + self.library.backgroundNotification.show = false self.searchLibrarySongs() localStorage.setItem("librarySongs", JSON.stringify(library)) } @@ -1706,7 +1828,7 @@ const app = new Vue({ } else { self.library.songs.listing = library self.library.songs.downloadState = 2 - self.library.downloadNotification.show = false + self.library.backgroundNotification.show = false self.searchLibrarySongs() localStorage.setItem("librarySongs", JSON.stringify(library)) console.log(library) @@ -1731,8 +1853,8 @@ const app = new Vue({ return } this.library.albums.downloadState = 1 - this.library.downloadNotification.show = true - this.library.downloadNotification.message = "Updating library albums..." + this.library.backgroundNotification.show = true + this.library.backgroundNotification.message = app.getLz('notification.updatingLibraryAlbums') function downloadChunk() { self.library.albums.downloadState = 1 @@ -1746,13 +1868,13 @@ const app = new Vue({ limit: 100, } if (downloaded == null) { - app.mk.api.library.albums("", params, {includeResponseMeta: !0}).then((response) => { - processChunk(response) + app.mk.api.v3.music(`/v1/me/library/albums/`, params).then((response) => { + processChunk(response.data) }) } else { - if (downloaded.next != null && typeof downloaded.next === "function") { - downloaded.next("", params, {includeResponseMeta: !0}).then((response) => { - processChunk(response) + if (downloaded.next != null) { + app.mk.api.v3.music(downloaded.next, params).then((response) => { + processChunk(response.data) }) } else { console.log("Download next", downloaded.next) @@ -1763,10 +1885,10 @@ const app = new Vue({ function processChunk(response) { downloaded = response library = library.concat(downloaded.data) - self.library.downloadNotification.show = true - self.library.downloadNotification.message = "Updating library albums..." - self.library.downloadNotification.total = downloaded.meta.total - self.library.downloadNotification.progress = library.length + self.library.backgroundNotification.show = true + self.library.backgroundNotification.message = app.getLz('notification.updatingLibraryAlbums') + self.library.backgroundNotification.total = downloaded.meta.total + self.library.backgroundNotification.progress = library.length if (downloaded.meta.total == 0) { self.library.albums.downloadState = 3 return @@ -1775,7 +1897,7 @@ const app = new Vue({ console.log("downloaded.next is undefined") self.library.albums.listing = library self.library.albums.downloadState = 2 - self.library.downloadNotification.show = false + self.library.backgroundNotification.show = false localStorage.setItem("libraryAlbums", JSON.stringify(library)) self.searchLibraryAlbums(index) } @@ -1786,7 +1908,7 @@ const app = new Vue({ } else { self.library.albums.listing = library self.library.albums.downloadState = 2 - self.library.downloadNotification.show = false + self.library.backgroundNotification.show = false localStorage.setItem("libraryAlbums", JSON.stringify(library)) self.searchLibraryAlbums(index) console.log(library) @@ -1811,8 +1933,8 @@ const app = new Vue({ return } this.library.artists.downloadState = 1 - this.library.downloadNotification.show = true - this.library.downloadNotification.message = "Updating library artists..." + this.library.backgroundNotification.show = true + this.library.backgroundNotification.message = app.getLz('notification.updatingLibraryArtists') function downloadChunk() { self.library.artists.downloadState = 1 @@ -1827,13 +1949,14 @@ const app = new Vue({ limit: 100, } if (downloaded == null) { - app.mk.api.library.artists("", params, {includeResponseMeta: !0}).then((response) => { - processChunk(response) + app.mk.api.v3.music(`/v1/me/library/artists/`, params).then((response) => { + processChunk(response.data) }) + } else { - if (downloaded.next != null && typeof downloaded.next === "function") { - downloaded.next("", "artists", {includeResponseMeta: !0}).then((response) => { - processChunk(response) + if (downloaded.next != null) { + app.mk.api.v3.music(downloaded.next, params).then((response) => { + processChunk(response.data) }) } else { console.log("Download next", downloaded.next) @@ -1845,10 +1968,10 @@ const app = new Vue({ function processChunk(response) { downloaded = response library = library.concat(downloaded.data) - self.library.downloadNotification.show = true - self.library.downloadNotification.message = "Updating library artists..." - self.library.downloadNotification.total = downloaded.meta.total - self.library.downloadNotification.progress = library.length + self.library.backgroundNotification.show = true + self.library.backgroundNotification.message = app.getLz('notification.updatingLibraryArtists') + self.library.backgroundNotification.total = downloaded.meta.total + self.library.backgroundNotification.progress = library.length if (downloaded.meta.total == 0) { self.library.albums.downloadState = 3 return @@ -1868,7 +1991,7 @@ const app = new Vue({ } else { self.library.artists.listing = library self.library.artists.downloadState = 2 - self.library.downloadNotification.show = false + self.library.backgroundNotification.show = false localStorage.setItem("libraryArtists", JSON.stringify(library)) self.searchLibraryArtists(index) console.log(library) @@ -1880,59 +2003,62 @@ const app = new Vue({ getTotalTime() { try { if (app.showingPlaylist.relationships.tracks.data.length > 0) { - let time = Math.round([].concat(...app.showingPlaylist.relationships.tracks.data).reduce((a, {attributes: {durationInMillis}}) => a + durationInMillis, 0) / 1000); + let time = Math.round([].concat(...app.showingPlaylist.relationships.tracks.data).reduce((a, { attributes: { durationInMillis } }) => a + durationInMillis, 0) / 1000); let hours = Math.floor(time / 3600) let mins = Math.floor(time / 60) % 60 let secs = time % 60 - return app.showingPlaylist.relationships.tracks.data.length + " track" + (app.showingPlaylist.relationships.tracks.data.length > 1 ? "s" : "") + ", " + ((hours > 0) ? (hours + (" hour" + ((hours > 1) ? "s, " : ", "))) : "") + ((mins > 0) ? (mins + (" minute" + ((mins > 1) ? "s, " : ", "))) : "") + secs + (" second" + ((secs > 1) ? "s." : ".")); + return app.showingPlaylist.relationships.tracks.data.length + " " + app.getLz('term.tracks') +", " + ((hours > 0) ? (hours + (" " + ((hours > 1) ? app.getLz('term.time.hours') + ", " : app.getLz('term.time.hour') +", "))) : "") + ((mins > 0) ? (mins + ((mins > 1) ? " " + app.getLz('term.time.minutes') + ", " : " " + app.getLz('term.time.minute') + ", ")) : "") + secs + ((secs > 1) ? " " + app.getLz('term.time.seconds') + "." : " " + app.getLz('term.time.second') + "."); } else return "" } catch (err) { return "" } }, async getLibrarySongs() { - let response = await this.mkapi("songs", true, "", {limit: 100}, {includeResponseMeta: !0}) - this.library.songs.listing = response.data - this.library.songs.meta = response.meta + let response = await this.mkapi("songs", true, "", { limit: 100 }, { includeResponseMeta: !0 }) + this.library.songs.listing = response.data.data + this.library.songs.meta = response.data.meta }, async getLibraryAlbums() { - let response = await this.mkapi("albums", true, "", {limit: 100}, {includeResponseMeta: !0}) - this.library.albums.listing = response.data - this.library.albums.meta = response.meta + let response = await this.mkapi("albums", true, "", { limit: 100 }, { includeResponseMeta: !0 }) + this.library.albums.listing = response.data.data + this.library.albums.meta = response.data.meta }, async getListenNow(attempt = 0) { + if (this.listennow.timestamp > Date.now() - 120000) { + return + } + if (attempt > 3) { return } try { - this.listennow = await this.mk.api.personalRecommendations("", - { - name: "listen-now", - with: "friendsMix,library,social", - "art[social-profiles:url]": "c", - "art[url]": "c,f", - "omit[resource]": "autos", - "relate[editorial-items]": "contents", - extend: ["editorialCard", "editorialVideo"], - "extend[albums]": ["artistUrl"], - "extend[library-albums]": ["artistUrl", "editorialVideo"], - "extend[playlists]": ["artistNames", "editorialArtwork", "editorialVideo"], - "extend[library-playlists]": ["artistNames", "editorialArtwork", "editorialVideo"], - "extend[social-profiles]": "topGenreNames", - "include[albums]": "artists", - "include[songs]": "artists", - "include[music-videos]": "artists", - "fields[albums]": ["artistName", "artistUrl", "artwork", "contentRating", "editorialArtwork", "editorialVideo", "name", "playParams", "releaseDate", "url"], - "fields[artists]": ["name", "url"], - "extend[stations]": ["airDate", "supportsAirTimeUpdates"], - "meta[stations]": "inflectionPoints", - types: "artists,albums,editorial-items,library-albums,library-playlists,music-movies,music-videos,playlists,stations,uploaded-audios,uploaded-videos,activities,apple-curators,curators,tv-shows,social-upsells", - platform: "web" - }, - { - includeResponseMeta: !0, - reload: !0 - }); + this.listennow = (await this.mk.api.v3.music(`v1/me/recommendations?timezone=${encodeURIComponent(this.formatTimezoneOffset())}`, { + name: "listen-now", + with: "friendsMix,library,social", + "art[social-profiles:url]": "c", + "art[url]": "c,f", + "omit[resource]": "autos", + "relate[editorial-items]": "contents", + extend: ["editorialCard", "editorialVideo"], + "extend[albums]": ["artistUrl"], + "extend[library-albums]": ["artistUrl", "editorialVideo"], + "extend[playlists]": ["artistNames", "editorialArtwork", "editorialVideo"], + "extend[library-playlists]": ["artistNames", "editorialArtwork", "editorialVideo"], + "extend[social-profiles]": "topGenreNames", + "include[albums]": "artists", + "include[songs]": "artists", + "include[music-videos]": "artists", + "fields[albums]": ["artistName", "artistUrl", "artwork", "contentRating", "editorialArtwork", "editorialVideo", "name", "playParams", "releaseDate", "url"], + "fields[artists]": ["name", "url"], + "extend[stations]": ["airDate", "supportsAirTimeUpdates"], + "meta[stations]": "inflectionPoints", + types: "artists,albums,editorial-items,library-albums,library-playlists,music-movies,music-videos,playlists,stations,uploaded-audios,uploaded-videos,activities,apple-curators,curators,tv-shows,social-upsells", + platform: "web" + }, { + includeResponseMeta: !0, + reload: !0 + })).data; + this.listennow.timestamp = Date.now() console.log(this.listennow) } catch (e) { console.log(e) @@ -1940,23 +2066,26 @@ const app = new Vue({ } }, async getBrowsePage(attempt = 0) { + if (this.browsepage.timestamp > Date.now() - 120000) { + return + } if (attempt > 3) { return } try { - let browse = await this.mk.api.groupings("", - { - platform: "web", - name: "music", - "omit[resource:artists]": "relationships", - "include[albums]": "artists", - "include[songs]": "artists", - "include[music-videos]": "artists", - extend: "editorialArtwork,artistUrl", - "fields[artists]": "name,url,artwork,editorialArtwork,genreNames,editorialNotes", - "art[url]": "f" - }); - this.browsepage = browse[0]; + let browse = await app.mk.api.v3.music(`/v1/editorial/${app.mk.storefrontId}/groupings`, { + platform: "web", + name: "music", + "omit[resource:artists]": "relationships", + "include[albums]": "artists", + "include[songs]": "artists", + "include[music-videos]": "artists", + extend: "editorialArtwork,artistUrl", + "fields[artists]": "name,url,artwork,editorialArtwork,genreNames,editorialNotes", + "art[url]": "f" + }); + this.browsepage = browse.data.data[0]; + this.browsepage.timestamp = Date.now() console.log(this.browsepage) } catch (e) { console.log(e) @@ -1968,11 +2097,10 @@ const app = new Vue({ return } try { - this.radio.personal = await this.mkapi("recentRadioStations", false, "", - { - "platform": "web", - "art[url]": "f" - }); + this.radio.personal = (await app.mk.api.v3.music(`/v1/me/recent/radio-stations`, { + "platform": "web", + "art[url]": "f" + })).data.data; } catch (e) { console.log(e) this.getRadioStations(attempt + 1) @@ -1993,13 +2121,11 @@ const app = new Vue({ newPlaylistFolder(name = "New Folder") { let self = this this.mk.api.v3.music( - "/v1/me/library/playlist-folders/", - {}, - { + "/v1/me/library/playlist-folders/", {}, { fetchOptions: { method: "POST", body: JSON.stringify({ - attributes: {name: name} + attributes: { name: name } }) } } @@ -2058,7 +2184,11 @@ const app = new Vue({ removeFromLibrary(kind, id) { let self = this let truekind = (!kind.endsWith("s")) ? (kind + "s") : kind; - this.mk.api.library.remove({[truekind]: id}).then((data) => { + app.mk.api.v3.music(`v1/me/library/${truekind}/${id.toString()}`, {}, { + fetchOptions: { + method: "DELETE" + } + }).then((data) => { self.getLibrarySongsFull(true) }) }, @@ -2082,10 +2212,10 @@ const app = new Vue({ let req = new XMLHttpRequest(); let url = `https://www.youtube.com/watch?&v=${id}`; req.open('GET', url, true); - req.onerror = function (e) { + req.onerror = function(e) { this.loadMXM(); } - req.onload = function () { + req.onload = function() { // console.log(this.responseText); res = this.responseText; let captionurl1 = res.substring(res.indexOf(`{"playerCaptionsRenderer":{"baseUrl":"`) + (`{"playerCaptionsRenderer":{"baseUrl":"`).length); @@ -2097,10 +2227,10 @@ const app = new Vue({ let req2 = new XMLHttpRequest(); req2.open('GET', newurl, true); - req2.onerror = function (e) { + req2.onerror = function(e) { app.loadMXM(); } - req2.onload = function () { + req2.onload = function() { try { const ttmlLyrics = this.responseText; if (ttmlLyrics) { @@ -2149,7 +2279,7 @@ const app = new Vue({ req.overrideMimeType("application/json"); req.open('GET', url, true); req.setRequestHeader("authority", "apic-desktop.musixmatch.com"); - req.onload = function () { + req.onload = function() { let jsonResponse = JSON.parse(this.responseText); let status2 = jsonResponse["message"]["header"]["status_code"]; if (status2 == 200) { @@ -2174,7 +2304,7 @@ const app = new Vue({ } }; - req.onerror = function () { + req.onerror = function() { console.log('error'); app.loadAMLyrics(); }; @@ -2192,7 +2322,7 @@ const app = new Vue({ req.overrideMimeType("application/json"); req.open('GET', url, true); req.setRequestHeader("authority", "apic-desktop.musixmatch.com"); - req.onload = function () { + req.onload = function() { let jsonResponse = JSON.parse(this.responseText); console.log(jsonResponse); let status1 = jsonResponse["message"]["header"]["status_code"]; @@ -2208,8 +2338,7 @@ const app = new Vue({ lrcrich = jsonResponse["message"]["body"]["macro_calls"]["track.richsync.get"]["message"]["body"]["richsync"]["richsync_body"]; richsync = JSON.parse(lrcrich); app.richlyrics = richsync; - } catch (_) { - } + } catch (_) {} } if (lrcfile == "") { @@ -2240,7 +2369,7 @@ const app = new Vue({ }); app.lyrics = preLrc.reverse(); } else { - preLrc = richsync.map(function (item) { + preLrc = richsync.map(function(item) { return { startTime: item.ts, endTime: item.te, @@ -2283,7 +2412,7 @@ const app = new Vue({ req2.overrideMimeType("application/json"); req2.open('GET', url2, true); req2.setRequestHeader("authority", "apic-desktop.musixmatch.com"); - req2.onload = function () { + req2.onload = function() { let jsonResponse2 = JSON.parse(this.responseText); console.log(jsonResponse2); let status2 = jsonResponse2["message"]["header"]["status_code"]; @@ -2354,15 +2483,15 @@ const app = new Vue({ line: "lrcInstrumental" }); } - preLrc.push({startTime: start, endTime: end, line: element.textContent}); + preLrc.push({ startTime: start, endTime: end, line: element.textContent }); endTimes.push(end); } // first line dot if (preLrc.length > 0) - preLrc.unshift({startTime: 0, endTime: preLrc[0].startTime, line: "lrcInstrumental"}); + preLrc.unshift({ startTime: 0, endTime: preLrc[0].startTime, line: "lrcInstrumental" }); } else { for (element of lyricsLines) { - preLrc.push({startTime: 9999999, endTime: 9999999, line: element.textContent}); + preLrc.push({ startTime: 9999999, endTime: 9999999, line: element.textContent }); } } this.lyrics = preLrc; @@ -2412,8 +2541,8 @@ const app = new Vue({ // let duration = this.mk.nowPlayingItem.attributes.durationInMillis let start2 = this.hmsToSecondsOnly(start) let end2 = this.hmsToSecondsOnly(end) - // let currentProgress = ((100 * (currentTime)) / (end2)) - // check if currenttime is between start and end + // let currentProgress = ((100 * (currentTime)) / (end2)) + // check if currenttime is between start and end this.player.lyricsDebug.start = start2 this.player.lyricsDebug.end = end2 this.player.lyricsDebug.current = currentTime @@ -2430,15 +2559,17 @@ const app = new Vue({ console.log(id, truekind, isLibrary) try { if (truekind.includes("artist")) { - app.mk.setStationQueue({artist: 'a-' + id}).then(() => { + app.mk.setStationQueue({ artist: 'a-' + id }).then(() => { app.mk.play() }) } else if (truekind == "radioStations") { - this.mk.setStationQueue({url: raurl}).then(function (queue) { + this.mk.setStationQueue({ url: raurl }).then(function(queue) { MusicKit.getInstance().play() }); } else { - this.mk.setQueue({[truekind]: [id]}).then(function (queue) { + this.mk.setQueue({ + [truekind]: [id] + }).then(function(queue) { MusicKit.getInstance().play() }) } @@ -2475,49 +2606,64 @@ const app = new Vue({ app.mk.stop().then(() => { - this.mk.clearQueue().then(function (_) { - if (app.mk.shuffleMode == 1) { - shuffleArray(query) - } - app.mk.queue.append(query) - if (childIndex != -1) { - app.mk.changeToMediaAtIndex(childIndex) - } else if (item) { - app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () { - app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1) - app.mk.play() + if (item) { + app.mk.setQueue({ + [item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id + }).then(function () { + app.mk.play().then(() => { + if (app.mk.shuffleMode == 1) { + shuffleArray(query) + } else { + for (let i = 0; i < query.length; i++) { + if (query[i].id == item.id) {query.splice(0, i+1); + break;} + } + } + app.mk.queue.append(query) }) - } else { - app.mk.play() - } - }) + }) + } else { + this.mk.clearQueue().then(function (_) { + if (app.mk.shuffleMode == 1) { + shuffleArray(query) + } + app.mk.queue.append(query) + if (childIndex != -1) { + app.mk.changeToMediaAtIndex(childIndex) + } else { + app.mk.play() + } + }) + } }) } else { app.mk.stop().then(() => { if (truekind == "playlists" && (id.startsWith("p.") || id.startsWith("pl.u"))) { - app.mk.setQueue({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () { - app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1).then(function () { + app.mk.setQueue({ + [item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id + }).then(function() { + app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1).then(function() { if ((app.showingPlaylist && app.showingPlaylist.id == id)) { - let query = app.showingPlaylist.relationships.tracks.data.map(item => new MusicKit.MediaItem(item)), - u; - - u = query; - + let query = app.showingPlaylist.relationships.tracks.data.map(item => new MusicKit.MediaItem(item)); + let u = query; if (app.mk.shuffleMode == 1) { shuffleArray(u) } else { for (let i = 0; i < app.showingPlaylist.relationships.tracks.data.length; i++) { - if (app.showingPlaylist.relationships.tracks.data[i].id == item.id) u.splice(0, i+1); + if (app.showingPlaylist.relationships.tracks.data[i].id == item.id) {u.splice(0, i+1); break;} } } - app.mk.queue.append(u) } else { - app.getPlaylistFromID(id, true).then(function () { + app.getPlaylistFromID(id, true).then(function() { let query = app.showingPlaylist.relationships.tracks.data.map(item => new MusicKit.MediaItem(item)); let u = query; if (app.mk.shuffleMode == 1) { shuffleArray(u) + } else { + for (let i = 0; i < app.showingPlaylist.relationships.tracks.data.length; i++) { + if (app.showingPlaylist.relationships.tracks.data[i].id == item.id) {u.splice(0, i+1); break;} + } } app.mk.queue.append(u) }) @@ -2526,14 +2672,18 @@ const app = new Vue({ }) } else { - this.mk.setQueue({[truekind]: [id]}).then(function (queue) { + this.mk.setQueue({ + [truekind]: [id] + }).then(function(queue) { if (item && ((queue._itemIDs[childIndex] != item.id))) { childIndex = queue._itemIDs.indexOf(item.id) } if (childIndex != -1) { app.mk.changeToMediaAtIndex(childIndex) } else if (item) { - app.mk.playNext({[item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id}).then(function () { + app.mk.playNext({ + [item.attributes.playParams.kind ?? item.type]: item.attributes.playParams.id ?? item.id + }).then(function() { app.mk.changeToMediaAtIndex(app.mk.queue._itemIDs.indexOf(item.id) ?? 1) app.mk.play() }) @@ -2548,8 +2698,7 @@ const app = new Vue({ console.log(err) try { app.mk.stop() - } catch (e) { - } + } catch (e) {} this.playMediaItemById(item.attributes.playParams.id ?? item.id, item.attributes.playParams.kind ?? item.type, item.attributes.playParams.isLibrary ?? false, item.attributes.url) } @@ -2606,34 +2755,37 @@ const app = new Vue({ if (term == "") { return } - this.mk.api.search(this.search.term, - { - types: "activities,albums,apple-curators,artists,curators,editorial-items,music-movies,music-videos,playlists,songs,stations,tv-episodes,uploaded-videos,record-labels", - "relate[editorial-items]": "contents", - "include[editorial-items]": "contents", - "include[albums]": "artists", - "include[artists]": "artists", - "include[songs]": "artists,albums", - "include[music-videos]": "artists", - "extend": "artistUrl", - "fields[artists]": "url,name,artwork,hero", - "fields[albums]": "artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url", - "with": "serverBubbles,lyricHighlights", - "art[url]": "c,f", - "omit[resource]": "autos", - "platform": "web", - limit: 25 - }).then(function (results) { - self.search.results = results + //this.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/search?term=${this.search.term}` + this.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/search?term=${this.search.term}`, { + types: "activities,albums,apple-curators,artists,curators,editorial-items,music-movies,music-videos,playlists,songs,stations,tv-episodes,uploaded-videos,record-labels", + "relate[editorial-items]": "contents", + "include[editorial-items]": "contents", + "include[albums]": "artists", + "include[artists]": "artists", + "include[songs]": "artists,albums", + "include[music-videos]": "artists", + "extend": "artistUrl", + "fields[artists]": "url,name,artwork,hero", + "fields[albums]": "artistName,artistUrl,artwork,contentRating,editorialArtwork,name,playParams,releaseDate,url", + "with": "serverBubbles,lyricHighlights", + "art[url]": "c,f", + "omit[resource]": "autos", + "platform": "web", + limit: 25 + }).then(function(results) { + results.data.results["meta"] = results.data.meta + self.search.results = results.data.results }) - await this.mk.api.socialSearch(this.search.term, { + + await app.mk.api.v3.music(`v1/social/${app.mk.storefrontId}/search?term=${app.search.term}`, { types: ["playlists", "social-profiles"], limit: 25, with: ["serverBubbles", "lyricSnippet"], "art[url]": "f", "art[social-profiles:url]": "c" - }, {includeResponseMeta: !0}).then(function (results) { - self.search.resultsSocial = results + }, { includeResponseMeta: !0 }).then(function(results) { + results.data.results["meta"] = results.data.meta + self.search.resultsSocial = results.data.results }) }, async inLibrary(items = []) { @@ -2647,25 +2799,37 @@ const app = new Vue({ type = type.replace("library-", "") let id = item.attributes.playParams.catalogId ?? item.id - let index = types.findIndex(function (type) { + let index = types.findIndex(function(type) { return type.type == this }, type) if (index == -1) { - types.push({type: type, id: [id]}) + types.push({ type: type, id: [id] }) } else { types[index].id.push(id) } } - return await this.mk.api.catalogResources(types, { - "omit[resource]": "autos", - relate: "library", - fields: "inLibrary" + types2 = types.map(function(item) { + return { + [`ids[${item.type}]`]: [item.id] + } }) + types2 = types2.reduce(function(result, item) { + var key = Object.keys(item)[0]; //first property: a, b, c + result[key] = item[key]; + return result; + }, {}); + return (await this.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}`, {... { + "omit[resource]": "autos", + relate: "library", + fields: "inLibrary" + }, + ...types2 + })).data.data }, isInLibrary(playParams) { let self = this let id = "" - // ugly code to check if current playback item is in library + // ugly code to check if current playback item is in library if (typeof playParams == "undefined") { return true } @@ -2711,7 +2875,7 @@ const app = new Vue({ // if rgb return `rgb(${rgb[0]},${rgb[1]},${rgb[2]})` }, - getNowPlayingArtworkBG(size = 600) { + getNowPlayingArtworkBG(size = 32, force = false) { let self = this if (typeof this.mk.nowPlayingItem === "undefined") return; let bginterval = setInterval(() => { @@ -2720,7 +2884,7 @@ const app = new Vue({ } try { - if (this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] != this.currentTrackID && document.querySelector('.bg-artwork')) { + if ((this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] != this.currentTrackID && document.querySelector('.bg-artwork')) || force) { if (document.querySelector('.bg-artwork')) { clearInterval(bginterval); } @@ -2752,24 +2916,21 @@ const app = new Vue({ try { clearInterval(bginterval); - } catch (err) { - } + } catch (err) {} } else { this.setLibraryArtBG() } } else if (this.mk.nowPlayingItem["id"] == this.currentTrackID) { try { clearInterval(bginterval); - } catch (err) { - } + } catch (err) {} } } catch (e) { if (this.mk.nowPlayingItem && this.mk.nowPlayingItem["id"] && document.querySelector('.bg-artwork')) { this.setLibraryArtBG() try { clearInterval(bginterval); - } catch (err) { - } + } catch (err) {} } } }, 200) @@ -2822,22 +2983,25 @@ const app = new Vue({ this.currentArtUrl = (this.mk["nowPlayingItem"]["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50); try { document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`); - } catch (e) { - } + } catch (e) {} } else { - let data = await this.mk.api.library.song(this.mk.nowPlayingItem.id); + let data = await this.mk.api.v3.music(`/v1/me/library/songs/${this.mk.nowPlayingItem.id}`); + data = data.data.data[0]; if (data != null && data !== "" && data.attributes != null && data.attributes.artwork != null) { - this.currentArtUrl = (data["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50); + this.currentArtUrl = (data["attributes"]["artwork"]["url"] ?? '').replace('{w}', 50).replace('{h}', 50); + // if (this.currentArtUrl != ""){ + // let attr = MusicKitInterop.getAttributes(); + // attr.artwork.url = this.currentArtUrl; + // ipcRenderer.send('forceUpdateRPC',attr) + // } try { document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`); - } catch (e) { - } + } catch (e) {} } else { this.currentArtUrl = ''; try { document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("${this.currentArtUrl}")`); - } catch (e) { - } + } catch (e) {} } } } catch (e) { @@ -2846,23 +3010,22 @@ const app = new Vue({ }, async setLibraryArt() { if (typeof this.mk.nowPlayingItem === "undefined") return; - const data = await this.mk.api.library.song(this.mk.nowPlayingItem["id"]) try { - const data = await this.mk.api.library.song(this.mk.nowPlayingItem.id) + const data = await this.mk.api.v3.music(`/v1/me/library/songs/${this.mk.nowPlayingItem.id}`); + data = data.data.data[0]; if (data != null && data !== "") { document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', 'url("' + (data["attributes"]["artwork"]["url"]).toString() + '")'); } else { document.querySelector('.app-playback-controls .artwork').style.setProperty('--artwork', `url("")`); } - } catch (e) { - } + } catch (e) {} }, async setLibraryArtBG() { if (typeof this.mk.nowPlayingItem === "undefined") return; - const data = await this.mk.api.library.song(this.mk.nowPlayingItem["id"]) try { - const data = await this.mk.api.library.song(this.mk.nowPlayingItem.id) + const data = await this.mk.api.v3.music(`/v1/me/library/songs/${this.mk.nowPlayingItem.id}`); + data = data.data.data[0]; if (data != null && data !== "") { getBase64FromUrl((data["attributes"]["artwork"]["url"]).toString()).then(img => { @@ -2872,14 +3035,13 @@ const app = new Vue({ self.$store.commit("setLCDArtwork", img) }) } - } catch (e) { - } + } catch (e) {} }, quickPlay(query) { let self = this - MusicKit.getInstance().api.search(query, {limit: 2, types: 'songs'}).then(function (data) { - MusicKit.getInstance().setQueue({song: data["songs"]['data'][0]["id"]}).then(function (queue) { + MusicKit.getInstance().api.search(query, { limit: 2, types: 'songs' }).then(function(data) { + MusicKit.getInstance().setQueue({ song: data["songs"]['data'][0]["id"] }).then(function(queue) { MusicKit.getInstance().play() setTimeout(() => { self.$forceUpdate() @@ -2896,7 +3058,7 @@ const app = new Vue({ } id = item.id } - let response = await this.mk.api.v3.music(`/v1/me/ratings/${type}?platform=web&ids=${id}`) + let response = await this.mk.api.v3.music(`/v1/me/ratings/${type}?platform=web&ids=${type.includes('library') ? item.id : id}`) if (response.data.data.length != 0) { let value = response.data.data[0].attributes.value return value @@ -2914,18 +3076,15 @@ const app = new Vue({ id = item.id } this.mk.api.v3.music(`/v1/me/ratings/${type}/${id}`, {}, { - fetchOptions: - { - method: "PUT", - body: JSON.stringify( - { - "type": "rating", - "attributes": { - "value": 1 - } - } - ) - } + fetchOptions: { + method: "PUT", + body: JSON.stringify({ + "type": "rating", + "attributes": { + "value": 1 + } + }) + } }) }, dislike(item) { @@ -2938,18 +3097,15 @@ const app = new Vue({ id = item.id } this.mk.api.v3.music(`/v1/me/ratings/${type}/${id}`, {}, { - fetchOptions: - { - method: "PUT", - body: JSON.stringify( - { - "type": "rating", - "attributes": { - "value": -1 - } - } - ) - } + fetchOptions: { + method: "PUT", + body: JSON.stringify({ + "type": "rating", + "attributes": { + "value": -1 + } + }) + } }) }, unlove(item) { @@ -2962,31 +3118,50 @@ const app = new Vue({ id = item.id } this.mk.api.v3.music(`/v1/me/ratings/${type}/${id}`, {}, { - fetchOptions: - { - method: "DELETE", - } + fetchOptions: { + method: "DELETE", + } }) }, volumeWheel(event) { + if (this.cfg.audio.maxVolume < 1.0 && this.cfg.audio.maxVolume > 0.01) { + this.cfg.audio.volumePrecision = 0.01 + this.cfg.audio.volumeRoundMax = this.cfg.audio.maxVolume - 0.01 + this.cfg.audio.volumeRoundMin = 0.01 + } if (event.deltaY < 0) { - if (this.mk.volume < 1) { - if (this.mk.volume <= 0.9) { - this.mk.volume += 0.1 + if (this.mk.volume < this.cfg.audio.maxVolume) { + if (this.mk.volume <= this.cfg.audio.volumeRoundMax) { + this.mk.volume += this.cfg.audio.volumePrecision } else { - this.mk.volume = 1 + this.mk.volume = this.cfg.audio.maxVolume } } } else if (event.deltaY > 0) { if (this.mk.volume > 0) { - if (this.mk.volume >= 0.1) { - this.mk.volume -= 0.1 + if (this.mk.volume >= this.cfg.audio.volumeRoundMin) { + this.mk.volume -= this.cfg.audio.volumePrecision } else { this.mk.volume = 0 } } } }, + muteButtonPressed() { + if( this.cfg.audio.muted ) { + this.mk.volume = this.cfg.audio.lastVolume; + this.cfg.audio.muted = false; + } else { + this.cfg.audio.lastVolume = this.cfg.audio.volume; + this.mk.volume = 0; + this.cfg.audio.muted = true; + } + }, + checkMuteChange() { + if( this.cfg.audio.muted ) { + this.cfg.audio.muted = false; + } + }, async apiCall(url, callback) { const xmlHttp = new XMLHttpRequest(); @@ -3013,8 +3188,9 @@ const app = new Vue({ }, fetchPlaylist(id, callback) { // id can be found in playlist.attributes.playParams.globalId - this.mk.api.playlist(id).then(res => { - callback(res) + // this.mk.api. + this.mk.api.v3.music(`/v1/catalog/${app.mk.storefrontId}/playlists/${id}`).then(res => { + callback(res.data.data[0]) }) // tracks are found in relationship.data @@ -3040,11 +3216,11 @@ const app = new Vue({ let data_type = this.mk.nowPlayingItem.playParams.kind let item_id = this.mk.nowPlayingItem.attributes.playParams.id ?? this.mk.nowPlayingItem.id let isLibrary = this.mk.nowPlayingItem.attributes.playParams.isLibrary ?? false - let params = {"fields[songs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library", "t": "1"} - // let res = await app.mkapi(data_type, isLibrary , item_id, params); - // if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) { - // item_id = res.relationships.library.data[0].id - // } + let params = { "fields[songs]": "inLibrary", "fields[albums]": "inLibrary", "relate": "library", "t": "1" } + // let res = await app.mkapi(data_type, isLibrary , item_id, params); + // if (res && res.relationships && res.relationships.library && res.relationships.library.data && res.relationships.library.data.length > 0) { + // item_id = res.relationships.library.data[0].id + // } app.selectedMediaItems = [] app.select_selectMediaItem(item_id, data_type, 0, '12344', isLibrary) let useMenu = "normal" @@ -3053,14 +3229,13 @@ const app = new Vue({ items: [] }, normal: { - headerItems: [ - { + headerItems: [{ "icon": "./assets/feather/heart.svg", "id": "love", - "name": "Love", + "name": app.getLz('action.love'), "hidden": false, "disabled": true, - "action": function () { + "action": function() { app.love(app.mk.nowPlayingItem) } }, @@ -3068,57 +3243,55 @@ const app = new Vue({ "icon": "./assets/feather/heart.svg", "id": "unlove", "active": true, - "name": "Unlove", + "name": app.getLz('action.unlove'), "hidden": true, - "action": function () { + "action": function() { app.unlove(app.mk.nowPlayingItem) } }, { "icon": "./assets/feather/thumbs-down.svg", "id": "dislike", - "name": "Dislike", + "name": app.getLz('action.dislike'), "hidden": false, "disabled": true, - "action": function () { + "action": function() { app.dislike(app.mk.nowPlayingItem) } }, { "icon": "./assets/feather/thumbs-down.svg", "id": "undo_dislike", - "name": "Undo dislike", + "name": app.getLz('action.undoDislike'), "active": true, "hidden": true, - "action": function () { + "action": function() { app.unlove(app.mk.nowPlayingItem) } }, ], - items: [ - { + items: [{ "icon": "./assets/feather/list.svg", - "name": "Add to Playlist...", - "hidden": true, - "action": function () { + "name": app.getLz('action.addToPlaylist')+" ...", + "action": function() { app.promptAddToPlaylist() } }, { "icon": "./assets/feather/plus.svg", "id": "addToLibrary", - "name": "Add to Library...", + "name": app.getLz('action.addToLibrary')+" ...", "disabled": false, - "action": function () { + "action": function() { app.addToLibrary(app.mk.nowPlayingItem.id); // if (!isLibrary) {app.addToLibrary(item_id); this.mk.nowPlayingItem.attributes.playParams["isLibrary"] = true} else { app.removeFromLibrary(data_type,item_id); this.mk.nowPlayingItem.attributes.playParams["isLibrary"] = false}; } }, { "icon": "./assets/feather/radio.svg", - "name": "Start Radio", - "action": function () { - app.mk.setStationQueue({song: app.mk.nowPlayingItem.id}).then(() => { + "name": app.getLz('action.startRadio'), + "action": function() { + app.mk.setStationQueue({ song: app.mk.nowPlayingItem.id }).then(() => { app.mk.play() app.selectedMediaItems = [] }) @@ -3145,7 +3318,7 @@ const app = new Vue({ // } this.showMenuPanel(menus[useMenu], event) - try{ + try { let rating = await app.getRating(app.mk.nowPlayingItem) if (rating == 0) { menus.normal.headerItems.find(x => x.id == 'love').disabled = false @@ -3157,7 +3330,7 @@ const app = new Vue({ menus.normal.headerItems.find(x => x.id == 'undo_dislike').hidden = false menus.normal.headerItems.find(x => x.id == 'dislike').hidden = true } - } catch(err) { + } catch (err) { } }, @@ -3167,31 +3340,32 @@ const app = new Vue({ app.cfg.lastfm.auth_token = ""; app.cfg.lastfm.enabled = false; const element = document.getElementById('lfmConnect'); - element.innerHTML = 'Connect'; + element.innerHTML = getLz('term.connect'); element.onclick = app.LastFMAuthenticate; }, LastFMAuthenticate() { console.log("[LastFM] Received LastFM authentication callback") const element = document.getElementById('lfmConnect'); + // new key : f9986d12aab5a0fe66193c559435ede3 window.open('https://www.last.fm/api/auth?api_key=f9986d12aab5a0fe66193c559435ede3&cb=cider://auth/lastfm'); - element.innerText = 'Connecting...'; + element.innerText = app.getLz('term.connecting') + '...'; /* Just a timeout for the button */ setTimeout(() => { - if (element.innerText === 'Connecting...') { - element.innerText = 'Connect'; + if (element.innerText === app.getLz('term.connecting') +'...') { + element.innerText = app.getLz('term.connect'); console.warn('[LastFM] Attempted connection timed out.'); } }, 20000); - ipcRenderer.on('LastfmAuthenticated', function (_event, lfmAuthKey) { + ipcRenderer.on('LastfmAuthenticated', function(_event, lfmAuthKey) { app.cfg.lastfm.auth_token = lfmAuthKey; app.cfg.lastfm.enabled = true; - element.innerHTML = `Disconnect\n

(Authed: ${lfmAuthKey})

`; + element.innerHTML = `${app.getLz('term.disconnect')}\n

(${app.getLz('term.authed')}: ${lfmAuthKey})

`; element.onclick = app.LastFMDeauthorize; }); }, - parseSCTagToRG: function (tag) { + parseSCTagToRG: function(tag) { let soundcheck = tag.split(" ") let numbers = [] for (item of soundcheck) { @@ -3223,15 +3397,106 @@ const app = new Vue({ ipcRenderer.send('setFullScreen', false); app.appMode = 'player'; } - } + }, + miniPlayer(flag) { + if (flag) { + this.tmpWidth = window.innerWidth; + this.tmpHeight = window.innerHeight; + ipcRenderer.send('unmaximize'); + ipcRenderer.send('windowmin', 250, 250) + ipcRenderer.send('windowresize', 300, 300, false) + app.appMode = 'mini'; + } else { + ipcRenderer.send('windowmin', 844, 410) + ipcRenderer.send('windowresize', this.tmpWidth, this.tmpHeight, false) + ipcRenderer.send('windowontop', false) + this.cfg.visual.miniplayer_top_toggle = true; + app.appMode = 'player'; + } + }, + pinMiniPlayer() { + if (this.cfg.visual.miniplayer_top_toggle) { + ipcRenderer.send('windowontop', true) + this.cfg.visual.miniplayer_top_toggle = false + } else { + ipcRenderer.send('windowontop', false) + this.cfg.visual.miniplayer_top_toggle = true; + } + }, + formatTimezoneOffset: (e = new Date) => { + let leadingZeros = (e, s = 2) => { + let n = "" + e; + for (; n.length < s;) + n = "0" + n; + return n + } - } + const s = e.getTimezoneOffset(), + n = Math.floor(Math.abs(s) / 60), + d = Math.round(Math.abs(s) % 60); + let h = "+"; + return 0 !== s && (h = s > 0 ? "-" : "+"), + `${h}${leadingZeros(n, 2)}:${leadingZeros(d, 2)}` + }, + toggleHideUserInfo() { + if(this.chrome.hideUserInfo) { + this.cfg.visual.showuserinfo = true + this.chrome.hideUserInfo = false + } else { + this.cfg.visual.showuserinfo = false + this.chrome.hideUserInfo = true + } + }, + isElementOverflowing(selector) { + try{ + let element = document.querySelector(selector); + var overflowX = element.offsetWidth < element.scrollWidth, + overflowY = element.offsetHeight < element.scrollHeight; + element.setAttribute('data-value', '\xa0\xa0\xa0\xa0' + element.textContent); + + return (overflowX || overflowY); } catch (e) { return false} + }, + async showWebRemoteQR(){ + //this.webremoteqr = await ipcRenderer.invoke('setRemoteQR','') + this.webremoteurl = await ipcRenderer.invoke('showQR','') + //this.modals.qrcode = true; + }, + checkMarquee() { + if(isElementOverflowing('#app-main > div.app-chrome > div.app-chrome--center > div > div > div.playback-info > div.song-artist') == true) { + document.getElementsByClassName('song-artist')[0].classList.add('marquee'); + document.getElementsByClassName('song-artist')[1].classList.add('marquee-after'); + } + if(isElementOverflowing('#app-main > div.app-chrome > div.app-chrome--center > div > div > div.playback-info > div.song-name') == true) { + document.getElementsByClassName('song-name')[0].classList.add('marquee'); + document.getElementsByClassName('song-name')[1].classList.add('marquee-after'); + } + }, + closeWindow(){ + switch (app.cfg.general.close_behavior) { + case 0: + case '0': + // the minimizeToTray plugin will handle this + window.close(); + break; + case 1: + case '1': + ipcRenderer.send('minimize'); + break; + case 2: + case '2': + ipcRenderer.send('minimizeTray'); + break; + + } + } + } + }) Vue.component('animated-number', { template: "
{{ displayNumber }}
", - props: {'number': {default: 0}}, + props: { 'number': { default: 0 } }, data() { return { @@ -3284,7 +3549,7 @@ Vue.component('sidebar-library-item', { required: false } }, - data: function () { + data: function() { return { app: app, svgIconData: "" @@ -3299,7 +3564,7 @@ Vue.component('sidebar-library-item', { }); // Key binds -document.addEventListener('keydown', function (e) { +document.addEventListener('keydown', function(e) { if (e.keyCode === 70 && e.ctrlKey) { app.$refs.searchInput.focus() app.$refs.searchInput.select() @@ -3314,11 +3579,37 @@ app.hangtimer = setTimeout(() => { }, 10000) // add event listener for when window.location.hash changes -window.addEventListener("hashchange", function () { +window.addEventListener("hashchange", function() { app.appRoute(window.location.hash) }); -document.addEventListener('musickitloaded', function () { + +function fallbackinitMusicKit() { + const request = new XMLHttpRequest(); + + function loadAlternateKey() { + let parsedJson = JSON.parse(this.responseText) + MusicKit.configure({ + developerToken: parsedJson.developerToken, + app: { + name: 'Apple Music', + build: '1978.4.1', + version: "1.0" + }, + sourceType: 24, + suppressErrorDialog: true + }); + setTimeout(() => { + app.init() + }, 1000) + } + + request.addEventListener("load", loadAlternateKey); + request.open("GET", "https://raw.githubusercontent.com/lujjjh/LitoMusic/main/token.json"); + request.send(); +} + +document.addEventListener('musickitloaded', function() { // MusicKit global is now defined function initMusicKit() { let parsedJson = JSON.parse(this.responseText) @@ -3337,35 +3628,11 @@ document.addEventListener('musickitloaded', function () { }, 1000) } - function fallbackinitMusicKit() { - const request = new XMLHttpRequest(); - - function loadAlternateKey() { - let parsedJson = JSON.parse(this.responseText) - MusicKit.configure({ - developerToken: parsedJson.developerToken, - app: { - name: 'Apple Music', - build: '1978.4.1', - version: "1.0" - }, - sourceType: 24, - suppressErrorDialog: true - }); - setTimeout(() => { - app.init() - }, 1000) - } - - request.addEventListener("load", loadAlternateKey); - request.open("GET", "https://raw.githubusercontent.com/lujjjh/LitoMusic/main/token.json"); - request.send(); - } const request = new XMLHttpRequest(); request.timeout = 5000; request.addEventListener("load", initMusicKit); - request.onreadystatechange = function (aEvt) { + request.onreadystatechange = function(aEvt) { if (request.readyState == 4) { if (request.status != 200) fallbackinitMusicKit() @@ -3375,7 +3642,7 @@ document.addEventListener('musickitloaded', function () { request.send(); // check for widevine failure and reconfigure the instance. - window.addEventListener("drmUnsupported", function () { + window.addEventListener("drmUnsupported", function() { initMusicKit() }); }); @@ -3387,7 +3654,7 @@ if ('serviceWorker' in navigator) { }); } -const getBase64FromUrl = async (url) => { +const getBase64FromUrl = async(url) => { const data = await fetch(url); const blob = await data.blob(); return new Promise((resolve) => { @@ -3400,6 +3667,10 @@ const getBase64FromUrl = async (url) => { }); } +function Clone (obj) { + return JSON.parse(JSON.stringify(obj)); +} + function uuidv4() { return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) @@ -3442,10 +3713,10 @@ function xmlToJson(xml) { for (var i = 0; i < xml.childNodes.length; i++) { var item = xml.childNodes.item(i); var nodeName = item.nodeName; - if (typeof (obj[nodeName]) == "undefined") { + if (typeof(obj[nodeName]) == "undefined") { obj[nodeName] = xmlToJson(item); } else { - if (typeof (obj[nodeName].push) == "undefined") { + if (typeof(obj[nodeName].push) == "undefined") { var old = obj[nodeName]; obj[nodeName] = []; obj[nodeName].push(old); @@ -3468,11 +3739,10 @@ var checkIfScrollIsStatic = setInterval(() => { try { if (position === document.getElementsByClassName('lyric-body')[0].scrollTop) { clearInterval(checkIfScrollIsStatic) - // do something + // do something } position = document.getElementsByClassName('lyric-body')[0].scrollTop - } catch (e) { - } + } catch (e) {} }, 50); @@ -3491,4 +3761,22 @@ webGPU().then() let screenWidth = screen.width; let screenHeight = screen.height; +// Key bind to unjam MusicKit in case it fails: CTRL+F10 +document.addEventListener('keydown', function(event) { + if (event.ctrlKey && event.keyCode == 121) { + try { + app.mk._services.mediaItemPlayback._currentPlayer.stop() + } catch (e) { } + try { + app.mk._services.mediaItemPlayback._currentPlayer.destroy() + } catch (e) { } + } +}); +document.addEventListener('keydown', function(event) { + if (event.ctrlKey && event.keyCode == 122) { + try { + ipcRenderer.send('detachDT','') + } catch (e) { } + } +}); diff --git a/src/renderer/js/WSAPI_Interop.js b/src/renderer/js/WSAPI_Interop.js new file mode 100644 index 00000000..e86327be --- /dev/null +++ b/src/renderer/js/WSAPI_Interop.js @@ -0,0 +1,108 @@ +const wsapi = { + cache: {playParams: {id: 0}, status: null, remainingTime: 0}, + playbackCache: {status: null, time: Date.now()}, + search(term, limit) { + MusicKit.getInstance().api.search(term, {limit: limit, types: 'songs,artists,albums,playlists'}).then((results)=>{ + ipcRenderer.send('wsapi-returnSearch', JSON.stringify(results)) + }) + }, + searchLibrary(term, limit) { + MusicKit.getInstance().api.library.search(term, {limit: limit, types: 'library-songs,library-artists,library-albums,library-playlists'}).then((results)=>{ + ipcRenderer.send('wsapi-returnSearchLibrary', JSON.stringify(results)) + }) + }, + getAttributes: function () { + const mk = MusicKit.getInstance(); + const nowPlayingItem = mk.nowPlayingItem; + const isPlayingExport = mk.isPlaying; + const remainingTimeExport = mk.currentPlaybackTimeRemaining; + const attributes = (nowPlayingItem != null ? nowPlayingItem.attributes : {}); + + attributes.status = isPlayingExport ? isPlayingExport : false; + attributes.name = attributes.name ? attributes.name : 'No Title Found'; + attributes.artwork = attributes.artwork ? attributes.artwork : {url: ''}; + attributes.artwork.url = attributes.artwork.url ? attributes.artwork.url : ''; + attributes.playParams = attributes.playParams ? attributes.playParams : {id: 'no-id-found'}; + attributes.playParams.id = attributes.playParams.id ? attributes.playParams.id : 'no-id-found'; + attributes.albumName = attributes.albumName ? attributes.albumName : ''; + attributes.artistName = attributes.artistName ? attributes.artistName : ''; + attributes.genreNames = attributes.genreNames ? attributes.genreNames : []; + attributes.remainingTime = remainingTimeExport ? (remainingTimeExport * 1000) : 0; + attributes.durationInMillis = attributes.durationInMillis ? attributes.durationInMillis : 0; + attributes.startTime = Date.now(); + attributes.endTime = attributes.endTime ? attributes.endTime : Date.now(); + attributes.volume = mk.volume; + attributes.shuffleMode = mk.shuffleMode; + attributes.repeatMode = mk.repeatMode; + attributes.autoplayEnabled = mk.autoplayEnabled; + return attributes + }, + moveQueueItem(oldPosition, newPosition) { + MusicKit.getInstance().queue._queueItems.splice(newPosition,0,MusicKit.getInstance().queue._queueItems.splice(oldPosition,1)[0]) + MusicKit.getInstance().queue._reindex() + }, + setAutoplay(value) { + MusicKit.getInstance().autoplayEnabled = value + }, + returnDynamic(data, type) { + ipcRenderer.send('wsapi-returnDynamic', JSON.stringify(data), type) + }, + musickitApi(method, id, params, library = false) { + if (library) { + MusicKit.getInstance().api.library[method](id, params).then((results)=>{ + ipcRenderer.send('wsapi-returnMusicKitApi', JSON.stringify(results), method) + }) + } else { + MusicKit.getInstance().api[method](id, params).then((results)=>{ + ipcRenderer.send('wsapi-returnMusicKitApi', JSON.stringify(results), method) + }) + } + }, + getPlaybackState () { + ipcRenderer.send('wsapi-updatePlaybackState', MusicKitInterop.getAttributes()); + }, + getLyrics() { + ipcRenderer.send('wsapi-returnLyrics',JSON.stringify(app.lyrics)); + }, + getQueue() { + ipcRenderer.send('wsapi-returnQueue', JSON.stringify(MusicKit.getInstance().queue)) + }, + playNext(type, id) { + var request = {} + request[type] = id + MusicKit.getInstance().playNext(request) + }, + playLater(type, id) { + var request = {} + request[type] = id + MusicKit.getInstance().playLater(request) + }, + love() { + + }, + playTrackById(id, kind = "song") { + MusicKit.getInstance().setQueue({ [kind]: id }).then(function (queue) { + MusicKit.getInstance().play() + }) + }, + quickPlay(term) { + // Quick play by song name + MusicKit.getInstance().api.search(term, { limit: 2, types: 'songs' }).then(function (data) { + MusicKit.getInstance().setQueue({ song: data["songs"][0]["id"] }).then(function (queue) { + MusicKit.getInstance().play() + }) + }) + }, + toggleShuffle() { + MusicKit.getInstance().shuffleMode = MusicKit.getInstance().shuffleMode === 0 ? 1 : 0 + }, + toggleRepeat() { + if(MusicKit.getInstance().repeatMode == 0) { + MusicKit.getInstance().repeatMode = 1 + }else if(MusicKit.getInstance().repeatMode == 1){ + MusicKit.getInstance().repeatMode = 2 + }else{ + MusicKit.getInstance().repeatMode = 0 + } + } +} \ No newline at end of file diff --git a/src/renderer/js/bootbox.min.js b/src/renderer/js/bootbox.min.js new file mode 100644 index 00000000..822080e5 --- /dev/null +++ b/src/renderer/js/bootbox.min.js @@ -0,0 +1 @@ +!function(t,e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?module.exports=e(require("jquery")):t.bootbox=e(t.jQuery)}(this,function e(c,p){"use strict";var r,n,i,l;Object.keys||(Object.keys=(r=Object.prototype.hasOwnProperty,n=!{toString:null}.propertyIsEnumerable("toString"),l=(i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"]).length,function(t){if("function"!=typeof t&&("object"!=typeof t||null===t))throw new TypeError("Object.keys called on non-object");var e,o,a=[];for(e in t)r.call(t,e)&&a.push(e);if(n)for(o=0;o