diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..bdaa4581 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +; http://editorconfig.org/ + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yml,yaml}] +indent_size = 2 + +[{vendor,inc/phpseclib}/**] +; Use editor default (possible autodetection). +indent_style = +indent_size = +end_of_line = +trim_trailing_whitespace = +insert_final_newline = \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..b702f289 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [LaswitchTech] diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..cc599e09 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,69 @@ +name: Bug report +description: Create a report to help us improve +title: "" +labels: ["bug"] +assignees: + - LouisOuellet + +body: + - type: textarea + id: description + attributes: + label: Description + description: Describe the bug or feature. + placeholder: "Description of the bug or feature" + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: Provide clear steps to reproduce. + placeholder: | + 1. First Step + 2. Second Step + 3. And so on... + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected behavior + placeholder: "What you expected to happen" + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual behavior + placeholder: "What actually happened" + validations: + required: true + + - type: input + id: python_version + attributes: + label: Python version + placeholder: "e.g. 3.11.2" + validations: + required: false + + - type: input + id: os_version + attributes: + label: Operating system version + placeholder: "e.g. Windows 10 / macOS 13.4 / Ubuntu 22.04" + validations: + required: false + + - type: textarea + id: logs + attributes: + label: Screenshots or Logs + description: Paste logs or attach screenshots. + placeholder: "Paste your logs or attach the screenshot" + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..8005e322 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,2 @@ +blank_issues_enabled: false +contact_links: [] diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..db233359 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: feature request +assignees: 'LouisOuellet' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..d82c1128 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,48 @@ +name: Feature request +description: Suggest an idea for this project +title: "" +labels: ["feature request"] +assignees: + - LouisOuellet + +body: + - type: textarea + id: problem + attributes: + label: Is your feature request related to a problem? + description: Describe the problem this feature would solve. + placeholder: > + A clear and concise description of what the problem is. + Example: I'm always frustrated when [...] + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Describe the solution you'd like + description: Describe what you want to happen. + placeholder: > + A clear and concise description of the desired solution. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Describe alternatives you've considered + description: Describe any alternative solutions or features you've considered. + placeholder: > + A clear and concise description of any alternative approaches. + validations: + required: false + + - type: textarea + id: context + attributes: + label: Additional context + description: Add any other context or screenshots about the feature request. + placeholder: > + Add any other context, links, or screenshots here. + validations: + required: false diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 00000000..c7c7e698 --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,13 @@ +# Configuration for probot-no-response - https://github.com/probot/no-response + +# Number of days of inactivity before an Issue is closed for lack of response +daysUntilClose: 14 +# Label requiring a response +responseRequiredLabel: need more info +# Comment to post when closing an Issue for lack of response. Set to `false` to disable +closeComment: > + This issue has been automatically closed because there has been no response + to our request for more information from the original author. With only the + information that is currently in the issue, we don't have enough information + to take action. Please reach out if you have or find the answers we need so + that we can investigate further. \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..4cde3ed5 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,60 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set Tag as Filename + id: tag_name + run: echo "TAG_NAME=${GITHUB_REF##*/}" >> $GITHUB_ENV + + - name: Create ZIP file + run: zip -r "${{ env.TAG_NAME }}.zip" . + + - name: Generate Changelog + id: generate_changelog + run: | + # Find the most recent tag before the current one + PREV_TAG=$(git describe --tags --abbrev=0 HEAD^) + + # Create a new CHANGELOG.md file with headers + echo -e "# Changelog\n" > CHANGELOG.md + + # List commit messages between the previous tag and current HEAD + git log ${PREV_TAG}..HEAD --pretty=format:"* %s" >> CHANGELOG.md + + # List unique contributors for these commits + echo -e "\n\n# Contributors\n" >> CHANGELOG.md + git log ${PREV_TAG}..HEAD --format='%aN' | sort -u | awk '{print "* " $0}' >> CHANGELOG.md + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_PAT }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: false + body_path: ./CHANGELOG.md + + - name: Upload Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_PAT }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./${{ env.TAG_NAME }}.zip + asset_name: source.zip + asset_content_type: application/zip diff --git a/.gitignore b/.gitignore index b7faf403..4ef19446 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,52 @@ +# Python +/build/ + +# Environments +.env +.venv +env/ +venv/ +.venv/ +ENV/ +env.bak/ +venv.bak/ +TOKEN +runtime + +# Mac OS X +.DS_Store +*.DS_Store + +# Git +.git + +# Filetypes +*.cfg +*.log +*.db + +# Unique Directories +/tmp/ +/data/ +/dist/Replicator/ +!/dist/macos/ +!/dist/linux/ +!/dist/windows/ + +# Exclusions for Python projects +!build.cfg + # Byte-compiled / optimized / DLL files __pycache__/ -*.py[codz] +*.py[cod] *$py.class -# C extensions -*.so - # Distribution / packaging .Python build/ develop-eggs/ -dist/ +config/ +logs/ downloads/ eggs/ .eggs/ @@ -46,7 +82,7 @@ htmlcov/ nosetests.xml coverage.xml *.cover -*.py.cover +*.py,cover .hypothesis/ .pytest_cache/ cover/ @@ -82,47 +118,13 @@ target/ profile_default/ ipython_config.py -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# UV -# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -#uv.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock -#poetry.toml - # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. -# https://pdm-project.org/en/latest/usage/project/#working-with-version-control #pdm.lock -#pdm.toml -.pdm-python -.pdm-build/ - -# pixi -# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. -#pixi.lock -# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one -# in the .venv directory. It is recommended not to include this directory in version control. -.pixi +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ @@ -134,74 +136,11 @@ celerybeat.pid # SageMath parsed files *.sage.py -# Environments -.env -.envrc -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ +# building source files +src/bin/freerdp/source +src/bin/freerdp/install +src/bin/freerdp/build -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -# Abstra -# Abstra is an AI-powered process automation framework. -# Ignore directories containing user credentials, local state, and settings. -# Learn more at https://abstra.io/docs -.abstra/ - -# Visual Studio Code -# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore -# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore -# and can be added to the global gitignore or merged into this file. However, if you prefer, -# you could uncomment the following to ignore the entire vscode folder -# .vscode/ - -# Ruff stuff: -.ruff_cache/ - -# PyPI configuration file -.pypirc - -# Cursor -# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to -# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data -# refer to https://docs.cursor.com/context/ignore-files -.cursorignore -.cursorindexingignore - -# Marimo -marimo/_static/ -marimo/_lsp/ -__marimo__/ +# Exclusions +!src/bin/freerdp/*/*/lib/ +!src/bin/freerdp/*/*/xfreerdp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..137e0dc7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "src/core"] + path = src/core + url = https://github.com/LaswitchTech/corePY.git + branch = dev diff --git a/README.md b/README.md index 714570af..09556cf1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,49 @@ +

+ # Replicator -Data Replication Software, Replacement for Windows DFSR with support for Local, SMB and FTP filesystems. +![License](https://img.shields.io/github/license/LaswitchTech/Replicator?style=for-the-badge) +![GitHub repo size](https://img.shields.io/github/repo-size/LaswitchTech/Replicator?style=for-the-badge&logo=github) +![GitHub top language](https://img.shields.io/github/languages/top/LaswitchTech/Replicator?style=for-the-badge) +![GitHub Downloads](https://img.shields.io/github/downloads/LaswitchTech/Replicator/total?style=for-the-badge) +![Version](https://img.shields.io/github/v/release/LaswitchTech/Replicator?label=Version&style=for-the-badge) + +## Description +Replicator is a cross-platform Python application designed to provide replication services similar to Windows DFSR. It supports local filesystems and SMB making it a versatile solution for data replication needs across different operating systems. + +## Features + - **Cross-Platform Compatibility**: Replicator is compatible with Windows, macOS and Linux, with specific adjustments made to ensure seamless operation on both operating systems. + - **SMB Support**: The application can replicate data to and from SMB shares, making it suitable for networked environments. + - **Configurable Replication Modes**: Users can choose between different replication modes (e.g., Mirror, Incremental) to suit their specific needs. + - **Scheduling**: Replication tasks can be scheduled to run at specific times or intervals, allowing for automated data synchronization. + - **Conflict Resolution**: The application includes strategies for resolving conflicts that may arise during replication, ensuring data integrity and consistency. + - **Service Integration**: Replicator can be integrated with system services to run in the background, providing continuous replication without user intervention. + - **Logging and Debugging**: The application includes logging features for easier debugging and tracking of issues during the replication process. + +## License +This software is distributed under the [GPLv3](LICENSE) license. + +## Security +Please disclose any vulnerabilities found responsibly – report security issues to the maintainers privately. See [SECURITY.md](SECURITY.md) for more information. + +## Contributing +Contributions to Replicator are welcome! If you have ideas for new features or have found bugs, please open an issue or submit a pull request. + +### How to Contribute + - **Fork the Repository**: Create a fork of the repository on GitHub. + - **Create a New Branch**: For new features or bug fixes, create a new branch in your fork. + - **Submit a Pull Request**: Once your changes are ready, submit a pull request to the main repository. + +## To Do + - ~~**Support for Local**: Add support for Local filesystems.~~ + - ~~**Support for SMB**: Add support for SMB Shares.~~ + - ~~**Support for FTP**: Add support for FTP Shares.~~ --- REMOVED --- + - ~~**Support for SSHFS**: Add support for SSH filesystems.~~ --- REMOVED --- + - ~~**Mode Mirror**: Add replication mode Mirror.~~ + - **Mode Incremental**: Add replication mode Incremental. + - ~~**Direction**: Add replication direction (One way, Two way).~~ + - ~~**Scheduling**: Add scheduling capabilities for replication tasks.~~ + - ~~**Conflict Resolution**: Implement conflict resolution strategies for file changes.~~ + - ~~**Service Integration**: Integrate with system services for background operation.~~ + +## Wait, where is the documentation? +Review the [Documentation](https://laswitchtech.com/en/blog/projects/replicator/index). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..86201e0b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,10 @@ +# Security Policy + +Security vulnerabilities can be reported for the current stable release and the `stable` branch. + +## Reporting a Vulnerability + +You have multiple options on reporting vulnerabilities + +* Send an e-mail to [Support Team](mailto:support@laswitchtech.com) +* Open a [Github Issue](https://github.com/LaswitchTech/Replicator/issues) diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..45c7a584 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +v0.0.1 diff --git a/build.cfg b/build.cfg new file mode 100644 index 00000000..098a7b7b --- /dev/null +++ b/build.cfg @@ -0,0 +1,11 @@ +# Replicator build configuration + +NAME=Replicator +ENTRY=src/main.py +MODE=windowed +PKG=auto +CLEAN=0 +DMG=1 +SYSTEM_PYQT=0 + +ADD_DATA=src/core:core;src/icons:icons;src/bin:bin;src/replicator:replicator diff --git a/build.sh b/build.sh new file mode 120000 index 00000000..64329510 --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +src/core/build.sh \ No newline at end of file diff --git a/cli.bat b/cli.bat new file mode 100644 index 00000000..eb9b7f0a --- /dev/null +++ b/cli.bat @@ -0,0 +1,71 @@ +@echo off +setlocal EnableExtensions EnableDelayedExpansion + +REM --------------------------------------------------------------------------- +REM Replicator CLI launcher (Windows) +REM - Ensures a local venv exists (.venv) +REM - Installs minimal runtime deps (PyQt5) +REM - Runs src\main.py with a visible console +REM +REM Note: If you double-click this file, the console may flash and close. +REM Run it from an existing Command Prompt for persistent output. +REM --------------------------------------------------------------------------- + +set "SCRIPT_DIR=%~dp0" +set "VENV_DIR=%SCRIPT_DIR%.venv" +set "VENV_PY=%VENV_DIR%\Scripts\python.exe" + +REM Prefer Windows Python Launcher +set "PY_CMD=" +set "PY_ARGS=" +where py >nul 2>&1 +if %ERRORLEVEL%==0 ( + set "PY_CMD=py" + set "PY_ARGS=-3.11" +) else ( + where python >nul 2>&1 + if %ERRORLEVEL%==0 ( + set "PY_CMD=python" + set "PY_ARGS=" + ) +) + +if "%PY_CMD%"=="" ( + echo ERROR: Python not found. Install Python 3.11+ and ensure either `py` or `python` is available in PATH. + exit /b 1 +) + +REM Create venv if missing +if not exist "%VENV_PY%" ( + echo Creating virtualenv: %VENV_DIR% + %PY_CMD% %PY_ARGS% -m venv "%VENV_DIR%" + if %ERRORLEVEL% NEQ 0 ( + echo ERROR: Failed to create virtualenv. + exit /b %ERRORLEVEL% + ) +) + +REM Upgrade pip/wheel +"%VENV_PY%" -m pip install --upgrade pip wheel >nul + +REM Install minimal deps (idempotent) +echo Installing minimal runtime deps (PyQt5)... +"%VENV_PY%" -m pip install "PyQt5>=5.15,<6" >nul + +REM Prefer the built console companion if available +if exist "%SCRIPT_DIR%dist\windows\Replicator-cli.exe" ( + "%SCRIPT_DIR%dist\windows\Replicator-cli.exe" %* + endlocal + exit /b %ERRORLEVEL% +) + +REM Fallback: Run the source entry in console mode (dev checkout) +if not exist "%SCRIPT_DIR%src\main.py" ( + echo ERROR: Entry not found: %SCRIPT_DIR%src\main.py + echo NOTE: Replicator-cli.exe not found at %SCRIPT_DIR%dist\windows\Replicator-cli.exe + exit /b 1 +) + +"%VENV_PY%" "%SCRIPT_DIR%src\main.py" %* +endlocal +exit /b %ERRORLEVEL% diff --git a/cli.sh b/cli.sh new file mode 100755 index 00000000..ea005e83 --- /dev/null +++ b/cli.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$ROOT_DIR" + +exec "./launch.sh" "$@" diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/generic/libqtuiotouchplugin.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/generic/libqtuiotouchplugin.dylib new file mode 100755 index 00000000..8a3f54df Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/generic/libqtuiotouchplugin.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/iconengines/libqsvgicon.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/iconengines/libqsvgicon.dylib new file mode 100755 index 00000000..3b074a83 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/iconengines/libqsvgicon.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqgif.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqgif.dylib new file mode 100755 index 00000000..ab755e86 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqgif.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqicns.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqicns.dylib new file mode 100755 index 00000000..c7ece31f Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqicns.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqico.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqico.dylib new file mode 100755 index 00000000..20ef8c61 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqico.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqjpeg.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqjpeg.dylib new file mode 100755 index 00000000..273191e6 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqjpeg.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqmacheif.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqmacheif.dylib new file mode 100755 index 00000000..078c5029 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqmacheif.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqmacjp2.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqmacjp2.dylib new file mode 100755 index 00000000..632cfbce Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqmacjp2.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqsvg.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqsvg.dylib new file mode 100755 index 00000000..d04f4a04 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqsvg.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqtga.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqtga.dylib new file mode 100755 index 00000000..816cf64d Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqtga.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqtiff.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqtiff.dylib new file mode 100755 index 00000000..59014c67 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqtiff.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqwbmp.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqwbmp.dylib new file mode 100755 index 00000000..09dae7c6 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqwbmp.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqwebp.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqwebp.dylib new file mode 100755 index 00000000..e080a932 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/imageformats/libqwebp.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqcocoa.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqcocoa.dylib new file mode 100755 index 00000000..7d7f2702 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqcocoa.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqminimal.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqminimal.dylib new file mode 100755 index 00000000..832360b6 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqminimal.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqoffscreen.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqoffscreen.dylib new file mode 100755 index 00000000..c0188c9f Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqoffscreen.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqwebgl.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqwebgl.dylib new file mode 100755 index 00000000..9981cead Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platforms/libqwebgl.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platformthemes/libqxdgdesktopportal.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platformthemes/libqxdgdesktopportal.dylib new file mode 100755 index 00000000..c8b3a7b4 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/platformthemes/libqxdgdesktopportal.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/styles/libqmacstyle.dylib b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/styles/libqmacstyle.dylib new file mode 100755 index 00000000..79b51b23 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/plugins/styles/libqmacstyle.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/translations b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/translations new file mode 120000 index 00000000..447e157c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/Qt5/translations @@ -0,0 +1 @@ +../../../Resources/PyQt5/Qt5/translations \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtCore.abi3.so b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtCore.abi3.so new file mode 100755 index 00000000..0d8e8edd Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtCore.abi3.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtGui.abi3.so b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtGui.abi3.so new file mode 100755 index 00000000..890191f9 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtGui.abi3.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtSvg.abi3.so b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtSvg.abi3.so new file mode 100755 index 00000000..0e6614fc Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtSvg.abi3.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtWidgets.abi3.so b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtWidgets.abi3.so new file mode 100755 index 00000000..705b6dc6 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/QtWidgets.abi3.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/sip.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/sip.cpython-311-darwin.so new file mode 100755 index 00000000..2a9b08c1 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/PyQt5/sip.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/Python b/dist/macos/Replicator.app/Contents/Frameworks/Python new file mode 120000 index 00000000..e485e133 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/Python @@ -0,0 +1 @@ +Python.framework/Versions/3.11/Python \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Python b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Python new file mode 120000 index 00000000..be758541 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Python @@ -0,0 +1 @@ +Versions/Current/Python \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Resources b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Resources new file mode 120000 index 00000000..953ee36f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/Python b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/Python new file mode 100755 index 00000000..3cbfd4d1 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/Python differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/Resources/Info.plist b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/Resources/Info.plist new file mode 100644 index 00000000..c7e76894 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/Resources/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + Python + CFBundleGetInfoString + Python Runtime and Library + CFBundleIdentifier + org.python.python + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Python + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.11.14, (c) 2001-2023 Python Software Foundation. + CFBundleLongVersionString + 3.11.14, (c) 2001-2023 Python Software Foundation. + CFBundleSignature + ???? + CFBundleVersion + 3.11.14 + + diff --git a/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/_CodeSignature/CodeResources b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/_CodeSignature/CodeResources new file mode 100644 index 00000000..3b059e78 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/3.11/_CodeSignature/CodeResources @@ -0,0 +1,128 @@ + + + + + files + + Resources/Info.plist + + 5cCbGbqwL3PCsmrGaOO/Pg3ax4c= + + + files2 + + Resources/Info.plist + + hash2 + + f6GvCgok6FC7HDI6N5dv6y5nBc2YA8Y0hRxKn+fj6M4= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/Current b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/Current new file mode 120000 index 00000000..902b2c90 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/Python.framework/Versions/Current @@ -0,0 +1 @@ +3.11 \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtCore b/dist/macos/Replicator.app/Contents/Frameworks/QtCore new file mode 120000 index 00000000..eb4d1ef3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtCore @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtCore.framework/Versions/5/QtCore \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtDBus b/dist/macos/Replicator.app/Contents/Frameworks/QtDBus new file mode 120000 index 00000000..509df15f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtDBus @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtDBus.framework/Versions/5/QtDBus \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtGui b/dist/macos/Replicator.app/Contents/Frameworks/QtGui new file mode 120000 index 00000000..70a2b83f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtGui @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtGui.framework/Versions/5/QtGui \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtNetwork b/dist/macos/Replicator.app/Contents/Frameworks/QtNetwork new file mode 120000 index 00000000..642f5624 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtNetwork @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtNetwork.framework/Versions/5/QtNetwork \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtPrintSupport b/dist/macos/Replicator.app/Contents/Frameworks/QtPrintSupport new file mode 120000 index 00000000..531f139d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtPrintSupport @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtQml b/dist/macos/Replicator.app/Contents/Frameworks/QtQml new file mode 120000 index 00000000..4671a083 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtQml @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtQml.framework/Versions/5/QtQml \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtQmlModels b/dist/macos/Replicator.app/Contents/Frameworks/QtQmlModels new file mode 120000 index 00000000..042a8ead --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtQmlModels @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtQmlModels.framework/Versions/5/QtQmlModels \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtQuick b/dist/macos/Replicator.app/Contents/Frameworks/QtQuick new file mode 120000 index 00000000..60c0937b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtQuick @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtQuick.framework/Versions/5/QtQuick \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtSvg b/dist/macos/Replicator.app/Contents/Frameworks/QtSvg new file mode 120000 index 00000000..a9847407 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtSvg @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtSvg.framework/Versions/5/QtSvg \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtWebSockets b/dist/macos/Replicator.app/Contents/Frameworks/QtWebSockets new file mode 120000 index 00000000..8a6e3c10 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtWebSockets @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtWebSockets.framework/Versions/5/QtWebSockets \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/QtWidgets b/dist/macos/Replicator.app/Contents/Frameworks/QtWidgets new file mode 120000 index 00000000..deba0910 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/QtWidgets @@ -0,0 +1 @@ +PyQt5/Qt5/lib/QtWidgets.framework/Versions/5/QtWidgets \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/base_library.zip b/dist/macos/Replicator.app/Contents/Frameworks/base_library.zip new file mode 120000 index 00000000..89ddc936 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/base_library.zip @@ -0,0 +1 @@ +../Resources/base_library.zip \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/bin b/dist/macos/Replicator.app/Contents/Frameworks/bin new file mode 120000 index 00000000..5423f908 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/bin @@ -0,0 +1 @@ +../Resources/bin \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/core b/dist/macos/Replicator.app/Contents/Frameworks/core new file mode 120000 index 00000000..8f7c1f19 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/core @@ -0,0 +1 @@ +../Resources/core \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/icons b/dist/macos/Replicator.app/Contents/Frameworks/icons new file mode 120000 index 00000000..92077459 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/icons @@ -0,0 +1 @@ +../Resources/icons \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/libcrypto.3.dylib b/dist/macos/Replicator.app/Contents/Frameworks/libcrypto.3.dylib new file mode 100755 index 00000000..c68b11e2 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/libcrypto.3.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/liblzma.5.dylib b/dist/macos/Replicator.app/Contents/Frameworks/liblzma.5.dylib new file mode 100755 index 00000000..7321eb16 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/liblzma.5.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/libmpdec.4.dylib b/dist/macos/Replicator.app/Contents/Frameworks/libmpdec.4.dylib new file mode 100755 index 00000000..88c33980 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/libmpdec.4.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/libsqlite3.dylib b/dist/macos/Replicator.app/Contents/Frameworks/libsqlite3.dylib new file mode 100755 index 00000000..b19e2d9d Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/libsqlite3.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/libssl.3.dylib b/dist/macos/Replicator.app/Contents/Frameworks/libssl.3.dylib new file mode 100755 index 00000000..b8632371 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/libssl.3.dylib differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3.11 b/dist/macos/Replicator.app/Contents/Frameworks/python3.11 new file mode 120000 index 00000000..79569286 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/python3.11 @@ -0,0 +1 @@ +python3__dot__11 \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_bisect.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_bisect.cpython-311-darwin.so new file mode 100755 index 00000000..eb8e9e20 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_bisect.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_blake2.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_blake2.cpython-311-darwin.so new file mode 100755 index 00000000..ac715c0a Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_blake2.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_bz2.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_bz2.cpython-311-darwin.so new file mode 100755 index 00000000..a963a4dc Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_bz2.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_cn.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_cn.cpython-311-darwin.so new file mode 100755 index 00000000..f539e948 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_cn.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_hk.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_hk.cpython-311-darwin.so new file mode 100755 index 00000000..a0becafc Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_hk.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_iso2022.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_iso2022.cpython-311-darwin.so new file mode 100755 index 00000000..e305d2dc Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_iso2022.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_jp.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_jp.cpython-311-darwin.so new file mode 100755 index 00000000..63875754 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_jp.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_kr.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_kr.cpython-311-darwin.so new file mode 100755 index 00000000..5daca109 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_kr.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_tw.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_tw.cpython-311-darwin.so new file mode 100755 index 00000000..f4222c57 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_codecs_tw.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_contextvars.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_contextvars.cpython-311-darwin.so new file mode 100755 index 00000000..17767664 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_contextvars.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_csv.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_csv.cpython-311-darwin.so new file mode 100755 index 00000000..0763582a Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_csv.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_ctypes.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_ctypes.cpython-311-darwin.so new file mode 100755 index 00000000..a775bc0a Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_ctypes.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_datetime.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_datetime.cpython-311-darwin.so new file mode 100755 index 00000000..2c73069e Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_datetime.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_decimal.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_decimal.cpython-311-darwin.so new file mode 100755 index 00000000..74ec6bdb Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_decimal.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_hashlib.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_hashlib.cpython-311-darwin.so new file mode 100755 index 00000000..d8ec992d Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_hashlib.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_heapq.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_heapq.cpython-311-darwin.so new file mode 100755 index 00000000..809b0f5e Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_heapq.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_json.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_json.cpython-311-darwin.so new file mode 100755 index 00000000..2c2ea0c3 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_json.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_lzma.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_lzma.cpython-311-darwin.so new file mode 100755 index 00000000..53fc01b7 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_lzma.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_md5.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_md5.cpython-311-darwin.so new file mode 100755 index 00000000..4631558d Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_md5.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_multibytecodec.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_multibytecodec.cpython-311-darwin.so new file mode 100755 index 00000000..10003664 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_multibytecodec.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_opcode.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_opcode.cpython-311-darwin.so new file mode 100755 index 00000000..9ee91e82 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_opcode.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_pickle.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_pickle.cpython-311-darwin.so new file mode 100755 index 00000000..458d4078 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_pickle.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_posixsubprocess.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_posixsubprocess.cpython-311-darwin.so new file mode 100755 index 00000000..9771de57 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_posixsubprocess.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_random.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_random.cpython-311-darwin.so new file mode 100755 index 00000000..d1b136be Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_random.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_scproxy.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_scproxy.cpython-311-darwin.so new file mode 100755 index 00000000..75a7df4b Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_scproxy.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha1.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha1.cpython-311-darwin.so new file mode 100755 index 00000000..8c47cbeb Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha1.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha256.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha256.cpython-311-darwin.so new file mode 100755 index 00000000..902123f5 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha256.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha3.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha3.cpython-311-darwin.so new file mode 100755 index 00000000..e73af632 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha3.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha512.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha512.cpython-311-darwin.so new file mode 100755 index 00000000..ed3e2a48 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sha512.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_socket.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_socket.cpython-311-darwin.so new file mode 100755 index 00000000..57a31974 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_socket.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sqlite3.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sqlite3.cpython-311-darwin.so new file mode 100755 index 00000000..99f741ca Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_sqlite3.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_ssl.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_ssl.cpython-311-darwin.so new file mode 100755 index 00000000..802a2af3 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_ssl.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_statistics.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_statistics.cpython-311-darwin.so new file mode 100755 index 00000000..cec70bda Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_statistics.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_struct.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_struct.cpython-311-darwin.so new file mode 100755 index 00000000..c71be608 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_struct.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_typing.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_typing.cpython-311-darwin.so new file mode 100755 index 00000000..4a7f1342 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/_typing.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/array.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/array.cpython-311-darwin.so new file mode 100755 index 00000000..41dd25a5 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/array.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/binascii.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/binascii.cpython-311-darwin.so new file mode 100755 index 00000000..a2fff8b9 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/binascii.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/fcntl.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/fcntl.cpython-311-darwin.so new file mode 100755 index 00000000..2f283375 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/fcntl.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/grp.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/grp.cpython-311-darwin.so new file mode 100755 index 00000000..7b95d54b Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/grp.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/math.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/math.cpython-311-darwin.so new file mode 100755 index 00000000..2b48ee51 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/math.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/pyexpat.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/pyexpat.cpython-311-darwin.so new file mode 100755 index 00000000..1f478850 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/pyexpat.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/resource.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/resource.cpython-311-darwin.so new file mode 100755 index 00000000..cff7d1fb Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/resource.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/select.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/select.cpython-311-darwin.so new file mode 100755 index 00000000..f22a57bd Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/select.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/termios.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/termios.cpython-311-darwin.so new file mode 100755 index 00000000..40437079 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/termios.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/unicodedata.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/unicodedata.cpython-311-darwin.so new file mode 100755 index 00000000..286d7065 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/unicodedata.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/zlib.cpython-311-darwin.so b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/zlib.cpython-311-darwin.so new file mode 100755 index 00000000..f9ca3c9c Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Frameworks/python3__dot__11/lib-dynload/zlib.cpython-311-darwin.so differ diff --git a/dist/macos/Replicator.app/Contents/Frameworks/replicator b/dist/macos/Replicator.app/Contents/Frameworks/replicator new file mode 120000 index 00000000..f50463de --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Frameworks/replicator @@ -0,0 +1 @@ +../Resources/replicator \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Info.plist b/dist/macos/Replicator.app/Contents/Info.plist new file mode 100644 index 00000000..fc99d631 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDisplayName + Replicator + CFBundleExecutable + Replicator + CFBundleIconFile + icon.icns + CFBundleIdentifier + Replicator + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Replicator + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.0.0 + NSHighResolutionCapable + + + diff --git a/dist/macos/Replicator.app/Contents/MacOS/Replicator b/dist/macos/Replicator.app/Contents/MacOS/Replicator new file mode 100755 index 00000000..50763987 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/MacOS/Replicator differ diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/lib b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/lib new file mode 120000 index 00000000..a64516e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/lib @@ -0,0 +1 @@ +../../../Frameworks/PyQt5/Qt5/lib \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/plugins b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/plugins new file mode 120000 index 00000000..1d5e3b1a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/plugins @@ -0,0 +1 @@ +../../../Frameworks/PyQt5/Qt5/plugins \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_ar.qm b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_ar.qm new file mode 100644 index 00000000..33eda481 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_ar.qm differ diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_bg.qm b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_bg.qm new file mode 100644 index 00000000..ad48af72 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_bg.qm differ diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_ca.qm b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_ca.qm new file mode 100644 index 00000000..ae864657 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_ca.qm differ diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_cs.qm b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_cs.qm new file mode 100644 index 00000000..40aec718 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_cs.qm differ diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_da.qm b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_da.qm new file mode 100644 index 00000000..eefbe648 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_da.qm differ diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_de.qm b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_de.qm new file mode 100644 index 00000000..2e94a253 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_de.qm differ diff --git a/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_en.qm b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_en.qm new file mode 100644 index 00000000..be651eed --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/PyQt5/Qt5/translations/qt_en.qm @@ -0,0 +1 @@ + + This issue has been automatically closed because there has been no response + to our request for more information from the original author. With only the + information that is currently in the issue, we don't have enough information + to take action. Please reach out if you have or find the answers we need so + that we can investigate further. \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/.github/workflows/release.yml b/dist/macos/Replicator.app/Contents/Resources/core/.github/workflows/release.yml new file mode 100644 index 00000000..4cde3ed5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/.github/workflows/release.yml @@ -0,0 +1,60 @@ +name: Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set Tag as Filename + id: tag_name + run: echo "TAG_NAME=${GITHUB_REF##*/}" >> $GITHUB_ENV + + - name: Create ZIP file + run: zip -r "${{ env.TAG_NAME }}.zip" . + + - name: Generate Changelog + id: generate_changelog + run: | + # Find the most recent tag before the current one + PREV_TAG=$(git describe --tags --abbrev=0 HEAD^) + + # Create a new CHANGELOG.md file with headers + echo -e "# Changelog\n" > CHANGELOG.md + + # List commit messages between the previous tag and current HEAD + git log ${PREV_TAG}..HEAD --pretty=format:"* %s" >> CHANGELOG.md + + # List unique contributors for these commits + echo -e "\n\n# Contributors\n" >> CHANGELOG.md + git log ${PREV_TAG}..HEAD --format='%aN' | sort -u | awk '{print "* " $0}' >> CHANGELOG.md + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_PAT }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: false + body_path: ./CHANGELOG.md + + - name: Upload Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GH_PAT }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./${{ env.TAG_NAME }}.zip + asset_name: source.zip + asset_content_type: application/zip diff --git a/dist/macos/Replicator.app/Contents/Resources/core/.gitignore b/dist/macos/Replicator.app/Contents/Resources/core/.gitignore new file mode 100644 index 00000000..3554cd79 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/.gitignore @@ -0,0 +1,137 @@ +# Python +/build/ + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +TOKEN +runtime + +# Mac OS X +.DS_Store +*.DS_Store + +# Git +.git + +# Filetypes +*.cfg +*.log +*.db + +# Unique Directories +/tmp/ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +.Python +build/ +develop-eggs/ +config/ +logs/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# building source files +src/bin/freerdp/source +src/bin/freerdp/install +src/bin/freerdp/build + +# Exclusions +!src/bin/freerdp/*/*/lib/ +!src/bin/freerdp/*/*/xfreerdp diff --git a/dist/macos/Replicator.app/Contents/Resources/core/LICENSE b/dist/macos/Replicator.app/Contents/Resources/core/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/dist/macos/Replicator.app/Contents/Resources/core/README.md b/dist/macos/Replicator.app/Contents/Resources/core/README.md new file mode 100644 index 00000000..c11ae7f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/README.md @@ -0,0 +1,38 @@ +

+ +# corePY +![License](https://img.shields.io/github/license/LaswitchTech/corePY?style=for-the-badge) +![GitHub repo size](https://img.shields.io/github/repo-size/LaswitchTech/corePY?style=for-the-badge&logo=github) +![GitHub top language](https://img.shields.io/github/languages/top/LaswitchTech/corePY?style=for-the-badge) +![GitHub Downloads](https://img.shields.io/github/downloads/LaswitchTech/corePY/total?style=for-the-badge) +![Version](https://img.shields.io/github/v/release/LaswitchTech/corePY?label=Version&style=for-the-badge) + +## Description +corePY is a framework of libraries designed to facilitate the creation of python-based applications. + +## Features + - **Uniform Styling**: corePY provides a consistent look and feel across all applications built using its libraries. + - **Modular Architecture**: The framework is designed with modularity in mind, allowing developers to easily integrate and extend functionality. + - **Cross-Platform Support**: corePY is compatible with multiple operating systems, ensuring broad accessibility for users. + - **Command-Line**: corePY includes a robust command-line interface for managing applications and performing various tasks. + +## License +This software is distributed under the [GPLv3](LICENSE) license. + +## Security +Please disclose any vulnerabilities found responsibly – report security issues to the maintainers privately. See [SECURITY.md](SECURITY.md) for more information. + +## Contributing +Contributions to corePY are welcome! If you have ideas for new features or have found bugs, please open an issue or submit a pull request. + +### How to Contribute + - **Fork the Repository**: Create a fork of the repository on GitHub. + - **Create a New Branch**: For new features or bug fixes, create a new branch in your fork. + - **Submit a Pull Request**: Once your changes are ready, submit a pull request to the main repository. + +## To Do + - **Provisioning System**: Develop a provisioning system for easier deployment and management. + - **Log on file**: Add the ability to save the log on file. + +## Wait, where is the documentation? +Review the [Documentation](https://laswitchtech.com/en/blog/projects/corepy/index). diff --git a/dist/macos/Replicator.app/Contents/Resources/core/SECURITY.md b/dist/macos/Replicator.app/Contents/Resources/core/SECURITY.md new file mode 100644 index 00000000..4a0c7af6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/SECURITY.md @@ -0,0 +1,10 @@ +# Security Policy + +Security vulnerabilities can be reported for the current stable release and the `stable` branch. + +## Reporting a Vulnerability + +You have multiple options on reporting vulnerabilities + +* Send an e-mail to [Support Team](mailto:support@laswitchtech.com) +* Open a [Github Issue](https://github.com/LaswitchTech/corePY/issues) diff --git a/dist/macos/Replicator.app/Contents/Resources/core/VERSION b/dist/macos/Replicator.app/Contents/Resources/core/VERSION new file mode 100644 index 00000000..3e7bcf08 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/VERSION @@ -0,0 +1 @@ +v1.0.4 diff --git a/dist/macos/Replicator.app/Contents/Resources/core/__init__.py b/dist/macos/Replicator.app/Contents/Resources/core/__init__.py new file mode 100644 index 00000000..4223ff4c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/__init__.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# src/core/__init__.py + +from .application import Application +from .cli import CommandLine +from .helper import Helper +from .configuration import Configuration +from .log import Log +from .ui import MsgBox, StepIndicator, Form + +from .network.diagnostic import Diagnostic +from .network.tools import Tools + +from .database import SQLite +from .filesystem import FileSystem + +__version__ = "1.0.0" + +__all__ = ["Application", "CommandLine", "Helper", "Configuration", "Log", "MsgBox", "StepIndicator", "Form", "Diagnostic", "Tools", "SQLite", "FileSystem"] diff --git a/dist/macos/Replicator.app/Contents/Resources/core/application.py b/dist/macos/Replicator.app/Contents/Resources/core/application.py new file mode 100644 index 00000000..1bacf1ef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/application.py @@ -0,0 +1,478 @@ +#!/usr/bin/env python3 +# src/core/application.py +from __future__ import annotations + +from typing import Optional, Iterable +from PyQt5.QtCore import pyqtSignal, Qt, QThread +from PyQt5.QtWidgets import QProxyStyle, QStyle, QApplication, QProgressDialog, QPushButton + +from .helper import Helper +from .configuration import Configuration +from .log import Log +from .service import Service +from .ui import MsgBox +import os +import subprocess + +# --------------------------------------------------------------------------- +# Custom Style to suppress focus rectangles +# --------------------------------------------------------------------------- + +class NoFocusRectStyle(QProxyStyle): + def drawPrimitive(self, element, option, painter, widget=None): + if element == QStyle.PE_FrameFocusRect: + return # skip drawing the focus rect completely + super().drawPrimitive(element, option, painter, widget) + +# --------------------------------------------------------------------------- +# Application update dialog +# --------------------------------------------------------------------------- + +class ApplicationDialog(QProgressDialog): + canceled_by_user = pyqtSignal() + + def __init__(self, parent=None): + super().__init__("Updating...", "Cancel", 0, 0, parent) + self.setWindowModality(Qt.WindowModal) + self.setWindowFlags( + Qt.Dialog | Qt.WindowTitleHint + | Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint + ) + self.setObjectName("ApplicationDialog") + self.setMinimumDuration(0) + self.setAutoReset(False) + self.setFixedWidth(300) + + # Replace default Cancel button with our own so we can style it if needed + btn = QPushButton("Cancel", self) + btn.clicked.connect(self._on_cancel) + self.setCancelButton(btn) + + def _on_cancel(self): + self.canceled_by_user.emit() + self.reject() + +# --------------------------------------------------------------------------- +# Background worker for application update +# --------------------------------------------------------------------------- + +class ApplicationThread(QThread): + + finished_with_result = pyqtSignal(int, bool) # rc, canceled + progress_text = pyqtSignal(str) # label to show in dialog + + def __init__( + self, + repo_root: str, + tasks: list[tuple[list[str], str | None]] | None = None, + logger: Log | None = None, + parent=None, + ): + super().__init__(parent) + self._repo_root = repo_root + self._tasks = tasks or [] + self._logger = logger + + def run(self) -> None: + import time + + rc = -1 + canceled = False + + def run_command(args: list[str]) -> int: + nonlocal canceled + try: + proc = subprocess.Popen(args) + except Exception as e: + if self._logger: + self._logger.append( + f"[ApplicationThread] Failed to start command {args!r}: {e}", + channel="system", + level="error", + ) + return -1 + + while True: + if self.isInterruptionRequested(): + canceled = True + try: + proc.terminate() + except Exception: + pass + try: + return proc.wait() + except Exception: + return -1 + + r = proc.poll() + if r is not None: + return r + + time.sleep(0.05) + + # ---- 1) update repository --------------------------------------------------- + if self._logger: + self._logger.append( + f"[ApplicationThread] Starting git pull in {self._repo_root}", + channel="system", + level="info", + ) + + self.progress_text.emit("Updating application files...") + rc = run_command(["sudo", "git", "-C", self._repo_root, "pull", "--recurse-submodules"]) + + if self._logger: + self._logger.append( + f"[ApplicationThread] git pull finished ({rc})", + channel="system", + level="info" if rc == 0 else "error", + ) + + if rc != 0 or canceled: + self.finished_with_result.emit(rc if rc is not None else -1, canceled) + return + + # ---- 2) Post-update tasks ----------------------------------------- + for args, label in self._tasks: + if label: + self.progress_text.emit(label) + + rc = run_command(args) + + if self._logger: + self._logger.append( + f"[ApplicationThread] Command finished ({rc}): {' '.join(args)}", + channel="system", + level="info" if rc == 0 else "error", + ) + + if rc != 0 or canceled: + break + + self.finished_with_result.emit(rc if rc is not None else -1, canceled) + +# --------------------------------------------------------------------------- +# Application class +# --------------------------------------------------------------------------- + +class Application(QApplication): + + updating = pyqtSignal(object) + + def __init__(self, name: Optional[str] = None, argv=None): + + # Initialize QApplication + super().__init__(argv or []) + + # Application name + if name: + self.setApplicationName(name) + + # Set application mode + self._mode = "gui" + + # Set application style + self.setStyle('Fusion') + + # Use custom style to suppress focus rectangles + self.setStyle(NoFocusRectStyle(self.style())) + + # Main window placeholder (e.g. Client) + self._mainWindow = None + + # Helper + self._helper = Helper() + + # Configuration manager + self._configuration = Configuration() + self._configuration.configChanged.connect(self.reset) + + # Default configuration entries + self._configuration.add("administration.update", None, "button", label="Check for Updates", action=self.update) + + # Save any new defaults + self._configuration.save() + + # Logger + self._logger = Log() + + # Service manager + self._service = Service(self._logger, self._configuration) + + # Initial stylesheet load + self._loadStylesheet() + + # ------------------------------------------------------------------ + # Properties / accessors + # ------------------------------------------------------------------ + + @property + def helper(self) -> Helper: + return self._helper + + @property + def logger(self) -> Log: + return self._logger + + @property + def configuration(self) -> Configuration: + return self._configuration + + @property + def service(self) -> Service: + return self._service + + @property + def mainWindow(self): + return self._mainWindow + + @property + def name(self) -> str: + return self.applicationName() + + @property + def mode(self) -> str: + return self._mode + + # ------------------------------------------------------------------ + # Main window management + # ------------------------------------------------------------------ + + def set_mainWindow(self, window): + self._mainWindow = window + self._loadStylesheet() + self._mainWindow.show() + + # ------------------------------------------------------------------ + # Stylesheet handling + # ------------------------------------------------------------------ + + def _loadStylesheet(self): + + # Base stylesheet (e.g. core/styles/style.css) + base_css = self._helper.load_stylesheet("core/styles/style.css") # you can implement this in Helper + + # Retrieve icon paths + check_svg = self._helper.get_path("core/icons/check.svg") + chevron_up_svg = self._helper.get_path("core/icons/chevron-up.svg") + chevron_down_svg = self._helper.get_path("core/icons/chevron-down.svg") + chevron_expand_svg = self._helper.get_path("core/icons/chevron-expand.svg") + + # Override styles + override = ( + "\n" + "QCheckBox::indicator:checked { " + f"image: {self._helper.qss_url(check_svg)};" + " }\n" + "QComboBox::down-arrow { " + f"image: {self._helper.qss_url(chevron_expand_svg)};" + " }\n" + "QSpinBox::up-arrow { " + f"image: {self._helper.qss_url(chevron_up_svg)};" + " }\n" + "QSpinBox::down-arrow { " + f"image: {self._helper.qss_url(chevron_down_svg)};" + " }\n" + ) + + # Start with base + global overrides + css = (base_css or "") + override + + # If main window has its own override, append it + if self._mainWindow and hasattr(self._mainWindow, "override"): + css += self._mainWindow.override() + + # Apply combined stylesheet + self.setStyleSheet(css) + + # ------------------------------------------------------------------ + # UI reset on configuration change + # ------------------------------------------------------------------ + + def reset(self): + + # Do nothing if no main window + if not self._mainWindow: + return + + # Call main window reset if available + if hasattr(self._mainWindow, 'reset'): + self._loadStylesheet() + self._mainWindow.reset() + + # ------------------------------------------------------------------ + # System Helpers + # ------------------------------------------------------------------ + + def _run_system_command(self, args: list[str], wait: bool = False) -> int | None: + + # Only attempt on Linux; ignore silently on other platforms + try: + os_name = self._helper.get_os() + except Exception: + os_name = None + + if os_name != "linux": + if self._logger: + self._logger.append( + f"[Application] Ignoring system command {args!r} on non-Linux OS: {os_name}", + channel="system", + level="warning", + ) + return None + + try: + if wait: + proc = subprocess.Popen(args) + rc = proc.wait() + if self._logger: + self._logger.append( + f"[Application] (wait) Command finished ({rc}): {' '.join(args)}", + channel="system", + level="info", + ) + return rc + else: + subprocess.Popen(args) + if self._logger: + self._logger.append( + f"[Application] Executed system command: {' '.join(args)}", + channel="system", + level="info", + ) + return None + except Exception as e: + if self._logger: + self._logger.append( + f"[Application] Failed to execute system command {args!r}: {e}", + channel="system", + level="error", + ) + return None + + def shutdown(self) -> None: + self._run_system_command(["systemctl", "poweroff"]) + + def restart(self) -> None: + self._run_system_command(["systemctl", "reboot"]) + + # ------------------------------------------------------------------ + # Application Helpers + # ------------------------------------------------------------------ + + def update(self): + # Determine repo root + try: + here = os.path.abspath(os.path.dirname(__file__)) + repo_root = os.path.abspath(os.path.join(here, "..", "..")) + except Exception as e: + if self._logger: + self._logger.append( + f"[Application] Failed to determine repository root for update: {e}", + channel="system", + level="error", + ) + MsgBox.show( + parent=self._mainWindow, + title="Update Failed", + message="Failed to determine the repository root for the update.", + icon="error", + buttons=("OK"), + default="OK", + icon_lookup_fn=self._helper.get_path, + ) + return + + # Only attempt on Linux + try: + os_name = self._helper.get_os() + except Exception: + os_name = None + + if os_name != "linux": + if self._logger: + self._logger.append( + "[Application] Update ignored on non-Linux OS.", + channel="system", + level="warning", + ) + MsgBox.show( + parent=self._mainWindow, + title="Update Not Available", + message="Updating is only supported on Linux systems.", + icon="info", + buttons=("OK"), + default="OK", + icon_lookup_fn=self._helper.get_path, + ) + return + + # --- Build post-update task list via listener ------------------------- + tasks: list[tuple[list[str], str | None]] = [] + + def add_task(args: list[str], label: str | None = None) -> None: + tasks.append((args, label)) + + # Let external code (main.py) register tasks. + # Those tasks *will* run after git pull in ApplicationThread. + self.updating.emit(add_task) + + # --- Create dialog + worker ------------------------------------------ + dlg_parent = self._mainWindow if self._mainWindow is not None else None + progress = ApplicationDialog(parent=dlg_parent) + progress.setLabelText(f"Updating {self.name}...") + + worker = ApplicationThread(repo_root, tasks=tasks, logger=self._logger, parent=self) + + # Update label whenever the worker reports a progress text + worker.progress_text.connect(progress.setLabelText) + + def on_worker_finished(rc: int, canceled: bool) -> None: + progress.close() + + if canceled: + MsgBox.show( + parent=self._mainWindow, + title="Update Canceled", + message="The update was canceled. The application may not be fully up to date.", + icon="warning", + buttons=("OK"), + default="OK", + icon_lookup_fn=self._helper.get_path, + ) + return + + if rc not in (0, None): + MsgBox.show( + parent=self._mainWindow, + title="Update Failed", + message=f"Update failed with exit code {rc}. Check the logs for details.", + icon="error", + buttons=("OK"), + default="OK", + icon_lookup_fn=self._helper.get_path, + ) + return + + # Everything (git + tasks) succeeded + buttons: Iterable[str] = ("Exit", "OK") + choice = MsgBox.show( + parent=self._mainWindow, + title="Update Successful", + message="The application has been updated. Please restart the application to apply the latest changes.", + icon="info", + buttons=buttons, + default="OK", + icon_lookup_fn=self._helper.get_path, + ) + if choice == "Exit": + self.quit() + + def on_user_cancel() -> None: + worker.requestInterruption() + + progress.canceled_by_user.connect(on_user_cancel) + worker.finished_with_result.connect(on_worker_finished) + + progress.show() + worker.start() diff --git a/dist/macos/Replicator.app/Contents/Resources/core/build.sh b/dist/macos/Replicator.app/Contents/Resources/core/build.sh new file mode 100755 index 00000000..932220a7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/build.sh @@ -0,0 +1,1402 @@ +#!/bin/bash +set -euo pipefail + +# ----------------------------------------------------------------------------- +# build.sh (generic PyInstaller build script) +# - Designed to be reused across LaswitchTech projects +# - Defaults work out-of-the-box for this repo (Replicator) +# ----------------------------------------------------------------------------- + +log() { + echo "$(date +'%Y-%m-%d %H:%M:%S') - $*" +} + +die() { + echo "ERROR: $*" >&2 + exit 1 +} + +detect_os() { + case "$(uname -s)" in + Darwin) echo "macos" ;; + Linux) echo "linux" ;; + WindowsNT|MINGW64*|MINGW32*|MSYS*|CYGWIN*) echo "windows" ;; + *) echo "unsupported" ;; + esac +} + + +# Portable in-place sed (macOS vs GNU) +sed_inplace() { + # usage: sed_inplace 's/a/b/' file + if sed --version >/dev/null 2>&1; then + sed -i "$1" "$2" + else + sed -i '' "$1" "$2" + fi +} + +# ----------------------------------------------------------------------------- +# corePY vendored bin sync +# Some projects vendor corePY under src/core/src and keep binaries there. +# To make PyInstaller data inclusion consistent, mirror vendored binaries into +# src/bin (overwriting existing content). +# ----------------------------------------------------------------------------- + +sync_vendored_bins() { + local src_dir="src/core/src/bin" + local dst_dir="src/bin" + + [ -d "$src_dir" ] || return 0 + + log "Syncing vendored binaries: $src_dir -> $dst_dir" + mkdir -p "$dst_dir" + + # Use cp -R to stay portable across macOS/Linux/Windows Git Bash. + # Trailing '/.' copies contents (including hidden files) into destination. + cp -R "$src_dir/." "$dst_dir/" 2>/dev/null || cp -R "$src_dir"/* "$dst_dir/" 2>/dev/null || true +} + +# +# Icon generation +# - macOS: icon.svg -> icon.icns (every build) +# - Windows: icon.svg -> icon.ico (best-effort, every build) +# Requires: iconutil (macOS) + either rsvg-convert (librsvg) OR inkscape. +# Windows ICO generation prefers: ImageMagick (magick/convert) OR Python + Pillow. +# ----------------------------------------------------------------------------- + +generate_icns_from_svg_macos() { + [ "$OS" = "macos" ] || return 0 + + local svg="src/icons/icon.svg" + local out="src/icons/icon.icns" + + [ -f "$svg" ] || return 0 + + if ! command -v iconutil >/dev/null 2>&1; then + log "WARN: iconutil not found; cannot generate .icns from $svg" + return 0 + fi + + local renderer="" + if command -v rsvg-convert >/dev/null 2>&1; then + renderer="rsvg" + elif command -v inkscape >/dev/null 2>&1; then + renderer="inkscape" + else + log "WARN: Neither rsvg-convert nor inkscape found; cannot generate .icns from $svg" + log " Install one of them (recommended: brew install librsvg)" + return 0 + fi + + mkdir -p "build" + + local iconset="build/icon.iconset" + rm -rf "$iconset" + mkdir -p "$iconset" + + # Required sizes for iconutil + local sizes=(16 32 128 256 512) + + log "Regenerating macOS icon: $out (from $svg using $renderer)" + + for s in "${sizes[@]}"; do + local s2=$((s * 2)) + + if [ "$renderer" = "rsvg" ]; then + rsvg-convert -w "$s" -h "$s" "$svg" -o "$iconset/icon_${s}x${s}.png" + rsvg-convert -w "$s2" -h "$s2" "$svg" -o "$iconset/icon_${s}x${s}@2x.png" + else + # inkscape CLI (v1+) + inkscape "$svg" --export-type=png --export-width="$s" --export-height="$s" --export-filename="$iconset/icon_${s}x${s}.png" >/dev/null 2>&1 + inkscape "$svg" --export-type=png --export-width="$s2" --export-height="$s2" --export-filename="$iconset/icon_${s}x${s}@2x.png" >/dev/null 2>&1 + fi + done + + # Build .icns + iconutil -c icns "$iconset" -o "$out" + + # Cleanup iconset directory (keep build folder) + rm -rf "$iconset" +} + +# ----------------------------------------------------------------------------- +# Windows icon generation: icon.svg -> icon.ico +# Best-effort: uses inkscape/rsvg-convert to render PNGs then combines to ICO. +# Prefers ImageMagick; falls back to Python+Pillow if available. +# ----------------------------------------------------------------------------- + +generate_ico_from_svg_windows() { + [ "$OS" = "windows" ] || return 0 + + local svg="src/icons/icon.svg" + local out="src/icons/icon.ico" + + [ -f "$svg" ] || return 0 + + local renderer="" + if command -v rsvg-convert >/dev/null 2>&1; then + renderer="rsvg" + elif command -v inkscape >/dev/null 2>&1; then + renderer="inkscape" + else + log "WARN: Neither rsvg-convert nor inkscape found; cannot generate .ico from $svg" + log " Install one of them (recommended: Inkscape)" + return 0 + fi + + mkdir -p "build" + + local tmpdir="build/icon.ico.tmp" + rm -rf "$tmpdir" + mkdir -p "$tmpdir" + + # Common ICO sizes + local sizes=(16 24 32 48 64 128 256) + + log "Regenerating Windows icon: $out (from $svg using $renderer)" + + for s in "${sizes[@]}"; do + if [ "$renderer" = "rsvg" ]; then + rsvg-convert -w "$s" -h "$s" "$svg" -o "$tmpdir/${s}.png" + else + # inkscape CLI (v1+) + inkscape "$svg" --export-type=png --export-width="$s" --export-height="$s" --export-filename="$tmpdir/${s}.png" >/dev/null 2>&1 + fi + done + + # Combine PNGs into ICO + if command -v magick >/dev/null 2>&1; then + # ImageMagick 7+ + magick "$tmpdir/16.png" "$tmpdir/24.png" "$tmpdir/32.png" "$tmpdir/48.png" "$tmpdir/64.png" "$tmpdir/128.png" "$tmpdir/256.png" "$out" 2>/dev/null || true + elif command -v convert >/dev/null 2>&1; then + # ImageMagick 6 (convert) + convert "$tmpdir/16.png" "$tmpdir/24.png" "$tmpdir/32.png" "$tmpdir/48.png" "$tmpdir/64.png" "$tmpdir/128.png" "$tmpdir/256.png" "$out" 2>/dev/null || true + else + # Fallback: Python + Pillow (if available) + python - <<'PY' "$tmpdir" "$out" 2>/dev/null || true +import sys +from pathlib import Path + +tmpdir = Path(sys.argv[1]) +out = Path(sys.argv[2]) + +try: + from PIL import Image +except Exception: + raise SystemExit(1) + +sizes = [16, 24, 32, 48, 64, 128, 256] +imgs = [] +for s in sizes: + p = tmpdir / f"{s}.png" + if p.exists(): + imgs.append(Image.open(p)) + +if not imgs: + raise SystemExit(1) + +# Pillow writes multi-size ICO when you pass sizes +base = imgs[-1] +base.save(out, format="ICO", sizes=[(s, s) for s in sizes]) +PY + fi + + if [ -f "$out" ]; then + log "Windows icon generated: $out" + else + log "WARN: Failed to generate $out (install ImageMagick or Python Pillow for best results)" + fi + + rm -rf "$tmpdir" +} + +# Guess app name from current folder if not provided +infer_name() { + local base + base="$(basename "$(pwd)")" + # keep it simple: only allow alnum, dash, underscore + echo "$base" | tr -cd '[:alnum:]_-' +} + +show_help() { + cat <<'EOF' +Usage: + ./build.sh [options] + +Options: + --name NAME App name (default: folder name) + --entry PATH Entry script/module for PyInstaller (default: src/main.py) + --config PATH Path to build.cfg (default: ./build.cfg if present) + --windowed Build GUI app (no console) (macOS: --windowed; Linux: still onefile) + --console Build console app (default) + --icon PATH Icon path (macOS: .icns recommended) + --add-data SRC:DST Add data folder/file (repeatable). Uses PyInstaller --add-data=SRC:DST. + --hidden-import MOD Add hidden import (repeatable) + --onefile Force onefile (default on Linux) + --onedir Force onedir (default on macOS) + --python PY Python 3.11 binary (default: python3.11 from PATH) + --system-pyqt On Linux ARM, prefer APT PyQt5 with --system-site-packages + --clean Remove build/dist artifacts before building + --debug-pyi Enable PyInstaller debug output (--log-level=DEBUG --debug=all) + --dmg On macOS, create a DMG (only meaningful for onedir .app) + --gen-install Generate install/run wrapper scripts into repo root (default) + --no-gen-install Do not generate install/run wrapper scripts + --venv-dir DIR Virtualenv directory for wrapper scripts (default: .venv) + --requirements PATH Requirements file used by wrapper scripts if present (default: requirements.txt) + -h, --help Show this help + +Examples: + ./build.sh --name Replicator --entry src/main.py --windowed --add-data src/app:app + ./build.sh --console --hidden-import PyQt5.QtSvg +EOF +} + +# ----------------------------------------------------------------------------- +# Defaults (good for Replicator) +# ----------------------------------------------------------------------------- +OS="$(detect_os)" +[ "$OS" = "unsupported" ] && die "Unsupported operating system." + +APP_NAME="$(infer_name)" +ENTRY="src/main.py" +MODE="console" # console|windowed + +# Packaging defaults: macOS prefers onedir (for .app), Linux prefers onefile +PKG="" # empty = auto, or onefile/onedir + +# +# Python discovery +# - macOS/Linux: prefer python3.11 +# - Windows (Git Bash): prefer the Python Launcher when available, but only if the requested runtime exists. +PYTHON_BIN="" +PYTHON_LAUNCH_ARGS="" + +python_cmd_ok() { + # usage: python_cmd_ok [args...] + # returns 0 if command runs and Python version is >= 3.11 + "$@" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' >/tmp/.replicator_pyver 2>/dev/null || return 1 + local ver + ver="$(cat /tmp/.replicator_pyver 2>/dev/null || true)" + rm -f /tmp/.replicator_pyver 2>/dev/null || true + case "$ver" in + 3.11|3.12|3.13|3.14|3.15|3.16|3.17|3.18|3.19|4.*) return 0 ;; + *) return 1 ;; + esac +} + +# Candidate selection (ordered) +if command -v python3.11 >/dev/null 2>&1 && python_cmd_ok python3.11; then + PYTHON_BIN="python3.11" + PYTHON_LAUNCH_ARGS="" +elif [ "$OS" = "windows" ] && command -v py >/dev/null 2>&1; then + # Try explicit 3.11 first, then any 3.x that satisfies >=3.11 + if python_cmd_ok py -3.11; then + PYTHON_BIN="py" + PYTHON_LAUNCH_ARGS="-3.11" + elif python_cmd_ok py -3.12; then + PYTHON_BIN="py" + PYTHON_LAUNCH_ARGS="-3.12" + elif python_cmd_ok py -3.13; then + PYTHON_BIN="py" + PYTHON_LAUNCH_ARGS="-3.13" + elif python_cmd_ok py -3; then + PYTHON_BIN="py" + PYTHON_LAUNCH_ARGS="-3" + fi +fi + +# Fallbacks (Git Bash often exposes only `python`) +if [ -z "$PYTHON_BIN" ]; then + if command -v python3 >/dev/null 2>&1 && python_cmd_ok python3; then + PYTHON_BIN="python3" + PYTHON_LAUNCH_ARGS="" + elif command -v python >/dev/null 2>&1 && python_cmd_ok python; then + PYTHON_BIN="python" + PYTHON_LAUNCH_ARGS="" + fi +fi + +# If user supplied --python, we still validate it later in the script. + +python_exec() { + # Wrapper so we can call: python_exec -m venv ... + [ -n "${PYTHON_BIN:-}" ] || die "Python not found. Install Python 3.11+ and ensure it is in PATH (python) or via the Windows Python Launcher (py)." + + if [ -n "${PYTHON_LAUNCH_ARGS:-}" ]; then + # shellcheck disable=SC2086 + "$PYTHON_BIN" ${PYTHON_LAUNCH_ARGS} "$@" + else + "$PYTHON_BIN" "$@" + fi +} + +venv_python_path() { + if [ "$OS" = "windows" ]; then + echo "$VENV_DIR/Scripts/python.exe" + else + echo "$VENV_DIR/bin/python" + fi +} + +venv_activate_path() { + if [ "$OS" = "windows" ]; then + echo "$VENV_DIR/Scripts/activate" + else + echo "$VENV_DIR/bin/activate" + fi +} + +USE_SYSTEM_PYQT=0 + +# macOS DMG toggle +MAKE_DMG=0 + +# PyInstaller debug toggle +PYI_DEBUG=0 + +# Icon (optional) +ICON_FILE="" + +# Repeatable arrays +declare -a ADD_DATA +ADD_DATA=() + +declare -a HIDDEN_IMPORTS +HIDDEN_IMPORTS=() + +# Common default data folders (only add if they exist) +# Replicator usually has icons/app/styles/img in some projects; keep generic. +DEFAULT_DATA_CANDIDATES=( + "src/app:app" + "src/styles:styles" + "src/icons:icons" + "src/img:img" + "assets:assets" +) + +# Optional config file +CFG_FILE="" + +# Wrapper script defaults +GENERATE_INSTALL=1 +VENV_DIR=".venv" +REQ_FILE="requirements.txt" + +# Load simple KEY=VALUE config (no code execution) +# Supported keys: +# NAME, ENTRY, MODE, PKG, ICON, PYTHON, SYSTEM_PYQT, DMG, CLEAN +# ADD_DATA, HIDDEN_IMPORTS +# Notes: +# - Lines beginning with # or ; are ignored +# - Whitespace around keys/values is trimmed +# - ADD_DATA / HIDDEN_IMPORTS can be comma or semicolon separated +trim_ws() { + # trim leading/trailing whitespace + local s="$1" + s="${s#${s%%[![:space:]]*}}" + s="${s%${s##*[![:space:]]}}" + echo "$s" +} + +split_list() { + # split comma/semicolon separated list into lines + echo "$1" | tr ';' '\n' | tr ',' '\n' +} + +apply_cfg_kv() { + local key="$1" val="$2" + key="$(trim_ws "$key")" + val="$(trim_ws "$val")" + [ -z "$key" ] && return 0 + + case "$key" in + NAME) + APP_NAME="$val" + ;; + ENTRY) + ENTRY="$val" + ;; + MODE) + # console|windowed + if [ "$val" = "console" ] || [ "$val" = "windowed" ]; then + MODE="$val" + fi + ;; + PKG) + # onefile|onedir|auto + if [ "$val" = "onefile" ] || [ "$val" = "onedir" ]; then + PKG="$val" + elif [ "$val" = "auto" ]; then + PKG="" + fi + ;; + ICON) + ICON_FILE="$val" + ;; + PYTHON) + PYTHON_BIN="$val" + ;; + SYSTEM_PYQT) + if [ "$val" = "1" ] || [ "$val" = "true" ] || [ "$val" = "yes" ]; then + USE_SYSTEM_PYQT=1 + elif [ "$val" = "0" ] || [ "$val" = "false" ] || [ "$val" = "no" ]; then + USE_SYSTEM_PYQT=0 + fi + ;; + DMG) + if [ "$val" = "1" ] || [ "$val" = "true" ] || [ "$val" = "yes" ]; then + MAKE_DMG=1 + elif [ "$val" = "0" ] || [ "$val" = "false" ] || [ "$val" = "no" ]; then + MAKE_DMG=0 + fi + ;; + CLEAN) + if [ "$val" = "1" ] || [ "$val" = "true" ] || [ "$val" = "yes" ]; then + CLEAN=1 + elif [ "$val" = "0" ] || [ "$val" = "false" ] || [ "$val" = "no" ]; then + CLEAN=0 + fi + ;; + ADD_DATA) + # replaces current list + ADD_DATA=() + while IFS= read -r item; do + item="$(trim_ws "$item")" + [ -n "$item" ] && ADD_DATA+=("$item") + done < <(split_list "$val") + ;; + HIDDEN_IMPORTS) + # replaces current list + HIDDEN_IMPORTS=() + while IFS= read -r item; do + item="$(trim_ws "$item")" + [ -n "$item" ] && HIDDEN_IMPORTS+=("$item") + done < <(split_list "$val") + ;; + GEN_INSTALL) + if [ "$val" = "1" ] || [ "$val" = "true" ] || [ "$val" = "yes" ]; then + GENERATE_INSTALL=1 + elif [ "$val" = "0" ] || [ "$val" = "false" ] || [ "$val" = "no" ]; then + GENERATE_INSTALL=0 + fi + ;; + VENV_DIR) + VENV_DIR="$val" + ;; + REQUIREMENTS) + REQ_FILE="$val" + ;; + *) + # unknown keys ignored for forward-compat + ;; + esac +} + +load_cfg_file() { + local f="$1" + [ -f "$f" ] || return 0 + log "Loading config: $f" + + while IFS= read -r line || [ -n "$line" ]; do + # strip CR (Windows line endings) + line="${line%$'\r'}" + + # ignore comments/blank lines + case "$(trim_ws "$line")" in + ""|\#*|\;*) continue ;; + esac + + # allow inline comments after a value using # + # (only if there is at least one space before #) + if echo "$line" | grep -q "[[:space:]]#"; then + line="$(echo "$line" | sed 's/[[:space:]]#.*$//')" + fi + + if echo "$line" | grep -q "="; then + local k v + k="${line%%=*}" + v="${line#*=}" + apply_cfg_kv "$k" "$v" + fi + done < "$f" +} + +# ----------------------------------------------------------------------------- +# Parse args +# ----------------------------------------------------------------------------- +while [ $# -gt 0 ]; do + case "$1" in + --name) + shift + [ $# -gt 0 ] || die "--name requires a value" + APP_NAME="$1" + ;; + --entry) + shift + [ $# -gt 0 ] || die "--entry requires a value" + ENTRY="$1" + ;; + --config) + shift + [ $# -gt 0 ] || die "--config requires a value" + CFG_FILE="$1" + ;; + --windowed) + MODE="windowed" + ;; + --console) + MODE="console" + ;; + --icon) + shift + [ $# -gt 0 ] || die "--icon requires a value" + ICON_FILE="$1" + ;; + --add-data) + shift + [ $# -gt 0 ] || die "--add-data requires a value like SRC:DST" + ADD_DATA+=("$1") + ;; + --hidden-import) + shift + [ $# -gt 0 ] || die "--hidden-import requires a module name" + HIDDEN_IMPORTS+=("$1") + ;; + --onefile) + PKG="onefile" + ;; + --onedir) + PKG="onedir" + ;; + --python) + shift + [ $# -gt 0 ] || die "--python requires a path/binary" + PYTHON_BIN="$1" + ;; + --system-pyqt) + USE_SYSTEM_PYQT=1 + ;; + --clean) + CLEAN=1 + ;; + --debug-pyi) + PYI_DEBUG=1 + ;; + --dmg) + MAKE_DMG=1 + ;; + --gen-install) + GENERATE_INSTALL=1 + ;; + --no-gen-install) + GENERATE_INSTALL=0 + ;; + --venv-dir) + shift + [ $# -gt 0 ] || die "--venv-dir requires a value" + VENV_DIR="$1" + ;; + --requirements) + shift + [ $# -gt 0 ] || die "--requirements requires a value" + REQ_FILE="$1" + ;; + -h|--help) + show_help + exit 0 + ;; + *) + die "Unknown option: $1 (use --help)" + ;; + esac + shift +done + +# ----------------------------------------------------------------------------- +# Load config (if provided, or if ./build.cfg exists) +# CLI flags should override config values. +# ----------------------------------------------------------------------------- + +# Capture what the user explicitly set via CLI so we can re-apply after config +CLI_APP_NAME="$APP_NAME" +CLI_ENTRY="$ENTRY" +CLI_MODE="$MODE" +CLI_PKG="$PKG" +CLI_ICON="$ICON_FILE" +CLI_PYTHON_BIN="$PYTHON_BIN" +CLI_USE_SYSTEM_PYQT="$USE_SYSTEM_PYQT" +CLI_MAKE_DMG="$MAKE_DMG" +CLI_CLEAN="${CLEAN:-0}" +CLI_ADD_DATA=("${ADD_DATA[@]+${ADD_DATA[@]}}") +CLI_HIDDEN_IMPORTS=("${HIDDEN_IMPORTS[@]+${HIDDEN_IMPORTS[@]}}") +CLI_GENERATE_INSTALL="$GENERATE_INSTALL" +CLI_VENV_DIR="$VENV_DIR" +CLI_REQ_FILE="$REQ_FILE" + +# Determine config path +if [ -z "$CFG_FILE" ] && [ -f "build.cfg" ]; then + CFG_FILE="build.cfg" +fi + +# Apply config +if [ -n "$CFG_FILE" ]; then + load_cfg_file "$CFG_FILE" +fi + +# Re-apply CLI values only when the user actually supplied flags. +# Heuristic: if arrays were empty pre-config but are non-empty post-config, +# we only override them when CLI provided values (captured arrays non-empty). +# Scalars: if CLI value differs from the default-initialized value AND the flag was used, +# we treat it as explicitly set. For simplicity, we treat any CLI value as authoritative +# when it differs from what config loaded. + +# Scalars +[ "$CLI_APP_NAME" != "$(infer_name)" ] && APP_NAME="$CLI_APP_NAME" || true +[ "$CLI_ENTRY" != "src/main.py" ] && ENTRY="$CLI_ENTRY" || true +[ "$CLI_MODE" != "console" ] && MODE="$CLI_MODE" || true +[ -n "$CLI_PKG" ] && PKG="$CLI_PKG" || true +[ -n "$CLI_ICON" ] && ICON_FILE="$CLI_ICON" || true +[ "$CLI_PYTHON_BIN" != "$(command -v python3.11 || true)" ] && PYTHON_BIN="$CLI_PYTHON_BIN" || true +[ "$CLI_USE_SYSTEM_PYQT" != "0" ] && USE_SYSTEM_PYQT="$CLI_USE_SYSTEM_PYQT" || true +[ "$CLI_MAKE_DMG" != "0" ] && MAKE_DMG="$CLI_MAKE_DMG" || true +if [ "$CLI_CLEAN" = "1" ]; then CLEAN=1; fi +# New CLI re-apply for wrapper script settings +if [ "$CLI_GENERATE_INSTALL" != "1" ]; then + GENERATE_INSTALL="$CLI_GENERATE_INSTALL" +fi +if [ "$CLI_VENV_DIR" != ".venv" ]; then + VENV_DIR="$CLI_VENV_DIR" +fi +if [ "$CLI_REQ_FILE" != "requirements.txt" ]; then + REQ_FILE="$CLI_REQ_FILE" +fi + +# Arrays +if [ "${#CLI_ADD_DATA[@]}" -gt 0 ]; then + nonempty=0 + for v in "${CLI_ADD_DATA[@]}"; do + [ -n "$v" ] && nonempty=1 + done + if [ "$nonempty" -eq 1 ]; then + ADD_DATA=("${CLI_ADD_DATA[@]}") + fi +fi + +if [ "${#CLI_HIDDEN_IMPORTS[@]}" -gt 0 ]; then + nonempty=0 + for v in "${CLI_HIDDEN_IMPORTS[@]}"; do + [ -n "$v" ] && nonempty=1 + done + if [ "$nonempty" -eq 1 ]; then + HIDDEN_IMPORTS=("${CLI_HIDDEN_IMPORTS[@]}") + fi +fi + +# ----------------------------------------------------------------------------- +# Regenerate platform icons from icon.svg on every build (if present) +# ----------------------------------------------------------------------------- +sync_vendored_bins +generate_icns_from_svg_macos +generate_ico_from_svg_windows + +# ----------------------------------------------------------------------------- +# Generate developer-friendly install/run wrapper scripts (if enabled) +# ----------------------------------------------------------------------------- +generate_wrapper_scripts() { + [ "${GENERATE_INSTALL:-1}" -eq 1 ] || return 0 + + local out_dir="$1" # e.g. . (repo root) + mkdir -p "$out_dir" + + # --------------------------------------------------------------------------- + # POSIX shell wrapper (macOS/Linux + Windows Git Bash) + # --------------------------------------------------------------------------- + cat >"$out_dir/launch.sh" <<'SH' +#!/usr/bin/env bash +set -euo pipefail + +# Replicator dev launcher (macOS/Linux + Windows Git Bash) +# - Creates a virtualenv if missing +# - Installs runtime deps (prefers requirements.txt if present) +# - Runs src/main.py + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$ROOT_DIR" + +VENV_DIR="__VENV_DIR__" +REQ_FILE="__REQ_FILE__" + +# Detect Windows Git Bash (MSYS/MINGW/CYGWIN) +UNAME_S="$(uname -s 2>/dev/null || echo '')" +IS_WINDOWS=0 +case "$UNAME_S" in + MINGW*|MSYS*|CYGWIN*) IS_WINDOWS=1 ;; + *) IS_WINDOWS=0 ;; +esac + +# Choose python command +PY_CMD="" +PY_ARGS=() + +# Prefer explicit python3.11 on macOS/Linux +if command -v python3.11 >/dev/null 2>&1; then + PY_CMD="python3.11" +elif [ "$IS_WINDOWS" -eq 1 ] && command -v py >/dev/null 2>&1; then + # Prefer Windows Python Launcher (does NOT require python.exe in PATH) + PY_CMD="py" + PY_ARGS=(-3.11) +elif command -v python3 >/dev/null 2>&1; then + PY_CMD="python3" +elif command -v python >/dev/null 2>&1; then + PY_CMD="python" +else + echo "ERROR: Python not found in PATH. On Windows, install Python 3.11+ and/or ensure the Python Launcher (py) is available." >&2 + exit 1 +fi + +# Resolve venv python/activate paths +if [ "$IS_WINDOWS" -eq 1 ]; then + VENV_PY="$VENV_DIR/Scripts/python.exe" + ACTIVATE_SH="$VENV_DIR/Scripts/activate" +else + VENV_PY="$VENV_DIR/bin/python" + ACTIVATE_SH="$VENV_DIR/bin/activate" +fi + +# Create venv if needed +if [ ! -x "$VENV_PY" ]; then + echo "Creating virtualenv: $VENV_DIR" + # shellcheck disable=SC2086 + "$PY_CMD" "${PY_ARGS[@]}" -m venv "$VENV_DIR" +fi + +# Activate venv +# shellcheck disable=SC1090 +source "$ACTIVATE_SH" + +python -m pip install --upgrade pip wheel + +if [ -f "$REQ_FILE" ]; then + echo "Installing requirements from $REQ_FILE" + python -m pip install -r "$REQ_FILE" +else + echo "Installing minimal runtime deps (PyQt5)" + python -m pip install "PyQt5>=5.15,<6" +fi + +exec python "src/main.py" "$@" +SH + + # Patch placeholders + sed_inplace "s|__VENV_DIR__|$VENV_DIR|g" "$out_dir/launch.sh" + sed_inplace "s|__REQ_FILE__|$REQ_FILE|g" "$out_dir/launch.sh" + chmod +x "$out_dir/launch.sh" || true + + # CLI convenience (same as launch.sh but kept as a stable name for docs/scripts) + cat >"$out_dir/cli.sh" <<'SH' +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$ROOT_DIR" + +exec "./launch.sh" "$@" +SH + chmod +x "$out_dir/cli.sh" || true + + # --------------------------------------------------------------------------- + # Windows: VBS launcher (launch.vbs) and CLI .bat launcher (cli.bat) + # --------------------------------------------------------------------------- + cat >"$out_dir/launch.vbs" <<'VBS' +' Replicator Windows launcher (no console) +' - Prefers launching the built binary if present +' - Falls back to launching Git Bash + launch.sh if available + +Option Explicit + +Dim shell, fso, scriptDir, exePath, bashPath, cmd +Set shell = CreateObject("WScript.Shell") +Set fso = CreateObject("Scripting.FileSystemObject") + +scriptDir = fso.GetParentFolderName(WScript.ScriptFullName) + +' Try built EXE first +exePath = scriptDir & "\\dist\\windows\\Replicator.exe" +If fso.FileExists(exePath) Then + shell.CurrentDirectory = scriptDir + shell.Run Chr(34) & exePath & Chr(34), 1, False + WScript.Quit 0 +End If + +' Fallback: Git Bash launch.sh (if user is in a dev checkout) +bashPath = shell.ExpandEnvironmentStrings("%ProgramFiles%") & "\\Git\\bin\\bash.exe" +If fso.FileExists(bashPath) Then + cmd = Chr(34) & bashPath & Chr(34) & " -lc " & Chr(34) & "cd \"" & scriptDir & "\" && ./launch.sh" & Chr(34) + shell.Run cmd, 0, False +End If +VBS + + cat >"$out_dir/cli.bat" <<'BAT' +@echo off +setlocal EnableExtensions EnableDelayedExpansion + +REM --------------------------------------------------------------------------- +REM Replicator CLI launcher (Windows) +REM - Ensures a local venv exists (.venv) +REM - Installs minimal runtime deps (PyQt5) +REM - Runs src\main.py with a visible console +REM +REM Note: If you double-click this file, the console may flash and close. +REM Run it from an existing Command Prompt for persistent output. +REM --------------------------------------------------------------------------- + +set "SCRIPT_DIR=%~dp0" +set "VENV_DIR=%SCRIPT_DIR%.venv" +set "VENV_PY=%VENV_DIR%\Scripts\python.exe" + +REM Prefer Windows Python Launcher +set "PY_CMD=" +set "PY_ARGS=" +where py >nul 2>&1 +if %ERRORLEVEL%==0 ( + set "PY_CMD=py" + set "PY_ARGS=-3.11" +) else ( + where python >nul 2>&1 + if %ERRORLEVEL%==0 ( + set "PY_CMD=python" + set "PY_ARGS=" + ) +) + +if "%PY_CMD%"=="" ( + echo ERROR: Python not found. Install Python 3.11+ and ensure either `py` or `python` is available in PATH. + exit /b 1 +) + +REM Create venv if missing +if not exist "%VENV_PY%" ( + echo Creating virtualenv: %VENV_DIR% + %PY_CMD% %PY_ARGS% -m venv "%VENV_DIR%" + if %ERRORLEVEL% NEQ 0 ( + echo ERROR: Failed to create virtualenv. + exit /b %ERRORLEVEL% + ) +) + +REM Upgrade pip/wheel +"%VENV_PY%" -m pip install --upgrade pip wheel >nul + +REM Install minimal deps (idempotent) +echo Installing minimal runtime deps (PyQt5)... +"%VENV_PY%" -m pip install "PyQt5>=5.15,<6" >nul + +REM Prefer the built console companion if available +if exist "%SCRIPT_DIR%dist\windows\Replicator-cli.exe" ( + "%SCRIPT_DIR%dist\windows\Replicator-cli.exe" %* + endlocal + exit /b %ERRORLEVEL% +) + +REM Fallback: Run the source entry in console mode (dev checkout) +if not exist "%SCRIPT_DIR%src\main.py" ( + echo ERROR: Entry not found: %SCRIPT_DIR%src\main.py + echo NOTE: Replicator-cli.exe not found at %SCRIPT_DIR%dist\windows\Replicator-cli.exe + exit /b 1 +) + +"%VENV_PY%" "%SCRIPT_DIR%src\main.py" %* +endlocal +exit /b %ERRORLEVEL% +BAT +} + +# ----------------------------------------------------------------------------- +# Validate +# ----------------------------------------------------------------------------- +[ -n "$PYTHON_BIN" ] || die "Python not found. Install Python 3.11+ and ensure it is available as python (Windows/Git Bash) or via the Windows Python Launcher (py), or as python3.11 (macOS/Linux)." +[ -f "$ENTRY" ] || die "Entry not found: $ENTRY" + +# Validate python runtime is actually runnable and >= 3.11 +if ! python_exec -c "import sys; assert (sys.version_info.major, sys.version_info.minor) >= (3, 11), sys.version" >/dev/null 2>&1; then + if [ "$OS" = "windows" ] && [ "$PYTHON_BIN" = "py" ]; then + die "Python launcher found, but no suitable Python 3.11+ runtime is installed. Install Python 3.11+ (check 'Add python.exe to PATH') or run: py --list to verify installed versions." + fi + die "Python is not runnable or is < 3.11. Install Python 3.11+ and try again." +fi + +ARCH="$(uname -m)" +if [ "$OS" = "linux" ] && { [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "armv7l" ] || [ "$ARCH" = "armhf" ]; }; then + # Auto-enable system PyQt on ARM unless explicitly overridden by user (flag) + # Keeping your prior behavior but behind the switch. + : +fi + +# Auto package choice +if [ -z "$PKG" ]; then + if [ "$OS" = "macos" ]; then + PKG="onedir" + else + PKG="onefile" + fi +fi + +# Auto icon discovery if not provided +if [ -z "$ICON_FILE" ]; then + if [ "$OS" = "macos" ] && [ -f "src/icons/icon.icns" ]; then + ICON_FILE="src/icons/icon.icns" + elif [ "$OS" = "windows" ] && [ -f "src/icons/icon.ico" ]; then + ICON_FILE="src/icons/icon.ico" + elif [ -f "src/icons/icon.png" ]; then + ICON_FILE="src/icons/icon.png" + fi +fi + +# Add default data folders if present (and not already provided) +for cand in "${DEFAULT_DATA_CANDIDATES[@]}"; do + src="${cand%%:*}" + if [ -e "$src" ]; then + # Avoid duplicates + dup=0 + for existing in "${ADD_DATA[@]+${ADD_DATA[@]}}"; do + [ "$existing" = "$cand" ] && dup=1 + done + [ "$dup" -eq 0 ] && ADD_DATA+=("$cand") + fi +done + +# ----------------------------------------------------------------------------- +# Prepare output +# ----------------------------------------------------------------------------- +FINAL_DIR="dist/$OS" + +if [ "${CLEAN:-0}" -eq 1 ]; then + log "Cleaning build artifacts..." + rm -rf build dist *.spec || true +fi + +mkdir -p "$FINAL_DIR" +generate_wrapper_scripts "." + +# +# ----------------------------------------------------------------------------- +# Create/verify venv (Python 3.11) +# ----------------------------------------------------------------------------- +NEED_RECREATE=0 +if [ ! -x "$(venv_python_path)" ]; then + NEED_RECREATE=1 +else + VENV_VER="$("$(venv_python_path)" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' || echo unknown)" + if [ "$VENV_VER" != "3.11" ]; then + NEED_RECREATE=1 + fi +fi + +if [ "$NEED_RECREATE" -eq 1 ]; then + log "Creating fresh Python 3.11 virtual environment in $VENV_DIR..." + rm -rf "$VENV_DIR" + if [ "$USE_SYSTEM_PYQT" -eq 1 ]; then + python_exec -m venv --system-site-packages "$VENV_DIR" + else + python_exec -m venv "$VENV_DIR" + fi +fi + +# shellcheck disable=SC1091 +source "$(venv_activate_path)" + +ACTIVE_VER="$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')" +[ "$ACTIVE_VER" = "3.11" ] || die "Active Python is $ACTIVE_VER, expected 3.11. On Windows, install Python 3.11 and/or use: py -3.11" +log "Using Python $(python -V)" + +log "Updating pip..." +python -m pip install --upgrade pip wheel + +log "Installing build dependencies..." +python -m pip install "pyinstaller>=6.9,<7" + +# PyInstaller on Windows requires .ico (or Pillow for automatic conversion from .png). +# Install Pillow when building on Windows so we can safely use .png icons or generate .ico. +if [ "$OS" = "windows" ]; then + python -m pip install "pillow>=10,<12" || true +fi + + +# Optional: system PyQt5 on Linux ARM (APT) +if [ "$USE_SYSTEM_PYQT" -eq 1 ]; then + if [ "$OS" != "linux" ]; then + die "--system-pyqt is only supported on Linux" + fi + if command -v apt-get >/dev/null 2>&1; then + log "Installing system PyQt5 via APT (requires sudo)..." + sudo apt-get update + sudo apt-get install -y python3-pyqt5 python3-pyqt5.qtsvg + else + die "APT not found; cannot install system PyQt5. Install PyQt5 manually or omit --system-pyqt." + fi +else + # Default: wheels + # (Only install PyQt5 if the project uses it; safe to install regardless.) + python -m pip install "PyQt5>=5.15,<6" || true +fi + +# Ensure SIP bindings are bundled for PyQt5. +# Note: the importable module is typically `PyQt5.sip` (not `sip`). +# PyInstaller may still emit a non-fatal warning about hidden import "sip" depending on hooks. +has_pyqt5=0 +if python -c "import importlib.util; import sys; sys.exit(0 if importlib.util.find_spec('PyQt5') else 1)" >/dev/null 2>&1; then + has_pyqt5=1 +fi + +if [ "$has_pyqt5" -eq 1 ]; then + # Add PyQt5.sip unless the user already provided it. + found=0 + for h in "${HIDDEN_IMPORTS[@]+${HIDDEN_IMPORTS[@]}}"; do + [ "$h" = "PyQt5.sip" ] && found=1 + done + if [ "$found" -eq 0 ]; then + HIDDEN_IMPORTS+=("PyQt5.sip") + fi + + # If the user ever provided `sip`, normalize it early. + for i in "${!HIDDEN_IMPORTS[@]}"; do + if [ "${HIDDEN_IMPORTS[$i]}" = "sip" ]; then + HIDDEN_IMPORTS[$i]="PyQt5.sip" + fi + done +fi + +# ----------------------------------------------------------------------------- +# Build +# ----------------------------------------------------------------------------- +log "Building $APP_NAME for $OS ($PKG, $MODE) from entry: $ENTRY" + +PYI_ARGS=( + --name "$APP_NAME" + --noconfirm +) + +# Optional PyInstaller debug +if [ "${PYI_DEBUG:-0}" -eq 1 ]; then + PYI_ARGS+=(--log-level=DEBUG --debug=all) +fi + +# Packaging +if [ "$PKG" = "onefile" ]; then + PYI_ARGS+=(--onefile) +else + PYI_ARGS+=(--onedir) +fi + +# Window mode +if [ "$MODE" = "windowed" ]; then + PYI_ARGS+=(--windowed) +fi + +# Icon +if [ -n "$ICON_FILE" ] && [ -f "$ICON_FILE" ]; then + if [ "$OS" = "windows" ]; then + ext="${ICON_FILE##*.}" + ext="$(echo "$ext" | tr '[:upper:]' '[:lower:]')" + + # On Windows, PyInstaller only accepts .ico/.exe as icon inputs unless Pillow is installed. + # If the provided icon is .png, convert it to a temporary .ico using Pillow. + if [ "$ext" = "png" ]; then + mkdir -p build + ICO_FROM_PNG="build/icon_from_png.ico" + python - <<'PY' "$ICON_FILE" "$ICO_FROM_PNG" || true +import sys +from pathlib import Path + +src = Path(sys.argv[1]) +dst = Path(sys.argv[2]) + +try: + from PIL import Image +except Exception as e: + raise SystemExit(1) + +img = Image.open(src).convert("RGBA") +# Common Windows icon sizes +sizes = [(16,16), (24,24), (32,32), (48,48), (64,64), (128,128), (256,256)] +img.save(dst, format="ICO", sizes=sizes) +print(dst) +PY + if [ -f "$ICO_FROM_PNG" ]; then + PYI_ARGS+=(--icon "$ICO_FROM_PNG") + else + log "WARN: Failed to convert PNG icon to ICO; continuing without --icon" + fi + else + # .ico/.exe already + PYI_ARGS+=(--icon "$ICON_FILE") + fi + else + PYI_ARGS+=(--icon "$ICON_FILE") + fi +fi + +# Hidden imports +# NOTE: +# - PyQt5 typically exposes SIP bindings as `PyQt5.sip` (and ships `PyQt5_sip` as a wheel). +# - Users sometimes add `sip` as a hidden import; that module often does not exist and causes warnings. +# We normalize `sip` -> `PyQt5.sip` when available, and skip hidden imports that cannot be resolved. +can_import() { + # usage: can_import module.name + python - </dev/null 2>&1 +import importlib.util +spec = importlib.util.find_spec("$1") +raise SystemExit(0 if spec is not None else 1) +PY +} + +for hi in "${HIDDEN_IMPORTS[@]+${HIDDEN_IMPORTS[@]}}"; do + [ -n "$hi" ] || continue + + # Normalize common SIP hidden import for PyQt5. + # The standalone `sip` module is often NOT importable even if the sip build tooling is installed. + if [ "$hi" = "sip" ]; then + if can_import "PyQt5.sip"; then + log "Normalizing hidden import: sip -> PyQt5.sip" + hi="PyQt5.sip" + else + log "WARN: Skipping hidden import not found: sip (and PyQt5.sip not available)" + continue + fi + fi + + if can_import "$hi"; then + PYI_ARGS+=(--hidden-import "$hi") + else + log "WARN: Skipping hidden import not found: $hi" + fi +done + +# Data +# PyInstaller (on some versions) requires the equals form: --add-data=SRC:DST +for ad in "${ADD_DATA[@]+${ADD_DATA[@]}}"; do + # Allow config/CLI to provide either: + # - SRC:DST + # - --add-data=SRC:DST + # - --add-data SRC:DST (accidentally split by callers) + [ -n "$ad" ] || continue + if [ "$ad" = "--add-data" ]; then + # Skip stray flag (the next token would have been the value) + continue + fi + + if [[ "$ad" == --add-data=* ]]; then + PYI_ARGS+=("$ad") + else + PYI_ARGS+=("--add-data=$ad") + fi + +done + +# Extra sanity checks (don’t fail builds for optional modules) +log "Running a quick import sanity check (best-effort)..." +python - <<'PY' || true +import sys +print("Python:", sys.version) +try: + import PyInstaller # noqa + print("PyInstaller OK") +except Exception as e: + print("PyInstaller import failed:", e) +PY + +# Print PyInstaller command for debug +log "PyInstaller command:" +printf ' %q ' pyinstaller "${PYI_ARGS[@]}" "$ENTRY" +printf '\n' + + +# Execute PyInstaller +pyinstaller "${PYI_ARGS[@]}" "$ENTRY" + +# --------------------------------------------------------------------------- +# Windows: also build a console-subsystem companion EXE for CLI usage. +# - Keeps the main EXE as --windowed (nice for double-click) +# - Produces -cli.exe without --windowed so stdout/stderr work in terminals +# --------------------------------------------------------------------------- +if [ "$OS" = "windows" ] && [ "$MODE" = "windowed" ]; then + CLI_APP_NAME="${APP_NAME}-cli" + + log "Building $CLI_APP_NAME for $OS ($PKG, console) from entry: $ENTRY" + + # Copy args and adjust for console build + PYI_CLI_ARGS=("${PYI_ARGS[@]}") + + # Replace --name value + for i in "${!PYI_CLI_ARGS[@]}"; do + if [ "${PYI_CLI_ARGS[$i]}" = "--name" ]; then + PYI_CLI_ARGS[$((i+1))]="$CLI_APP_NAME" + fi + done + + # Remove --windowed if present + PYI_CLI_ARGS_STRIPPED=() + for a in "${PYI_CLI_ARGS[@]}"; do + if [ "$a" = "--windowed" ]; then + continue + fi + PYI_CLI_ARGS_STRIPPED+=("$a") + done + + log "PyInstaller command (CLI companion):" + printf ' %q ' pyinstaller "${PYI_CLI_ARGS_STRIPPED[@]}" "$ENTRY" + printf '\n' + + pyinstaller "${PYI_CLI_ARGS_STRIPPED[@]}" "$ENTRY" +fi + +# ----------------------------------------------------------------------------- +# Collect output +# ----------------------------------------------------------------------------- +if [ "$OS" = "macos" ]; then + # If entry builds a .app bundle, it'll appear under dist/.app for onedir+windowed. + if [ -d "dist/$APP_NAME.app" ]; then + log "Moving .app to $FINAL_DIR/" + rm -rf "$FINAL_DIR/$APP_NAME.app" || true + mv "dist/$APP_NAME.app" "$FINAL_DIR/" + + if [ "$MAKE_DMG" -eq 1 ]; then + log "Creating DMG..." + DMG_NAME="$FINAL_DIR/$APP_NAME.dmg" + hdiutil create "$DMG_NAME" -volname "$APP_NAME" -srcfolder "$FINAL_DIR/$APP_NAME.app" -ov -format UDZO + log "DMG created at $DMG_NAME" + fi + else + # Non-windowed or non-app outputs (e.g., console onedir) + log "Moving build output to $FINAL_DIR/" + rm -rf "$FINAL_DIR/$APP_NAME" || true + mv "dist/$APP_NAME" "$FINAL_DIR/" + fi +else + log "Moving build output to $FINAL_DIR/" + + # Windows onefile creates dist/.exe; onedir creates dist// + # Move all matching outputs for this app (and its -cli companion). + if [ "$OS" = "windows" ]; then + # Clean old outputs + rm -f "$FINAL_DIR/${APP_NAME}.exe" "$FINAL_DIR/${APP_NAME}-cli.exe" || true + rm -rf "$FINAL_DIR/$APP_NAME" "$FINAL_DIR/${APP_NAME}-cli" || true + + # Prefer moving EXEs if they exist + if [ -f "dist/${APP_NAME}.exe" ]; then + mv "dist/${APP_NAME}.exe" "$FINAL_DIR/" + elif [ -f "dist/$APP_NAME" ]; then + mv "dist/$APP_NAME" "$FINAL_DIR/" || true + fi + + if [ -f "dist/${APP_NAME}-cli.exe" ]; then + mv "dist/${APP_NAME}-cli.exe" "$FINAL_DIR/" + elif [ -f "dist/${APP_NAME}-cli" ]; then + mv "dist/${APP_NAME}-cli" "$FINAL_DIR/" || true + fi + + # If onedir outputs were produced, move them too + if [ -d "dist/$APP_NAME" ]; then + rm -rf "$FINAL_DIR/$APP_NAME" || true + mv "dist/$APP_NAME" "$FINAL_DIR/" + fi + if [ -d "dist/${APP_NAME}-cli" ]; then + rm -rf "$FINAL_DIR/${APP_NAME}-cli" || true + mv "dist/${APP_NAME}-cli" "$FINAL_DIR/" + fi + + else + rm -rf "$FINAL_DIR/$APP_NAME" || true + mv "dist/$APP_NAME" "$FINAL_DIR/" + fi +fi + +log "Build completed successfully. Output: $FINAL_DIR" + +# --------------------------------------------------------------------------- +# Windows: create a .lnk shortcut (best-effort) +# --------------------------------------------------------------------------- +if [ "$OS" = "windows" ]; then + EXE_PATH="$(pwd)/$FINAL_DIR/$APP_NAME.exe" + LNK_PATH="$(pwd)/$FINAL_DIR/$APP_NAME.lnk" + + # Create a shortcut inside dist/windows (so we can ship it alongside the exe) + if [ -f "$EXE_PATH" ]; then + mkdir -p "$FINAL_DIR" || true + cat >"build/make_shortcut.vbs" <<'VBS' +Option Explicit +Dim shell, args, exePath, lnkPath +Set shell = CreateObject("WScript.Shell") +Set args = WScript.Arguments +exePath = args.Item(0) +lnkPath = args.Item(1) +Dim sc +Set sc = shell.CreateShortcut(lnkPath) +sc.TargetPath = exePath +sc.WorkingDirectory = CreateObject("Scripting.FileSystemObject").GetParentFolderName(exePath) +sc.WindowStyle = 1 +sc.Description = "Replicator" +sc.Save +VBS + + if command -v cscript >/dev/null 2>&1; then + cscript //nologo "build/make_shortcut.vbs" "$(cygpath -w "$EXE_PATH" 2>/dev/null || echo "$EXE_PATH")" "$(cygpath -w "$LNK_PATH" 2>/dev/null || echo "$LNK_PATH")" >/dev/null 2>&1 || true + fi + + # Fallback: create a .url shortcut (always works) + if [ ! -f "$LNK_PATH" ]; then + cat >"$FINAL_DIR/$APP_NAME.url" </dev/null 2>&1; then + cscript //nologo "build/make_shortcut.vbs" "$(cygpath -w "$CLI_EXE_PATH" 2>/dev/null || echo "$CLI_EXE_PATH")" "$(cygpath -w "$CLI_LNK_PATH" 2>/dev/null || echo "$CLI_LNK_PATH")" >/dev/null 2>&1 || true + fi + if [ ! -f "$CLI_LNK_PATH" ]; then + cat >"$FINAL_DIR/${APP_NAME}-cli.url" < [folder-name]" >&2 + exit 1 +fi + +TARGET_BIN="$1" +TARGET_DIR="${2:-$TARGET_BIN}" + +# Root of your project (adjust if needed) +PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +UNAME_OS="$(uname -s)" + +case "$UNAME_OS" in + Linux) + OS="linux" + ;; + Darwin) + OS="macos" + ;; + *) + echo "Unsupported OS: $UNAME_OS" >&2 + exit 1 + ;; +esac +ARCH="$(uname -m)" + +case "$ARCH" in + armv6l|armv7l|armhf) + ARCH="armhf" + ;; + aarch64|arm64) + ARCH="arm64" + ;; + *) + echo "Unsupported architecture: $ARCH" >&2 + exit 1 + ;; +esac + +DEST_DIR="$PROJECT_ROOT/src/bin/${TARGET_DIR}/${OS}/${ARCH}" +mkdir -p "$DEST_DIR" + +SOURCE_BIN="$(command -v "${TARGET_BIN}" || true)" + +if [[ -z "$SOURCE_BIN" ]]; then + echo "${TARGET_BIN} not found in PATH. Attempting installation..." + + if [[ "$OS" == "macos" ]]; then + if ! command -v brew >/dev/null 2>&1; then + echo "Homebrew is required but not installed." >&2 + exit 1 + fi + echo "Installing ${TARGET_BIN} using Homebrew..." + brew install "${TARGET_BIN}" || { + echo "Failed to install ${TARGET_BIN} via Homebrew." >&2 + exit 1 + } + elif [[ "$OS" == "linux" ]]; then + echo "Installing ${TARGET_BIN} using apt-get..." + sudo apt-get update -y + sudo apt-get install -y "${TARGET_BIN}" || { + echo "Failed to install ${TARGET_BIN} via apt-get." >&2 + exit 1 + } + fi + + SOURCE_BIN="$(command -v "${TARGET_BIN}" || true)" + if [[ -z "$SOURCE_BIN" ]]; then + echo "Installation succeeded but ${TARGET_BIN} is still not in PATH." >&2 + exit 1 + fi +fi + +echo "Found ${TARGET_BIN} at: $SOURCE_BIN" +echo "Copying to: $DEST_DIR/${TARGET_BIN}" + +cp "$SOURCE_BIN" "$DEST_DIR/${TARGET_BIN}" +chmod 755 "$DEST_DIR/${TARGET_BIN}" + +echo "Done." diff --git a/dist/macos/Replicator.app/Contents/Resources/core/cli.py b/dist/macos/Replicator.app/Contents/Resources/core/cli.py new file mode 100644 index 00000000..0baf85c6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/cli.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python3 +# src/core/cli.py +import sys +from typing import Any, Optional + +from PyQt5.QtWidgets import QApplication + +from .helper import Helper +from .configuration import Configuration +from .log import Log +from .service import Service + +# --------------------------------------------------------------------------- +# CommandLine class +# --------------------------------------------------------------------------- + +class CommandLine(QApplication): + + def __init__(self, name: Optional[str] = None, argv=None): + + # Initialize QApplication + super().__init__(argv or []) + + # Application name + if name: + self.setApplicationName(name) + + # Set application mode + self._mode = "cli" + + # Initialize command line + self._commands: dict[str, Any] = {} + + # Add help command + self.add("help", "Show this help message", self.help) + + # Helper + self._helper = Helper() + + # Configuration manager + self._configuration = Configuration() + + # Logger + self._logger = Log() + + # Service manager + self._service = Service(self._logger, self._configuration) + + # Initialize core commands + if hasattr(self._configuration, "cli") and callable(getattr(self._configuration, "cli")): + self._configuration.cli(self) + if hasattr(self._logger, "cli") and callable(getattr(self._logger, "cli")): + self._logger.cli(self) + if hasattr(self._service, "cli") and callable(getattr(self._service, "cli")): + self._service.cli(self) + + # ------------------------------------------------------------------ + # Properties / accessors + # ------------------------------------------------------------------ + + @property + def helper(self) -> Helper: + return self._helper + + @property + def logger(self) -> Log: + return self._logger + + @property + def configuration(self) -> Configuration: + return self._configuration + + @property + def service(self) -> Service: + return self._service + + @property + def name(self) -> str: + return self.applicationName() + + @property + def mode(self) -> str: + return self._mode + + # ------------------------------------------------------------------ + # Core API + # ------------------------------------------------------------------ + + def help(self) -> None: + print() + print(f"Usage: {self.name} [command] [options]") + print() + print("Available commands:") + print() + + # Group entries by category while preserving insertion order. + # Category order is the order we first see a category during add(). + categories_order: list[str] = [] + grouped: dict[str, list[tuple[str, str]]] = {} + + # Build usage strings including required arguments + # Preserve insertion order (the order commands were added) + for cmd, info in self._commands.items(): + category = info.get("category") or "General" + # Capitalize category + category = category.capitalize() + if category not in grouped: + grouped[category] = [] + categories_order.append(category) + + desc = info.get("description", "") or "" + args_required = info.get("args_required", 0) or 0 + arg_names = info.get("arg_names") or [] + + # Ensure we have at least `args_required` argument labels + if len(arg_names) < args_required: + # Pad with generic placeholders if needed + start_index = len(arg_names) + 1 + for i in range(start_index, args_required + 1): + arg_names.append(f"") + + usage = cmd + if args_required > 0: + usage += " " + " ".join(arg_names[:args_required]) + + grouped[category].append((usage, desc)) + + # Compute padding for alignment across all commands + all_entries: list[tuple[str, str]] = [] + for cat in categories_order: + all_entries.extend(grouped.get(cat, [])) + + if all_entries: + max_cmd_len = max(len(usage) for usage, _ in all_entries) + else: + max_cmd_len = 0 + + # Print grouped commands with a simple separator/header per category + for idx, cat in enumerate(categories_order): + if idx != 0: + print() + print(f"[{cat}]") + for usage, desc in grouped.get(cat, []): + print(f" {usage:<{max_cmd_len}} {desc}") + + print() + + def add(self, command: str, description: str = "", callable: Optional[callable] = None, args: int = 0, arg_names: Optional[list[str]] = None) -> None: + # Support category prefixes using dot notation (e.g. "service.status"). + # The CLI token remains the final segment ("--status"), while the prefix + # is used only for grouping in help output. + category: Optional[str] = None + + raw = command.lstrip("-") + if "." in raw: + parts = [p for p in raw.split(".") if p] + if len(parts) >= 2: + category = ".".join(parts[:-1]) + command = parts[-1] + + if not command.startswith("--"): + command = f"--{command}" + # Normalize argument names + if arg_names is None: + arg_names = [] + # Store command metadata + self._commands[command] = { + "description": description, + "callable": callable, + "args_required": args, + "arg_names": arg_names, + "category": category, + } + + def run(self, command: str, *args: Any, **kwargs: Any) -> Any: + cmd = self._commands.get(command) + if not cmd: + raise ValueError(f"Command not found: {command}") + + required = cmd.get("args_required", 0) + arg_names = cmd.get("arg_names") or [] + + if len(arg_names) < required: + # Pad missing argument names with generic placeholders + start_index = len(arg_names) + 1 + for i in range(start_index, required + 1): + arg_names.append(f"") + + if len(args) < required: + missing = required - len(args) + missing_list = " ".join(arg_names[len(args):required]) + raise ValueError(f"Missing {missing} argument(s) for {command}: {missing_list}") + + func = cmd.get("callable") + if not func: + raise ValueError(f"Command has no callable: {command}") + + return func(*args, **kwargs) + + def exec(self) -> int: + argv = list(self.arguments()) # includes program name as first element + + # No command provided: show help and exit 0 + if len(argv) < 2: + self.help() + return 0 + + commands: list[tuple[str, list[str]]] = [] + + current_cmd: Optional[str] = None + current_args: list[str] = [] + + # Parse argv into (command, args) groups + for arg in argv[1:]: + if arg.startswith("--"): + # Starting a new command + if current_cmd is not None: + commands.append((current_cmd, current_args)) + current_cmd = arg + current_args = [] + else: + # Positional argument for the current command + if current_cmd is None: + # We got an argument before any command; treat as error + print(f"Error: unexpected argument '{arg}' before any command.", file=sys.stderr) + return 1 + current_args.append(arg) + + # Append the last pending command + if current_cmd is not None: + commands.append((current_cmd, current_args)) + + # Still no valid command? Show help. + if not commands: + self.help() + return 0 + + exit_code = 0 + + # Execute each command in sequence; stop on first error + for command, cmd_args in commands: + try: + self.run(command, *cmd_args) + except Exception as e: + print(f"Error in {command}: {e}", file=sys.stderr) + exit_code = 1 + break + + return exit_code diff --git a/dist/macos/Replicator.app/Contents/Resources/core/configuration.py b/dist/macos/Replicator.app/Contents/Resources/core/configuration.py new file mode 100644 index 00000000..7b24a7ad --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/configuration.py @@ -0,0 +1,765 @@ +#!/usr/bin/env python3 +# src/core/configuration.py +from __future__ import annotations + +import os +import json +import shutil +import sys +from collections import defaultdict +from typing import Any, Tuple, Optional, TYPE_CHECKING +from urllib import request as _urlrequest, error as _urlerror + +from PyQt5.QtCore import pyqtSignal, QObject +from PyQt5.QtWidgets import ( + QDialog, QVBoxLayout, QTabWidget, QWidget, QFormLayout, + QLabel, QPushButton, QHBoxLayout, QApplication, QFileDialog, + QLineEdit, QComboBox, QCheckBox, QSpinBox +) + +# Allow this module to be used both as part of the 'app' package and as a standalone script +try: + from .helper import Helper + from .ui import Form + from .network.tools import Tools +except ImportError: # likely running as a top-level script + from helper import Helper + from ui import Form + from network.tools import Tools + +if TYPE_CHECKING: + # For type hints only, avoids circular import at runtime + try: + from .application import Application + except ImportError: + from application import Application + +class Configuration(QObject): + + # Emitted after a successful save (or when we choose to later) + configChanged = pyqtSignal(dict) + + def __init__( + self, + helper: Optional[Helper] = None, + filename: str = "configuration.cfg" + ): + + # Initialize QObject + super().__init__() + + # Retrieve the application instance (may be None in CLI usage) + self._app: Application | None = QApplication.instance() # type: ignore[valid-type] + + # Ensure we have either an Application or an explicit Helper + if self._app is None and helper is None: + raise RuntimeError( + "Configuration must be created after QApplication/Application or with an explicit Helper." + ) + + # --- auto-wire from QApplication if not provided --- + if helper is None and self._app is not None: + # narrow the type for linters / IDEs + # no runtime import to avoid circular imports + helper = self._app.helper # type: ignore[attr-defined] + + # Helper + self._helper: Helper = helper + + # Parent + self._parent = None + + # Root directory for config files + self.root_dir = helper.root_dir + self._filename = filename + + # Actual config values (nested dict) + self._data: dict[str, Any] = {} + + # Schema: key -> {"default": ..., "widget": "text"/"select"/...} + self._schema: dict[str, dict[str, Any]] = {} + + # UI widgets mapped by config key + self._widgets: dict[str, Any] = {} + + # Actual QLabel widgets mapped by config key (for show/hide) + self._widget_labels: dict[str, Any] = {} + + # Labels: key → display label (e.g. "freerdp" -> "FreeRDP", + # "freerdp.display" -> "Display") + self._labels: dict[str, str] = {} + + # Load existing file if any + self.load() + + # Add built-in administration actions + self.add("administration.import", None, "button", label="Import Configuration", action=self.import_cfg) + self.add("administration.export", None, "button", label="Export Configuration", action=self.export_cfg) + + # Built-in provisioning settings + self.add("provisioning.host", "", "text", label="Host/URL") + self.add("provisioning.token", "", "password", label="Token") + self.add("provisioning.appid", self._app.applicationName() if self._app else "corePY App", "text", label="App ID") + + # ------------------------------------------------------------------ + # Core API + # ------------------------------------------------------------------ + + def load(self, file: str | None = None) -> None: + if file is not None: + self._filename = file + + config_dir = self._get_config_dir() + os.makedirs(config_dir, exist_ok=True) + + path = os.path.join(config_dir, self._filename) + if not os.path.exists(path): + # Nothing yet, keep empty data + self._data = {} + return + + try: + with open(path, "r", encoding="utf-8") as f: + data = json.load(f) + if isinstance(data, dict): + self._data = data + else: + self._data = {} + except Exception as e: + print(f"[Configuration] Failed loading {self._filename}: {e}") + self._data = {} + + def save(self) -> None: + config_dir = self._get_config_dir() + os.makedirs(config_dir, exist_ok=True) + + path = os.path.join(config_dir, self._filename) + try: + with open(path, "w", encoding="utf-8") as f: + json.dump(self._data, f, indent=2) + # Notify listeners + self.configChanged.emit(self._data) + except Exception as e: + print(f"[Configuration] Failed saving {self._filename}: {e}") + + def add(self, key: str, default_value: Any, widget: str | None = None, **options: Any) -> None: + self._schema[key] = { + "default": default_value, + "widget": widget, + "options": options or {}, + } + + # If there's no value yet in self._data, apply the default now + try: + current = self.get(key, _no_fallback=True) + except KeyError: + # Not present at all → set default + self.set(key, default_value) + + def get(self, key: str, default: Any | None = None, _no_fallback: bool = False) -> Any: + parts = key.split(".") + node: Any = self._data + + for part in parts: + if not isinstance(node, dict) or part not in node: + # Missing key + if _no_fallback: + raise KeyError(key) + # explicit default wins + if default is not None: + return default + # fall back to schema default if any + meta = self._schema.get(key) + if meta is not None: + return meta.get("default") + return None + node = node[part] + + return node + + def set(self, key: str, value: Any) -> None: + parts = key.split(".") + if not parts: + return + + node = self._data + for part in parts[:-1]: + if part not in node or not isinstance(node[part], dict): + node[part] = {} + node = node[part] + + node[parts[-1]] = value + + def input(self, key: str, show_label: bool = False) -> QWidget: + if key not in self._schema: + raise KeyError(f"Configuration key not defined in schema: {key}") + + widget, label_text = self._build_widget_for_key(key) + + if not show_label: + return widget + + container = QWidget() + layout = QHBoxLayout(container) + layout.setContentsMargins(0, 0, 0, 0) + label = QLabel(label_text) + layout.addWidget(label) + layout.addWidget(widget) + return container + + def label(self, key: str, label: str | None = None) -> str: + if label is not None: + self._labels[key] = label + + if key in self._labels: + return self._labels[key] + + # Fallback: nice label from the last segment + return self._nice_label(key.split(".")[-1]) + + def reload(self, key: str, value: Any) -> None: + self.set(key, value) + w = self._widgets.get(key) + if w is None: + return + + if isinstance(w, QLineEdit): + w.setText(str(value) if value is not None else "") + elif isinstance(w, QComboBox): + idx = w.findText(str(value)) + if idx >= 0: + w.setCurrentIndex(idx) + elif isinstance(w, QCheckBox): + w.setChecked(bool(value)) + elif isinstance(w, QSpinBox): + try: + w.setValue(int(value)) + except Exception: + pass + else: + # Custom widgets (ColorButton, FileInput, PictureButton, etc.) + # Prefer a color-specific API if available, then fall back to a generic setter. + if hasattr(w, "setHex") and callable(getattr(w, "setHex")): + # Color button / color-like widget + w.setHex(value) + elif hasattr(w, "setValue") and callable(getattr(w, "setValue")): + w.setValue(value) + + def visibility(self, key: str, visible: bool) -> None: + w = self._widgets.get(key) + if w is not None: + w.setVisible(visible) + + lbl = self._widget_labels.get(key) + if lbl is not None: + lbl.setVisible(visible) + + def reset(self, save: bool = False) -> None: + # Start with a clean configuration dict + self._data = {} + + # 1) Rebuild data from schema defaults + for key, meta in self._schema.items(): + default = meta.get("default") + self.set(key, default) + + # 2) Push defaults into widgets so the UI reflects the new values + for key in self._schema.keys(): + try: + value = self.get(key, _no_fallback=True) + except KeyError: + continue + self.reload(key, value) + + # 3) Optionally persist and notify listeners + if save: + self.save() + + # ------------------------------------------------------------------ + # Convenience properties + # ------------------------------------------------------------------ + + @property + def data(self) -> dict[str, Any]: + return self._data + + @property + def schema(self) -> dict[str, dict[str, Any]]: + return self._schema + + # ------------------------------------------------------------------ + # core API Callables + # ------------------------------------------------------------------ + + def cli(self, cli: QApplication = None) -> None: + # cli.add("config.import", "Import configuration from the given file.", self.import_from_path, args=1, arg_names=[""]) + # cli.add("config.provision", "Contact the provisioning server and import the returned configuration.", self.provision) + pass + + # ------------------------------------------------------------------ + # UI dialog builder + # ------------------------------------------------------------------ + + def show(self, parent=None): + + # Only use a QWidget as dialog parent, otherwise use None + + if parent is not None and isinstance(parent, QWidget): + self._parent = parent + + dlg = QDialog(self._parent) + dlg.setWindowTitle("Configuration") + dlg.setObjectName("configurationWindow") + + root = QVBoxLayout(dlg) + tabs = QTabWidget() + root.addWidget(tabs) + + # structure[category][subcategory] = [(full_key, meta), ...] + structure: dict[str, dict[str | None, list[Tuple[str, dict[str, Any]]]]] = defaultdict( + lambda: defaultdict(list) + ) + + for full_key, meta in self._schema.items(): + parts = full_key.split(".") + if len(parts) == 1: + category = parts[0] + subcat: str | None = None + name = parts[0] + elif len(parts) == 2: + category = parts[0] + subcat = None + name = parts[1] + else: + category = parts[0] + subcat = parts[1] + name = ".".join(parts[2:]) # rare case of deeper nesting + + structure[category][subcat].append((full_key, meta)) + + # Build tabs + self._widgets.clear() + self._widget_labels.clear() + + for category, subcats in structure.items(): + # Top-level tab widget + cat_widget = QWidget() + cat_layout = QVBoxLayout(cat_widget) + + # If there's more than one subcategory (or exactly one non-None), + # we add a nested QTabWidget, otherwise a simple form. + non_none_subs = [s for s in subcats.keys() if s is not None] + + if non_none_subs: + # There are sub-tabs + subtabs = QTabWidget() + cat_layout.addWidget(subtabs) + + # subcat == None → put those fields in a "General" sub-tab + if None in subcats: + general_tab = QWidget() + general_form = QFormLayout(general_tab) + self._populate_form(general_form, subcats[None]) + subtabs.addTab(general_tab, "General") + + for subcat_name, fields in subcats.items(): + if subcat_name is None: + continue + sub_widget = QWidget() + sub_form = QFormLayout(sub_widget) + self._populate_form(sub_form, fields) + subtabs.addTab(sub_widget, self.label(f"{category}.{subcat_name}")) + else: + # Only a single bucket (no sub-tabs) + only_fields = subcats.get(None, []) + form = QFormLayout() + cat_layout.addLayout(form) + self._populate_form(form, only_fields) + + tabs.addTab(cat_widget, self.label(category)) + + # Buttons row (Reset / Cancel / Save) + btn_row = QHBoxLayout() + btn_row.addStretch(1) + reset_btn = QPushButton("Reset") + save_btn = QPushButton("Save") + cancel_btn = QPushButton("Cancel") + btn_row.addWidget(reset_btn) + btn_row.addWidget(cancel_btn) + btn_row.addWidget(save_btn) + root.addLayout(btn_row) + + # Wire buttons + def on_save(): + self._update_from_widgets() + self.save() + dlg.accept() + + def on_cancel(): + dlg.reject() + + def on_reset(): + # Reset all values back to their defaults and keep the dialog open. + # Do not save immediately; let the user confirm with Save. + self.reset(save=False) + + save_btn.clicked.connect(on_save) + cancel_btn.clicked.connect(on_cancel) + reset_btn.clicked.connect(on_reset) + + dlg.exec_() + + # ------------------------------------------------------------------ + # Import / Export + # ------------------------------------------------------------------ + + def _import_dict(self, imported: dict[str, Any]) -> bool: + if not isinstance(imported, dict): + print(f"[Configuration] Imported configuration is not a dict: {type(imported)}") + return False + + collected_keys: list[str] = [] + + def _apply(prefix: str, node: dict[str, Any]) -> None: + for key, value in node.items(): + if isinstance(value, dict): + new_prefix = f"{prefix}.{key}" if prefix else key + _apply(new_prefix, value) + else: + full_key = f"{prefix}.{key}" if prefix else key + # Use the existing setter so we don't stomp entire blocks + self.set(full_key, value) + collected_keys.append(full_key) + + _apply("", imported) + + # After applying, reload each key recursively with imported values + for full_key in collected_keys: + node = imported + parts = full_key.split(".") + for part in parts[:-1]: + node = node.get(part, {}) + value = node.get(parts[-1], None) + self.reload(full_key, value) + + # Persist and notify listeners via save() + self.save() + return True + + def import_from_path(self, path: str) -> bool: + try: + with open(path, "r", encoding="utf-8") as f: + imported = json.load(f) + except Exception as e: + print(f"[Configuration] Failed importing configuration from {path}: {e}") + return False + + return self._import_dict(imported) + + def import_cfg(self, parent: Optional[QWidget] = None) -> bool: + # Allow this method to be called as a Qt slot callback (clicked(bool)), where parent might be a bool + if not isinstance(parent, QWidget): + parent = self._parent if isinstance(self._parent, QWidget) else None + path, _ = QFileDialog.getOpenFileName( + parent, + "Import configuration", + "", + "Config files (*.cfg);;All files (*)", + ) + if not path: + return False # User cancelled + + try: + with open(path, "r", encoding="utf-8") as f: + imported = json.load(f) + except Exception as e: + print(f"[Configuration] Failed importing configuration from {path}: {e}") + return False + + return self._import_dict(imported) + + def export_cfg(self, parent: Optional[QWidget] = None) -> bool: + # Allow this method to be called as a Qt slot callback (clicked(bool)), where parent might be a bool + if not isinstance(parent, QWidget): + parent = self._parent if isinstance(self._parent, QWidget) else None + path, _ = QFileDialog.getSaveFileName( + parent, + "Export configuration", + "configuration.cfg", + "Config files (*.cfg);;All files (*)", + ) + if not path: + return False # User cancelled + + # Ensure latest config is written to disk + self.save() + + config_dir = self._get_config_dir() + src = os.path.join(config_dir, self._filename) + + try: + shutil.copy2(src, path) + return True + except Exception as e: + print(f"[Configuration] Failed exporting configuration to {path}: {e}") + return False + + # ------------------------------------------------------------------ + # Provisioning + # ------------------------------------------------------------------ + + def provision(self) -> int: + app: Application | None = QApplication.instance() + appname = app.applicationName() if app is not None else "unknown" + host = self.get("provisioning.host", "") or "" + token = self.get("provisioning.token", "") or "" + appid = self.get("provisioning.appid", appname) or "unknown" + + if not host: + print("[Configuration] provisioning.host is not set; cannot provision.", file=sys.stderr) + return 1 + + # Allow host to be either full URL or just hostname. If no scheme, default to https. + url = host.strip() + if not url.lower().startswith(("http://", "https://")): + url = "https://" + url + + # Helper and Tools are always available because Configuration enforces helper in __init__ + helper = self._helper # type: ignore[attr-defined] + tools = Tools(helper=helper) + + # Identify device + try: + serial = helper.get_serial() or "" + except Exception: + serial = "" + + try: + os_name = helper.get_os() or "" + except Exception: + os_name = "" + + try: + hostname = tools.host() or "" + except Exception: + hostname = "" + + private_ip = "" + try: + ips = tools.ip() or [] + if ips: + private_ip = ips[0] + except Exception: + private_ip = "" + + mac = "" + try: + macs = tools.mac() or [] + if macs: + mac = macs[0] + except Exception: + mac = "" + + public_ip = "" + try: + public_ip = tools.wan() or "" + except Exception: + public_ip = "" + + payload = { + "appid": appid or app.applicationName() or "unknown", + "serial": serial, + "mac": mac, + "hostname": hostname, + "private_ip": private_ip, + "public_ip": public_ip, + "os": os_name, + } + + data = json.dumps(payload).encode("utf-8") + + headers = { + "Content-Type": "application/json", + } + if token: + headers["Authorization"] = f"Bearer {token}" + + req = _urlrequest.Request(url, data=data, headers=headers, method="POST") + + try: + with _urlrequest.urlopen(req, timeout=10) as resp: + body = resp.read() + except _urlerror.URLError as e: + print(f"[Configuration] Provisioning request failed: {e}", file=sys.stderr) + return 1 + + try: + imported = json.loads(body.decode("utf-8")) + except Exception as e: + print(f"[Configuration] Failed to parse provisioning response as JSON: {e}", file=sys.stderr) + return 1 + + if not isinstance(imported, dict): + print(f"[Configuration] Provisioning response is not a JSON object: {type(imported)}", file=sys.stderr) + return 1 + + # Use the existing internal import helper so we don't stomp entire blocks + ok = self._import_dict(imported) + + # Return code + return 0 if ok else 1 + + # ------------------------------------------------------------------ + # Internal helpers + # ------------------------------------------------------------------ + + def _build_widget_for_key(self, full_key: str) -> Tuple[QWidget, str]: + meta = self._schema.get(full_key, {}) + widget_type = meta.get("widget") + options = meta.get("options", {}) or {} + current_value = self.get(full_key) + + # Infer widget type if not explicitly set + if widget_type is None: + if isinstance(current_value, bool): + widget_type = "checkbox" + elif isinstance(current_value, int): + widget_type = "spin" + elif isinstance(current_value, str) and "choices" in options: + widget_type = "select" + else: + widget_type = "text" + + # Build widget via Form helpers + if widget_type == "checkbox": + w = Form.checkbox(checked=bool(current_value)) + elif widget_type in ("spin", "integer", "number"): + w = Form.spin( + value=int(current_value) if current_value is not None else 0, + minimum=options.get("min", 0), + maximum=options.get("max", 65535), + ) + elif widget_type == "select": + w = Form.select( + items=options.get("choices", []), + current=current_value, + ) + elif widget_type == "password": + w = Form.password( + text=current_value or "", + placeholder=options.get("placeholder", "") + ) + elif widget_type == "color": + w = Form.color(initial=current_value or "#000000") + elif widget_type == "picture": + w = Form.picture(initial=current_value or "") + elif widget_type == "file": + w = Form.file( + initial=current_value or "", + caption=options.get("caption", "Select File"), + directory=options.get("directory", ""), + filter=options.get("filter", "All Files (*)"), + as_base64=options.get("as_base64", False), + on_changed=options.get("on_changed", None), + ) + elif widget_type == "wifi": + w = Form.wifi( + current=current_value or "" + ) + elif widget_type == "button": + w = Form.button( + label=options.get("label", "Button"), + icon=options.get("icon", None), + action=options.get("action", None) + ) + else: + # default: text line + w = Form.text( + text=current_value or "", + placeholder=options.get("placeholder", "") + ) + + # --- generic on_changed wiring for basic widgets --- + callback = options.get("on_changed") + if callback is not None: + from PyQt5.QtWidgets import QLineEdit, QComboBox, QCheckBox, QSpinBox + + try: + if isinstance(w, QCheckBox): + w.toggled.connect(callback) + elif isinstance(w, QLineEdit): + w.textChanged.connect(callback) + elif isinstance(w, QSpinBox): + w.valueChanged.connect(callback) + elif isinstance(w, QComboBox): + w.currentTextChanged.connect(callback) + + # Initial call so state (e.g. visibility) is correct + callback(current_value) + except Exception as e: + print(f"[Configuration] on_changed for {full_key} failed: {e}") + + # Register this widget for saving (used by _update_from_widgets) + self._widgets[full_key] = w + + label_text = options.get( + "label", + self.label(full_key) + ) + return w, label_text + + def _populate_form( + self, + form_layout, + fields: list[Tuple[str, dict[str, Any]]] + ) -> None: + for full_key, _meta in fields: + w, label_text = self._build_widget_for_key(full_key) + label_widget = QLabel(label_text) + form_layout.addRow(label_widget, w) + + # Keep track of the label widget so we can hide/show it + self._widget_labels[full_key] = label_widget + + def _nice_label(self, raw: str) -> str: + s = raw.replace("_", " ").replace("-", " ") + if not s: + return "" + return s[0].upper() + s[1:] + + def _update_from_widgets(self) -> None: + for key, widget in self._widgets.items(): + value: Any + + if isinstance(widget, QLineEdit): + value = widget.text() + elif isinstance(widget, QComboBox): + value = widget.currentText() + elif isinstance(widget, QCheckBox): + value = widget.isChecked() + elif isinstance(widget, QSpinBox): + value = widget.value() + else: + if hasattr(widget, "hex") and callable(getattr(widget, "hex")): + value = widget.hex() + elif hasattr(widget, "value") and callable(getattr(widget, "value")): + value = widget.value() + else: + continue + + self.set(key, value) + + def _get_config_dir(self) -> str: + """Return the directory used to store configuration files. + + Prefer Helper.get_config_path() (new, OS-appropriate location). + Fall back to the legacy project-root `config/` directory if the + helper doesn't provide get_config_path(). + """ + # Preferred: OS-appropriate config directory via Helper + try: + # Let Helper resolve the app name (or use the QApplication name) + return self._helper.get_config_path(ensure=True, scope="system") + except Exception: + # Legacy fallback (kept for backward compatibility) + return os.path.join(self.root_dir, "config") diff --git a/dist/macos/Replicator.app/Contents/Resources/core/database/__init__.py b/dist/macos/Replicator.app/Contents/Resources/core/database/__init__.py new file mode 100644 index 00000000..287f550f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/database/__init__.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 +# src/core/filesystem/__init__.py + +from .sqlite import SQLite + +__version__ = "1.0.0" + +__all__ = ["SQLite"] diff --git a/dist/macos/Replicator.app/Contents/Resources/core/database/sqlite.py b/dist/macos/Replicator.app/Contents/Resources/core/database/sqlite.py new file mode 100644 index 00000000..7489d1c3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/database/sqlite.py @@ -0,0 +1,324 @@ +#!/usr/bin/env python3 +# src/core/database/sqlite.py + +from __future__ import annotations + +import os +import sqlite3 +from contextlib import contextmanager +from typing import Any, Optional, Iterable, Dict, List, Tuple, Union + +from PyQt5.QtWidgets import QApplication + +try: + from core.helper import Helper + from core.log import Log +except ImportError: + from helper import Helper + from log import Log + + +Row = Dict[str, Any] + + +class SQLite: + """ + Lightweight SQLite wrapper for corePY. + + Features: + - Auto-wires Helper/Logger from QApplication when available + - Centralized DB path handling + - Connection lifecycle (connect/close) + - CRUD for tables (exists, create, drop, list, columns) + - CRUD for records (insert/select/update/delete/upsert) + - Parameterized queries (safe) + - Transaction context manager + """ + + def __init__( + self, + *, + helper: Optional[Helper] = None, + logger: Optional[Log] = None, + db_path: Optional[str] = None, + app_name: Optional[str] = None, + ensure_dir: bool = True, + timeout: float = 30.0, + ): + super().__init__() + + # --- auto-wire from QApplication if not provided --- + if helper is None or logger is None: + app = QApplication.instance() + if app is not None: + helper = helper or getattr(app, "helper", None) + logger = logger or getattr(app, "logger", None) + + self._helper: Helper = helper or Helper() + self._logger: Optional[Log] = logger + + self._timeout = float(timeout) + + # Determine DB path + self._db_path = self._resolve_db_path( + db_path=db_path, + app_name=app_name or getattr(QApplication.instance(), "name", None) or "corePY", + ) + + if ensure_dir: + self._ensure_parent_dir(self._db_path) + + self._conn: Optional[sqlite3.Connection] = None + + # ------------------------------------------------------------------ + # Path / connection + # ------------------------------------------------------------------ + + def _resolve_db_path(self, *, db_path: Optional[str], app_name: str) -> str: + if db_path: + return os.path.abspath(db_path) + + # Prefer corePY's config/data folder if Helper exposes one; else fallback to ~/./ + # Adjust this to your Helper conventions if you already have something like get_path("config") etc. + base = None + try: + # If your helper has a dedicated config/data directory, use it + # Example patterns used in your projects: helper.get_path("config"), helper.get_path("Data"), etc. + base = self._helper.get_path("config") # may be None depending on your helper + except Exception: + base = None + + if not base or not os.path.isdir(base): + home = os.path.expanduser("~") + base = os.path.join(home, f".{app_name.lower()}") + + return os.path.join(base, "database.sqlite") + + def _ensure_parent_dir(self, path: str) -> None: + parent = os.path.dirname(path) + if parent and not os.path.isdir(parent): + os.makedirs(parent, exist_ok=True) + + @property + def path(self) -> str: + return self._db_path + + def connect(self) -> sqlite3.Connection: + if self._conn is not None: + return self._conn + + self._log(f"[SQLite] opening: {self._db_path}", level="debug", channel="sqlite") + + conn = sqlite3.connect( + self._db_path, + timeout=self._timeout, + isolation_level=None, # we manage transactions manually when needed + check_same_thread=False, + ) + conn.row_factory = sqlite3.Row + + # IMPORTANT: set _conn before running any PRAGMAs to avoid recursion + self._conn = conn + + # Sensible defaults (execute directly on the connection to avoid calling self.execute/connect) + conn.execute("PRAGMA foreign_keys = ON;") + conn.execute("PRAGMA journal_mode = WAL;") # good concurrency for desktop apps + conn.execute("PRAGMA synchronous = NORMAL;") # good balance for WAL + + return conn + + def close(self) -> None: + if self._conn is not None: + try: + self._conn.close() + except Exception: + pass + self._conn = None + + # ------------------------------------------------------------------ + # Low-level query helpers + # ------------------------------------------------------------------ + + def execute(self, sql: str, params: Union[Tuple[Any, ...], Dict[str, Any], None] = None) -> sqlite3.Cursor: + conn = self.connect() + cur = conn.cursor() + if params is None: + cur.execute(sql) + else: + cur.execute(sql, params) + return cur + + def executemany(self, sql: str, seq: Iterable[Union[Tuple[Any, ...], Dict[str, Any]]]) -> int: + conn = self.connect() + cur = conn.cursor() + cur.executemany(sql, seq) + return cur.rowcount + + def query(self, sql: str, params: Union[Tuple[Any, ...], Dict[str, Any], None] = None) -> List[Row]: + cur = self.execute(sql, params) + rows = cur.fetchall() + return [dict(r) for r in rows] + + def one(self, sql: str, params: Union[Tuple[Any, ...], Dict[str, Any], None] = None) -> Optional[Row]: + cur = self.execute(sql, params) + r = cur.fetchone() + return dict(r) if r else None + + def scalar(self, sql: str, params: Union[Tuple[Any, ...], Dict[str, Any], None] = None) -> Any: + cur = self.execute(sql, params) + r = cur.fetchone() + if not r: + return None + # sqlite3.Row is indexable + return r[0] + + @contextmanager + def transaction(self): + """ + Usage: + with db.transaction(): + db.insert(...) + db.update(...) + """ + conn = self.connect() + try: + conn.execute("BEGIN;") + yield + conn.execute("COMMIT;") + except Exception: + conn.execute("ROLLBACK;") + raise + + # ------------------------------------------------------------------ + # Table CRUD + # ------------------------------------------------------------------ + + def list_tables(self) -> List[str]: + rows = self.query( + "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name;" + ) + return [r["name"] for r in rows] + + def table_exists(self, table: str) -> bool: + r = self.scalar( + "SELECT 1 FROM sqlite_master WHERE type='table' AND name=? LIMIT 1;", + (table,), + ) + return bool(r) + + def drop_table(self, table: str) -> None: + self.execute(f'DROP TABLE IF EXISTS "{table}";') + + def create_table(self, table: str, columns_sql: str) -> None: + """ + columns_sql example: + "id INTEGER PRIMARY KEY, name TEXT NOT NULL, created_utc TEXT" + """ + self.execute(f'CREATE TABLE IF NOT EXISTS "{table}" ({columns_sql});') + + def columns(self, table: str) -> List[Row]: + # PRAGMA doesn't accept binding for identifiers; table must be trusted input + return self.query(f'PRAGMA table_info("{table}");') + + # ------------------------------------------------------------------ + # Record CRUD + # ------------------------------------------------------------------ + + def insert(self, table: str, data: Row) -> int: + keys = list(data.keys()) + cols = ", ".join([f'"{k}"' for k in keys]) + placeholders = ", ".join([f":{k}" for k in keys]) + sql = f'INSERT INTO "{table}" ({cols}) VALUES ({placeholders});' + cur = self.execute(sql, data) + return int(cur.lastrowid or 0) + + def select( + self, + table: str, + where: Optional[str] = None, + params: Union[Tuple[Any, ...], Dict[str, Any], None] = None, + *, + columns: Optional[List[str]] = None, + order_by: Optional[str] = None, + limit: Optional[int] = None, + offset: Optional[int] = None, + ) -> List[Row]: + cols = "*" + if columns: + cols = ", ".join([f'"{c}"' for c in columns]) + + sql = f'SELECT {cols} FROM "{table}"' + if where: + sql += f" WHERE {where}" + if order_by: + sql += f" ORDER BY {order_by}" + if limit is not None: + sql += f" LIMIT {int(limit)}" + if offset is not None: + sql += f" OFFSET {int(offset)}" + sql += ";" + return self.query(sql, params) + + def update(self, table: str, data: Row, where: str, params: Union[Tuple[Any, ...], Dict[str, Any]]) -> int: + keys = list(data.keys()) + set_clause = ", ".join([f'"{k}"=:{k}' for k in keys]) + sql = f'UPDATE "{table}" SET {set_clause} WHERE {where};' + + merged: Dict[str, Any] + if isinstance(params, dict): + merged = dict(params) + else: + # If params is tuple, we can't merge by name; require dict for update WHERE params + raise ValueError("SQLite.update requires WHERE params as dict for safe named binding.") + + merged.update(data) + cur = self.execute(sql, merged) + return int(cur.rowcount or 0) + + def delete(self, table: str, where: str, params: Union[Tuple[Any, ...], Dict[str, Any]]) -> int: + sql = f'DELETE FROM "{table}" WHERE {where};' + cur = self.execute(sql, params) + return int(cur.rowcount or 0) + + def upsert( + self, + table: str, + data: Row, + conflict_columns: List[str], + update_columns: Optional[List[str]] = None, + ) -> None: + """ + INSERT ... ON CONFLICT(...) DO UPDATE SET ... + """ + keys = list(data.keys()) + cols = ", ".join([f'"{k}"' for k in keys]) + placeholders = ", ".join([f":{k}" for k in keys]) + + conflict = ", ".join([f'"{c}"' for c in conflict_columns]) + + if update_columns is None: + update_columns = [k for k in keys if k not in conflict_columns] + + if update_columns: + set_clause = ", ".join([f'"{k}"=excluded."{k}"' for k in update_columns]) + sql = ( + f'INSERT INTO "{table}" ({cols}) VALUES ({placeholders}) ' + f"ON CONFLICT({conflict}) DO UPDATE SET {set_clause};" + ) + else: + sql = ( + f'INSERT INTO "{table}" ({cols}) VALUES ({placeholders}) ' + f"ON CONFLICT({conflict}) DO NOTHING;" + ) + + self.execute(sql, data) + + # ------------------------------------------------------------------ + # Logging + # ------------------------------------------------------------------ + + def _log(self, msg: str, *, level: str = "info", channel: str = "sqlite") -> None: + if self._logger is not None and hasattr(self._logger, "append"): + self._logger.append(msg, level=level, channel=channel) # type: ignore[call-arg] + else: + print(msg) diff --git a/dist/macos/Replicator.app/Contents/Resources/core/filesystem/__init__.py b/dist/macos/Replicator.app/Contents/Resources/core/filesystem/__init__.py new file mode 100644 index 00000000..1d9dfde4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/filesystem/__init__.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +# src/core/filesystem/__init__.py + +from .filesystem import FileSystem +from .share import Share + +__version__ = "1.0.0" + +__all__ = ["FileSystem", "Share"] diff --git a/dist/macos/Replicator.app/Contents/Resources/core/filesystem/filesystem.py b/dist/macos/Replicator.app/Contents/Resources/core/filesystem/filesystem.py new file mode 100644 index 00000000..a9902378 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/filesystem/filesystem.py @@ -0,0 +1,382 @@ +#!/usr/bin/env python3 +# corePY/filesystem/filesystem.py + +from __future__ import annotations + +import os +import shutil +from dataclasses import dataclass +from pathlib import Path +from typing import Optional, Union, Iterable, Tuple + +from PyQt5.QtWidgets import QApplication + +try: + from core.helper import Helper +except ImportError: + from helper import Helper + +PathLike = Union[str, os.PathLike] + +@dataclass(frozen=True) +class CommandSpec: + """A simple command container useful for logging/execution.""" + + argv: list[str] + label: str + sensitive: bool = False + + +class FileSystem: + """Cross-platform filesystem helper. + + Goals: + - Provide *basic* operations (read/copy/delete) for files/folders. + - Prefer native tools when asked to preserve metadata: + - Windows: robocopy (best for NTFS ACLs) + - Linux/macOS: rsync (best for POSIX perms/ACL/xattrs when supported) + - Fall back to Python stdlib when tools are missing. + + Notes: + - UNC paths (\\\\server\\share\\path) are treated as normal paths on Windows. + - "preserve_metadata" is best-effort; some filesystems/mounts can't store all metadata. + """ + + def __init__( + self, + helper: Optional[Helper] = None, + logger: Optional[object] = None, + ): + super().__init__() + + # --- auto-wire from QApplication if not provided --- + if helper is None or logger is None: + app = QApplication.instance() + if app is None: + raise RuntimeError("FileSystem must be created after QApplication/Application.") + helper = helper or app.helper # type: ignore[attr-defined] + logger = logger or getattr(app, "logger", None) + + self._helper: Helper = helper + self._logger = logger + self._os: str = self._helper.get_os() + + # Cache for tool capability detection + self._rsync_caps: Optional[dict[str, bool]] = None + + # ------------------------------------------------------------------ + # Small helpers + # ------------------------------------------------------------------ + + def _p(self, path: PathLike) -> str: + return str(path) + + def _log(self, msg: str, level: str = "debug", channel: str = "filesystem") -> None: + if self._logger is not None and hasattr(self._logger, "append"): + try: + self._logger.append(msg, level=level, channel=channel) # type: ignore[call-arg] + return + except Exception: + pass + # Fallback: silent unless explicitly needed + + def _rsync_capabilities(self) -> dict[str, bool]: + """Detect which rsync flags are supported on this host. + + macOS often ships an older rsync that does not support -A/-X. + We detect capabilities once and cache them. + """ + if self._rsync_caps is not None: + return self._rsync_caps + + caps = { + "has_rsync": False, + "acls": False, # -A / --acls + "xattrs": False, # -X / --xattrs + "hardlinks": False, # -H / --hard-links + "numeric_ids": False, # --numeric-ids + } + + rsync = shutil.which("rsync") + if not rsync: + self._rsync_caps = caps + return caps + + caps["has_rsync"] = True + + # Try `--help` (most reliable to see flag availability) + rc, out = self._helper.run([rsync, "--help"]) + if rc != 0: + # If help fails, assume minimal support + self._rsync_caps = caps + return caps + + help_text = out or "" + + # Look for common help strings + if "--acls" in help_text or " -A" in help_text: + caps["acls"] = True + if "--xattrs" in help_text or " -X" in help_text: + caps["xattrs"] = True + if "--hard-links" in help_text or " -H" in help_text: + caps["hardlinks"] = True + if "--numeric-ids" in help_text: + caps["numeric_ids"] = True + + self._rsync_caps = caps + return caps + + def _build_rsync_args(self, *, allow_deletion: bool, preserve_metadata: bool) -> Optional[list[str]]: + """Build a safe rsync argv for the current host. + + We always include `-a` (archive) when preserve_metadata=True. + Additional flags (-H/-A/-X/--numeric-ids) are appended only if supported. + """ + caps = self._rsync_capabilities() + if not caps.get("has_rsync"): + return None + + rsync = shutil.which("rsync") or "rsync" + + args: list[str] = [rsync] + + if preserve_metadata: + # archive mode preserves perms, times, symlinks, etc. + args.append("-a") + else: + # minimal recursion + times (best-effort) + args.extend(["-r", "-t"]) + + if caps.get("hardlinks"): + args.append("-H") + if preserve_metadata and caps.get("acls"): + args.append("-A") + if preserve_metadata and caps.get("xattrs"): + args.append("-X") + if preserve_metadata and caps.get("numeric_ids"): + args.append("--numeric-ids") + + if allow_deletion: + args.append("--delete") + + return args + + def exists(self, path: PathLike) -> bool: + return os.path.exists(self._p(path)) + + def is_file(self, path: PathLike) -> bool: + return os.path.isfile(self._p(path)) + + def is_dir(self, path: PathLike) -> bool: + return os.path.isdir(self._p(path)) + + def mkdirs(self, path: PathLike) -> None: + os.makedirs(self._p(path), exist_ok=True) + + # ------------------------------------------------------------------ + # Read operations + # ------------------------------------------------------------------ + + def read_bytes(self, path: PathLike) -> bytes: + p = self._p(path) + with open(p, "rb") as f: + return f.read() + + def read_text(self, path: PathLike, encoding: str = "utf-8", errors: str = "strict") -> str: + p = self._p(path) + with open(p, "r", encoding=encoding, errors=errors) as f: + return f.read() + + # ------------------------------------------------------------------ + # Delete operations + # ------------------------------------------------------------------ + + def delete(self, path: PathLike) -> bool: + """Delete a file or folder (recursive). Returns True if deleted, False if not found.""" + p = self._p(path) + if not os.path.exists(p): + return False + + if os.path.isdir(p) and not os.path.islink(p): + shutil.rmtree(p) + else: + os.remove(p) + return True + + # ------------------------------------------------------------------ + # Copy operations + # ------------------------------------------------------------------ + + def copy( + self, + src: PathLike, + dst: PathLike, + *, + preserve_metadata: bool = True, + allow_deletion: bool = False, + ) -> bool: + """Copy file or directory from src to dst. + + If src is a directory: + - preserve_metadata=True prefers robocopy (Windows) or rsync (Linux/macOS) + - allow_deletion=True makes it a mirror (best-effort with stdlib fallback) + + Returns: + - True on success + - False on failure + """ + src_s = self._p(src) + dst_s = self._p(dst) + + if not os.path.exists(src_s): + self._log(f"[FileSystem] copy: source not found: {src_s}", level="warning") + return False + + try: + if os.path.isdir(src_s): + return self._copy_dir(src_s, dst_s, preserve_metadata=preserve_metadata, allow_deletion=allow_deletion) + else: + return self._copy_file(src_s, dst_s, preserve_metadata=preserve_metadata) + except Exception as e: + self._log(f"[FileSystem] copy failed: {src_s} -> {dst_s} ({e})", level="error") + return False + + def _copy_file(self, src: str, dst: str, *, preserve_metadata: bool = True) -> bool: + self.mkdirs(os.path.dirname(dst) or ".") + + # shutil.copy2 preserves basic metadata (mtime/atime + mode where possible) + if preserve_metadata: + shutil.copy2(src, dst) + else: + shutil.copy(src, dst) + + return True + + def _copy_dir( + self, + src: str, + dst: str, + *, + preserve_metadata: bool = True, + allow_deletion: bool = False, + ) -> bool: + # Prefer native tools when metadata matters + if preserve_metadata: + cmd = self.build_mirror_command(src, dst, allow_deletion=allow_deletion) + if cmd is not None: + self._log(f"[FileSystem] executing: {cmd.label}: {' '.join(cmd.argv)}") + rc, out = self._helper.run(cmd.argv) + + # robocopy has special return codes: 0-7 are generally success-ish. + if cmd.argv and os.path.basename(cmd.argv[0]).lower().startswith("robocopy"): + ok = rc <= 7 + else: + ok = rc == 0 + + if not ok: + self._log(f"[FileSystem] tool copy failed rc={rc}: {out}", level="warning") + return ok + + # Fallback: Python stdlib directory copy + # Ensure destination exists + os.makedirs(dst, exist_ok=True) + + # Copy/update files + for root, dirs, files in os.walk(src): + rel = os.path.relpath(root, src) + target_root = dst if rel == "." else os.path.join(dst, rel) + os.makedirs(target_root, exist_ok=True) + + for d in dirs: + os.makedirs(os.path.join(target_root, d), exist_ok=True) + + for f in files: + s = os.path.join(root, f) + t = os.path.join(target_root, f) + # copy2 for metadata best-effort + shutil.copy2(s, t) + + # Mirror delete extras if requested (best-effort) + if allow_deletion: + self._mirror_delete_extras(src, dst) + + return True + + def _mirror_delete_extras(self, src: str, dst: str) -> None: + """Delete files/dirs that exist in dst but not in src (best-effort).""" + # Walk destination and compare + for root, dirs, files in os.walk(dst, topdown=False): + rel = os.path.relpath(root, dst) + src_root = src if rel == "." else os.path.join(src, rel) + + # Remove files not present in src + for f in files: + d_path = os.path.join(root, f) + s_path = os.path.join(src_root, f) + if not os.path.exists(s_path): + try: + os.remove(d_path) + except Exception as e: + self._log(f"[FileSystem] mirror delete file failed: {d_path} ({e})", level="warning") + + # Remove dirs not present in src + for d in dirs: + d_path = os.path.join(root, d) + s_path = os.path.join(src_root, d) + if not os.path.exists(s_path): + try: + shutil.rmtree(d_path) + except Exception as e: + self._log(f"[FileSystem] mirror delete dir failed: {d_path} ({e})", level="warning") + + # ------------------------------------------------------------------ + # Command generation (reusable by Replicator) + # ------------------------------------------------------------------ + + def build_mirror_command(self, src_dir: PathLike, dst_dir: PathLike, *, allow_deletion: bool) -> Optional[CommandSpec]: + """Build the best command to mirror src_dir -> dst_dir on this host. + + Returns a CommandSpec or None if no suitable tool is available. + """ + src = self._p(src_dir) + dst = self._p(dst_dir) + + # ------------------------- + # Windows: robocopy + # ------------------------- + if self._os == "windows": + # robocopy is typically available in PATH on Windows + robocopy = shutil.which("robocopy") or "robocopy" + + # /MIR implies /E + delete extras; /E copies subdirs including empty + # /COPY:DATSOU preserves Data, Attributes, Timestamps, Security (ACL), Owner, Auditing + # /DCOPY:DAT preserves directory timestamps + # /R /W keep retries low for UI responsiveness + args = [ + robocopy, + src, + dst, + "/MIR" if allow_deletion else "/E", + "/COPY:DATSOU", + "/DCOPY:DAT", + "/R:1", + "/W:1", + ] + return CommandSpec(argv=args, label="robocopy") + + # ------------------------- + # Linux/macOS: rsync + # ------------------------- + if self._os in ("linux", "macos"): + # Use trailing slashes to copy contents of src into dst + src_arg = src.rstrip("/") + "/" + dst_arg = dst.rstrip("/") + "/" + + base = self._build_rsync_args(allow_deletion=allow_deletion, preserve_metadata=True) + if not base: + return None + + args = base + [src_arg, dst_arg] + return CommandSpec(argv=args, label="rsync") + + return None diff --git a/dist/macos/Replicator.app/Contents/Resources/core/filesystem/share.py b/dist/macos/Replicator.app/Contents/Resources/core/filesystem/share.py new file mode 100644 index 00000000..8ff56eaa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/filesystem/share.py @@ -0,0 +1,617 @@ +#!/usr/bin/env python3 +# src/core/filesystem/share.py + +"""Share mounting utilities for corePY (SMB-only). + +Goal +---- +Provide a single, cross-platform interface for mounting/unmounting SMB shares. + +Supported protocol: + - SMB (CIFS / Windows shares) + +Backends +-------- +Native OS tools (preferred): + * Linux: mount.cifs / umount + * macOS: mount_smbfs / umount + * Windows: net use + +Notes +----- +* Many mount operations require elevated privileges depending on target path. + This class does not force privilege escalation; you can pass `elevate=True` + to prefix commands with sudo on Unix-like systems. +* On Windows, SMB mounting via `net use` maps network resources to a drive letter. + - If you pass a drive letter (e.g. `mount_point='Z:'`), it will map directly. + - If you pass a directory path, corePY will map the share to a free drive letter + and create a directory junction at `mount_point` pointing to that drive. +""" + +from __future__ import annotations + +import os +import platform +import shlex +import shutil +import subprocess +import time +from dataclasses import dataclass +from pathlib import Path +from typing import Dict, List, Optional, Tuple +from urllib.parse import quote, unquote + + +class ShareError(RuntimeError): + pass + + +@dataclass +class ShareAuth: + username: Optional[str] = None + password: Optional[str] = None + domain: Optional[str] = None + + +@dataclass +class ShareTarget: + protocol: str # smb + host: str + path: str = "" # share name and optional subpath (e.g. "Share" or "Share/dir") + port: Optional[int] = None # unused for smb, kept for compatibility + + def normalized_protocol(self) -> str: + p = (self.protocol or "").strip().lower() + if p in {"cifs"}: + return "smb" + return p + + def decoded_path(self) -> str: + # Accept either raw share names or percent-encoded ones (e.g. "Test%20with%20spaces"). + try: + return unquote(self.path or "") + except Exception: + return self.path or "" + + +class Share: + """Mount and unmount SMB shares.""" + + def __init__(self, logger=None, bin_root: Optional[str] = None): + self._logger = logger + self._bin_root = Path(bin_root) if bin_root else None + + self._backend: Optional[str] = None # native_smb_linux|native_smb_macos|native_smb_windows + self._last_cmd: Optional[List[str]] = None + self._last_mount_point: Optional[str] = None + self._last_probe_ok: Optional[bool] = None + self._last_probe_message: Optional[str] = None + self._last_windows_drive: Optional[str] = None + self._last_windows_junction: Optional[str] = None + self._last_windows_unc: Optional[str] = None + + # --------------------------------------------------------------------- + # Public API + # --------------------------------------------------------------------- + + def mount( + self, + protocol: str, + host: str, + remote: str, + mount_point: str, + auth: Optional[ShareAuth] = None, + *, + port: Optional[int] = None, + options: Optional[Dict[str, str]] = None, + read_only: bool = False, + elevate: bool = False, + timeout: int = 60, + ) -> None: + """Mount a share. + + Parameters + ---------- + protocol: + smb + host: + Hostname or IP. + remote: + SMB share name and optional path (e.g. "Share" or "Share/dir"). + mount_point: + Local mount directory (Linux/macOS) or drive letter like "Z:" (Windows). + auth: + Username/password/domain. + options: + Backend-specific mount options. + read_only: + Attempt to mount read-only. + elevate: + On Linux/macOS, prefix with sudo. + timeout: + Seconds. + """ + auth = auth or ShareAuth() + options = options or {} + + target = ShareTarget(protocol=protocol, host=host, path=remote or "", port=port) + p = target.normalized_protocol() + + # Normalize remote path early (accept percent-encoded share names) + target.path = target.decoded_path() + + self._log_debug(f"Mount request: protocol={p} host={host} remote={remote} mount_point={mount_point}") + + if p != "smb": + raise ShareError(f"Unsupported protocol: {protocol}. Supported protocol(s): smb") + + # Ensure mountpoint exists for directory-based mounts + # On Windows, directory mounts are implemented as symlinks and any pre-created empty directory will be replaced. + if not self._is_windows_drive_letter(mount_point): + Path(mount_point).mkdir(parents=True, exist_ok=True) + + self._mount_smb(target, mount_point, auth, options, read_only, elevate, timeout) + + # Probe the mount to confirm it is usable. + ok, msg = self._probe_mount(mount_point, timeout=timeout) + self._last_probe_ok = ok + self._last_probe_message = msg + self._log_debug(f"Share mount probe: mount_point={mount_point} ok={ok} msg={msg}") + + if not ok: + raise ShareError(f"Mount completed but mount probe failed: {msg}") + + self._last_mount_point = mount_point + + def umount(self, mount_point: Optional[str] = None, *, elevate: bool = False, timeout: int = 60) -> None: + """Unmount a share.""" + mp = mount_point or self._last_mount_point + if not mp: + raise ShareError("No mount point provided, and no previous mount point is known.") + + self._log_debug(f"Unmount request: mount_point={mp} backend={self._backend}") + + # Best-effort probe before unmount. + ok_before, msg_before = self._probe_mount(mp, timeout=min(5, timeout)) + self._log_debug(f"Share pre-unmount probe: mount_point={mp} ok={ok_before} msg={msg_before}") + + system = platform.system().lower() + if system == "windows": + # If we created a directory symlink, remove it first, then disconnect. + drive: Optional[str] = None + unc: Optional[str] = None + + if mp and not self._is_windows_drive_letter(mp): + # Directory-style mount (symlink) + junction = mp + unc = self._last_windows_unc + try: + if junction and os.path.exists(junction): + # Remove symlink directory (best-effort) + self._run(["cmd", "/c", "rmdir", "/S", "/Q", junction], timeout=timeout) + except Exception: + pass + else: + # Drive-letter mount + drive = mp + + if drive: + # Example: net use Z: /delete /y + self._run(["net", "use", drive, "/delete", "/y"], timeout=timeout) + + if unc: + # Example: net use \\server\Share /delete /y + self._run(["net", "use", unc, "/delete", "/y"], timeout=timeout) + + # Clear remembered mapping + self._last_windows_drive = None + self._last_windows_junction = None + self._last_windows_unc = None + + ok_after, msg_after = self._probe_mount(mp, timeout=min(5, timeout)) + self._log_debug(f"Share post-unmount probe: mount_point={mp} ok={ok_after} msg={msg_after}") + return + + # Linux/macOS + umount_bin = shutil.which("umount") or "umount" + cmd = (["sudo"] if elevate else []) + [umount_bin, mp] + self._run(cmd, timeout=timeout) + + ok_after, msg_after = self._probe_mount(mp, timeout=min(5, timeout)) + self._log_debug(f"Share post-unmount probe: mount_point={mp} ok={ok_after} msg={msg_after}") + + # --------------------------------------------------------------------- + # SMB + # --------------------------------------------------------------------- + + def _mount_smb( + self, + target: ShareTarget, + mount_point: str, + auth: ShareAuth, + options: Dict[str, str], + read_only: bool, + elevate: bool, + timeout: int, + ) -> None: + system = platform.system().lower() + + if system == "windows": + self._backend = "native_smb_windows" + + # `net use` supports mapping to a drive letter. + # If the caller provided a directory path, we: + # 1) create an authenticated connection to the UNC path (no drive letter) + # 2) create a directory symlink at mount_point pointing to that UNC path + # + # IMPORTANT: `mklink /J` (junction) cannot target mapped drives / UNC paths + # and will fail with "Local volumes are required...". For UNC we must use + # a directory symbolic link (`mklink /D`). + + unc = self._smb_unc(target.host, target.path) + + junction_path: Optional[str] = None + drive_letter: Optional[str] = None + + if self._is_windows_drive_letter(mount_point): + # Drive-letter style mount + drive_letter = mount_point.upper() + + cmd = ["net", "use", drive_letter, unc] + if auth.username: + if auth.domain: + cmd += [f"/user:{auth.domain}\\{auth.username}"] + else: + cmd += [f"/user:{auth.username}"] + if auth.password is not None: + cmd += [auth.password] + cmd += ["/persistent:no"] + + # Retry once on 1219 by clearing existing connections to that host + try: + self._run(cmd, timeout=timeout) + except ShareError as e: + if "1219" in str(e): + self._log_debug(f"Windows SMB: detected error 1219; clearing connections to host {target.host} and retrying") + try: + self._run(["net", "use", f"\\\\{target.host}\\*", "/delete", "/y"], timeout=timeout) + except Exception: + pass + self._run(cmd, timeout=timeout) + else: + raise + + self._last_windows_drive = drive_letter + self._last_windows_junction = None + self._last_windows_unc = None + return + + # Directory-style mount (symlink to UNC) + junction_path = mount_point + + # 1) Create (or refresh) an authenticated connection to the UNC path + # without assigning a drive letter. + cmd = ["net", "use", unc] + if auth.username: + if auth.domain: + cmd += [f"/user:{auth.domain}\\{auth.username}"] + else: + cmd += [f"/user:{auth.username}"] + # Avoid interactive password prompt: pass empty string when password is None. + cmd += [(auth.password if auth.password is not None else "")] + cmd += ["/persistent:no"] + + try: + self._run(cmd, timeout=timeout) + except ShareError as e: + if "1219" in str(e): + self._log_debug(f"Windows SMB: detected error 1219; clearing connections to host {target.host} and retrying") + try: + self._run(["net", "use", f"\\\\{target.host}\\*", "/delete", "/y"], timeout=timeout) + except Exception: + pass + self._run(cmd, timeout=timeout) + else: + raise + + # 2) Create a directory symlink pointing to the UNC path. + try: + if os.path.exists(junction_path): + self._run(["cmd", "/c", "rmdir", "/S", "/Q", junction_path], timeout=timeout) + + # NOTE: Creating symlinks may require admin privileges unless Developer Mode is enabled. + self._run(["cmd", "/c", "mklink", "/D", junction_path, unc], timeout=timeout) + + self._last_windows_drive = None + self._last_windows_junction = junction_path + self._last_windows_unc = unc + except Exception: + # Best-effort rollback of the UNC connection + try: + self._run(["net", "use", unc, "/delete", "/y"], timeout=timeout) + except Exception: + pass + raise + + return + + if system == "darwin": + self._backend = "native_smb_macos" + mount_smbfs = self._bin("mount_smbfs") + + # Format: //user:pass@server/share /mnt/point + userinfo = "" + if auth.username: + userinfo = auth.username + if auth.password: + userinfo += ":" + self._url_escape(auth.password) + userinfo += "@" + + # For SMB URLs, the path portion must be URL-encoded (but keep '/'). + path = (target.path or "").lstrip("/") + path = quote(path, safe="/") + url = f"//{userinfo}{target.host}/{path}" + if read_only: + cmd = (["sudo"] if elevate else []) + [mount_smbfs, "-o", "ro", url, mount_point] + else: + cmd = (["sudo"] if elevate else []) + [mount_smbfs, url, mount_point] + + self._run(cmd, timeout=timeout) + return + + # Linux + self._backend = "native_smb_linux" + mount_cifs = self._bin("mount.cifs") + + share, subpath = self._split_share_and_subpath(target.path) + if not share: + raise ShareError("SMB mount requires a share name (remote='Share' or 'Share/subpath').") + + unc = f"//{target.host}/{share}" + + mount_opts: Dict[str, str] = {} + if auth.username is not None: + mount_opts["username"] = auth.username + if auth.password is not None: + mount_opts["password"] = auth.password + if auth.domain: + mount_opts["domain"] = auth.domain + if read_only: + mount_opts["ro"] = "" + + # Allow caller overrides + mount_opts.update(options) + + opts_str = self._kv_to_mount_opts(mount_opts) + + cmd = (["sudo"] if elevate else []) + [mount_cifs, unc, mount_point] + if opts_str: + cmd += ["-o", opts_str] + + self._run(cmd, timeout=timeout) + + # If a subpath was requested, verify it exists (informational only) + if subpath: + check_path = os.path.join(mount_point, subpath) + if not os.path.exists(check_path): + self._log_debug(f"Warning: SMB subpath does not exist after mount: {check_path}") + + # --------------------------------------------------------------------- + # Helpers + # --------------------------------------------------------------------- + + def _run(self, cmd: List[str], *, timeout: int) -> None: + self._last_cmd = cmd + printable = [shlex.quote(str(c)) for c in cmd] + self._log_debug("Executing: " + " ".join(printable)) + + try: + # On Windows, launching console utilities from a GUI process can flash a console window. + # Use CREATE_NO_WINDOW / SW_HIDE best-effort to avoid visible windows. + run_kwargs: Dict[str, object] = { + "stdout": subprocess.PIPE, + "stderr": subprocess.PIPE, + "text": True, + "timeout": timeout, + "check": False, + "stdin": subprocess.DEVNULL, + } + + if platform.system().lower() == "windows": + # Hide console window (best-effort) + create_no_window = getattr(subprocess, "CREATE_NO_WINDOW", 0) + if create_no_window: + run_kwargs["creationflags"] = int(create_no_window) + + # Some Windows builds still flash; STARTUPINFO can help in many cases. + try: + si = subprocess.STARTUPINFO() # type: ignore[attr-defined] + si.dwFlags |= getattr(subprocess, "STARTF_USESHOWWINDOW", 1) + si.wShowWindow = getattr(subprocess, "SW_HIDE", 0) + run_kwargs["startupinfo"] = si + except Exception: + pass + + completed = subprocess.run(cmd, **run_kwargs) # type: ignore[arg-type] + except FileNotFoundError as e: + raise ShareError(f"Required executable not found: {cmd[0]}") from e + except subprocess.TimeoutExpired as e: + raise ShareError(f"Command timed out after {timeout}s: {' '.join(cmd)}") from e + + if completed.returncode != 0: + msg = (completed.stderr or completed.stdout or "").strip() + raise ShareError(f"Mount command failed (code {completed.returncode}): {msg}") + + if completed.stdout: + self._log_debug(completed.stdout.strip()) + + def _bin(self, name: str) -> str: + """Resolve an executable. + + Resolution order: + 1) PATH + 2) Bundled binary under src/bin/[name]/[OS]/[arch]/(bin/)[exe] (best-effort) + """ + candidates = [name] + if platform.system().lower() == "windows" and not name.lower().endswith(".exe"): + candidates.insert(0, name + ".exe") + + # PATH first + for c in candidates: + p = shutil.which(c) + if p: + return p + + # Bundled fallback + root = self._resolve_bin_root() + os_name = self._os_folder() + arch = self._arch_folder() + + for c in candidates: + bundled_bin = root / name / os_name / arch / "bin" / c + bundled_flat = root / name / os_name / arch / c + for bundled in (bundled_bin, bundled_flat): + if bundled.exists() and bundled.is_file(): + return str(bundled) + + return candidates[0] + + def _resolve_bin_root(self) -> Path: + if self._bin_root: + return self._bin_root + + here = Path(__file__).resolve() + + search_roots: List[Path] = [] + try: + search_roots.append(Path.cwd()) + except Exception: + pass + + search_roots.append(here.parent) + search_roots.extend(list(here.parents)) + search_roots.append(here.parent.parent) + search_roots.append(here.parent.parent.parent) + + for root in search_roots: + candidate = root / "src" / "bin" + if candidate.exists(): + self._bin_root = candidate + return candidate + + for root in search_roots: + candidate = root / "bin" + if candidate.exists(): + self._bin_root = candidate + return candidate + + self._bin_root = Path.cwd() / "src" / "bin" + return self._bin_root + + def _os_folder(self) -> str: + s = platform.system().lower() + if s == "darwin": + return "macos" + if s == "windows": + return "windows" + return "linux" + + def _arch_folder(self) -> str: + m = (platform.machine() or "").lower() + if m in {"x86_64", "amd64"}: + return "x86_64" + if m in {"aarch64", "arm64"}: + return "arm64" + if m.startswith("arm"): + return "arm" + if m in {"i386", "i686", "x86"}: + return "x86" + return m or "unknown" + + def _is_windows_drive_letter(self, s: str) -> bool: + return len(s) == 2 and s[1] == ":" and s[0].isalpha() + + def _smb_unc(self, host: str, remote: str) -> str: + remote = unquote(remote or "") + remote = remote.replace("/", "\\").lstrip("\\") + return f"\\\\{host}\\{remote}" + + def _split_share_and_subpath(self, remote: str) -> Tuple[str, str]: + r = unquote(remote or "").lstrip("/") + if not r: + return "", "" + parts = r.split("/") + share = parts[0] + sub = "/".join(parts[1:]) if len(parts) > 1 else "" + return share, sub + + def _kv_to_mount_opts(self, d: Dict[str, str]) -> str: + parts = [] + for k, v in d.items(): + if v is None: + continue + if v == "": + parts.append(str(k)) + else: + parts.append(f"{k}={v}") + return ",".join(parts) + + def _url_escape(self, s: str) -> str: + # Minimal escaping suitable for passwords in smb URLs + safe = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~" + out = [] + for ch in s: + if ch in safe: + out.append(ch) + else: + out.append("%" + format(ord(ch), "02X")) + return "".join(out) + + def _log_debug(self, msg: str) -> None: + if self._logger is not None: + for method in ("debug", "info"): + if hasattr(self._logger, method): + getattr(self._logger, method)(msg) + return + + def _probe_mount(self, mount_point: str, *, timeout: int = 10) -> Tuple[bool, str]: + """Best-effort probe to determine if a mount point is usable.""" + try: + if self._is_windows_drive_letter(mount_point): + return self._probe_windows_drive(mount_point) + + mp = str(mount_point) + if not os.path.exists(mp): + return False, "mount point does not exist" + if not os.path.isdir(mp): + return False, "mount point is not a directory" + + deadline = time.time() + float(timeout) + last_err: Optional[str] = None + while time.time() < deadline: + try: + _ = os.listdir(mp) + return True, "listdir ok" + except Exception as e: + last_err = str(e) + time.sleep(0.25) + + return False, f"listdir failed: {last_err or 'unknown error'}" + except Exception as e: + return False, f"probe exception: {e}" + + def _probe_windows_drive(self, drive: str) -> Tuple[bool, str]: + try: + d = drive.upper() + if not d.endswith(":"): + d += ":" + root = d + "\\" + if not os.path.exists(root): + return False, "drive root does not exist" + try: + _ = os.listdir(root) + return True, "drive listdir ok" + except Exception as e: + return False, f"drive listdir failed: {e}" + except Exception as e: + return False, f"drive probe exception: {e}" diff --git a/dist/macos/Replicator.app/Contents/Resources/core/helper.py b/dist/macos/Replicator.app/Contents/Resources/core/helper.py new file mode 100644 index 00000000..c7a638c6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/helper.py @@ -0,0 +1,391 @@ +#!/usr/bin/env python3 +# src/core/helper.py +import os +import sys +import platform +import subprocess + +from pathlib import Path +from PyQt5.QtWidgets import QApplication + +class Helper: + """ + Small collection of cross-app helpers. + """ + + def __init__(self, root_dir: str | None = None, script_dir: str | None = None): + if script_dir is None: + if getattr(sys, "frozen", False): + script_dir = os.path.dirname(sys.executable) + else: + script_dir = os.path.dirname(os.path.abspath(__file__)) + self.script_dir = script_dir + + if root_dir is None: + # If we are in .../src/app, root_dir should be project root (two levels up). + base = os.path.dirname(self.script_dir) # e.g. .../src + parent = os.path.dirname(base) # e.g. project_root + self.root_dir = parent + else: + self.root_dir = root_dir + + self.home_dir = os.path.expanduser("~") + + def get_path(self, rel_path: str, type: str = "SYS") -> str | None: + """ + Locate a resource file according to the specified type. + Wrapper around get_sys_path, get_config_path, get_data_path. + + Types: + - SYS: Search in standard system locations (PyInstaller, .app Resources, src/) + - CONFIG: User or system configuration directory (see get_config_path) + - DATA: User or system data directory (see get_data_path) + """ + rel = rel_path.replace("\\", "/") + + if type.upper() == "SYS": + return self.get_sys_path(rel) + elif type.upper() == "CONFIG": + return self.get_config_path(rel) + elif type.upper() == "DATA": + return self.get_data_path(rel) + else: + print(f"[Helper] Unknown path type: {type}") + return None + + def get_sys_path(self, rel_path: str) -> str | None: + rel = rel_path.replace("\\", "/") + + # 1) PyInstaller onefile temp dir + meipass = getattr(sys, "_MEIPASS", None) + if meipass: + p = os.path.join(meipass, rel) + if os.path.exists(p): + return p + + # 2) Next to the frozen exe + if getattr(sys, "frozen", False): + p = os.path.join(self.script_dir, rel) + if os.path.exists(p): + return p + + # 3) macOS .app Resources in onefile + if getattr(sys, "frozen", False) and self.get_os() == "macos": + # .../Replicator.app/Contents/MacOS/Replicator -> parents[1] = Contents + contents = Path(sys.executable).resolve().parents[1] + p = contents / "Resources" / rel + if p.exists(): + return str(p) + + # 4) macOS .app Resources + res = os.path.join(self.root_dir, "Resources", rel) + if os.path.exists(res): + return res + + # 5) repo src/ + src = os.path.join(self.root_dir, "src", rel) + if os.path.exists(src): + return src + + print(f"[Helper] Could not find resource: {rel}") + return None + + def _get_app_name(self, app_name: str | None = None) -> str: + """Resolve the application name used for user directories.""" + if app_name: + name = str(app_name).strip() + if name: + return name + + # Prefer QApplication name when running with a Qt app + try: + qapp = QApplication.instance() + if qapp: + qname = (qapp.applicationName() or "").strip() + if qname: + return qname + except Exception: + pass + + # Fallback: executable/script name + try: + base = os.path.basename(sys.executable if getattr(sys, "frozen", False) else sys.argv[0]) + name = os.path.splitext(base)[0].strip() + return name or "app" + except Exception: + return "app" + + def get_data_path( + self, + rel_path: str | None = None, + app_name: str | None = None, + scope: str | None = None, + ensure: bool = True, + ) -> str: + """Return the OS-appropriate directory for app *data*. + + Scope: + - scope="user" (default): per-user data directory + - scope="system": system-wide/shared data directory (requires appropriate permissions) + + Defaults by OS: + - Windows: + user -> %LOCALAPPDATA%\\ + system -> %PROGRAMDATA%\\ + - macOS: + user -> ~/Library/Application Support/ + system -> ~/Library/Application Support/ + - Linux: + user -> $XDG_DATA_HOME/ (fallback ~/.local/share/) + system -> /var/lib/ + + If `rel_path` is provided, it is appended under the app directory. + If `ensure` is True, the directory is created (or its parent if `rel_path` looks like a file). + + Notes: + - If scope="system" is requested but the target is not writable, this function falls back + to the user scope directory. + - You can set COREPY_DATA_SCOPE to "user" or "system" to change the default scope. + """ + name = self._get_app_name(app_name) + os_name = self.get_os() + + # Resolve scope: explicit arg wins, then env override, then default to "user" + resolved_scope = (scope or os.environ.get("COREPY_DATA_SCOPE") or "user").strip().lower() + if resolved_scope not in ("user", "system"): + resolved_scope = "user" + + if os_name == "windows": + if resolved_scope == "system": + base = os.environ.get("PROGRAMDATA") or os.environ.get("ALLUSERSPROFILE") or self.home_dir + root = Path(base) / name + else: + base = os.environ.get("LOCALAPPDATA") or os.environ.get("APPDATA") or self.home_dir + root = Path(base) / name + elif os_name == "macos": + # if resolved_scope == "system": + # root = Path("/Library") / "Application Support" / name + # else: + # root = Path(self.home_dir) / "Library" / "Application Support" / name + root = Path(self.home_dir) / "Library" / "Application Support" / name + else: + if resolved_scope == "system": + root = Path("/var") / "lib" / name + else: + xdg = os.environ.get("XDG_DATA_HOME") + if xdg: + root = Path(xdg) / name + else: + root = Path(self.home_dir) / ".local" / "share" / name + + if rel_path: + rel = rel_path.replace("\\", "/").lstrip("/") + root = root / rel + + if ensure: + # If rel_path includes a filename, create parent; otherwise create dir + target_dir = root.parent if root.suffix else root + target_dir.mkdir(parents=True, exist_ok=True) + + if resolved_scope == "system" and ensure: + try: + # If we cannot write to the chosen system directory, fall back to user scope. + probe_dir = root.parent if root.suffix else root + if not os.access(str(probe_dir), os.W_OK): + fallback = self.get_data_path(rel_path=rel_path, app_name=app_name, scope="user", ensure=ensure) + return fallback + except Exception: + fallback = self.get_data_path(rel_path=rel_path, app_name=app_name, scope="user", ensure=ensure) + return fallback + + return str(root) + + def get_config_path( + self, + rel_path: str | None = None, + app_name: str | None = None, + scope: str | None = None, + ensure: bool = True, + ) -> str: + """Return the OS-appropriate directory for app *configuration*. + + Scope: + - scope="user" (default): per-user configuration directory + - scope="system": system-wide/shared configuration directory (requires appropriate permissions) + + Defaults by OS: + - Windows: + user -> %APPDATA%\\ + system -> %PROGRAMDATA%\\\\config + - macOS: + user -> ~/Library/Preferences/ + system -> /Library/Preferences/ + - Linux: + user -> $XDG_CONFIG_HOME/ (fallback ~/.config/) + system -> /etc/ + + If `rel_path` is provided, it is appended under the app directory. + If `ensure` is True, the directory is created (or its parent if `rel_path` looks like a file). + + Notes: + - If scope="system" is requested but the target is not writable, this function falls back + to the user scope directory. + - You can set COREPY_CONFIG_SCOPE to "user" or "system" to change the default scope. + """ + name = self._get_app_name(app_name) + os_name = self.get_os() + + # Resolve scope: explicit arg wins, then env override, then default to "user" + resolved_scope = (scope or os.environ.get("COREPY_CONFIG_SCOPE") or "user").strip().lower() + if resolved_scope not in ("user", "system"): + resolved_scope = "user" + + if os_name == "windows": + if resolved_scope == "system": + base = os.environ.get("PROGRAMDATA") or os.environ.get("ALLUSERSPROFILE") or self.home_dir + root = Path(base) / name / "config" + else: + base = os.environ.get("APPDATA") or os.environ.get("LOCALAPPDATA") or self.home_dir + root = Path(base) / name + elif os_name == "macos": + if resolved_scope == "system": + root = Path("/Library") / "Preferences" / name + else: + root = Path(self.home_dir) / "Library" / "Preferences" / name + else: + if resolved_scope == "system": + root = Path("/etc") / name + else: + xdg = os.environ.get("XDG_CONFIG_HOME") + if xdg: + root = Path(xdg) / name + else: + root = Path(self.home_dir) / ".config" / name + + if rel_path: + rel = rel_path.replace("\\", "/").lstrip("/") + root = root / rel + + if ensure: + target_dir = root.parent if root.suffix else root + target_dir.mkdir(parents=True, exist_ok=True) + + if resolved_scope == "system" and ensure: + try: + probe_dir = root.parent if root.suffix else root + if not os.access(str(probe_dir), os.W_OK): + fallback = self.get_config_path(rel_path=rel_path, app_name=app_name, scope="user", ensure=ensure) + return fallback + except Exception: + fallback = self.get_config_path(rel_path=rel_path, app_name=app_name, scope="user", ensure=ensure) + return fallback + + return str(root) + + @staticmethod + def get_os() -> str: + name = platform.system() + if name == "Darwin": + return "macos" + if name == "Linux": + return "linux" + if name == "Windows": + return "windows" + return "unknown" + + @staticmethod + def get_arch() -> str: + arch = platform.machine().lower() + if arch in ("x86_64", "amd64"): + return "x86_64" + if arch in ("aarch64", "arm64"): + return "arm64" + if arch in ("i386", "i686", "x86", "i86pc"): + return "x86" + if arch in ("armv7l", "armv8l", "arm"): + return "armhf" + return "unknown" + + @staticmethod + def get_serial() -> str: + # Linux / Pi: /proc/cpuinfo usually contains a 'Serial' line + try: + if Helper.get_os() == "linux": + cpuinfo_path = "/proc/cpuinfo" + if os.path.exists(cpuinfo_path): + with open(cpuinfo_path, "r", encoding="utf-8", errors="ignore") as f: + for line in f: + if line.lower().startswith("serial"): + parts = line.split(":", 1) + if len(parts) == 2: + return parts[1].strip() + except Exception: + # Swallow errors and fall through to empty string + pass + + # Fallback: nothing suitable found + return "" + + @staticmethod + def get_screen_resolution() -> tuple[int, int]: + app = QApplication.instance() + if not app: + return (0, 0) + screen = app.primaryScreen() + size = screen.size() + return (size.width(), size.height()) + + @staticmethod + def get_now() -> str: + from datetime import datetime + return datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + @staticmethod + def file_exists(path: str | None) -> bool: + return bool(path) and os.path.isfile(path) + + @staticmethod + def dir_exists(path: str | None) -> bool: + return bool(path) and os.path.isdir(path) + + @staticmethod + def join(*paths: str) -> str: + return os.path.join(*paths) + + @staticmethod + def qss_url(p: str | None) -> str: + """ + Return a url("...") QSS literal, or url("") for None. + """ + if not p: + return 'url("")' + return f'url("{p.replace(os.sep, "/")}")' + + @staticmethod + def run(cmd): + try: + p = subprocess.run( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + timeout=6 + ) + return p.returncode, (p.stdout or "").strip() + except Exception as e: + return 1, f"{type(e).__name__}: {e}" + + # ---------- StyleSheet Handling ---------- + def load_stylesheet(self, rel_path: str) -> str | None: + """ + Load a stylesheet from a relative path. + """ + p = self.get_path(rel_path) + if not p: + return None + try: + with open(p, "r", encoding="utf-8") as f: + return f.read() + except Exception as e: + print(f"[Helper] Failed to load stylesheet {rel_path}: {e}") + return None diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/0-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/0-circle-fill.svg new file mode 100644 index 00000000..e17575cd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/0-circle-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/0-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/0-circle.svg new file mode 100644 index 00000000..b3b4ce3d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/0-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/0-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/0-square-fill.svg new file mode 100644 index 00000000..4da93699 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/0-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/0-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/0-square.svg new file mode 100644 index 00000000..1c76aa4b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/0-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/1-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/1-circle-fill.svg new file mode 100644 index 00000000..7bb27ab3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/1-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/1-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/1-circle.svg new file mode 100644 index 00000000..6349aa1c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/1-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/1-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/1-square-fill.svg new file mode 100644 index 00000000..f3aff4c7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/1-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/1-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/1-square.svg new file mode 100644 index 00000000..218c0133 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/1-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/123.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/123.svg new file mode 100644 index 00000000..47a886fa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/123.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/2-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/2-circle-fill.svg new file mode 100644 index 00000000..19b53162 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/2-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/2-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/2-circle.svg new file mode 100644 index 00000000..35c78c0b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/2-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/2-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/2-square-fill.svg new file mode 100644 index 00000000..7d1af27e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/2-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/2-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/2-square.svg new file mode 100644 index 00000000..2b0787b8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/2-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/3-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/3-circle-fill.svg new file mode 100644 index 00000000..5dccb79a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/3-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/3-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/3-circle.svg new file mode 100644 index 00000000..34d70f25 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/3-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/3-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/3-square-fill.svg new file mode 100644 index 00000000..97e0d8eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/3-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/3-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/3-square.svg new file mode 100644 index 00000000..9366c9b9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/3-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/4-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/4-circle-fill.svg new file mode 100644 index 00000000..895307cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/4-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/4-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/4-circle.svg new file mode 100644 index 00000000..7fab0bbf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/4-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/4-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/4-square-fill.svg new file mode 100644 index 00000000..56bccf93 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/4-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/4-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/4-square.svg new file mode 100644 index 00000000..478e909c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/4-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/5-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/5-circle-fill.svg new file mode 100644 index 00000000..576a0879 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/5-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/5-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/5-circle.svg new file mode 100644 index 00000000..b1e9060a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/5-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/5-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/5-square-fill.svg new file mode 100644 index 00000000..d8e7940d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/5-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/5-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/5-square.svg new file mode 100644 index 00000000..a3d26093 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/5-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/6-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/6-circle-fill.svg new file mode 100644 index 00000000..a22914b7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/6-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/6-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/6-circle.svg new file mode 100644 index 00000000..f9be6c54 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/6-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/6-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/6-square-fill.svg new file mode 100644 index 00000000..8ae78384 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/6-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/6-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/6-square.svg new file mode 100644 index 00000000..53a8ab46 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/6-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/7-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/7-circle-fill.svg new file mode 100644 index 00000000..7ff2cd4c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/7-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/7-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/7-circle.svg new file mode 100644 index 00000000..56039ba6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/7-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/7-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/7-square-fill.svg new file mode 100644 index 00000000..c2cdc624 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/7-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/7-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/7-square.svg new file mode 100644 index 00000000..257f8d05 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/7-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/8-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/8-circle-fill.svg new file mode 100644 index 00000000..8964170f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/8-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/8-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/8-circle.svg new file mode 100644 index 00000000..3a68a2da --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/8-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/8-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/8-square-fill.svg new file mode 100644 index 00000000..84854522 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/8-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/8-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/8-square.svg new file mode 100644 index 00000000..2ae63555 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/8-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/9-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/9-circle-fill.svg new file mode 100644 index 00000000..f251ce3e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/9-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/9-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/9-circle.svg new file mode 100644 index 00000000..5ace6bd8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/9-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/9-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/9-square-fill.svg new file mode 100644 index 00000000..154faca2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/9-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/9-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/9-square.svg new file mode 100644 index 00000000..98f9ac6e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/9-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/activity.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/activity.svg new file mode 100644 index 00000000..c9d3bb65 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/activity.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-engines-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-engines-fill.svg new file mode 100644 index 00000000..a79a83e5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-engines-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-engines.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-engines.svg new file mode 100644 index 00000000..b49f2414 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-engines.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-fill.svg new file mode 100644 index 00000000..0d84afcc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane.svg new file mode 100644 index 00000000..90cea15f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/airplane.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/alarm-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/alarm-fill.svg new file mode 100644 index 00000000..6d50427d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/alarm-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/alarm.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/alarm.svg new file mode 100644 index 00000000..e45b01ae --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/alarm.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/alexa.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/alexa.svg new file mode 100644 index 00000000..42639938 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/alexa.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/align-bottom.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-bottom.svg new file mode 100644 index 00000000..02a8534d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-bottom.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/align-center.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-center.svg new file mode 100644 index 00000000..9edc0dca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-center.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/align-end.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-end.svg new file mode 100644 index 00000000..a8282591 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-end.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/align-middle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-middle.svg new file mode 100644 index 00000000..552515e2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-middle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/align-start.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-start.svg new file mode 100644 index 00000000..d3f1a531 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-start.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/align-top.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-top.svg new file mode 100644 index 00000000..fbae04db --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/align-top.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/alipay.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/alipay.svg new file mode 100644 index 00000000..c8eaaae7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/alipay.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/alphabet-uppercase.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/alphabet-uppercase.svg new file mode 100644 index 00000000..a7f55ffd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/alphabet-uppercase.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/alphabet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/alphabet.svg new file mode 100644 index 00000000..667a14ae --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/alphabet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/alt.svg new file mode 100644 index 00000000..cd136689 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/amazon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/amazon.svg new file mode 100644 index 00000000..d2d9618a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/amazon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/amd.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/amd.svg new file mode 100644 index 00000000..35bc7e41 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/amd.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/android.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/android.svg new file mode 100644 index 00000000..81f9d2bd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/android.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/android2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/android2.svg new file mode 100644 index 00000000..16d52154 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/android2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/anthropic.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/anthropic.svg new file mode 100644 index 00000000..4a2df0df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/anthropic.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/app-indicator.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/app-indicator.svg new file mode 100644 index 00000000..b720a400 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/app-indicator.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/app.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/app.svg new file mode 100644 index 00000000..597cca3b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/app.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/apple-music.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/apple-music.svg new file mode 100644 index 00000000..28f3c582 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/apple-music.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/apple.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/apple.svg new file mode 100644 index 00000000..a2acef2b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/apple.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/archive-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/archive-fill.svg new file mode 100644 index 00000000..85ea9e7b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/archive-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/archive.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/archive.svg new file mode 100644 index 00000000..06c03fec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/archive.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-down.svg new file mode 100644 index 00000000..e6ab5a39 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-left.svg new file mode 100644 index 00000000..e46a840f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-right.svg new file mode 100644 index 00000000..abd788c2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-up.svg new file mode 100644 index 00000000..c1c8dece --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-90deg-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-down.svg new file mode 100644 index 00000000..77e8a322 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-left.svg new file mode 100644 index 00000000..7d9c376c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-right.svg new file mode 100644 index 00000000..a1f8b5f1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-up.svg new file mode 100644 index 00000000..af49eee0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-bar-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-clockwise.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-clockwise.svg new file mode 100644 index 00000000..d191029a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-clockwise.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-counterclockwise.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-counterclockwise.svg new file mode 100644 index 00000000..2f1df604 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-counterclockwise.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-circle-fill.svg new file mode 100644 index 00000000..4bee2fd3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-circle.svg new file mode 100644 index 00000000..ed256319 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-circle-fill.svg new file mode 100644 index 00000000..fd7d7501 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-circle.svg new file mode 100644 index 00000000..c2ea60a9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-square-fill.svg new file mode 100644 index 00000000..135695e4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-square.svg new file mode 100644 index 00000000..5f292e48 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left.svg new file mode 100644 index 00000000..b1b7ad1f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-circle-fill.svg new file mode 100644 index 00000000..2a19ac4b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-circle.svg new file mode 100644 index 00000000..21dd81ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-square-fill.svg new file mode 100644 index 00000000..40109aa0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-square.svg new file mode 100644 index 00000000..e1449658 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right.svg new file mode 100644 index 00000000..0c4ca1a0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-short.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-short.svg new file mode 100644 index 00000000..214c54d4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-short.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-square-fill.svg new file mode 100644 index 00000000..42dfed3b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-square.svg new file mode 100644 index 00000000..d33f1b80 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-up.svg new file mode 100644 index 00000000..46578dfd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down.svg new file mode 100644 index 00000000..fa3a1ff2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-circle-fill.svg new file mode 100644 index 00000000..c550c553 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-circle.svg new file mode 100644 index 00000000..4e4d71cb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-right.svg new file mode 100644 index 00000000..25eba34e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-short.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-short.svg new file mode 100644 index 00000000..1adfaf29 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-short.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-square-fill.svg new file mode 100644 index 00000000..d8830057 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-square.svg new file mode 100644 index 00000000..a0df7050 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left.svg new file mode 100644 index 00000000..3599fe3a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-repeat.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-repeat.svg new file mode 100644 index 00000000..d448df7e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-repeat.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-return-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-return-left.svg new file mode 100644 index 00000000..b058ffbe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-return-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-return-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-return-right.svg new file mode 100644 index 00000000..5ad5ff17 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-return-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-circle-fill.svg new file mode 100644 index 00000000..cec28527 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-circle.svg new file mode 100644 index 00000000..7b3271a2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-short.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-short.svg new file mode 100644 index 00000000..c068ec02 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-short.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-square-fill.svg new file mode 100644 index 00000000..99e1ec42 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-square.svg new file mode 100644 index 00000000..0eafc08c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right.svg new file mode 100644 index 00000000..2a1a0514 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-through-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-through-heart-fill.svg new file mode 100644 index 00000000..18d576ce --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-through-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-through-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-through-heart.svg new file mode 100644 index 00000000..27fdbb74 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-through-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-circle-fill.svg new file mode 100644 index 00000000..833888df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-circle.svg new file mode 100644 index 00000000..9aef366d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-circle-fill.svg new file mode 100644 index 00000000..b5065a38 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-circle.svg new file mode 100644 index 00000000..dd0fdfa8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-square-fill.svg new file mode 100644 index 00000000..75f471c0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-square.svg new file mode 100644 index 00000000..56fbb1e5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left.svg new file mode 100644 index 00000000..8b1704e6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-circle-fill.svg new file mode 100644 index 00000000..7c191562 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-circle.svg new file mode 100644 index 00000000..381ab1de --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-square-fill.svg new file mode 100644 index 00000000..a6fc9ae7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-square.svg new file mode 100644 index 00000000..c54d2321 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right.svg new file mode 100644 index 00000000..45504520 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-short.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-short.svg new file mode 100644 index 00000000..09387cb7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-short.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-square-fill.svg new file mode 100644 index 00000000..5cad3c67 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-square.svg new file mode 100644 index 00000000..0329da58 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up.svg new file mode 100644 index 00000000..20033f9d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrow-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-angle-contract.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-angle-contract.svg new file mode 100644 index 00000000..7828deff --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-angle-contract.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-angle-expand.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-angle-expand.svg new file mode 100644 index 00000000..aae25f45 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-angle-expand.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-collapse-vertical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-collapse-vertical.svg new file mode 100644 index 00000000..5da861fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-collapse-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-collapse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-collapse.svg new file mode 100644 index 00000000..a4b7c648 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-collapse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-expand-vertical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-expand-vertical.svg new file mode 100644 index 00000000..13b8db29 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-expand-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-expand.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-expand.svg new file mode 100644 index 00000000..7ee3c4a8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-expand.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-fullscreen.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-fullscreen.svg new file mode 100644 index 00000000..04b08df5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-fullscreen.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-move.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-move.svg new file mode 100644 index 00000000..3783f04b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-move.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-vertical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-vertical.svg new file mode 100644 index 00000000..6c3386a8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows.svg new file mode 100644 index 00000000..12e56492 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/arrows.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/aspect-ratio-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/aspect-ratio-fill.svg new file mode 100644 index 00000000..47c33a72 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/aspect-ratio-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/aspect-ratio.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/aspect-ratio.svg new file mode 100644 index 00000000..8cb89876 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/aspect-ratio.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/asterisk.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/asterisk.svg new file mode 100644 index 00000000..408c80a6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/asterisk.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/at.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/at.svg new file mode 100644 index 00000000..73d85964 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/at.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/award-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/award-fill.svg new file mode 100644 index 00000000..7c484a69 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/award-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/award.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/award.svg new file mode 100644 index 00000000..f24db7b0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/award.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/back.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/back.svg new file mode 100644 index 00000000..78333a7b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/back.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack-fill.svg new file mode 100644 index 00000000..e002e853 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack.svg new file mode 100644 index 00000000..377011a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack2-fill.svg new file mode 100644 index 00000000..f97c5498 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack2.svg new file mode 100644 index 00000000..51ca845c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack2.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack3-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack3-fill.svg new file mode 100644 index 00000000..8eead8d8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack3-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack3.svg new file mode 100644 index 00000000..7debe2d1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack4-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack4-fill.svg new file mode 100644 index 00000000..e8473134 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack4-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack4.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack4.svg new file mode 100644 index 00000000..355923f5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backpack4.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-fill.svg new file mode 100644 index 00000000..fe14f289 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-reverse-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-reverse-fill.svg new file mode 100644 index 00000000..bdfaf30b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-reverse-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-reverse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-reverse.svg new file mode 100644 index 00000000..7745329e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace-reverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace.svg new file mode 100644 index 00000000..987aaa1b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/backspace.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-3d-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-3d-fill.svg new file mode 100644 index 00000000..bdf92e92 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-3d-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-3d.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-3d.svg new file mode 100644 index 00000000..cfeec162 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-3d.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-4k-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-4k-fill.svg new file mode 100644 index 00000000..920101b0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-4k-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-4k.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-4k.svg new file mode 100644 index 00000000..35d76a86 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-4k.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-8k-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-8k-fill.svg new file mode 100644 index 00000000..0e065416 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-8k-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-8k.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-8k.svg new file mode 100644 index 00000000..63798a39 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-8k.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ad-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ad-fill.svg new file mode 100644 index 00000000..34113ed2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ad-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ad.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ad.svg new file mode 100644 index 00000000..0cf2533c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ad.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ar-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ar-fill.svg new file mode 100644 index 00000000..38371125 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ar-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ar.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ar.svg new file mode 100644 index 00000000..c0344974 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-ar.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-cc-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-cc-fill.svg new file mode 100644 index 00000000..4676e2a7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-cc-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-cc.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-cc.svg new file mode 100644 index 00000000..35459b94 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-cc.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-hd-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-hd-fill.svg new file mode 100644 index 00000000..ef2773e6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-hd-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-hd.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-hd.svg new file mode 100644 index 00000000..3fb7c774 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-hd.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-sd-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-sd-fill.svg new file mode 100644 index 00000000..f1fda89e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-sd-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-sd.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-sd.svg new file mode 100644 index 00000000..3993e401 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-sd.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-tm-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-tm-fill.svg new file mode 100644 index 00000000..d9bbd656 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-tm-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-tm.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-tm.svg new file mode 100644 index 00000000..5c0b6d8b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-tm.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vo-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vo-fill.svg new file mode 100644 index 00000000..90be502a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vo-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vo.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vo.svg new file mode 100644 index 00000000..5082ed7d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vo.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vr-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vr-fill.svg new file mode 100644 index 00000000..edae16f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vr-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vr.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vr.svg new file mode 100644 index 00000000..814e5721 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-vr.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-wc-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-wc-fill.svg new file mode 100644 index 00000000..83b8367b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-wc-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-wc.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-wc.svg new file mode 100644 index 00000000..7b16cf33 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/badge-wc.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-check-fill.svg new file mode 100644 index 00000000..e09113e8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-check.svg new file mode 100644 index 00000000..7f031c61 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-dash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-dash-fill.svg new file mode 100644 index 00000000..118994ba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-dash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-dash.svg new file mode 100644 index 00000000..c857b827 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-fill.svg new file mode 100644 index 00000000..04215d20 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-heart-fill.svg new file mode 100644 index 00000000..ef00bbf6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-heart.svg new file mode 100644 index 00000000..3037e6d2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-plus-fill.svg new file mode 100644 index 00000000..b438daeb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-plus.svg new file mode 100644 index 00000000..545950b5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-x-fill.svg new file mode 100644 index 00000000..07eea18a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-x.svg new file mode 100644 index 00000000..1a2436d6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bag.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag.svg new file mode 100644 index 00000000..8e7537a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bag.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-fill.svg new file mode 100644 index 00000000..c8e82edd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-heart-fill.svg new file mode 100644 index 00000000..9edb3d7f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-heart.svg new file mode 100644 index 00000000..af91c689 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon.svg new file mode 100644 index 00000000..79c64138 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/balloon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ban-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ban-fill.svg new file mode 100644 index 00000000..f7435bde --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ban-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ban.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ban.svg new file mode 100644 index 00000000..87514d9b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ban.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bandaid-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bandaid-fill.svg new file mode 100644 index 00000000..df13e1f1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bandaid-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bandaid.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bandaid.svg new file mode 100644 index 00000000..77f805e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bandaid.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bank.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bank.svg new file mode 100644 index 00000000..c3689206 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bank.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bank2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bank2.svg new file mode 100644 index 00000000..94ab825f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bank2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-fill.svg new file mode 100644 index 00000000..a841929c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-line-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-line-fill.svg new file mode 100644 index 00000000..37efe41e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-line-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-line.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-line.svg new file mode 100644 index 00000000..ee4a972b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-line.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-steps.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-steps.svg new file mode 100644 index 00000000..654aa0d9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart-steps.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart.svg new file mode 100644 index 00000000..f4f8fda7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bar-chart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/basket-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket-fill.svg new file mode 100644 index 00000000..120ddf39 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/basket.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket.svg new file mode 100644 index 00000000..db15a997 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/basket2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket2-fill.svg new file mode 100644 index 00000000..7620f978 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/basket2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket2.svg new file mode 100644 index 00000000..4a511b38 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/basket3-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket3-fill.svg new file mode 100644 index 00000000..3d127bf0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/basket3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket3.svg new file mode 100644 index 00000000..43faea37 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/basket3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-charging.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-charging.svg new file mode 100644 index 00000000..c1240094 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-charging.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-full.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-full.svg new file mode 100644 index 00000000..33dbca9b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-full.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-half.svg new file mode 100644 index 00000000..2299b6ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-half.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-low.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-low.svg new file mode 100644 index 00000000..a550a394 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery-low.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/battery.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery.svg new file mode 100644 index 00000000..db8b6662 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/battery.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/beaker-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/beaker-fill.svg new file mode 100644 index 00000000..87f1e8aa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/beaker-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/beaker.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/beaker.svg new file mode 100644 index 00000000..b9458de0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/beaker.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/behance.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/behance.svg new file mode 100644 index 00000000..a5fe8738 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/behance.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-fill.svg new file mode 100644 index 00000000..d8ed0a14 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-slash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-slash-fill.svg new file mode 100644 index 00000000..b0c21eaf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-slash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-slash.svg new file mode 100644 index 00000000..4f9a4f68 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bell-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bell.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bell.svg new file mode 100644 index 00000000..9645d67d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bell.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bezier.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bezier.svg new file mode 100644 index 00000000..c2f2fadb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bezier.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bezier2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bezier2.svg new file mode 100644 index 00000000..fe553536 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bezier2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bicycle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bicycle.svg new file mode 100644 index 00000000..2a1794d3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bicycle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bing.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bing.svg new file mode 100644 index 00000000..a6f4e57a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bing.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/binoculars-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/binoculars-fill.svg new file mode 100644 index 00000000..a4cd4b6c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/binoculars-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/binoculars.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/binoculars.svg new file mode 100644 index 00000000..aea3ce61 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/binoculars.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/blockquote-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/blockquote-left.svg new file mode 100644 index 00000000..2b035d70 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/blockquote-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/blockquote-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/blockquote-right.svg new file mode 100644 index 00000000..b7ba5544 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/blockquote-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bluesky.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bluesky.svg new file mode 100644 index 00000000..ecae00fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bluesky.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bluetooth.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bluetooth.svg new file mode 100644 index 00000000..d72a384c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bluetooth.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/body-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/body-text.svg new file mode 100644 index 00000000..c2e9072b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/body-text.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/book-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/book-fill.svg new file mode 100644 index 00000000..5ceac950 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/book-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/book-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/book-half.svg new file mode 100644 index 00000000..f5fc89b6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/book-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/book.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/book.svg new file mode 100644 index 00000000..e8ad0a48 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/book.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-check-fill.svg new file mode 100644 index 00000000..b2062307 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-check.svg new file mode 100644 index 00000000..15dc47ae --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-dash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-dash-fill.svg new file mode 100644 index 00000000..c7cee4d2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-dash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-dash.svg new file mode 100644 index 00000000..34d50d78 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-fill.svg new file mode 100644 index 00000000..ff293b70 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-heart-fill.svg new file mode 100644 index 00000000..e4e0f368 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-heart.svg new file mode 100644 index 00000000..d8a05461 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-plus-fill.svg new file mode 100644 index 00000000..286983f4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-plus.svg new file mode 100644 index 00000000..51024239 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-star-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-star-fill.svg new file mode 100644 index 00000000..c6469d67 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-star-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-star.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-star.svg new file mode 100644 index 00000000..4c53fddb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-star.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-x-fill.svg new file mode 100644 index 00000000..3b7c86c0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-x.svg new file mode 100644 index 00000000..edb6cc27 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark.svg new file mode 100644 index 00000000..3fb22877 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmarks-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmarks-fill.svg new file mode 100644 index 00000000..3ee1ebfb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmarks-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmarks.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmarks.svg new file mode 100644 index 00000000..3db26993 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookmarks.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bookshelf.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookshelf.svg new file mode 100644 index 00000000..027a182c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bookshelf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/boombox-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/boombox-fill.svg new file mode 100644 index 00000000..c22f41f7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/boombox-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/boombox.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/boombox.svg new file mode 100644 index 00000000..9341caeb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/boombox.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-fill.svg new file mode 100644 index 00000000..117a3f3d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.css b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.css new file mode 100644 index 00000000..5f7ae28e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.css @@ -0,0 +1,2106 @@ +/*! + * Bootstrap Icons v1.13.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */ + +@font-face { + font-display: block; + font-family: "bootstrap-icons"; + src: url("./fonts/bootstrap-icons.woff2?e34853135f9e39acf64315236852cd5a") format("woff2"), +url("./fonts/bootstrap-icons.woff?e34853135f9e39acf64315236852cd5a") format("woff"); +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: bootstrap-icons !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.bi-123::before { content: "\f67f"; } +.bi-alarm-fill::before { content: "\f101"; } +.bi-alarm::before { content: "\f102"; } +.bi-align-bottom::before { content: "\f103"; } +.bi-align-center::before { content: "\f104"; } +.bi-align-end::before { content: "\f105"; } +.bi-align-middle::before { content: "\f106"; } +.bi-align-start::before { content: "\f107"; } +.bi-align-top::before { content: "\f108"; } +.bi-alt::before { content: "\f109"; } +.bi-app-indicator::before { content: "\f10a"; } +.bi-app::before { content: "\f10b"; } +.bi-archive-fill::before { content: "\f10c"; } +.bi-archive::before { content: "\f10d"; } +.bi-arrow-90deg-down::before { content: "\f10e"; } +.bi-arrow-90deg-left::before { content: "\f10f"; } +.bi-arrow-90deg-right::before { content: "\f110"; } +.bi-arrow-90deg-up::before { content: "\f111"; } +.bi-arrow-bar-down::before { content: "\f112"; } +.bi-arrow-bar-left::before { content: "\f113"; } +.bi-arrow-bar-right::before { content: "\f114"; } +.bi-arrow-bar-up::before { content: "\f115"; } +.bi-arrow-clockwise::before { content: "\f116"; } +.bi-arrow-counterclockwise::before { content: "\f117"; } +.bi-arrow-down-circle-fill::before { content: "\f118"; } +.bi-arrow-down-circle::before { content: "\f119"; } +.bi-arrow-down-left-circle-fill::before { content: "\f11a"; } +.bi-arrow-down-left-circle::before { content: "\f11b"; } +.bi-arrow-down-left-square-fill::before { content: "\f11c"; } +.bi-arrow-down-left-square::before { content: "\f11d"; } +.bi-arrow-down-left::before { content: "\f11e"; } +.bi-arrow-down-right-circle-fill::before { content: "\f11f"; } +.bi-arrow-down-right-circle::before { content: "\f120"; } +.bi-arrow-down-right-square-fill::before { content: "\f121"; } +.bi-arrow-down-right-square::before { content: "\f122"; } +.bi-arrow-down-right::before { content: "\f123"; } +.bi-arrow-down-short::before { content: "\f124"; } +.bi-arrow-down-square-fill::before { content: "\f125"; } +.bi-arrow-down-square::before { content: "\f126"; } +.bi-arrow-down-up::before { content: "\f127"; } +.bi-arrow-down::before { content: "\f128"; } +.bi-arrow-left-circle-fill::before { content: "\f129"; } +.bi-arrow-left-circle::before { content: "\f12a"; } +.bi-arrow-left-right::before { content: "\f12b"; } +.bi-arrow-left-short::before { content: "\f12c"; } +.bi-arrow-left-square-fill::before { content: "\f12d"; } +.bi-arrow-left-square::before { content: "\f12e"; } +.bi-arrow-left::before { content: "\f12f"; } +.bi-arrow-repeat::before { content: "\f130"; } +.bi-arrow-return-left::before { content: "\f131"; } +.bi-arrow-return-right::before { content: "\f132"; } +.bi-arrow-right-circle-fill::before { content: "\f133"; } +.bi-arrow-right-circle::before { content: "\f134"; } +.bi-arrow-right-short::before { content: "\f135"; } +.bi-arrow-right-square-fill::before { content: "\f136"; } +.bi-arrow-right-square::before { content: "\f137"; } +.bi-arrow-right::before { content: "\f138"; } +.bi-arrow-up-circle-fill::before { content: "\f139"; } +.bi-arrow-up-circle::before { content: "\f13a"; } +.bi-arrow-up-left-circle-fill::before { content: "\f13b"; } +.bi-arrow-up-left-circle::before { content: "\f13c"; } +.bi-arrow-up-left-square-fill::before { content: "\f13d"; } +.bi-arrow-up-left-square::before { content: "\f13e"; } +.bi-arrow-up-left::before { content: "\f13f"; } +.bi-arrow-up-right-circle-fill::before { content: "\f140"; } +.bi-arrow-up-right-circle::before { content: "\f141"; } +.bi-arrow-up-right-square-fill::before { content: "\f142"; } +.bi-arrow-up-right-square::before { content: "\f143"; } +.bi-arrow-up-right::before { content: "\f144"; } +.bi-arrow-up-short::before { content: "\f145"; } +.bi-arrow-up-square-fill::before { content: "\f146"; } +.bi-arrow-up-square::before { content: "\f147"; } +.bi-arrow-up::before { content: "\f148"; } +.bi-arrows-angle-contract::before { content: "\f149"; } +.bi-arrows-angle-expand::before { content: "\f14a"; } +.bi-arrows-collapse::before { content: "\f14b"; } +.bi-arrows-expand::before { content: "\f14c"; } +.bi-arrows-fullscreen::before { content: "\f14d"; } +.bi-arrows-move::before { content: "\f14e"; } +.bi-aspect-ratio-fill::before { content: "\f14f"; } +.bi-aspect-ratio::before { content: "\f150"; } +.bi-asterisk::before { content: "\f151"; } +.bi-at::before { content: "\f152"; } +.bi-award-fill::before { content: "\f153"; } +.bi-award::before { content: "\f154"; } +.bi-back::before { content: "\f155"; } +.bi-backspace-fill::before { content: "\f156"; } +.bi-backspace-reverse-fill::before { content: "\f157"; } +.bi-backspace-reverse::before { content: "\f158"; } +.bi-backspace::before { content: "\f159"; } +.bi-badge-3d-fill::before { content: "\f15a"; } +.bi-badge-3d::before { content: "\f15b"; } +.bi-badge-4k-fill::before { content: "\f15c"; } +.bi-badge-4k::before { content: "\f15d"; } +.bi-badge-8k-fill::before { content: "\f15e"; } +.bi-badge-8k::before { content: "\f15f"; } +.bi-badge-ad-fill::before { content: "\f160"; } +.bi-badge-ad::before { content: "\f161"; } +.bi-badge-ar-fill::before { content: "\f162"; } +.bi-badge-ar::before { content: "\f163"; } +.bi-badge-cc-fill::before { content: "\f164"; } +.bi-badge-cc::before { content: "\f165"; } +.bi-badge-hd-fill::before { content: "\f166"; } +.bi-badge-hd::before { content: "\f167"; } +.bi-badge-tm-fill::before { content: "\f168"; } +.bi-badge-tm::before { content: "\f169"; } +.bi-badge-vo-fill::before { content: "\f16a"; } +.bi-badge-vo::before { content: "\f16b"; } +.bi-badge-vr-fill::before { content: "\f16c"; } +.bi-badge-vr::before { content: "\f16d"; } +.bi-badge-wc-fill::before { content: "\f16e"; } +.bi-badge-wc::before { content: "\f16f"; } +.bi-bag-check-fill::before { content: "\f170"; } +.bi-bag-check::before { content: "\f171"; } +.bi-bag-dash-fill::before { content: "\f172"; } +.bi-bag-dash::before { content: "\f173"; } +.bi-bag-fill::before { content: "\f174"; } +.bi-bag-plus-fill::before { content: "\f175"; } +.bi-bag-plus::before { content: "\f176"; } +.bi-bag-x-fill::before { content: "\f177"; } +.bi-bag-x::before { content: "\f178"; } +.bi-bag::before { content: "\f179"; } +.bi-bar-chart-fill::before { content: "\f17a"; } +.bi-bar-chart-line-fill::before { content: "\f17b"; } +.bi-bar-chart-line::before { content: "\f17c"; } +.bi-bar-chart-steps::before { content: "\f17d"; } +.bi-bar-chart::before { content: "\f17e"; } +.bi-basket-fill::before { content: "\f17f"; } +.bi-basket::before { content: "\f180"; } +.bi-basket2-fill::before { content: "\f181"; } +.bi-basket2::before { content: "\f182"; } +.bi-basket3-fill::before { content: "\f183"; } +.bi-basket3::before { content: "\f184"; } +.bi-battery-charging::before { content: "\f185"; } +.bi-battery-full::before { content: "\f186"; } +.bi-battery-half::before { content: "\f187"; } +.bi-battery::before { content: "\f188"; } +.bi-bell-fill::before { content: "\f189"; } +.bi-bell::before { content: "\f18a"; } +.bi-bezier::before { content: "\f18b"; } +.bi-bezier2::before { content: "\f18c"; } +.bi-bicycle::before { content: "\f18d"; } +.bi-binoculars-fill::before { content: "\f18e"; } +.bi-binoculars::before { content: "\f18f"; } +.bi-blockquote-left::before { content: "\f190"; } +.bi-blockquote-right::before { content: "\f191"; } +.bi-book-fill::before { content: "\f192"; } +.bi-book-half::before { content: "\f193"; } +.bi-book::before { content: "\f194"; } +.bi-bookmark-check-fill::before { content: "\f195"; } +.bi-bookmark-check::before { content: "\f196"; } +.bi-bookmark-dash-fill::before { content: "\f197"; } +.bi-bookmark-dash::before { content: "\f198"; } +.bi-bookmark-fill::before { content: "\f199"; } +.bi-bookmark-heart-fill::before { content: "\f19a"; } +.bi-bookmark-heart::before { content: "\f19b"; } +.bi-bookmark-plus-fill::before { content: "\f19c"; } +.bi-bookmark-plus::before { content: "\f19d"; } +.bi-bookmark-star-fill::before { content: "\f19e"; } +.bi-bookmark-star::before { content: "\f19f"; } +.bi-bookmark-x-fill::before { content: "\f1a0"; } +.bi-bookmark-x::before { content: "\f1a1"; } +.bi-bookmark::before { content: "\f1a2"; } +.bi-bookmarks-fill::before { content: "\f1a3"; } +.bi-bookmarks::before { content: "\f1a4"; } +.bi-bookshelf::before { content: "\f1a5"; } +.bi-bootstrap-fill::before { content: "\f1a6"; } +.bi-bootstrap-reboot::before { content: "\f1a7"; } +.bi-bootstrap::before { content: "\f1a8"; } +.bi-border-all::before { content: "\f1a9"; } +.bi-border-bottom::before { content: "\f1aa"; } +.bi-border-center::before { content: "\f1ab"; } +.bi-border-inner::before { content: "\f1ac"; } +.bi-border-left::before { content: "\f1ad"; } +.bi-border-middle::before { content: "\f1ae"; } +.bi-border-outer::before { content: "\f1af"; } +.bi-border-right::before { content: "\f1b0"; } +.bi-border-style::before { content: "\f1b1"; } +.bi-border-top::before { content: "\f1b2"; } +.bi-border-width::before { content: "\f1b3"; } +.bi-border::before { content: "\f1b4"; } +.bi-bounding-box-circles::before { content: "\f1b5"; } +.bi-bounding-box::before { content: "\f1b6"; } +.bi-box-arrow-down-left::before { content: "\f1b7"; } +.bi-box-arrow-down-right::before { content: "\f1b8"; } +.bi-box-arrow-down::before { content: "\f1b9"; } +.bi-box-arrow-in-down-left::before { content: "\f1ba"; } +.bi-box-arrow-in-down-right::before { content: "\f1bb"; } +.bi-box-arrow-in-down::before { content: "\f1bc"; } +.bi-box-arrow-in-left::before { content: "\f1bd"; } +.bi-box-arrow-in-right::before { content: "\f1be"; } +.bi-box-arrow-in-up-left::before { content: "\f1bf"; } +.bi-box-arrow-in-up-right::before { content: "\f1c0"; } +.bi-box-arrow-in-up::before { content: "\f1c1"; } +.bi-box-arrow-left::before { content: "\f1c2"; } +.bi-box-arrow-right::before { content: "\f1c3"; } +.bi-box-arrow-up-left::before { content: "\f1c4"; } +.bi-box-arrow-up-right::before { content: "\f1c5"; } +.bi-box-arrow-up::before { content: "\f1c6"; } +.bi-box-seam::before { content: "\f1c7"; } +.bi-box::before { content: "\f1c8"; } +.bi-braces::before { content: "\f1c9"; } +.bi-bricks::before { content: "\f1ca"; } +.bi-briefcase-fill::before { content: "\f1cb"; } +.bi-briefcase::before { content: "\f1cc"; } +.bi-brightness-alt-high-fill::before { content: "\f1cd"; } +.bi-brightness-alt-high::before { content: "\f1ce"; } +.bi-brightness-alt-low-fill::before { content: "\f1cf"; } +.bi-brightness-alt-low::before { content: "\f1d0"; } +.bi-brightness-high-fill::before { content: "\f1d1"; } +.bi-brightness-high::before { content: "\f1d2"; } +.bi-brightness-low-fill::before { content: "\f1d3"; } +.bi-brightness-low::before { content: "\f1d4"; } +.bi-broadcast-pin::before { content: "\f1d5"; } +.bi-broadcast::before { content: "\f1d6"; } +.bi-brush-fill::before { content: "\f1d7"; } +.bi-brush::before { content: "\f1d8"; } +.bi-bucket-fill::before { content: "\f1d9"; } +.bi-bucket::before { content: "\f1da"; } +.bi-bug-fill::before { content: "\f1db"; } +.bi-bug::before { content: "\f1dc"; } +.bi-building::before { content: "\f1dd"; } +.bi-bullseye::before { content: "\f1de"; } +.bi-calculator-fill::before { content: "\f1df"; } +.bi-calculator::before { content: "\f1e0"; } +.bi-calendar-check-fill::before { content: "\f1e1"; } +.bi-calendar-check::before { content: "\f1e2"; } +.bi-calendar-date-fill::before { content: "\f1e3"; } +.bi-calendar-date::before { content: "\f1e4"; } +.bi-calendar-day-fill::before { content: "\f1e5"; } +.bi-calendar-day::before { content: "\f1e6"; } +.bi-calendar-event-fill::before { content: "\f1e7"; } +.bi-calendar-event::before { content: "\f1e8"; } +.bi-calendar-fill::before { content: "\f1e9"; } +.bi-calendar-minus-fill::before { content: "\f1ea"; } +.bi-calendar-minus::before { content: "\f1eb"; } +.bi-calendar-month-fill::before { content: "\f1ec"; } +.bi-calendar-month::before { content: "\f1ed"; } +.bi-calendar-plus-fill::before { content: "\f1ee"; } +.bi-calendar-plus::before { content: "\f1ef"; } +.bi-calendar-range-fill::before { content: "\f1f0"; } +.bi-calendar-range::before { content: "\f1f1"; } +.bi-calendar-week-fill::before { content: "\f1f2"; } +.bi-calendar-week::before { content: "\f1f3"; } +.bi-calendar-x-fill::before { content: "\f1f4"; } +.bi-calendar-x::before { content: "\f1f5"; } +.bi-calendar::before { content: "\f1f6"; } +.bi-calendar2-check-fill::before { content: "\f1f7"; } +.bi-calendar2-check::before { content: "\f1f8"; } +.bi-calendar2-date-fill::before { content: "\f1f9"; } +.bi-calendar2-date::before { content: "\f1fa"; } +.bi-calendar2-day-fill::before { content: "\f1fb"; } +.bi-calendar2-day::before { content: "\f1fc"; } +.bi-calendar2-event-fill::before { content: "\f1fd"; } +.bi-calendar2-event::before { content: "\f1fe"; } +.bi-calendar2-fill::before { content: "\f1ff"; } +.bi-calendar2-minus-fill::before { content: "\f200"; } +.bi-calendar2-minus::before { content: "\f201"; } +.bi-calendar2-month-fill::before { content: "\f202"; } +.bi-calendar2-month::before { content: "\f203"; } +.bi-calendar2-plus-fill::before { content: "\f204"; } +.bi-calendar2-plus::before { content: "\f205"; } +.bi-calendar2-range-fill::before { content: "\f206"; } +.bi-calendar2-range::before { content: "\f207"; } +.bi-calendar2-week-fill::before { content: "\f208"; } +.bi-calendar2-week::before { content: "\f209"; } +.bi-calendar2-x-fill::before { content: "\f20a"; } +.bi-calendar2-x::before { content: "\f20b"; } +.bi-calendar2::before { content: "\f20c"; } +.bi-calendar3-event-fill::before { content: "\f20d"; } +.bi-calendar3-event::before { content: "\f20e"; } +.bi-calendar3-fill::before { content: "\f20f"; } +.bi-calendar3-range-fill::before { content: "\f210"; } +.bi-calendar3-range::before { content: "\f211"; } +.bi-calendar3-week-fill::before { content: "\f212"; } +.bi-calendar3-week::before { content: "\f213"; } +.bi-calendar3::before { content: "\f214"; } +.bi-calendar4-event::before { content: "\f215"; } +.bi-calendar4-range::before { content: "\f216"; } +.bi-calendar4-week::before { content: "\f217"; } +.bi-calendar4::before { content: "\f218"; } +.bi-camera-fill::before { content: "\f219"; } +.bi-camera-reels-fill::before { content: "\f21a"; } +.bi-camera-reels::before { content: "\f21b"; } +.bi-camera-video-fill::before { content: "\f21c"; } +.bi-camera-video-off-fill::before { content: "\f21d"; } +.bi-camera-video-off::before { content: "\f21e"; } +.bi-camera-video::before { content: "\f21f"; } +.bi-camera::before { content: "\f220"; } +.bi-camera2::before { content: "\f221"; } +.bi-capslock-fill::before { content: "\f222"; } +.bi-capslock::before { content: "\f223"; } +.bi-card-checklist::before { content: "\f224"; } +.bi-card-heading::before { content: "\f225"; } +.bi-card-image::before { content: "\f226"; } +.bi-card-list::before { content: "\f227"; } +.bi-card-text::before { content: "\f228"; } +.bi-caret-down-fill::before { content: "\f229"; } +.bi-caret-down-square-fill::before { content: "\f22a"; } +.bi-caret-down-square::before { content: "\f22b"; } +.bi-caret-down::before { content: "\f22c"; } +.bi-caret-left-fill::before { content: "\f22d"; } +.bi-caret-left-square-fill::before { content: "\f22e"; } +.bi-caret-left-square::before { content: "\f22f"; } +.bi-caret-left::before { content: "\f230"; } +.bi-caret-right-fill::before { content: "\f231"; } +.bi-caret-right-square-fill::before { content: "\f232"; } +.bi-caret-right-square::before { content: "\f233"; } +.bi-caret-right::before { content: "\f234"; } +.bi-caret-up-fill::before { content: "\f235"; } +.bi-caret-up-square-fill::before { content: "\f236"; } +.bi-caret-up-square::before { content: "\f237"; } +.bi-caret-up::before { content: "\f238"; } +.bi-cart-check-fill::before { content: "\f239"; } +.bi-cart-check::before { content: "\f23a"; } +.bi-cart-dash-fill::before { content: "\f23b"; } +.bi-cart-dash::before { content: "\f23c"; } +.bi-cart-fill::before { content: "\f23d"; } +.bi-cart-plus-fill::before { content: "\f23e"; } +.bi-cart-plus::before { content: "\f23f"; } +.bi-cart-x-fill::before { content: "\f240"; } +.bi-cart-x::before { content: "\f241"; } +.bi-cart::before { content: "\f242"; } +.bi-cart2::before { content: "\f243"; } +.bi-cart3::before { content: "\f244"; } +.bi-cart4::before { content: "\f245"; } +.bi-cash-stack::before { content: "\f246"; } +.bi-cash::before { content: "\f247"; } +.bi-cast::before { content: "\f248"; } +.bi-chat-dots-fill::before { content: "\f249"; } +.bi-chat-dots::before { content: "\f24a"; } +.bi-chat-fill::before { content: "\f24b"; } +.bi-chat-left-dots-fill::before { content: "\f24c"; } +.bi-chat-left-dots::before { content: "\f24d"; } +.bi-chat-left-fill::before { content: "\f24e"; } +.bi-chat-left-quote-fill::before { content: "\f24f"; } +.bi-chat-left-quote::before { content: "\f250"; } +.bi-chat-left-text-fill::before { content: "\f251"; } +.bi-chat-left-text::before { content: "\f252"; } +.bi-chat-left::before { content: "\f253"; } +.bi-chat-quote-fill::before { content: "\f254"; } +.bi-chat-quote::before { content: "\f255"; } +.bi-chat-right-dots-fill::before { content: "\f256"; } +.bi-chat-right-dots::before { content: "\f257"; } +.bi-chat-right-fill::before { content: "\f258"; } +.bi-chat-right-quote-fill::before { content: "\f259"; } +.bi-chat-right-quote::before { content: "\f25a"; } +.bi-chat-right-text-fill::before { content: "\f25b"; } +.bi-chat-right-text::before { content: "\f25c"; } +.bi-chat-right::before { content: "\f25d"; } +.bi-chat-square-dots-fill::before { content: "\f25e"; } +.bi-chat-square-dots::before { content: "\f25f"; } +.bi-chat-square-fill::before { content: "\f260"; } +.bi-chat-square-quote-fill::before { content: "\f261"; } +.bi-chat-square-quote::before { content: "\f262"; } +.bi-chat-square-text-fill::before { content: "\f263"; } +.bi-chat-square-text::before { content: "\f264"; } +.bi-chat-square::before { content: "\f265"; } +.bi-chat-text-fill::before { content: "\f266"; } +.bi-chat-text::before { content: "\f267"; } +.bi-chat::before { content: "\f268"; } +.bi-check-all::before { content: "\f269"; } +.bi-check-circle-fill::before { content: "\f26a"; } +.bi-check-circle::before { content: "\f26b"; } +.bi-check-square-fill::before { content: "\f26c"; } +.bi-check-square::before { content: "\f26d"; } +.bi-check::before { content: "\f26e"; } +.bi-check2-all::before { content: "\f26f"; } +.bi-check2-circle::before { content: "\f270"; } +.bi-check2-square::before { content: "\f271"; } +.bi-check2::before { content: "\f272"; } +.bi-chevron-bar-contract::before { content: "\f273"; } +.bi-chevron-bar-down::before { content: "\f274"; } +.bi-chevron-bar-expand::before { content: "\f275"; } +.bi-chevron-bar-left::before { content: "\f276"; } +.bi-chevron-bar-right::before { content: "\f277"; } +.bi-chevron-bar-up::before { content: "\f278"; } +.bi-chevron-compact-down::before { content: "\f279"; } +.bi-chevron-compact-left::before { content: "\f27a"; } +.bi-chevron-compact-right::before { content: "\f27b"; } +.bi-chevron-compact-up::before { content: "\f27c"; } +.bi-chevron-contract::before { content: "\f27d"; } +.bi-chevron-double-down::before { content: "\f27e"; } +.bi-chevron-double-left::before { content: "\f27f"; } +.bi-chevron-double-right::before { content: "\f280"; } +.bi-chevron-double-up::before { content: "\f281"; } +.bi-chevron-down::before { content: "\f282"; } +.bi-chevron-expand::before { content: "\f283"; } +.bi-chevron-left::before { content: "\f284"; } +.bi-chevron-right::before { content: "\f285"; } +.bi-chevron-up::before { content: "\f286"; } +.bi-circle-fill::before { content: "\f287"; } +.bi-circle-half::before { content: "\f288"; } +.bi-circle-square::before { content: "\f289"; } +.bi-circle::before { content: "\f28a"; } +.bi-clipboard-check::before { content: "\f28b"; } +.bi-clipboard-data::before { content: "\f28c"; } +.bi-clipboard-minus::before { content: "\f28d"; } +.bi-clipboard-plus::before { content: "\f28e"; } +.bi-clipboard-x::before { content: "\f28f"; } +.bi-clipboard::before { content: "\f290"; } +.bi-clock-fill::before { content: "\f291"; } +.bi-clock-history::before { content: "\f292"; } +.bi-clock::before { content: "\f293"; } +.bi-cloud-arrow-down-fill::before { content: "\f294"; } +.bi-cloud-arrow-down::before { content: "\f295"; } +.bi-cloud-arrow-up-fill::before { content: "\f296"; } +.bi-cloud-arrow-up::before { content: "\f297"; } +.bi-cloud-check-fill::before { content: "\f298"; } +.bi-cloud-check::before { content: "\f299"; } +.bi-cloud-download-fill::before { content: "\f29a"; } +.bi-cloud-download::before { content: "\f29b"; } +.bi-cloud-drizzle-fill::before { content: "\f29c"; } +.bi-cloud-drizzle::before { content: "\f29d"; } +.bi-cloud-fill::before { content: "\f29e"; } +.bi-cloud-fog-fill::before { content: "\f29f"; } +.bi-cloud-fog::before { content: "\f2a0"; } +.bi-cloud-fog2-fill::before { content: "\f2a1"; } +.bi-cloud-fog2::before { content: "\f2a2"; } +.bi-cloud-hail-fill::before { content: "\f2a3"; } +.bi-cloud-hail::before { content: "\f2a4"; } +.bi-cloud-haze-fill::before { content: "\f2a6"; } +.bi-cloud-haze::before { content: "\f2a7"; } +.bi-cloud-haze2-fill::before { content: "\f2a8"; } +.bi-cloud-lightning-fill::before { content: "\f2a9"; } +.bi-cloud-lightning-rain-fill::before { content: "\f2aa"; } +.bi-cloud-lightning-rain::before { content: "\f2ab"; } +.bi-cloud-lightning::before { content: "\f2ac"; } +.bi-cloud-minus-fill::before { content: "\f2ad"; } +.bi-cloud-minus::before { content: "\f2ae"; } +.bi-cloud-moon-fill::before { content: "\f2af"; } +.bi-cloud-moon::before { content: "\f2b0"; } +.bi-cloud-plus-fill::before { content: "\f2b1"; } +.bi-cloud-plus::before { content: "\f2b2"; } +.bi-cloud-rain-fill::before { content: "\f2b3"; } +.bi-cloud-rain-heavy-fill::before { content: "\f2b4"; } +.bi-cloud-rain-heavy::before { content: "\f2b5"; } +.bi-cloud-rain::before { content: "\f2b6"; } +.bi-cloud-slash-fill::before { content: "\f2b7"; } +.bi-cloud-slash::before { content: "\f2b8"; } +.bi-cloud-sleet-fill::before { content: "\f2b9"; } +.bi-cloud-sleet::before { content: "\f2ba"; } +.bi-cloud-snow-fill::before { content: "\f2bb"; } +.bi-cloud-snow::before { content: "\f2bc"; } +.bi-cloud-sun-fill::before { content: "\f2bd"; } +.bi-cloud-sun::before { content: "\f2be"; } +.bi-cloud-upload-fill::before { content: "\f2bf"; } +.bi-cloud-upload::before { content: "\f2c0"; } +.bi-cloud::before { content: "\f2c1"; } +.bi-clouds-fill::before { content: "\f2c2"; } +.bi-clouds::before { content: "\f2c3"; } +.bi-cloudy-fill::before { content: "\f2c4"; } +.bi-cloudy::before { content: "\f2c5"; } +.bi-code-slash::before { content: "\f2c6"; } +.bi-code-square::before { content: "\f2c7"; } +.bi-code::before { content: "\f2c8"; } +.bi-collection-fill::before { content: "\f2c9"; } +.bi-collection-play-fill::before { content: "\f2ca"; } +.bi-collection-play::before { content: "\f2cb"; } +.bi-collection::before { content: "\f2cc"; } +.bi-columns-gap::before { content: "\f2cd"; } +.bi-columns::before { content: "\f2ce"; } +.bi-command::before { content: "\f2cf"; } +.bi-compass-fill::before { content: "\f2d0"; } +.bi-compass::before { content: "\f2d1"; } +.bi-cone-striped::before { content: "\f2d2"; } +.bi-cone::before { content: "\f2d3"; } +.bi-controller::before { content: "\f2d4"; } +.bi-cpu-fill::before { content: "\f2d5"; } +.bi-cpu::before { content: "\f2d6"; } +.bi-credit-card-2-back-fill::before { content: "\f2d7"; } +.bi-credit-card-2-back::before { content: "\f2d8"; } +.bi-credit-card-2-front-fill::before { content: "\f2d9"; } +.bi-credit-card-2-front::before { content: "\f2da"; } +.bi-credit-card-fill::before { content: "\f2db"; } +.bi-credit-card::before { content: "\f2dc"; } +.bi-crop::before { content: "\f2dd"; } +.bi-cup-fill::before { content: "\f2de"; } +.bi-cup-straw::before { content: "\f2df"; } +.bi-cup::before { content: "\f2e0"; } +.bi-cursor-fill::before { content: "\f2e1"; } +.bi-cursor-text::before { content: "\f2e2"; } +.bi-cursor::before { content: "\f2e3"; } +.bi-dash-circle-dotted::before { content: "\f2e4"; } +.bi-dash-circle-fill::before { content: "\f2e5"; } +.bi-dash-circle::before { content: "\f2e6"; } +.bi-dash-square-dotted::before { content: "\f2e7"; } +.bi-dash-square-fill::before { content: "\f2e8"; } +.bi-dash-square::before { content: "\f2e9"; } +.bi-dash::before { content: "\f2ea"; } +.bi-diagram-2-fill::before { content: "\f2eb"; } +.bi-diagram-2::before { content: "\f2ec"; } +.bi-diagram-3-fill::before { content: "\f2ed"; } +.bi-diagram-3::before { content: "\f2ee"; } +.bi-diamond-fill::before { content: "\f2ef"; } +.bi-diamond-half::before { content: "\f2f0"; } +.bi-diamond::before { content: "\f2f1"; } +.bi-dice-1-fill::before { content: "\f2f2"; } +.bi-dice-1::before { content: "\f2f3"; } +.bi-dice-2-fill::before { content: "\f2f4"; } +.bi-dice-2::before { content: "\f2f5"; } +.bi-dice-3-fill::before { content: "\f2f6"; } +.bi-dice-3::before { content: "\f2f7"; } +.bi-dice-4-fill::before { content: "\f2f8"; } +.bi-dice-4::before { content: "\f2f9"; } +.bi-dice-5-fill::before { content: "\f2fa"; } +.bi-dice-5::before { content: "\f2fb"; } +.bi-dice-6-fill::before { content: "\f2fc"; } +.bi-dice-6::before { content: "\f2fd"; } +.bi-disc-fill::before { content: "\f2fe"; } +.bi-disc::before { content: "\f2ff"; } +.bi-discord::before { content: "\f300"; } +.bi-display-fill::before { content: "\f301"; } +.bi-display::before { content: "\f302"; } +.bi-distribute-horizontal::before { content: "\f303"; } +.bi-distribute-vertical::before { content: "\f304"; } +.bi-door-closed-fill::before { content: "\f305"; } +.bi-door-closed::before { content: "\f306"; } +.bi-door-open-fill::before { content: "\f307"; } +.bi-door-open::before { content: "\f308"; } +.bi-dot::before { content: "\f309"; } +.bi-download::before { content: "\f30a"; } +.bi-droplet-fill::before { content: "\f30b"; } +.bi-droplet-half::before { content: "\f30c"; } +.bi-droplet::before { content: "\f30d"; } +.bi-earbuds::before { content: "\f30e"; } +.bi-easel-fill::before { content: "\f30f"; } +.bi-easel::before { content: "\f310"; } +.bi-egg-fill::before { content: "\f311"; } +.bi-egg-fried::before { content: "\f312"; } +.bi-egg::before { content: "\f313"; } +.bi-eject-fill::before { content: "\f314"; } +.bi-eject::before { content: "\f315"; } +.bi-emoji-angry-fill::before { content: "\f316"; } +.bi-emoji-angry::before { content: "\f317"; } +.bi-emoji-dizzy-fill::before { content: "\f318"; } +.bi-emoji-dizzy::before { content: "\f319"; } +.bi-emoji-expressionless-fill::before { content: "\f31a"; } +.bi-emoji-expressionless::before { content: "\f31b"; } +.bi-emoji-frown-fill::before { content: "\f31c"; } +.bi-emoji-frown::before { content: "\f31d"; } +.bi-emoji-heart-eyes-fill::before { content: "\f31e"; } +.bi-emoji-heart-eyes::before { content: "\f31f"; } +.bi-emoji-laughing-fill::before { content: "\f320"; } +.bi-emoji-laughing::before { content: "\f321"; } +.bi-emoji-neutral-fill::before { content: "\f322"; } +.bi-emoji-neutral::before { content: "\f323"; } +.bi-emoji-smile-fill::before { content: "\f324"; } +.bi-emoji-smile-upside-down-fill::before { content: "\f325"; } +.bi-emoji-smile-upside-down::before { content: "\f326"; } +.bi-emoji-smile::before { content: "\f327"; } +.bi-emoji-sunglasses-fill::before { content: "\f328"; } +.bi-emoji-sunglasses::before { content: "\f329"; } +.bi-emoji-wink-fill::before { content: "\f32a"; } +.bi-emoji-wink::before { content: "\f32b"; } +.bi-envelope-fill::before { content: "\f32c"; } +.bi-envelope-open-fill::before { content: "\f32d"; } +.bi-envelope-open::before { content: "\f32e"; } +.bi-envelope::before { content: "\f32f"; } +.bi-eraser-fill::before { content: "\f330"; } +.bi-eraser::before { content: "\f331"; } +.bi-exclamation-circle-fill::before { content: "\f332"; } +.bi-exclamation-circle::before { content: "\f333"; } +.bi-exclamation-diamond-fill::before { content: "\f334"; } +.bi-exclamation-diamond::before { content: "\f335"; } +.bi-exclamation-octagon-fill::before { content: "\f336"; } +.bi-exclamation-octagon::before { content: "\f337"; } +.bi-exclamation-square-fill::before { content: "\f338"; } +.bi-exclamation-square::before { content: "\f339"; } +.bi-exclamation-triangle-fill::before { content: "\f33a"; } +.bi-exclamation-triangle::before { content: "\f33b"; } +.bi-exclamation::before { content: "\f33c"; } +.bi-exclude::before { content: "\f33d"; } +.bi-eye-fill::before { content: "\f33e"; } +.bi-eye-slash-fill::before { content: "\f33f"; } +.bi-eye-slash::before { content: "\f340"; } +.bi-eye::before { content: "\f341"; } +.bi-eyedropper::before { content: "\f342"; } +.bi-eyeglasses::before { content: "\f343"; } +.bi-facebook::before { content: "\f344"; } +.bi-file-arrow-down-fill::before { content: "\f345"; } +.bi-file-arrow-down::before { content: "\f346"; } +.bi-file-arrow-up-fill::before { content: "\f347"; } +.bi-file-arrow-up::before { content: "\f348"; } +.bi-file-bar-graph-fill::before { content: "\f349"; } +.bi-file-bar-graph::before { content: "\f34a"; } +.bi-file-binary-fill::before { content: "\f34b"; } +.bi-file-binary::before { content: "\f34c"; } +.bi-file-break-fill::before { content: "\f34d"; } +.bi-file-break::before { content: "\f34e"; } +.bi-file-check-fill::before { content: "\f34f"; } +.bi-file-check::before { content: "\f350"; } +.bi-file-code-fill::before { content: "\f351"; } +.bi-file-code::before { content: "\f352"; } +.bi-file-diff-fill::before { content: "\f353"; } +.bi-file-diff::before { content: "\f354"; } +.bi-file-earmark-arrow-down-fill::before { content: "\f355"; } +.bi-file-earmark-arrow-down::before { content: "\f356"; } +.bi-file-earmark-arrow-up-fill::before { content: "\f357"; } +.bi-file-earmark-arrow-up::before { content: "\f358"; } +.bi-file-earmark-bar-graph-fill::before { content: "\f359"; } +.bi-file-earmark-bar-graph::before { content: "\f35a"; } +.bi-file-earmark-binary-fill::before { content: "\f35b"; } +.bi-file-earmark-binary::before { content: "\f35c"; } +.bi-file-earmark-break-fill::before { content: "\f35d"; } +.bi-file-earmark-break::before { content: "\f35e"; } +.bi-file-earmark-check-fill::before { content: "\f35f"; } +.bi-file-earmark-check::before { content: "\f360"; } +.bi-file-earmark-code-fill::before { content: "\f361"; } +.bi-file-earmark-code::before { content: "\f362"; } +.bi-file-earmark-diff-fill::before { content: "\f363"; } +.bi-file-earmark-diff::before { content: "\f364"; } +.bi-file-earmark-easel-fill::before { content: "\f365"; } +.bi-file-earmark-easel::before { content: "\f366"; } +.bi-file-earmark-excel-fill::before { content: "\f367"; } +.bi-file-earmark-excel::before { content: "\f368"; } +.bi-file-earmark-fill::before { content: "\f369"; } +.bi-file-earmark-font-fill::before { content: "\f36a"; } +.bi-file-earmark-font::before { content: "\f36b"; } +.bi-file-earmark-image-fill::before { content: "\f36c"; } +.bi-file-earmark-image::before { content: "\f36d"; } +.bi-file-earmark-lock-fill::before { content: "\f36e"; } +.bi-file-earmark-lock::before { content: "\f36f"; } +.bi-file-earmark-lock2-fill::before { content: "\f370"; } +.bi-file-earmark-lock2::before { content: "\f371"; } +.bi-file-earmark-medical-fill::before { content: "\f372"; } +.bi-file-earmark-medical::before { content: "\f373"; } +.bi-file-earmark-minus-fill::before { content: "\f374"; } +.bi-file-earmark-minus::before { content: "\f375"; } +.bi-file-earmark-music-fill::before { content: "\f376"; } +.bi-file-earmark-music::before { content: "\f377"; } +.bi-file-earmark-person-fill::before { content: "\f378"; } +.bi-file-earmark-person::before { content: "\f379"; } +.bi-file-earmark-play-fill::before { content: "\f37a"; } +.bi-file-earmark-play::before { content: "\f37b"; } +.bi-file-earmark-plus-fill::before { content: "\f37c"; } +.bi-file-earmark-plus::before { content: "\f37d"; } +.bi-file-earmark-post-fill::before { content: "\f37e"; } +.bi-file-earmark-post::before { content: "\f37f"; } +.bi-file-earmark-ppt-fill::before { content: "\f380"; } +.bi-file-earmark-ppt::before { content: "\f381"; } +.bi-file-earmark-richtext-fill::before { content: "\f382"; } +.bi-file-earmark-richtext::before { content: "\f383"; } +.bi-file-earmark-ruled-fill::before { content: "\f384"; } +.bi-file-earmark-ruled::before { content: "\f385"; } +.bi-file-earmark-slides-fill::before { content: "\f386"; } +.bi-file-earmark-slides::before { content: "\f387"; } +.bi-file-earmark-spreadsheet-fill::before { content: "\f388"; } +.bi-file-earmark-spreadsheet::before { content: "\f389"; } +.bi-file-earmark-text-fill::before { content: "\f38a"; } +.bi-file-earmark-text::before { content: "\f38b"; } +.bi-file-earmark-word-fill::before { content: "\f38c"; } +.bi-file-earmark-word::before { content: "\f38d"; } +.bi-file-earmark-x-fill::before { content: "\f38e"; } +.bi-file-earmark-x::before { content: "\f38f"; } +.bi-file-earmark-zip-fill::before { content: "\f390"; } +.bi-file-earmark-zip::before { content: "\f391"; } +.bi-file-earmark::before { content: "\f392"; } +.bi-file-easel-fill::before { content: "\f393"; } +.bi-file-easel::before { content: "\f394"; } +.bi-file-excel-fill::before { content: "\f395"; } +.bi-file-excel::before { content: "\f396"; } +.bi-file-fill::before { content: "\f397"; } +.bi-file-font-fill::before { content: "\f398"; } +.bi-file-font::before { content: "\f399"; } +.bi-file-image-fill::before { content: "\f39a"; } +.bi-file-image::before { content: "\f39b"; } +.bi-file-lock-fill::before { content: "\f39c"; } +.bi-file-lock::before { content: "\f39d"; } +.bi-file-lock2-fill::before { content: "\f39e"; } +.bi-file-lock2::before { content: "\f39f"; } +.bi-file-medical-fill::before { content: "\f3a0"; } +.bi-file-medical::before { content: "\f3a1"; } +.bi-file-minus-fill::before { content: "\f3a2"; } +.bi-file-minus::before { content: "\f3a3"; } +.bi-file-music-fill::before { content: "\f3a4"; } +.bi-file-music::before { content: "\f3a5"; } +.bi-file-person-fill::before { content: "\f3a6"; } +.bi-file-person::before { content: "\f3a7"; } +.bi-file-play-fill::before { content: "\f3a8"; } +.bi-file-play::before { content: "\f3a9"; } +.bi-file-plus-fill::before { content: "\f3aa"; } +.bi-file-plus::before { content: "\f3ab"; } +.bi-file-post-fill::before { content: "\f3ac"; } +.bi-file-post::before { content: "\f3ad"; } +.bi-file-ppt-fill::before { content: "\f3ae"; } +.bi-file-ppt::before { content: "\f3af"; } +.bi-file-richtext-fill::before { content: "\f3b0"; } +.bi-file-richtext::before { content: "\f3b1"; } +.bi-file-ruled-fill::before { content: "\f3b2"; } +.bi-file-ruled::before { content: "\f3b3"; } +.bi-file-slides-fill::before { content: "\f3b4"; } +.bi-file-slides::before { content: "\f3b5"; } +.bi-file-spreadsheet-fill::before { content: "\f3b6"; } +.bi-file-spreadsheet::before { content: "\f3b7"; } +.bi-file-text-fill::before { content: "\f3b8"; } +.bi-file-text::before { content: "\f3b9"; } +.bi-file-word-fill::before { content: "\f3ba"; } +.bi-file-word::before { content: "\f3bb"; } +.bi-file-x-fill::before { content: "\f3bc"; } +.bi-file-x::before { content: "\f3bd"; } +.bi-file-zip-fill::before { content: "\f3be"; } +.bi-file-zip::before { content: "\f3bf"; } +.bi-file::before { content: "\f3c0"; } +.bi-files-alt::before { content: "\f3c1"; } +.bi-files::before { content: "\f3c2"; } +.bi-film::before { content: "\f3c3"; } +.bi-filter-circle-fill::before { content: "\f3c4"; } +.bi-filter-circle::before { content: "\f3c5"; } +.bi-filter-left::before { content: "\f3c6"; } +.bi-filter-right::before { content: "\f3c7"; } +.bi-filter-square-fill::before { content: "\f3c8"; } +.bi-filter-square::before { content: "\f3c9"; } +.bi-filter::before { content: "\f3ca"; } +.bi-flag-fill::before { content: "\f3cb"; } +.bi-flag::before { content: "\f3cc"; } +.bi-flower1::before { content: "\f3cd"; } +.bi-flower2::before { content: "\f3ce"; } +.bi-flower3::before { content: "\f3cf"; } +.bi-folder-check::before { content: "\f3d0"; } +.bi-folder-fill::before { content: "\f3d1"; } +.bi-folder-minus::before { content: "\f3d2"; } +.bi-folder-plus::before { content: "\f3d3"; } +.bi-folder-symlink-fill::before { content: "\f3d4"; } +.bi-folder-symlink::before { content: "\f3d5"; } +.bi-folder-x::before { content: "\f3d6"; } +.bi-folder::before { content: "\f3d7"; } +.bi-folder2-open::before { content: "\f3d8"; } +.bi-folder2::before { content: "\f3d9"; } +.bi-fonts::before { content: "\f3da"; } +.bi-forward-fill::before { content: "\f3db"; } +.bi-forward::before { content: "\f3dc"; } +.bi-front::before { content: "\f3dd"; } +.bi-fullscreen-exit::before { content: "\f3de"; } +.bi-fullscreen::before { content: "\f3df"; } +.bi-funnel-fill::before { content: "\f3e0"; } +.bi-funnel::before { content: "\f3e1"; } +.bi-gear-fill::before { content: "\f3e2"; } +.bi-gear-wide-connected::before { content: "\f3e3"; } +.bi-gear-wide::before { content: "\f3e4"; } +.bi-gear::before { content: "\f3e5"; } +.bi-gem::before { content: "\f3e6"; } +.bi-geo-alt-fill::before { content: "\f3e7"; } +.bi-geo-alt::before { content: "\f3e8"; } +.bi-geo-fill::before { content: "\f3e9"; } +.bi-geo::before { content: "\f3ea"; } +.bi-gift-fill::before { content: "\f3eb"; } +.bi-gift::before { content: "\f3ec"; } +.bi-github::before { content: "\f3ed"; } +.bi-globe::before { content: "\f3ee"; } +.bi-globe2::before { content: "\f3ef"; } +.bi-google::before { content: "\f3f0"; } +.bi-graph-down::before { content: "\f3f1"; } +.bi-graph-up::before { content: "\f3f2"; } +.bi-grid-1x2-fill::before { content: "\f3f3"; } +.bi-grid-1x2::before { content: "\f3f4"; } +.bi-grid-3x2-gap-fill::before { content: "\f3f5"; } +.bi-grid-3x2-gap::before { content: "\f3f6"; } +.bi-grid-3x2::before { content: "\f3f7"; } +.bi-grid-3x3-gap-fill::before { content: "\f3f8"; } +.bi-grid-3x3-gap::before { content: "\f3f9"; } +.bi-grid-3x3::before { content: "\f3fa"; } +.bi-grid-fill::before { content: "\f3fb"; } +.bi-grid::before { content: "\f3fc"; } +.bi-grip-horizontal::before { content: "\f3fd"; } +.bi-grip-vertical::before { content: "\f3fe"; } +.bi-hammer::before { content: "\f3ff"; } +.bi-hand-index-fill::before { content: "\f400"; } +.bi-hand-index-thumb-fill::before { content: "\f401"; } +.bi-hand-index-thumb::before { content: "\f402"; } +.bi-hand-index::before { content: "\f403"; } +.bi-hand-thumbs-down-fill::before { content: "\f404"; } +.bi-hand-thumbs-down::before { content: "\f405"; } +.bi-hand-thumbs-up-fill::before { content: "\f406"; } +.bi-hand-thumbs-up::before { content: "\f407"; } +.bi-handbag-fill::before { content: "\f408"; } +.bi-handbag::before { content: "\f409"; } +.bi-hash::before { content: "\f40a"; } +.bi-hdd-fill::before { content: "\f40b"; } +.bi-hdd-network-fill::before { content: "\f40c"; } +.bi-hdd-network::before { content: "\f40d"; } +.bi-hdd-rack-fill::before { content: "\f40e"; } +.bi-hdd-rack::before { content: "\f40f"; } +.bi-hdd-stack-fill::before { content: "\f410"; } +.bi-hdd-stack::before { content: "\f411"; } +.bi-hdd::before { content: "\f412"; } +.bi-headphones::before { content: "\f413"; } +.bi-headset::before { content: "\f414"; } +.bi-heart-fill::before { content: "\f415"; } +.bi-heart-half::before { content: "\f416"; } +.bi-heart::before { content: "\f417"; } +.bi-heptagon-fill::before { content: "\f418"; } +.bi-heptagon-half::before { content: "\f419"; } +.bi-heptagon::before { content: "\f41a"; } +.bi-hexagon-fill::before { content: "\f41b"; } +.bi-hexagon-half::before { content: "\f41c"; } +.bi-hexagon::before { content: "\f41d"; } +.bi-hourglass-bottom::before { content: "\f41e"; } +.bi-hourglass-split::before { content: "\f41f"; } +.bi-hourglass-top::before { content: "\f420"; } +.bi-hourglass::before { content: "\f421"; } +.bi-house-door-fill::before { content: "\f422"; } +.bi-house-door::before { content: "\f423"; } +.bi-house-fill::before { content: "\f424"; } +.bi-house::before { content: "\f425"; } +.bi-hr::before { content: "\f426"; } +.bi-hurricane::before { content: "\f427"; } +.bi-image-alt::before { content: "\f428"; } +.bi-image-fill::before { content: "\f429"; } +.bi-image::before { content: "\f42a"; } +.bi-images::before { content: "\f42b"; } +.bi-inbox-fill::before { content: "\f42c"; } +.bi-inbox::before { content: "\f42d"; } +.bi-inboxes-fill::before { content: "\f42e"; } +.bi-inboxes::before { content: "\f42f"; } +.bi-info-circle-fill::before { content: "\f430"; } +.bi-info-circle::before { content: "\f431"; } +.bi-info-square-fill::before { content: "\f432"; } +.bi-info-square::before { content: "\f433"; } +.bi-info::before { content: "\f434"; } +.bi-input-cursor-text::before { content: "\f435"; } +.bi-input-cursor::before { content: "\f436"; } +.bi-instagram::before { content: "\f437"; } +.bi-intersect::before { content: "\f438"; } +.bi-journal-album::before { content: "\f439"; } +.bi-journal-arrow-down::before { content: "\f43a"; } +.bi-journal-arrow-up::before { content: "\f43b"; } +.bi-journal-bookmark-fill::before { content: "\f43c"; } +.bi-journal-bookmark::before { content: "\f43d"; } +.bi-journal-check::before { content: "\f43e"; } +.bi-journal-code::before { content: "\f43f"; } +.bi-journal-medical::before { content: "\f440"; } +.bi-journal-minus::before { content: "\f441"; } +.bi-journal-plus::before { content: "\f442"; } +.bi-journal-richtext::before { content: "\f443"; } +.bi-journal-text::before { content: "\f444"; } +.bi-journal-x::before { content: "\f445"; } +.bi-journal::before { content: "\f446"; } +.bi-journals::before { content: "\f447"; } +.bi-joystick::before { content: "\f448"; } +.bi-justify-left::before { content: "\f449"; } +.bi-justify-right::before { content: "\f44a"; } +.bi-justify::before { content: "\f44b"; } +.bi-kanban-fill::before { content: "\f44c"; } +.bi-kanban::before { content: "\f44d"; } +.bi-key-fill::before { content: "\f44e"; } +.bi-key::before { content: "\f44f"; } +.bi-keyboard-fill::before { content: "\f450"; } +.bi-keyboard::before { content: "\f451"; } +.bi-ladder::before { content: "\f452"; } +.bi-lamp-fill::before { content: "\f453"; } +.bi-lamp::before { content: "\f454"; } +.bi-laptop-fill::before { content: "\f455"; } +.bi-laptop::before { content: "\f456"; } +.bi-layer-backward::before { content: "\f457"; } +.bi-layer-forward::before { content: "\f458"; } +.bi-layers-fill::before { content: "\f459"; } +.bi-layers-half::before { content: "\f45a"; } +.bi-layers::before { content: "\f45b"; } +.bi-layout-sidebar-inset-reverse::before { content: "\f45c"; } +.bi-layout-sidebar-inset::before { content: "\f45d"; } +.bi-layout-sidebar-reverse::before { content: "\f45e"; } +.bi-layout-sidebar::before { content: "\f45f"; } +.bi-layout-split::before { content: "\f460"; } +.bi-layout-text-sidebar-reverse::before { content: "\f461"; } +.bi-layout-text-sidebar::before { content: "\f462"; } +.bi-layout-text-window-reverse::before { content: "\f463"; } +.bi-layout-text-window::before { content: "\f464"; } +.bi-layout-three-columns::before { content: "\f465"; } +.bi-layout-wtf::before { content: "\f466"; } +.bi-life-preserver::before { content: "\f467"; } +.bi-lightbulb-fill::before { content: "\f468"; } +.bi-lightbulb-off-fill::before { content: "\f469"; } +.bi-lightbulb-off::before { content: "\f46a"; } +.bi-lightbulb::before { content: "\f46b"; } +.bi-lightning-charge-fill::before { content: "\f46c"; } +.bi-lightning-charge::before { content: "\f46d"; } +.bi-lightning-fill::before { content: "\f46e"; } +.bi-lightning::before { content: "\f46f"; } +.bi-link-45deg::before { content: "\f470"; } +.bi-link::before { content: "\f471"; } +.bi-linkedin::before { content: "\f472"; } +.bi-list-check::before { content: "\f473"; } +.bi-list-nested::before { content: "\f474"; } +.bi-list-ol::before { content: "\f475"; } +.bi-list-stars::before { content: "\f476"; } +.bi-list-task::before { content: "\f477"; } +.bi-list-ul::before { content: "\f478"; } +.bi-list::before { content: "\f479"; } +.bi-lock-fill::before { content: "\f47a"; } +.bi-lock::before { content: "\f47b"; } +.bi-mailbox::before { content: "\f47c"; } +.bi-mailbox2::before { content: "\f47d"; } +.bi-map-fill::before { content: "\f47e"; } +.bi-map::before { content: "\f47f"; } +.bi-markdown-fill::before { content: "\f480"; } +.bi-markdown::before { content: "\f481"; } +.bi-mask::before { content: "\f482"; } +.bi-megaphone-fill::before { content: "\f483"; } +.bi-megaphone::before { content: "\f484"; } +.bi-menu-app-fill::before { content: "\f485"; } +.bi-menu-app::before { content: "\f486"; } +.bi-menu-button-fill::before { content: "\f487"; } +.bi-menu-button-wide-fill::before { content: "\f488"; } +.bi-menu-button-wide::before { content: "\f489"; } +.bi-menu-button::before { content: "\f48a"; } +.bi-menu-down::before { content: "\f48b"; } +.bi-menu-up::before { content: "\f48c"; } +.bi-mic-fill::before { content: "\f48d"; } +.bi-mic-mute-fill::before { content: "\f48e"; } +.bi-mic-mute::before { content: "\f48f"; } +.bi-mic::before { content: "\f490"; } +.bi-minecart-loaded::before { content: "\f491"; } +.bi-minecart::before { content: "\f492"; } +.bi-moisture::before { content: "\f493"; } +.bi-moon-fill::before { content: "\f494"; } +.bi-moon-stars-fill::before { content: "\f495"; } +.bi-moon-stars::before { content: "\f496"; } +.bi-moon::before { content: "\f497"; } +.bi-mouse-fill::before { content: "\f498"; } +.bi-mouse::before { content: "\f499"; } +.bi-mouse2-fill::before { content: "\f49a"; } +.bi-mouse2::before { content: "\f49b"; } +.bi-mouse3-fill::before { content: "\f49c"; } +.bi-mouse3::before { content: "\f49d"; } +.bi-music-note-beamed::before { content: "\f49e"; } +.bi-music-note-list::before { content: "\f49f"; } +.bi-music-note::before { content: "\f4a0"; } +.bi-music-player-fill::before { content: "\f4a1"; } +.bi-music-player::before { content: "\f4a2"; } +.bi-newspaper::before { content: "\f4a3"; } +.bi-node-minus-fill::before { content: "\f4a4"; } +.bi-node-minus::before { content: "\f4a5"; } +.bi-node-plus-fill::before { content: "\f4a6"; } +.bi-node-plus::before { content: "\f4a7"; } +.bi-nut-fill::before { content: "\f4a8"; } +.bi-nut::before { content: "\f4a9"; } +.bi-octagon-fill::before { content: "\f4aa"; } +.bi-octagon-half::before { content: "\f4ab"; } +.bi-octagon::before { content: "\f4ac"; } +.bi-option::before { content: "\f4ad"; } +.bi-outlet::before { content: "\f4ae"; } +.bi-paint-bucket::before { content: "\f4af"; } +.bi-palette-fill::before { content: "\f4b0"; } +.bi-palette::before { content: "\f4b1"; } +.bi-palette2::before { content: "\f4b2"; } +.bi-paperclip::before { content: "\f4b3"; } +.bi-paragraph::before { content: "\f4b4"; } +.bi-patch-check-fill::before { content: "\f4b5"; } +.bi-patch-check::before { content: "\f4b6"; } +.bi-patch-exclamation-fill::before { content: "\f4b7"; } +.bi-patch-exclamation::before { content: "\f4b8"; } +.bi-patch-minus-fill::before { content: "\f4b9"; } +.bi-patch-minus::before { content: "\f4ba"; } +.bi-patch-plus-fill::before { content: "\f4bb"; } +.bi-patch-plus::before { content: "\f4bc"; } +.bi-patch-question-fill::before { content: "\f4bd"; } +.bi-patch-question::before { content: "\f4be"; } +.bi-pause-btn-fill::before { content: "\f4bf"; } +.bi-pause-btn::before { content: "\f4c0"; } +.bi-pause-circle-fill::before { content: "\f4c1"; } +.bi-pause-circle::before { content: "\f4c2"; } +.bi-pause-fill::before { content: "\f4c3"; } +.bi-pause::before { content: "\f4c4"; } +.bi-peace-fill::before { content: "\f4c5"; } +.bi-peace::before { content: "\f4c6"; } +.bi-pen-fill::before { content: "\f4c7"; } +.bi-pen::before { content: "\f4c8"; } +.bi-pencil-fill::before { content: "\f4c9"; } +.bi-pencil-square::before { content: "\f4ca"; } +.bi-pencil::before { content: "\f4cb"; } +.bi-pentagon-fill::before { content: "\f4cc"; } +.bi-pentagon-half::before { content: "\f4cd"; } +.bi-pentagon::before { content: "\f4ce"; } +.bi-people-fill::before { content: "\f4cf"; } +.bi-people::before { content: "\f4d0"; } +.bi-percent::before { content: "\f4d1"; } +.bi-person-badge-fill::before { content: "\f4d2"; } +.bi-person-badge::before { content: "\f4d3"; } +.bi-person-bounding-box::before { content: "\f4d4"; } +.bi-person-check-fill::before { content: "\f4d5"; } +.bi-person-check::before { content: "\f4d6"; } +.bi-person-circle::before { content: "\f4d7"; } +.bi-person-dash-fill::before { content: "\f4d8"; } +.bi-person-dash::before { content: "\f4d9"; } +.bi-person-fill::before { content: "\f4da"; } +.bi-person-lines-fill::before { content: "\f4db"; } +.bi-person-plus-fill::before { content: "\f4dc"; } +.bi-person-plus::before { content: "\f4dd"; } +.bi-person-square::before { content: "\f4de"; } +.bi-person-x-fill::before { content: "\f4df"; } +.bi-person-x::before { content: "\f4e0"; } +.bi-person::before { content: "\f4e1"; } +.bi-phone-fill::before { content: "\f4e2"; } +.bi-phone-landscape-fill::before { content: "\f4e3"; } +.bi-phone-landscape::before { content: "\f4e4"; } +.bi-phone-vibrate-fill::before { content: "\f4e5"; } +.bi-phone-vibrate::before { content: "\f4e6"; } +.bi-phone::before { content: "\f4e7"; } +.bi-pie-chart-fill::before { content: "\f4e8"; } +.bi-pie-chart::before { content: "\f4e9"; } +.bi-pin-angle-fill::before { content: "\f4ea"; } +.bi-pin-angle::before { content: "\f4eb"; } +.bi-pin-fill::before { content: "\f4ec"; } +.bi-pin::before { content: "\f4ed"; } +.bi-pip-fill::before { content: "\f4ee"; } +.bi-pip::before { content: "\f4ef"; } +.bi-play-btn-fill::before { content: "\f4f0"; } +.bi-play-btn::before { content: "\f4f1"; } +.bi-play-circle-fill::before { content: "\f4f2"; } +.bi-play-circle::before { content: "\f4f3"; } +.bi-play-fill::before { content: "\f4f4"; } +.bi-play::before { content: "\f4f5"; } +.bi-plug-fill::before { content: "\f4f6"; } +.bi-plug::before { content: "\f4f7"; } +.bi-plus-circle-dotted::before { content: "\f4f8"; } +.bi-plus-circle-fill::before { content: "\f4f9"; } +.bi-plus-circle::before { content: "\f4fa"; } +.bi-plus-square-dotted::before { content: "\f4fb"; } +.bi-plus-square-fill::before { content: "\f4fc"; } +.bi-plus-square::before { content: "\f4fd"; } +.bi-plus::before { content: "\f4fe"; } +.bi-power::before { content: "\f4ff"; } +.bi-printer-fill::before { content: "\f500"; } +.bi-printer::before { content: "\f501"; } +.bi-puzzle-fill::before { content: "\f502"; } +.bi-puzzle::before { content: "\f503"; } +.bi-question-circle-fill::before { content: "\f504"; } +.bi-question-circle::before { content: "\f505"; } +.bi-question-diamond-fill::before { content: "\f506"; } +.bi-question-diamond::before { content: "\f507"; } +.bi-question-octagon-fill::before { content: "\f508"; } +.bi-question-octagon::before { content: "\f509"; } +.bi-question-square-fill::before { content: "\f50a"; } +.bi-question-square::before { content: "\f50b"; } +.bi-question::before { content: "\f50c"; } +.bi-rainbow::before { content: "\f50d"; } +.bi-receipt-cutoff::before { content: "\f50e"; } +.bi-receipt::before { content: "\f50f"; } +.bi-reception-0::before { content: "\f510"; } +.bi-reception-1::before { content: "\f511"; } +.bi-reception-2::before { content: "\f512"; } +.bi-reception-3::before { content: "\f513"; } +.bi-reception-4::before { content: "\f514"; } +.bi-record-btn-fill::before { content: "\f515"; } +.bi-record-btn::before { content: "\f516"; } +.bi-record-circle-fill::before { content: "\f517"; } +.bi-record-circle::before { content: "\f518"; } +.bi-record-fill::before { content: "\f519"; } +.bi-record::before { content: "\f51a"; } +.bi-record2-fill::before { content: "\f51b"; } +.bi-record2::before { content: "\f51c"; } +.bi-reply-all-fill::before { content: "\f51d"; } +.bi-reply-all::before { content: "\f51e"; } +.bi-reply-fill::before { content: "\f51f"; } +.bi-reply::before { content: "\f520"; } +.bi-rss-fill::before { content: "\f521"; } +.bi-rss::before { content: "\f522"; } +.bi-rulers::before { content: "\f523"; } +.bi-save-fill::before { content: "\f524"; } +.bi-save::before { content: "\f525"; } +.bi-save2-fill::before { content: "\f526"; } +.bi-save2::before { content: "\f527"; } +.bi-scissors::before { content: "\f528"; } +.bi-screwdriver::before { content: "\f529"; } +.bi-search::before { content: "\f52a"; } +.bi-segmented-nav::before { content: "\f52b"; } +.bi-server::before { content: "\f52c"; } +.bi-share-fill::before { content: "\f52d"; } +.bi-share::before { content: "\f52e"; } +.bi-shield-check::before { content: "\f52f"; } +.bi-shield-exclamation::before { content: "\f530"; } +.bi-shield-fill-check::before { content: "\f531"; } +.bi-shield-fill-exclamation::before { content: "\f532"; } +.bi-shield-fill-minus::before { content: "\f533"; } +.bi-shield-fill-plus::before { content: "\f534"; } +.bi-shield-fill-x::before { content: "\f535"; } +.bi-shield-fill::before { content: "\f536"; } +.bi-shield-lock-fill::before { content: "\f537"; } +.bi-shield-lock::before { content: "\f538"; } +.bi-shield-minus::before { content: "\f539"; } +.bi-shield-plus::before { content: "\f53a"; } +.bi-shield-shaded::before { content: "\f53b"; } +.bi-shield-slash-fill::before { content: "\f53c"; } +.bi-shield-slash::before { content: "\f53d"; } +.bi-shield-x::before { content: "\f53e"; } +.bi-shield::before { content: "\f53f"; } +.bi-shift-fill::before { content: "\f540"; } +.bi-shift::before { content: "\f541"; } +.bi-shop-window::before { content: "\f542"; } +.bi-shop::before { content: "\f543"; } +.bi-shuffle::before { content: "\f544"; } +.bi-signpost-2-fill::before { content: "\f545"; } +.bi-signpost-2::before { content: "\f546"; } +.bi-signpost-fill::before { content: "\f547"; } +.bi-signpost-split-fill::before { content: "\f548"; } +.bi-signpost-split::before { content: "\f549"; } +.bi-signpost::before { content: "\f54a"; } +.bi-sim-fill::before { content: "\f54b"; } +.bi-sim::before { content: "\f54c"; } +.bi-skip-backward-btn-fill::before { content: "\f54d"; } +.bi-skip-backward-btn::before { content: "\f54e"; } +.bi-skip-backward-circle-fill::before { content: "\f54f"; } +.bi-skip-backward-circle::before { content: "\f550"; } +.bi-skip-backward-fill::before { content: "\f551"; } +.bi-skip-backward::before { content: "\f552"; } +.bi-skip-end-btn-fill::before { content: "\f553"; } +.bi-skip-end-btn::before { content: "\f554"; } +.bi-skip-end-circle-fill::before { content: "\f555"; } +.bi-skip-end-circle::before { content: "\f556"; } +.bi-skip-end-fill::before { content: "\f557"; } +.bi-skip-end::before { content: "\f558"; } +.bi-skip-forward-btn-fill::before { content: "\f559"; } +.bi-skip-forward-btn::before { content: "\f55a"; } +.bi-skip-forward-circle-fill::before { content: "\f55b"; } +.bi-skip-forward-circle::before { content: "\f55c"; } +.bi-skip-forward-fill::before { content: "\f55d"; } +.bi-skip-forward::before { content: "\f55e"; } +.bi-skip-start-btn-fill::before { content: "\f55f"; } +.bi-skip-start-btn::before { content: "\f560"; } +.bi-skip-start-circle-fill::before { content: "\f561"; } +.bi-skip-start-circle::before { content: "\f562"; } +.bi-skip-start-fill::before { content: "\f563"; } +.bi-skip-start::before { content: "\f564"; } +.bi-slack::before { content: "\f565"; } +.bi-slash-circle-fill::before { content: "\f566"; } +.bi-slash-circle::before { content: "\f567"; } +.bi-slash-square-fill::before { content: "\f568"; } +.bi-slash-square::before { content: "\f569"; } +.bi-slash::before { content: "\f56a"; } +.bi-sliders::before { content: "\f56b"; } +.bi-smartwatch::before { content: "\f56c"; } +.bi-snow::before { content: "\f56d"; } +.bi-snow2::before { content: "\f56e"; } +.bi-snow3::before { content: "\f56f"; } +.bi-sort-alpha-down-alt::before { content: "\f570"; } +.bi-sort-alpha-down::before { content: "\f571"; } +.bi-sort-alpha-up-alt::before { content: "\f572"; } +.bi-sort-alpha-up::before { content: "\f573"; } +.bi-sort-down-alt::before { content: "\f574"; } +.bi-sort-down::before { content: "\f575"; } +.bi-sort-numeric-down-alt::before { content: "\f576"; } +.bi-sort-numeric-down::before { content: "\f577"; } +.bi-sort-numeric-up-alt::before { content: "\f578"; } +.bi-sort-numeric-up::before { content: "\f579"; } +.bi-sort-up-alt::before { content: "\f57a"; } +.bi-sort-up::before { content: "\f57b"; } +.bi-soundwave::before { content: "\f57c"; } +.bi-speaker-fill::before { content: "\f57d"; } +.bi-speaker::before { content: "\f57e"; } +.bi-speedometer::before { content: "\f57f"; } +.bi-speedometer2::before { content: "\f580"; } +.bi-spellcheck::before { content: "\f581"; } +.bi-square-fill::before { content: "\f582"; } +.bi-square-half::before { content: "\f583"; } +.bi-square::before { content: "\f584"; } +.bi-stack::before { content: "\f585"; } +.bi-star-fill::before { content: "\f586"; } +.bi-star-half::before { content: "\f587"; } +.bi-star::before { content: "\f588"; } +.bi-stars::before { content: "\f589"; } +.bi-stickies-fill::before { content: "\f58a"; } +.bi-stickies::before { content: "\f58b"; } +.bi-sticky-fill::before { content: "\f58c"; } +.bi-sticky::before { content: "\f58d"; } +.bi-stop-btn-fill::before { content: "\f58e"; } +.bi-stop-btn::before { content: "\f58f"; } +.bi-stop-circle-fill::before { content: "\f590"; } +.bi-stop-circle::before { content: "\f591"; } +.bi-stop-fill::before { content: "\f592"; } +.bi-stop::before { content: "\f593"; } +.bi-stoplights-fill::before { content: "\f594"; } +.bi-stoplights::before { content: "\f595"; } +.bi-stopwatch-fill::before { content: "\f596"; } +.bi-stopwatch::before { content: "\f597"; } +.bi-subtract::before { content: "\f598"; } +.bi-suit-club-fill::before { content: "\f599"; } +.bi-suit-club::before { content: "\f59a"; } +.bi-suit-diamond-fill::before { content: "\f59b"; } +.bi-suit-diamond::before { content: "\f59c"; } +.bi-suit-heart-fill::before { content: "\f59d"; } +.bi-suit-heart::before { content: "\f59e"; } +.bi-suit-spade-fill::before { content: "\f59f"; } +.bi-suit-spade::before { content: "\f5a0"; } +.bi-sun-fill::before { content: "\f5a1"; } +.bi-sun::before { content: "\f5a2"; } +.bi-sunglasses::before { content: "\f5a3"; } +.bi-sunrise-fill::before { content: "\f5a4"; } +.bi-sunrise::before { content: "\f5a5"; } +.bi-sunset-fill::before { content: "\f5a6"; } +.bi-sunset::before { content: "\f5a7"; } +.bi-symmetry-horizontal::before { content: "\f5a8"; } +.bi-symmetry-vertical::before { content: "\f5a9"; } +.bi-table::before { content: "\f5aa"; } +.bi-tablet-fill::before { content: "\f5ab"; } +.bi-tablet-landscape-fill::before { content: "\f5ac"; } +.bi-tablet-landscape::before { content: "\f5ad"; } +.bi-tablet::before { content: "\f5ae"; } +.bi-tag-fill::before { content: "\f5af"; } +.bi-tag::before { content: "\f5b0"; } +.bi-tags-fill::before { content: "\f5b1"; } +.bi-tags::before { content: "\f5b2"; } +.bi-telegram::before { content: "\f5b3"; } +.bi-telephone-fill::before { content: "\f5b4"; } +.bi-telephone-forward-fill::before { content: "\f5b5"; } +.bi-telephone-forward::before { content: "\f5b6"; } +.bi-telephone-inbound-fill::before { content: "\f5b7"; } +.bi-telephone-inbound::before { content: "\f5b8"; } +.bi-telephone-minus-fill::before { content: "\f5b9"; } +.bi-telephone-minus::before { content: "\f5ba"; } +.bi-telephone-outbound-fill::before { content: "\f5bb"; } +.bi-telephone-outbound::before { content: "\f5bc"; } +.bi-telephone-plus-fill::before { content: "\f5bd"; } +.bi-telephone-plus::before { content: "\f5be"; } +.bi-telephone-x-fill::before { content: "\f5bf"; } +.bi-telephone-x::before { content: "\f5c0"; } +.bi-telephone::before { content: "\f5c1"; } +.bi-terminal-fill::before { content: "\f5c2"; } +.bi-terminal::before { content: "\f5c3"; } +.bi-text-center::before { content: "\f5c4"; } +.bi-text-indent-left::before { content: "\f5c5"; } +.bi-text-indent-right::before { content: "\f5c6"; } +.bi-text-left::before { content: "\f5c7"; } +.bi-text-paragraph::before { content: "\f5c8"; } +.bi-text-right::before { content: "\f5c9"; } +.bi-textarea-resize::before { content: "\f5ca"; } +.bi-textarea-t::before { content: "\f5cb"; } +.bi-textarea::before { content: "\f5cc"; } +.bi-thermometer-half::before { content: "\f5cd"; } +.bi-thermometer-high::before { content: "\f5ce"; } +.bi-thermometer-low::before { content: "\f5cf"; } +.bi-thermometer-snow::before { content: "\f5d0"; } +.bi-thermometer-sun::before { content: "\f5d1"; } +.bi-thermometer::before { content: "\f5d2"; } +.bi-three-dots-vertical::before { content: "\f5d3"; } +.bi-three-dots::before { content: "\f5d4"; } +.bi-toggle-off::before { content: "\f5d5"; } +.bi-toggle-on::before { content: "\f5d6"; } +.bi-toggle2-off::before { content: "\f5d7"; } +.bi-toggle2-on::before { content: "\f5d8"; } +.bi-toggles::before { content: "\f5d9"; } +.bi-toggles2::before { content: "\f5da"; } +.bi-tools::before { content: "\f5db"; } +.bi-tornado::before { content: "\f5dc"; } +.bi-trash-fill::before { content: "\f5dd"; } +.bi-trash::before { content: "\f5de"; } +.bi-trash2-fill::before { content: "\f5df"; } +.bi-trash2::before { content: "\f5e0"; } +.bi-tree-fill::before { content: "\f5e1"; } +.bi-tree::before { content: "\f5e2"; } +.bi-triangle-fill::before { content: "\f5e3"; } +.bi-triangle-half::before { content: "\f5e4"; } +.bi-triangle::before { content: "\f5e5"; } +.bi-trophy-fill::before { content: "\f5e6"; } +.bi-trophy::before { content: "\f5e7"; } +.bi-tropical-storm::before { content: "\f5e8"; } +.bi-truck-flatbed::before { content: "\f5e9"; } +.bi-truck::before { content: "\f5ea"; } +.bi-tsunami::before { content: "\f5eb"; } +.bi-tv-fill::before { content: "\f5ec"; } +.bi-tv::before { content: "\f5ed"; } +.bi-twitch::before { content: "\f5ee"; } +.bi-twitter::before { content: "\f5ef"; } +.bi-type-bold::before { content: "\f5f0"; } +.bi-type-h1::before { content: "\f5f1"; } +.bi-type-h2::before { content: "\f5f2"; } +.bi-type-h3::before { content: "\f5f3"; } +.bi-type-italic::before { content: "\f5f4"; } +.bi-type-strikethrough::before { content: "\f5f5"; } +.bi-type-underline::before { content: "\f5f6"; } +.bi-type::before { content: "\f5f7"; } +.bi-ui-checks-grid::before { content: "\f5f8"; } +.bi-ui-checks::before { content: "\f5f9"; } +.bi-ui-radios-grid::before { content: "\f5fa"; } +.bi-ui-radios::before { content: "\f5fb"; } +.bi-umbrella-fill::before { content: "\f5fc"; } +.bi-umbrella::before { content: "\f5fd"; } +.bi-union::before { content: "\f5fe"; } +.bi-unlock-fill::before { content: "\f5ff"; } +.bi-unlock::before { content: "\f600"; } +.bi-upc-scan::before { content: "\f601"; } +.bi-upc::before { content: "\f602"; } +.bi-upload::before { content: "\f603"; } +.bi-vector-pen::before { content: "\f604"; } +.bi-view-list::before { content: "\f605"; } +.bi-view-stacked::before { content: "\f606"; } +.bi-vinyl-fill::before { content: "\f607"; } +.bi-vinyl::before { content: "\f608"; } +.bi-voicemail::before { content: "\f609"; } +.bi-volume-down-fill::before { content: "\f60a"; } +.bi-volume-down::before { content: "\f60b"; } +.bi-volume-mute-fill::before { content: "\f60c"; } +.bi-volume-mute::before { content: "\f60d"; } +.bi-volume-off-fill::before { content: "\f60e"; } +.bi-volume-off::before { content: "\f60f"; } +.bi-volume-up-fill::before { content: "\f610"; } +.bi-volume-up::before { content: "\f611"; } +.bi-vr::before { content: "\f612"; } +.bi-wallet-fill::before { content: "\f613"; } +.bi-wallet::before { content: "\f614"; } +.bi-wallet2::before { content: "\f615"; } +.bi-watch::before { content: "\f616"; } +.bi-water::before { content: "\f617"; } +.bi-whatsapp::before { content: "\f618"; } +.bi-wifi-1::before { content: "\f619"; } +.bi-wifi-2::before { content: "\f61a"; } +.bi-wifi-off::before { content: "\f61b"; } +.bi-wifi::before { content: "\f61c"; } +.bi-wind::before { content: "\f61d"; } +.bi-window-dock::before { content: "\f61e"; } +.bi-window-sidebar::before { content: "\f61f"; } +.bi-window::before { content: "\f620"; } +.bi-wrench::before { content: "\f621"; } +.bi-x-circle-fill::before { content: "\f622"; } +.bi-x-circle::before { content: "\f623"; } +.bi-x-diamond-fill::before { content: "\f624"; } +.bi-x-diamond::before { content: "\f625"; } +.bi-x-octagon-fill::before { content: "\f626"; } +.bi-x-octagon::before { content: "\f627"; } +.bi-x-square-fill::before { content: "\f628"; } +.bi-x-square::before { content: "\f629"; } +.bi-x::before { content: "\f62a"; } +.bi-youtube::before { content: "\f62b"; } +.bi-zoom-in::before { content: "\f62c"; } +.bi-zoom-out::before { content: "\f62d"; } +.bi-bank::before { content: "\f62e"; } +.bi-bank2::before { content: "\f62f"; } +.bi-bell-slash-fill::before { content: "\f630"; } +.bi-bell-slash::before { content: "\f631"; } +.bi-cash-coin::before { content: "\f632"; } +.bi-check-lg::before { content: "\f633"; } +.bi-coin::before { content: "\f634"; } +.bi-currency-bitcoin::before { content: "\f635"; } +.bi-currency-dollar::before { content: "\f636"; } +.bi-currency-euro::before { content: "\f637"; } +.bi-currency-exchange::before { content: "\f638"; } +.bi-currency-pound::before { content: "\f639"; } +.bi-currency-yen::before { content: "\f63a"; } +.bi-dash-lg::before { content: "\f63b"; } +.bi-exclamation-lg::before { content: "\f63c"; } +.bi-file-earmark-pdf-fill::before { content: "\f63d"; } +.bi-file-earmark-pdf::before { content: "\f63e"; } +.bi-file-pdf-fill::before { content: "\f63f"; } +.bi-file-pdf::before { content: "\f640"; } +.bi-gender-ambiguous::before { content: "\f641"; } +.bi-gender-female::before { content: "\f642"; } +.bi-gender-male::before { content: "\f643"; } +.bi-gender-trans::before { content: "\f644"; } +.bi-headset-vr::before { content: "\f645"; } +.bi-info-lg::before { content: "\f646"; } +.bi-mastodon::before { content: "\f647"; } +.bi-messenger::before { content: "\f648"; } +.bi-piggy-bank-fill::before { content: "\f649"; } +.bi-piggy-bank::before { content: "\f64a"; } +.bi-pin-map-fill::before { content: "\f64b"; } +.bi-pin-map::before { content: "\f64c"; } +.bi-plus-lg::before { content: "\f64d"; } +.bi-question-lg::before { content: "\f64e"; } +.bi-recycle::before { content: "\f64f"; } +.bi-reddit::before { content: "\f650"; } +.bi-safe-fill::before { content: "\f651"; } +.bi-safe2-fill::before { content: "\f652"; } +.bi-safe2::before { content: "\f653"; } +.bi-sd-card-fill::before { content: "\f654"; } +.bi-sd-card::before { content: "\f655"; } +.bi-skype::before { content: "\f656"; } +.bi-slash-lg::before { content: "\f657"; } +.bi-translate::before { content: "\f658"; } +.bi-x-lg::before { content: "\f659"; } +.bi-safe::before { content: "\f65a"; } +.bi-apple::before { content: "\f65b"; } +.bi-microsoft::before { content: "\f65d"; } +.bi-windows::before { content: "\f65e"; } +.bi-behance::before { content: "\f65c"; } +.bi-dribbble::before { content: "\f65f"; } +.bi-line::before { content: "\f660"; } +.bi-medium::before { content: "\f661"; } +.bi-paypal::before { content: "\f662"; } +.bi-pinterest::before { content: "\f663"; } +.bi-signal::before { content: "\f664"; } +.bi-snapchat::before { content: "\f665"; } +.bi-spotify::before { content: "\f666"; } +.bi-stack-overflow::before { content: "\f667"; } +.bi-strava::before { content: "\f668"; } +.bi-wordpress::before { content: "\f669"; } +.bi-vimeo::before { content: "\f66a"; } +.bi-activity::before { content: "\f66b"; } +.bi-easel2-fill::before { content: "\f66c"; } +.bi-easel2::before { content: "\f66d"; } +.bi-easel3-fill::before { content: "\f66e"; } +.bi-easel3::before { content: "\f66f"; } +.bi-fan::before { content: "\f670"; } +.bi-fingerprint::before { content: "\f671"; } +.bi-graph-down-arrow::before { content: "\f672"; } +.bi-graph-up-arrow::before { content: "\f673"; } +.bi-hypnotize::before { content: "\f674"; } +.bi-magic::before { content: "\f675"; } +.bi-person-rolodex::before { content: "\f676"; } +.bi-person-video::before { content: "\f677"; } +.bi-person-video2::before { content: "\f678"; } +.bi-person-video3::before { content: "\f679"; } +.bi-person-workspace::before { content: "\f67a"; } +.bi-radioactive::before { content: "\f67b"; } +.bi-webcam-fill::before { content: "\f67c"; } +.bi-webcam::before { content: "\f67d"; } +.bi-yin-yang::before { content: "\f67e"; } +.bi-bandaid-fill::before { content: "\f680"; } +.bi-bandaid::before { content: "\f681"; } +.bi-bluetooth::before { content: "\f682"; } +.bi-body-text::before { content: "\f683"; } +.bi-boombox::before { content: "\f684"; } +.bi-boxes::before { content: "\f685"; } +.bi-dpad-fill::before { content: "\f686"; } +.bi-dpad::before { content: "\f687"; } +.bi-ear-fill::before { content: "\f688"; } +.bi-ear::before { content: "\f689"; } +.bi-envelope-check-fill::before { content: "\f68b"; } +.bi-envelope-check::before { content: "\f68c"; } +.bi-envelope-dash-fill::before { content: "\f68e"; } +.bi-envelope-dash::before { content: "\f68f"; } +.bi-envelope-exclamation-fill::before { content: "\f691"; } +.bi-envelope-exclamation::before { content: "\f692"; } +.bi-envelope-plus-fill::before { content: "\f693"; } +.bi-envelope-plus::before { content: "\f694"; } +.bi-envelope-slash-fill::before { content: "\f696"; } +.bi-envelope-slash::before { content: "\f697"; } +.bi-envelope-x-fill::before { content: "\f699"; } +.bi-envelope-x::before { content: "\f69a"; } +.bi-explicit-fill::before { content: "\f69b"; } +.bi-explicit::before { content: "\f69c"; } +.bi-git::before { content: "\f69d"; } +.bi-infinity::before { content: "\f69e"; } +.bi-list-columns-reverse::before { content: "\f69f"; } +.bi-list-columns::before { content: "\f6a0"; } +.bi-meta::before { content: "\f6a1"; } +.bi-nintendo-switch::before { content: "\f6a4"; } +.bi-pc-display-horizontal::before { content: "\f6a5"; } +.bi-pc-display::before { content: "\f6a6"; } +.bi-pc-horizontal::before { content: "\f6a7"; } +.bi-pc::before { content: "\f6a8"; } +.bi-playstation::before { content: "\f6a9"; } +.bi-plus-slash-minus::before { content: "\f6aa"; } +.bi-projector-fill::before { content: "\f6ab"; } +.bi-projector::before { content: "\f6ac"; } +.bi-qr-code-scan::before { content: "\f6ad"; } +.bi-qr-code::before { content: "\f6ae"; } +.bi-quora::before { content: "\f6af"; } +.bi-quote::before { content: "\f6b0"; } +.bi-robot::before { content: "\f6b1"; } +.bi-send-check-fill::before { content: "\f6b2"; } +.bi-send-check::before { content: "\f6b3"; } +.bi-send-dash-fill::before { content: "\f6b4"; } +.bi-send-dash::before { content: "\f6b5"; } +.bi-send-exclamation-fill::before { content: "\f6b7"; } +.bi-send-exclamation::before { content: "\f6b8"; } +.bi-send-fill::before { content: "\f6b9"; } +.bi-send-plus-fill::before { content: "\f6ba"; } +.bi-send-plus::before { content: "\f6bb"; } +.bi-send-slash-fill::before { content: "\f6bc"; } +.bi-send-slash::before { content: "\f6bd"; } +.bi-send-x-fill::before { content: "\f6be"; } +.bi-send-x::before { content: "\f6bf"; } +.bi-send::before { content: "\f6c0"; } +.bi-steam::before { content: "\f6c1"; } +.bi-terminal-dash::before { content: "\f6c3"; } +.bi-terminal-plus::before { content: "\f6c4"; } +.bi-terminal-split::before { content: "\f6c5"; } +.bi-ticket-detailed-fill::before { content: "\f6c6"; } +.bi-ticket-detailed::before { content: "\f6c7"; } +.bi-ticket-fill::before { content: "\f6c8"; } +.bi-ticket-perforated-fill::before { content: "\f6c9"; } +.bi-ticket-perforated::before { content: "\f6ca"; } +.bi-ticket::before { content: "\f6cb"; } +.bi-tiktok::before { content: "\f6cc"; } +.bi-window-dash::before { content: "\f6cd"; } +.bi-window-desktop::before { content: "\f6ce"; } +.bi-window-fullscreen::before { content: "\f6cf"; } +.bi-window-plus::before { content: "\f6d0"; } +.bi-window-split::before { content: "\f6d1"; } +.bi-window-stack::before { content: "\f6d2"; } +.bi-window-x::before { content: "\f6d3"; } +.bi-xbox::before { content: "\f6d4"; } +.bi-ethernet::before { content: "\f6d5"; } +.bi-hdmi-fill::before { content: "\f6d6"; } +.bi-hdmi::before { content: "\f6d7"; } +.bi-usb-c-fill::before { content: "\f6d8"; } +.bi-usb-c::before { content: "\f6d9"; } +.bi-usb-fill::before { content: "\f6da"; } +.bi-usb-plug-fill::before { content: "\f6db"; } +.bi-usb-plug::before { content: "\f6dc"; } +.bi-usb-symbol::before { content: "\f6dd"; } +.bi-usb::before { content: "\f6de"; } +.bi-boombox-fill::before { content: "\f6df"; } +.bi-displayport::before { content: "\f6e1"; } +.bi-gpu-card::before { content: "\f6e2"; } +.bi-memory::before { content: "\f6e3"; } +.bi-modem-fill::before { content: "\f6e4"; } +.bi-modem::before { content: "\f6e5"; } +.bi-motherboard-fill::before { content: "\f6e6"; } +.bi-motherboard::before { content: "\f6e7"; } +.bi-optical-audio-fill::before { content: "\f6e8"; } +.bi-optical-audio::before { content: "\f6e9"; } +.bi-pci-card::before { content: "\f6ea"; } +.bi-router-fill::before { content: "\f6eb"; } +.bi-router::before { content: "\f6ec"; } +.bi-thunderbolt-fill::before { content: "\f6ef"; } +.bi-thunderbolt::before { content: "\f6f0"; } +.bi-usb-drive-fill::before { content: "\f6f1"; } +.bi-usb-drive::before { content: "\f6f2"; } +.bi-usb-micro-fill::before { content: "\f6f3"; } +.bi-usb-micro::before { content: "\f6f4"; } +.bi-usb-mini-fill::before { content: "\f6f5"; } +.bi-usb-mini::before { content: "\f6f6"; } +.bi-cloud-haze2::before { content: "\f6f7"; } +.bi-device-hdd-fill::before { content: "\f6f8"; } +.bi-device-hdd::before { content: "\f6f9"; } +.bi-device-ssd-fill::before { content: "\f6fa"; } +.bi-device-ssd::before { content: "\f6fb"; } +.bi-displayport-fill::before { content: "\f6fc"; } +.bi-mortarboard-fill::before { content: "\f6fd"; } +.bi-mortarboard::before { content: "\f6fe"; } +.bi-terminal-x::before { content: "\f6ff"; } +.bi-arrow-through-heart-fill::before { content: "\f700"; } +.bi-arrow-through-heart::before { content: "\f701"; } +.bi-badge-sd-fill::before { content: "\f702"; } +.bi-badge-sd::before { content: "\f703"; } +.bi-bag-heart-fill::before { content: "\f704"; } +.bi-bag-heart::before { content: "\f705"; } +.bi-balloon-fill::before { content: "\f706"; } +.bi-balloon-heart-fill::before { content: "\f707"; } +.bi-balloon-heart::before { content: "\f708"; } +.bi-balloon::before { content: "\f709"; } +.bi-box2-fill::before { content: "\f70a"; } +.bi-box2-heart-fill::before { content: "\f70b"; } +.bi-box2-heart::before { content: "\f70c"; } +.bi-box2::before { content: "\f70d"; } +.bi-braces-asterisk::before { content: "\f70e"; } +.bi-calendar-heart-fill::before { content: "\f70f"; } +.bi-calendar-heart::before { content: "\f710"; } +.bi-calendar2-heart-fill::before { content: "\f711"; } +.bi-calendar2-heart::before { content: "\f712"; } +.bi-chat-heart-fill::before { content: "\f713"; } +.bi-chat-heart::before { content: "\f714"; } +.bi-chat-left-heart-fill::before { content: "\f715"; } +.bi-chat-left-heart::before { content: "\f716"; } +.bi-chat-right-heart-fill::before { content: "\f717"; } +.bi-chat-right-heart::before { content: "\f718"; } +.bi-chat-square-heart-fill::before { content: "\f719"; } +.bi-chat-square-heart::before { content: "\f71a"; } +.bi-clipboard-check-fill::before { content: "\f71b"; } +.bi-clipboard-data-fill::before { content: "\f71c"; } +.bi-clipboard-fill::before { content: "\f71d"; } +.bi-clipboard-heart-fill::before { content: "\f71e"; } +.bi-clipboard-heart::before { content: "\f71f"; } +.bi-clipboard-minus-fill::before { content: "\f720"; } +.bi-clipboard-plus-fill::before { content: "\f721"; } +.bi-clipboard-pulse::before { content: "\f722"; } +.bi-clipboard-x-fill::before { content: "\f723"; } +.bi-clipboard2-check-fill::before { content: "\f724"; } +.bi-clipboard2-check::before { content: "\f725"; } +.bi-clipboard2-data-fill::before { content: "\f726"; } +.bi-clipboard2-data::before { content: "\f727"; } +.bi-clipboard2-fill::before { content: "\f728"; } +.bi-clipboard2-heart-fill::before { content: "\f729"; } +.bi-clipboard2-heart::before { content: "\f72a"; } +.bi-clipboard2-minus-fill::before { content: "\f72b"; } +.bi-clipboard2-minus::before { content: "\f72c"; } +.bi-clipboard2-plus-fill::before { content: "\f72d"; } +.bi-clipboard2-plus::before { content: "\f72e"; } +.bi-clipboard2-pulse-fill::before { content: "\f72f"; } +.bi-clipboard2-pulse::before { content: "\f730"; } +.bi-clipboard2-x-fill::before { content: "\f731"; } +.bi-clipboard2-x::before { content: "\f732"; } +.bi-clipboard2::before { content: "\f733"; } +.bi-emoji-kiss-fill::before { content: "\f734"; } +.bi-emoji-kiss::before { content: "\f735"; } +.bi-envelope-heart-fill::before { content: "\f736"; } +.bi-envelope-heart::before { content: "\f737"; } +.bi-envelope-open-heart-fill::before { content: "\f738"; } +.bi-envelope-open-heart::before { content: "\f739"; } +.bi-envelope-paper-fill::before { content: "\f73a"; } +.bi-envelope-paper-heart-fill::before { content: "\f73b"; } +.bi-envelope-paper-heart::before { content: "\f73c"; } +.bi-envelope-paper::before { content: "\f73d"; } +.bi-filetype-aac::before { content: "\f73e"; } +.bi-filetype-ai::before { content: "\f73f"; } +.bi-filetype-bmp::before { content: "\f740"; } +.bi-filetype-cs::before { content: "\f741"; } +.bi-filetype-css::before { content: "\f742"; } +.bi-filetype-csv::before { content: "\f743"; } +.bi-filetype-doc::before { content: "\f744"; } +.bi-filetype-docx::before { content: "\f745"; } +.bi-filetype-exe::before { content: "\f746"; } +.bi-filetype-gif::before { content: "\f747"; } +.bi-filetype-heic::before { content: "\f748"; } +.bi-filetype-html::before { content: "\f749"; } +.bi-filetype-java::before { content: "\f74a"; } +.bi-filetype-jpg::before { content: "\f74b"; } +.bi-filetype-js::before { content: "\f74c"; } +.bi-filetype-jsx::before { content: "\f74d"; } +.bi-filetype-key::before { content: "\f74e"; } +.bi-filetype-m4p::before { content: "\f74f"; } +.bi-filetype-md::before { content: "\f750"; } +.bi-filetype-mdx::before { content: "\f751"; } +.bi-filetype-mov::before { content: "\f752"; } +.bi-filetype-mp3::before { content: "\f753"; } +.bi-filetype-mp4::before { content: "\f754"; } +.bi-filetype-otf::before { content: "\f755"; } +.bi-filetype-pdf::before { content: "\f756"; } +.bi-filetype-php::before { content: "\f757"; } +.bi-filetype-png::before { content: "\f758"; } +.bi-filetype-ppt::before { content: "\f75a"; } +.bi-filetype-psd::before { content: "\f75b"; } +.bi-filetype-py::before { content: "\f75c"; } +.bi-filetype-raw::before { content: "\f75d"; } +.bi-filetype-rb::before { content: "\f75e"; } +.bi-filetype-sass::before { content: "\f75f"; } +.bi-filetype-scss::before { content: "\f760"; } +.bi-filetype-sh::before { content: "\f761"; } +.bi-filetype-svg::before { content: "\f762"; } +.bi-filetype-tiff::before { content: "\f763"; } +.bi-filetype-tsx::before { content: "\f764"; } +.bi-filetype-ttf::before { content: "\f765"; } +.bi-filetype-txt::before { content: "\f766"; } +.bi-filetype-wav::before { content: "\f767"; } +.bi-filetype-woff::before { content: "\f768"; } +.bi-filetype-xls::before { content: "\f76a"; } +.bi-filetype-xml::before { content: "\f76b"; } +.bi-filetype-yml::before { content: "\f76c"; } +.bi-heart-arrow::before { content: "\f76d"; } +.bi-heart-pulse-fill::before { content: "\f76e"; } +.bi-heart-pulse::before { content: "\f76f"; } +.bi-heartbreak-fill::before { content: "\f770"; } +.bi-heartbreak::before { content: "\f771"; } +.bi-hearts::before { content: "\f772"; } +.bi-hospital-fill::before { content: "\f773"; } +.bi-hospital::before { content: "\f774"; } +.bi-house-heart-fill::before { content: "\f775"; } +.bi-house-heart::before { content: "\f776"; } +.bi-incognito::before { content: "\f777"; } +.bi-magnet-fill::before { content: "\f778"; } +.bi-magnet::before { content: "\f779"; } +.bi-person-heart::before { content: "\f77a"; } +.bi-person-hearts::before { content: "\f77b"; } +.bi-phone-flip::before { content: "\f77c"; } +.bi-plugin::before { content: "\f77d"; } +.bi-postage-fill::before { content: "\f77e"; } +.bi-postage-heart-fill::before { content: "\f77f"; } +.bi-postage-heart::before { content: "\f780"; } +.bi-postage::before { content: "\f781"; } +.bi-postcard-fill::before { content: "\f782"; } +.bi-postcard-heart-fill::before { content: "\f783"; } +.bi-postcard-heart::before { content: "\f784"; } +.bi-postcard::before { content: "\f785"; } +.bi-search-heart-fill::before { content: "\f786"; } +.bi-search-heart::before { content: "\f787"; } +.bi-sliders2-vertical::before { content: "\f788"; } +.bi-sliders2::before { content: "\f789"; } +.bi-trash3-fill::before { content: "\f78a"; } +.bi-trash3::before { content: "\f78b"; } +.bi-valentine::before { content: "\f78c"; } +.bi-valentine2::before { content: "\f78d"; } +.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; } +.bi-wrench-adjustable-circle::before { content: "\f78f"; } +.bi-wrench-adjustable::before { content: "\f790"; } +.bi-filetype-json::before { content: "\f791"; } +.bi-filetype-pptx::before { content: "\f792"; } +.bi-filetype-xlsx::before { content: "\f793"; } +.bi-1-circle-fill::before { content: "\f796"; } +.bi-1-circle::before { content: "\f797"; } +.bi-1-square-fill::before { content: "\f798"; } +.bi-1-square::before { content: "\f799"; } +.bi-2-circle-fill::before { content: "\f79c"; } +.bi-2-circle::before { content: "\f79d"; } +.bi-2-square-fill::before { content: "\f79e"; } +.bi-2-square::before { content: "\f79f"; } +.bi-3-circle-fill::before { content: "\f7a2"; } +.bi-3-circle::before { content: "\f7a3"; } +.bi-3-square-fill::before { content: "\f7a4"; } +.bi-3-square::before { content: "\f7a5"; } +.bi-4-circle-fill::before { content: "\f7a8"; } +.bi-4-circle::before { content: "\f7a9"; } +.bi-4-square-fill::before { content: "\f7aa"; } +.bi-4-square::before { content: "\f7ab"; } +.bi-5-circle-fill::before { content: "\f7ae"; } +.bi-5-circle::before { content: "\f7af"; } +.bi-5-square-fill::before { content: "\f7b0"; } +.bi-5-square::before { content: "\f7b1"; } +.bi-6-circle-fill::before { content: "\f7b4"; } +.bi-6-circle::before { content: "\f7b5"; } +.bi-6-square-fill::before { content: "\f7b6"; } +.bi-6-square::before { content: "\f7b7"; } +.bi-7-circle-fill::before { content: "\f7ba"; } +.bi-7-circle::before { content: "\f7bb"; } +.bi-7-square-fill::before { content: "\f7bc"; } +.bi-7-square::before { content: "\f7bd"; } +.bi-8-circle-fill::before { content: "\f7c0"; } +.bi-8-circle::before { content: "\f7c1"; } +.bi-8-square-fill::before { content: "\f7c2"; } +.bi-8-square::before { content: "\f7c3"; } +.bi-9-circle-fill::before { content: "\f7c6"; } +.bi-9-circle::before { content: "\f7c7"; } +.bi-9-square-fill::before { content: "\f7c8"; } +.bi-9-square::before { content: "\f7c9"; } +.bi-airplane-engines-fill::before { content: "\f7ca"; } +.bi-airplane-engines::before { content: "\f7cb"; } +.bi-airplane-fill::before { content: "\f7cc"; } +.bi-airplane::before { content: "\f7cd"; } +.bi-alexa::before { content: "\f7ce"; } +.bi-alipay::before { content: "\f7cf"; } +.bi-android::before { content: "\f7d0"; } +.bi-android2::before { content: "\f7d1"; } +.bi-box-fill::before { content: "\f7d2"; } +.bi-box-seam-fill::before { content: "\f7d3"; } +.bi-browser-chrome::before { content: "\f7d4"; } +.bi-browser-edge::before { content: "\f7d5"; } +.bi-browser-firefox::before { content: "\f7d6"; } +.bi-browser-safari::before { content: "\f7d7"; } +.bi-c-circle-fill::before { content: "\f7da"; } +.bi-c-circle::before { content: "\f7db"; } +.bi-c-square-fill::before { content: "\f7dc"; } +.bi-c-square::before { content: "\f7dd"; } +.bi-capsule-pill::before { content: "\f7de"; } +.bi-capsule::before { content: "\f7df"; } +.bi-car-front-fill::before { content: "\f7e0"; } +.bi-car-front::before { content: "\f7e1"; } +.bi-cassette-fill::before { content: "\f7e2"; } +.bi-cassette::before { content: "\f7e3"; } +.bi-cc-circle-fill::before { content: "\f7e6"; } +.bi-cc-circle::before { content: "\f7e7"; } +.bi-cc-square-fill::before { content: "\f7e8"; } +.bi-cc-square::before { content: "\f7e9"; } +.bi-cup-hot-fill::before { content: "\f7ea"; } +.bi-cup-hot::before { content: "\f7eb"; } +.bi-currency-rupee::before { content: "\f7ec"; } +.bi-dropbox::before { content: "\f7ed"; } +.bi-escape::before { content: "\f7ee"; } +.bi-fast-forward-btn-fill::before { content: "\f7ef"; } +.bi-fast-forward-btn::before { content: "\f7f0"; } +.bi-fast-forward-circle-fill::before { content: "\f7f1"; } +.bi-fast-forward-circle::before { content: "\f7f2"; } +.bi-fast-forward-fill::before { content: "\f7f3"; } +.bi-fast-forward::before { content: "\f7f4"; } +.bi-filetype-sql::before { content: "\f7f5"; } +.bi-fire::before { content: "\f7f6"; } +.bi-google-play::before { content: "\f7f7"; } +.bi-h-circle-fill::before { content: "\f7fa"; } +.bi-h-circle::before { content: "\f7fb"; } +.bi-h-square-fill::before { content: "\f7fc"; } +.bi-h-square::before { content: "\f7fd"; } +.bi-indent::before { content: "\f7fe"; } +.bi-lungs-fill::before { content: "\f7ff"; } +.bi-lungs::before { content: "\f800"; } +.bi-microsoft-teams::before { content: "\f801"; } +.bi-p-circle-fill::before { content: "\f804"; } +.bi-p-circle::before { content: "\f805"; } +.bi-p-square-fill::before { content: "\f806"; } +.bi-p-square::before { content: "\f807"; } +.bi-pass-fill::before { content: "\f808"; } +.bi-pass::before { content: "\f809"; } +.bi-prescription::before { content: "\f80a"; } +.bi-prescription2::before { content: "\f80b"; } +.bi-r-circle-fill::before { content: "\f80e"; } +.bi-r-circle::before { content: "\f80f"; } +.bi-r-square-fill::before { content: "\f810"; } +.bi-r-square::before { content: "\f811"; } +.bi-repeat-1::before { content: "\f812"; } +.bi-repeat::before { content: "\f813"; } +.bi-rewind-btn-fill::before { content: "\f814"; } +.bi-rewind-btn::before { content: "\f815"; } +.bi-rewind-circle-fill::before { content: "\f816"; } +.bi-rewind-circle::before { content: "\f817"; } +.bi-rewind-fill::before { content: "\f818"; } +.bi-rewind::before { content: "\f819"; } +.bi-train-freight-front-fill::before { content: "\f81a"; } +.bi-train-freight-front::before { content: "\f81b"; } +.bi-train-front-fill::before { content: "\f81c"; } +.bi-train-front::before { content: "\f81d"; } +.bi-train-lightrail-front-fill::before { content: "\f81e"; } +.bi-train-lightrail-front::before { content: "\f81f"; } +.bi-truck-front-fill::before { content: "\f820"; } +.bi-truck-front::before { content: "\f821"; } +.bi-ubuntu::before { content: "\f822"; } +.bi-unindent::before { content: "\f823"; } +.bi-unity::before { content: "\f824"; } +.bi-universal-access-circle::before { content: "\f825"; } +.bi-universal-access::before { content: "\f826"; } +.bi-virus::before { content: "\f827"; } +.bi-virus2::before { content: "\f828"; } +.bi-wechat::before { content: "\f829"; } +.bi-yelp::before { content: "\f82a"; } +.bi-sign-stop-fill::before { content: "\f82b"; } +.bi-sign-stop-lights-fill::before { content: "\f82c"; } +.bi-sign-stop-lights::before { content: "\f82d"; } +.bi-sign-stop::before { content: "\f82e"; } +.bi-sign-turn-left-fill::before { content: "\f82f"; } +.bi-sign-turn-left::before { content: "\f830"; } +.bi-sign-turn-right-fill::before { content: "\f831"; } +.bi-sign-turn-right::before { content: "\f832"; } +.bi-sign-turn-slight-left-fill::before { content: "\f833"; } +.bi-sign-turn-slight-left::before { content: "\f834"; } +.bi-sign-turn-slight-right-fill::before { content: "\f835"; } +.bi-sign-turn-slight-right::before { content: "\f836"; } +.bi-sign-yield-fill::before { content: "\f837"; } +.bi-sign-yield::before { content: "\f838"; } +.bi-ev-station-fill::before { content: "\f839"; } +.bi-ev-station::before { content: "\f83a"; } +.bi-fuel-pump-diesel-fill::before { content: "\f83b"; } +.bi-fuel-pump-diesel::before { content: "\f83c"; } +.bi-fuel-pump-fill::before { content: "\f83d"; } +.bi-fuel-pump::before { content: "\f83e"; } +.bi-0-circle-fill::before { content: "\f83f"; } +.bi-0-circle::before { content: "\f840"; } +.bi-0-square-fill::before { content: "\f841"; } +.bi-0-square::before { content: "\f842"; } +.bi-rocket-fill::before { content: "\f843"; } +.bi-rocket-takeoff-fill::before { content: "\f844"; } +.bi-rocket-takeoff::before { content: "\f845"; } +.bi-rocket::before { content: "\f846"; } +.bi-stripe::before { content: "\f847"; } +.bi-subscript::before { content: "\f848"; } +.bi-superscript::before { content: "\f849"; } +.bi-trello::before { content: "\f84a"; } +.bi-envelope-at-fill::before { content: "\f84b"; } +.bi-envelope-at::before { content: "\f84c"; } +.bi-regex::before { content: "\f84d"; } +.bi-text-wrap::before { content: "\f84e"; } +.bi-sign-dead-end-fill::before { content: "\f84f"; } +.bi-sign-dead-end::before { content: "\f850"; } +.bi-sign-do-not-enter-fill::before { content: "\f851"; } +.bi-sign-do-not-enter::before { content: "\f852"; } +.bi-sign-intersection-fill::before { content: "\f853"; } +.bi-sign-intersection-side-fill::before { content: "\f854"; } +.bi-sign-intersection-side::before { content: "\f855"; } +.bi-sign-intersection-t-fill::before { content: "\f856"; } +.bi-sign-intersection-t::before { content: "\f857"; } +.bi-sign-intersection-y-fill::before { content: "\f858"; } +.bi-sign-intersection-y::before { content: "\f859"; } +.bi-sign-intersection::before { content: "\f85a"; } +.bi-sign-merge-left-fill::before { content: "\f85b"; } +.bi-sign-merge-left::before { content: "\f85c"; } +.bi-sign-merge-right-fill::before { content: "\f85d"; } +.bi-sign-merge-right::before { content: "\f85e"; } +.bi-sign-no-left-turn-fill::before { content: "\f85f"; } +.bi-sign-no-left-turn::before { content: "\f860"; } +.bi-sign-no-parking-fill::before { content: "\f861"; } +.bi-sign-no-parking::before { content: "\f862"; } +.bi-sign-no-right-turn-fill::before { content: "\f863"; } +.bi-sign-no-right-turn::before { content: "\f864"; } +.bi-sign-railroad-fill::before { content: "\f865"; } +.bi-sign-railroad::before { content: "\f866"; } +.bi-building-add::before { content: "\f867"; } +.bi-building-check::before { content: "\f868"; } +.bi-building-dash::before { content: "\f869"; } +.bi-building-down::before { content: "\f86a"; } +.bi-building-exclamation::before { content: "\f86b"; } +.bi-building-fill-add::before { content: "\f86c"; } +.bi-building-fill-check::before { content: "\f86d"; } +.bi-building-fill-dash::before { content: "\f86e"; } +.bi-building-fill-down::before { content: "\f86f"; } +.bi-building-fill-exclamation::before { content: "\f870"; } +.bi-building-fill-gear::before { content: "\f871"; } +.bi-building-fill-lock::before { content: "\f872"; } +.bi-building-fill-slash::before { content: "\f873"; } +.bi-building-fill-up::before { content: "\f874"; } +.bi-building-fill-x::before { content: "\f875"; } +.bi-building-fill::before { content: "\f876"; } +.bi-building-gear::before { content: "\f877"; } +.bi-building-lock::before { content: "\f878"; } +.bi-building-slash::before { content: "\f879"; } +.bi-building-up::before { content: "\f87a"; } +.bi-building-x::before { content: "\f87b"; } +.bi-buildings-fill::before { content: "\f87c"; } +.bi-buildings::before { content: "\f87d"; } +.bi-bus-front-fill::before { content: "\f87e"; } +.bi-bus-front::before { content: "\f87f"; } +.bi-ev-front-fill::before { content: "\f880"; } +.bi-ev-front::before { content: "\f881"; } +.bi-globe-americas::before { content: "\f882"; } +.bi-globe-asia-australia::before { content: "\f883"; } +.bi-globe-central-south-asia::before { content: "\f884"; } +.bi-globe-europe-africa::before { content: "\f885"; } +.bi-house-add-fill::before { content: "\f886"; } +.bi-house-add::before { content: "\f887"; } +.bi-house-check-fill::before { content: "\f888"; } +.bi-house-check::before { content: "\f889"; } +.bi-house-dash-fill::before { content: "\f88a"; } +.bi-house-dash::before { content: "\f88b"; } +.bi-house-down-fill::before { content: "\f88c"; } +.bi-house-down::before { content: "\f88d"; } +.bi-house-exclamation-fill::before { content: "\f88e"; } +.bi-house-exclamation::before { content: "\f88f"; } +.bi-house-gear-fill::before { content: "\f890"; } +.bi-house-gear::before { content: "\f891"; } +.bi-house-lock-fill::before { content: "\f892"; } +.bi-house-lock::before { content: "\f893"; } +.bi-house-slash-fill::before { content: "\f894"; } +.bi-house-slash::before { content: "\f895"; } +.bi-house-up-fill::before { content: "\f896"; } +.bi-house-up::before { content: "\f897"; } +.bi-house-x-fill::before { content: "\f898"; } +.bi-house-x::before { content: "\f899"; } +.bi-person-add::before { content: "\f89a"; } +.bi-person-down::before { content: "\f89b"; } +.bi-person-exclamation::before { content: "\f89c"; } +.bi-person-fill-add::before { content: "\f89d"; } +.bi-person-fill-check::before { content: "\f89e"; } +.bi-person-fill-dash::before { content: "\f89f"; } +.bi-person-fill-down::before { content: "\f8a0"; } +.bi-person-fill-exclamation::before { content: "\f8a1"; } +.bi-person-fill-gear::before { content: "\f8a2"; } +.bi-person-fill-lock::before { content: "\f8a3"; } +.bi-person-fill-slash::before { content: "\f8a4"; } +.bi-person-fill-up::before { content: "\f8a5"; } +.bi-person-fill-x::before { content: "\f8a6"; } +.bi-person-gear::before { content: "\f8a7"; } +.bi-person-lock::before { content: "\f8a8"; } +.bi-person-slash::before { content: "\f8a9"; } +.bi-person-up::before { content: "\f8aa"; } +.bi-scooter::before { content: "\f8ab"; } +.bi-taxi-front-fill::before { content: "\f8ac"; } +.bi-taxi-front::before { content: "\f8ad"; } +.bi-amd::before { content: "\f8ae"; } +.bi-database-add::before { content: "\f8af"; } +.bi-database-check::before { content: "\f8b0"; } +.bi-database-dash::before { content: "\f8b1"; } +.bi-database-down::before { content: "\f8b2"; } +.bi-database-exclamation::before { content: "\f8b3"; } +.bi-database-fill-add::before { content: "\f8b4"; } +.bi-database-fill-check::before { content: "\f8b5"; } +.bi-database-fill-dash::before { content: "\f8b6"; } +.bi-database-fill-down::before { content: "\f8b7"; } +.bi-database-fill-exclamation::before { content: "\f8b8"; } +.bi-database-fill-gear::before { content: "\f8b9"; } +.bi-database-fill-lock::before { content: "\f8ba"; } +.bi-database-fill-slash::before { content: "\f8bb"; } +.bi-database-fill-up::before { content: "\f8bc"; } +.bi-database-fill-x::before { content: "\f8bd"; } +.bi-database-fill::before { content: "\f8be"; } +.bi-database-gear::before { content: "\f8bf"; } +.bi-database-lock::before { content: "\f8c0"; } +.bi-database-slash::before { content: "\f8c1"; } +.bi-database-up::before { content: "\f8c2"; } +.bi-database-x::before { content: "\f8c3"; } +.bi-database::before { content: "\f8c4"; } +.bi-houses-fill::before { content: "\f8c5"; } +.bi-houses::before { content: "\f8c6"; } +.bi-nvidia::before { content: "\f8c7"; } +.bi-person-vcard-fill::before { content: "\f8c8"; } +.bi-person-vcard::before { content: "\f8c9"; } +.bi-sina-weibo::before { content: "\f8ca"; } +.bi-tencent-qq::before { content: "\f8cb"; } +.bi-wikipedia::before { content: "\f8cc"; } +.bi-alphabet-uppercase::before { content: "\f2a5"; } +.bi-alphabet::before { content: "\f68a"; } +.bi-amazon::before { content: "\f68d"; } +.bi-arrows-collapse-vertical::before { content: "\f690"; } +.bi-arrows-expand-vertical::before { content: "\f695"; } +.bi-arrows-vertical::before { content: "\f698"; } +.bi-arrows::before { content: "\f6a2"; } +.bi-ban-fill::before { content: "\f6a3"; } +.bi-ban::before { content: "\f6b6"; } +.bi-bing::before { content: "\f6c2"; } +.bi-cake::before { content: "\f6e0"; } +.bi-cake2::before { content: "\f6ed"; } +.bi-cookie::before { content: "\f6ee"; } +.bi-copy::before { content: "\f759"; } +.bi-crosshair::before { content: "\f769"; } +.bi-crosshair2::before { content: "\f794"; } +.bi-emoji-astonished-fill::before { content: "\f795"; } +.bi-emoji-astonished::before { content: "\f79a"; } +.bi-emoji-grimace-fill::before { content: "\f79b"; } +.bi-emoji-grimace::before { content: "\f7a0"; } +.bi-emoji-grin-fill::before { content: "\f7a1"; } +.bi-emoji-grin::before { content: "\f7a6"; } +.bi-emoji-surprise-fill::before { content: "\f7a7"; } +.bi-emoji-surprise::before { content: "\f7ac"; } +.bi-emoji-tear-fill::before { content: "\f7ad"; } +.bi-emoji-tear::before { content: "\f7b2"; } +.bi-envelope-arrow-down-fill::before { content: "\f7b3"; } +.bi-envelope-arrow-down::before { content: "\f7b8"; } +.bi-envelope-arrow-up-fill::before { content: "\f7b9"; } +.bi-envelope-arrow-up::before { content: "\f7be"; } +.bi-feather::before { content: "\f7bf"; } +.bi-feather2::before { content: "\f7c4"; } +.bi-floppy-fill::before { content: "\f7c5"; } +.bi-floppy::before { content: "\f7d8"; } +.bi-floppy2-fill::before { content: "\f7d9"; } +.bi-floppy2::before { content: "\f7e4"; } +.bi-gitlab::before { content: "\f7e5"; } +.bi-highlighter::before { content: "\f7f8"; } +.bi-marker-tip::before { content: "\f802"; } +.bi-nvme-fill::before { content: "\f803"; } +.bi-nvme::before { content: "\f80c"; } +.bi-opencollective::before { content: "\f80d"; } +.bi-pci-card-network::before { content: "\f8cd"; } +.bi-pci-card-sound::before { content: "\f8ce"; } +.bi-radar::before { content: "\f8cf"; } +.bi-send-arrow-down-fill::before { content: "\f8d0"; } +.bi-send-arrow-down::before { content: "\f8d1"; } +.bi-send-arrow-up-fill::before { content: "\f8d2"; } +.bi-send-arrow-up::before { content: "\f8d3"; } +.bi-sim-slash-fill::before { content: "\f8d4"; } +.bi-sim-slash::before { content: "\f8d5"; } +.bi-sourceforge::before { content: "\f8d6"; } +.bi-substack::before { content: "\f8d7"; } +.bi-threads-fill::before { content: "\f8d8"; } +.bi-threads::before { content: "\f8d9"; } +.bi-transparency::before { content: "\f8da"; } +.bi-twitter-x::before { content: "\f8db"; } +.bi-type-h4::before { content: "\f8dc"; } +.bi-type-h5::before { content: "\f8dd"; } +.bi-type-h6::before { content: "\f8de"; } +.bi-backpack-fill::before { content: "\f8df"; } +.bi-backpack::before { content: "\f8e0"; } +.bi-backpack2-fill::before { content: "\f8e1"; } +.bi-backpack2::before { content: "\f8e2"; } +.bi-backpack3-fill::before { content: "\f8e3"; } +.bi-backpack3::before { content: "\f8e4"; } +.bi-backpack4-fill::before { content: "\f8e5"; } +.bi-backpack4::before { content: "\f8e6"; } +.bi-brilliance::before { content: "\f8e7"; } +.bi-cake-fill::before { content: "\f8e8"; } +.bi-cake2-fill::before { content: "\f8e9"; } +.bi-duffle-fill::before { content: "\f8ea"; } +.bi-duffle::before { content: "\f8eb"; } +.bi-exposure::before { content: "\f8ec"; } +.bi-gender-neuter::before { content: "\f8ed"; } +.bi-highlights::before { content: "\f8ee"; } +.bi-luggage-fill::before { content: "\f8ef"; } +.bi-luggage::before { content: "\f8f0"; } +.bi-mailbox-flag::before { content: "\f8f1"; } +.bi-mailbox2-flag::before { content: "\f8f2"; } +.bi-noise-reduction::before { content: "\f8f3"; } +.bi-passport-fill::before { content: "\f8f4"; } +.bi-passport::before { content: "\f8f5"; } +.bi-person-arms-up::before { content: "\f8f6"; } +.bi-person-raised-hand::before { content: "\f8f7"; } +.bi-person-standing-dress::before { content: "\f8f8"; } +.bi-person-standing::before { content: "\f8f9"; } +.bi-person-walking::before { content: "\f8fa"; } +.bi-person-wheelchair::before { content: "\f8fb"; } +.bi-shadows::before { content: "\f8fc"; } +.bi-suitcase-fill::before { content: "\f8fd"; } +.bi-suitcase-lg-fill::before { content: "\f8fe"; } +.bi-suitcase-lg::before { content: "\f8ff"; } +.bi-suitcase::before { content: "\f900"; } +.bi-suitcase2-fill::before { content: "\f901"; } +.bi-suitcase2::before { content: "\f902"; } +.bi-vignette::before { content: "\f903"; } +.bi-bluesky::before { content: "\f7f9"; } +.bi-tux::before { content: "\f904"; } +.bi-beaker-fill::before { content: "\f905"; } +.bi-beaker::before { content: "\f906"; } +.bi-flask-fill::before { content: "\f907"; } +.bi-flask-florence-fill::before { content: "\f908"; } +.bi-flask-florence::before { content: "\f909"; } +.bi-flask::before { content: "\f90a"; } +.bi-leaf-fill::before { content: "\f90b"; } +.bi-leaf::before { content: "\f90c"; } +.bi-measuring-cup-fill::before { content: "\f90d"; } +.bi-measuring-cup::before { content: "\f90e"; } +.bi-unlock2-fill::before { content: "\f90f"; } +.bi-unlock2::before { content: "\f910"; } +.bi-battery-low::before { content: "\f911"; } +.bi-anthropic::before { content: "\f912"; } +.bi-apple-music::before { content: "\f913"; } +.bi-claude::before { content: "\f914"; } +.bi-openai::before { content: "\f915"; } +.bi-perplexity::before { content: "\f916"; } +.bi-css::before { content: "\f917"; } +.bi-javascript::before { content: "\f918"; } +.bi-typescript::before { content: "\f919"; } +.bi-fork-knife::before { content: "\f91a"; } +.bi-globe-americas-fill::before { content: "\f91b"; } +.bi-globe-asia-australia-fill::before { content: "\f91c"; } +.bi-globe-central-south-asia-fill::before { content: "\f91d"; } +.bi-globe-europe-africa-fill::before { content: "\f91e"; } diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.json b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.json new file mode 100644 index 00000000..9d8873b1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.json @@ -0,0 +1,2080 @@ +{ + "123": 63103, + "alarm-fill": 61697, + "alarm": 61698, + "align-bottom": 61699, + "align-center": 61700, + "align-end": 61701, + "align-middle": 61702, + "align-start": 61703, + "align-top": 61704, + "alt": 61705, + "app-indicator": 61706, + "app": 61707, + "archive-fill": 61708, + "archive": 61709, + "arrow-90deg-down": 61710, + "arrow-90deg-left": 61711, + "arrow-90deg-right": 61712, + "arrow-90deg-up": 61713, + "arrow-bar-down": 61714, + "arrow-bar-left": 61715, + "arrow-bar-right": 61716, + "arrow-bar-up": 61717, + "arrow-clockwise": 61718, + "arrow-counterclockwise": 61719, + "arrow-down-circle-fill": 61720, + "arrow-down-circle": 61721, + "arrow-down-left-circle-fill": 61722, + "arrow-down-left-circle": 61723, + "arrow-down-left-square-fill": 61724, + "arrow-down-left-square": 61725, + "arrow-down-left": 61726, + "arrow-down-right-circle-fill": 61727, + "arrow-down-right-circle": 61728, + "arrow-down-right-square-fill": 61729, + "arrow-down-right-square": 61730, + "arrow-down-right": 61731, + "arrow-down-short": 61732, + "arrow-down-square-fill": 61733, + "arrow-down-square": 61734, + "arrow-down-up": 61735, + "arrow-down": 61736, + "arrow-left-circle-fill": 61737, + "arrow-left-circle": 61738, + "arrow-left-right": 61739, + "arrow-left-short": 61740, + "arrow-left-square-fill": 61741, + "arrow-left-square": 61742, + "arrow-left": 61743, + "arrow-repeat": 61744, + "arrow-return-left": 61745, + "arrow-return-right": 61746, + "arrow-right-circle-fill": 61747, + "arrow-right-circle": 61748, + "arrow-right-short": 61749, + "arrow-right-square-fill": 61750, + "arrow-right-square": 61751, + "arrow-right": 61752, + "arrow-up-circle-fill": 61753, + "arrow-up-circle": 61754, + "arrow-up-left-circle-fill": 61755, + "arrow-up-left-circle": 61756, + "arrow-up-left-square-fill": 61757, + "arrow-up-left-square": 61758, + "arrow-up-left": 61759, + "arrow-up-right-circle-fill": 61760, + "arrow-up-right-circle": 61761, + "arrow-up-right-square-fill": 61762, + "arrow-up-right-square": 61763, + "arrow-up-right": 61764, + "arrow-up-short": 61765, + "arrow-up-square-fill": 61766, + "arrow-up-square": 61767, + "arrow-up": 61768, + "arrows-angle-contract": 61769, + "arrows-angle-expand": 61770, + "arrows-collapse": 61771, + "arrows-expand": 61772, + "arrows-fullscreen": 61773, + "arrows-move": 61774, + "aspect-ratio-fill": 61775, + "aspect-ratio": 61776, + "asterisk": 61777, + "at": 61778, + "award-fill": 61779, + "award": 61780, + "back": 61781, + "backspace-fill": 61782, + "backspace-reverse-fill": 61783, + "backspace-reverse": 61784, + "backspace": 61785, + "badge-3d-fill": 61786, + "badge-3d": 61787, + "badge-4k-fill": 61788, + "badge-4k": 61789, + "badge-8k-fill": 61790, + "badge-8k": 61791, + "badge-ad-fill": 61792, + "badge-ad": 61793, + "badge-ar-fill": 61794, + "badge-ar": 61795, + "badge-cc-fill": 61796, + "badge-cc": 61797, + "badge-hd-fill": 61798, + "badge-hd": 61799, + "badge-tm-fill": 61800, + "badge-tm": 61801, + "badge-vo-fill": 61802, + "badge-vo": 61803, + "badge-vr-fill": 61804, + "badge-vr": 61805, + "badge-wc-fill": 61806, + "badge-wc": 61807, + "bag-check-fill": 61808, + "bag-check": 61809, + "bag-dash-fill": 61810, + "bag-dash": 61811, + "bag-fill": 61812, + "bag-plus-fill": 61813, + "bag-plus": 61814, + "bag-x-fill": 61815, + "bag-x": 61816, + "bag": 61817, + "bar-chart-fill": 61818, + "bar-chart-line-fill": 61819, + "bar-chart-line": 61820, + "bar-chart-steps": 61821, + "bar-chart": 61822, + "basket-fill": 61823, + "basket": 61824, + "basket2-fill": 61825, + "basket2": 61826, + "basket3-fill": 61827, + "basket3": 61828, + "battery-charging": 61829, + "battery-full": 61830, + "battery-half": 61831, + "battery": 61832, + "bell-fill": 61833, + "bell": 61834, + "bezier": 61835, + "bezier2": 61836, + "bicycle": 61837, + "binoculars-fill": 61838, + "binoculars": 61839, + "blockquote-left": 61840, + "blockquote-right": 61841, + "book-fill": 61842, + "book-half": 61843, + "book": 61844, + "bookmark-check-fill": 61845, + "bookmark-check": 61846, + "bookmark-dash-fill": 61847, + "bookmark-dash": 61848, + "bookmark-fill": 61849, + "bookmark-heart-fill": 61850, + "bookmark-heart": 61851, + "bookmark-plus-fill": 61852, + "bookmark-plus": 61853, + "bookmark-star-fill": 61854, + "bookmark-star": 61855, + "bookmark-x-fill": 61856, + "bookmark-x": 61857, + "bookmark": 61858, + "bookmarks-fill": 61859, + "bookmarks": 61860, + "bookshelf": 61861, + "bootstrap-fill": 61862, + "bootstrap-reboot": 61863, + "bootstrap": 61864, + "border-all": 61865, + "border-bottom": 61866, + "border-center": 61867, + "border-inner": 61868, + "border-left": 61869, + "border-middle": 61870, + "border-outer": 61871, + "border-right": 61872, + "border-style": 61873, + "border-top": 61874, + "border-width": 61875, + "border": 61876, + "bounding-box-circles": 61877, + "bounding-box": 61878, + "box-arrow-down-left": 61879, + "box-arrow-down-right": 61880, + "box-arrow-down": 61881, + "box-arrow-in-down-left": 61882, + "box-arrow-in-down-right": 61883, + "box-arrow-in-down": 61884, + "box-arrow-in-left": 61885, + "box-arrow-in-right": 61886, + "box-arrow-in-up-left": 61887, + "box-arrow-in-up-right": 61888, + "box-arrow-in-up": 61889, + "box-arrow-left": 61890, + "box-arrow-right": 61891, + "box-arrow-up-left": 61892, + "box-arrow-up-right": 61893, + "box-arrow-up": 61894, + "box-seam": 61895, + "box": 61896, + "braces": 61897, + "bricks": 61898, + "briefcase-fill": 61899, + "briefcase": 61900, + "brightness-alt-high-fill": 61901, + "brightness-alt-high": 61902, + "brightness-alt-low-fill": 61903, + "brightness-alt-low": 61904, + "brightness-high-fill": 61905, + "brightness-high": 61906, + "brightness-low-fill": 61907, + "brightness-low": 61908, + "broadcast-pin": 61909, + "broadcast": 61910, + "brush-fill": 61911, + "brush": 61912, + "bucket-fill": 61913, + "bucket": 61914, + "bug-fill": 61915, + "bug": 61916, + "building": 61917, + "bullseye": 61918, + "calculator-fill": 61919, + "calculator": 61920, + "calendar-check-fill": 61921, + "calendar-check": 61922, + "calendar-date-fill": 61923, + "calendar-date": 61924, + "calendar-day-fill": 61925, + "calendar-day": 61926, + "calendar-event-fill": 61927, + "calendar-event": 61928, + "calendar-fill": 61929, + "calendar-minus-fill": 61930, + "calendar-minus": 61931, + "calendar-month-fill": 61932, + "calendar-month": 61933, + "calendar-plus-fill": 61934, + "calendar-plus": 61935, + "calendar-range-fill": 61936, + "calendar-range": 61937, + "calendar-week-fill": 61938, + "calendar-week": 61939, + "calendar-x-fill": 61940, + "calendar-x": 61941, + "calendar": 61942, + "calendar2-check-fill": 61943, + "calendar2-check": 61944, + "calendar2-date-fill": 61945, + "calendar2-date": 61946, + "calendar2-day-fill": 61947, + "calendar2-day": 61948, + "calendar2-event-fill": 61949, + "calendar2-event": 61950, + "calendar2-fill": 61951, + "calendar2-minus-fill": 61952, + "calendar2-minus": 61953, + "calendar2-month-fill": 61954, + "calendar2-month": 61955, + "calendar2-plus-fill": 61956, + "calendar2-plus": 61957, + "calendar2-range-fill": 61958, + "calendar2-range": 61959, + "calendar2-week-fill": 61960, + "calendar2-week": 61961, + "calendar2-x-fill": 61962, + "calendar2-x": 61963, + "calendar2": 61964, + "calendar3-event-fill": 61965, + "calendar3-event": 61966, + "calendar3-fill": 61967, + "calendar3-range-fill": 61968, + "calendar3-range": 61969, + "calendar3-week-fill": 61970, + "calendar3-week": 61971, + "calendar3": 61972, + "calendar4-event": 61973, + "calendar4-range": 61974, + "calendar4-week": 61975, + "calendar4": 61976, + "camera-fill": 61977, + "camera-reels-fill": 61978, + "camera-reels": 61979, + "camera-video-fill": 61980, + "camera-video-off-fill": 61981, + "camera-video-off": 61982, + "camera-video": 61983, + "camera": 61984, + "camera2": 61985, + "capslock-fill": 61986, + "capslock": 61987, + "card-checklist": 61988, + "card-heading": 61989, + "card-image": 61990, + "card-list": 61991, + "card-text": 61992, + "caret-down-fill": 61993, + "caret-down-square-fill": 61994, + "caret-down-square": 61995, + "caret-down": 61996, + "caret-left-fill": 61997, + "caret-left-square-fill": 61998, + "caret-left-square": 61999, + "caret-left": 62000, + "caret-right-fill": 62001, + "caret-right-square-fill": 62002, + "caret-right-square": 62003, + "caret-right": 62004, + "caret-up-fill": 62005, + "caret-up-square-fill": 62006, + "caret-up-square": 62007, + "caret-up": 62008, + "cart-check-fill": 62009, + "cart-check": 62010, + "cart-dash-fill": 62011, + "cart-dash": 62012, + "cart-fill": 62013, + "cart-plus-fill": 62014, + "cart-plus": 62015, + "cart-x-fill": 62016, + "cart-x": 62017, + "cart": 62018, + "cart2": 62019, + "cart3": 62020, + "cart4": 62021, + "cash-stack": 62022, + "cash": 62023, + "cast": 62024, + "chat-dots-fill": 62025, + "chat-dots": 62026, + "chat-fill": 62027, + "chat-left-dots-fill": 62028, + "chat-left-dots": 62029, + "chat-left-fill": 62030, + "chat-left-quote-fill": 62031, + "chat-left-quote": 62032, + "chat-left-text-fill": 62033, + "chat-left-text": 62034, + "chat-left": 62035, + "chat-quote-fill": 62036, + "chat-quote": 62037, + "chat-right-dots-fill": 62038, + "chat-right-dots": 62039, + "chat-right-fill": 62040, + "chat-right-quote-fill": 62041, + "chat-right-quote": 62042, + "chat-right-text-fill": 62043, + "chat-right-text": 62044, + "chat-right": 62045, + "chat-square-dots-fill": 62046, + "chat-square-dots": 62047, + "chat-square-fill": 62048, + "chat-square-quote-fill": 62049, + "chat-square-quote": 62050, + "chat-square-text-fill": 62051, + "chat-square-text": 62052, + "chat-square": 62053, + "chat-text-fill": 62054, + "chat-text": 62055, + "chat": 62056, + "check-all": 62057, + "check-circle-fill": 62058, + "check-circle": 62059, + "check-square-fill": 62060, + "check-square": 62061, + "check": 62062, + "check2-all": 62063, + "check2-circle": 62064, + "check2-square": 62065, + "check2": 62066, + "chevron-bar-contract": 62067, + "chevron-bar-down": 62068, + "chevron-bar-expand": 62069, + "chevron-bar-left": 62070, + "chevron-bar-right": 62071, + "chevron-bar-up": 62072, + "chevron-compact-down": 62073, + "chevron-compact-left": 62074, + "chevron-compact-right": 62075, + "chevron-compact-up": 62076, + "chevron-contract": 62077, + "chevron-double-down": 62078, + "chevron-double-left": 62079, + "chevron-double-right": 62080, + "chevron-double-up": 62081, + "chevron-down": 62082, + "chevron-expand": 62083, + "chevron-left": 62084, + "chevron-right": 62085, + "chevron-up": 62086, + "circle-fill": 62087, + "circle-half": 62088, + "circle-square": 62089, + "circle": 62090, + "clipboard-check": 62091, + "clipboard-data": 62092, + "clipboard-minus": 62093, + "clipboard-plus": 62094, + "clipboard-x": 62095, + "clipboard": 62096, + "clock-fill": 62097, + "clock-history": 62098, + "clock": 62099, + "cloud-arrow-down-fill": 62100, + "cloud-arrow-down": 62101, + "cloud-arrow-up-fill": 62102, + "cloud-arrow-up": 62103, + "cloud-check-fill": 62104, + "cloud-check": 62105, + "cloud-download-fill": 62106, + "cloud-download": 62107, + "cloud-drizzle-fill": 62108, + "cloud-drizzle": 62109, + "cloud-fill": 62110, + "cloud-fog-fill": 62111, + "cloud-fog": 62112, + "cloud-fog2-fill": 62113, + "cloud-fog2": 62114, + "cloud-hail-fill": 62115, + "cloud-hail": 62116, + "cloud-haze-fill": 62118, + "cloud-haze": 62119, + "cloud-haze2-fill": 62120, + "cloud-lightning-fill": 62121, + "cloud-lightning-rain-fill": 62122, + "cloud-lightning-rain": 62123, + "cloud-lightning": 62124, + "cloud-minus-fill": 62125, + "cloud-minus": 62126, + "cloud-moon-fill": 62127, + "cloud-moon": 62128, + "cloud-plus-fill": 62129, + "cloud-plus": 62130, + "cloud-rain-fill": 62131, + "cloud-rain-heavy-fill": 62132, + "cloud-rain-heavy": 62133, + "cloud-rain": 62134, + "cloud-slash-fill": 62135, + "cloud-slash": 62136, + "cloud-sleet-fill": 62137, + "cloud-sleet": 62138, + "cloud-snow-fill": 62139, + "cloud-snow": 62140, + "cloud-sun-fill": 62141, + "cloud-sun": 62142, + "cloud-upload-fill": 62143, + "cloud-upload": 62144, + "cloud": 62145, + "clouds-fill": 62146, + "clouds": 62147, + "cloudy-fill": 62148, + "cloudy": 62149, + "code-slash": 62150, + "code-square": 62151, + "code": 62152, + "collection-fill": 62153, + "collection-play-fill": 62154, + "collection-play": 62155, + "collection": 62156, + "columns-gap": 62157, + "columns": 62158, + "command": 62159, + "compass-fill": 62160, + "compass": 62161, + "cone-striped": 62162, + "cone": 62163, + "controller": 62164, + "cpu-fill": 62165, + "cpu": 62166, + "credit-card-2-back-fill": 62167, + "credit-card-2-back": 62168, + "credit-card-2-front-fill": 62169, + "credit-card-2-front": 62170, + "credit-card-fill": 62171, + "credit-card": 62172, + "crop": 62173, + "cup-fill": 62174, + "cup-straw": 62175, + "cup": 62176, + "cursor-fill": 62177, + "cursor-text": 62178, + "cursor": 62179, + "dash-circle-dotted": 62180, + "dash-circle-fill": 62181, + "dash-circle": 62182, + "dash-square-dotted": 62183, + "dash-square-fill": 62184, + "dash-square": 62185, + "dash": 62186, + "diagram-2-fill": 62187, + "diagram-2": 62188, + "diagram-3-fill": 62189, + "diagram-3": 62190, + "diamond-fill": 62191, + "diamond-half": 62192, + "diamond": 62193, + "dice-1-fill": 62194, + "dice-1": 62195, + "dice-2-fill": 62196, + "dice-2": 62197, + "dice-3-fill": 62198, + "dice-3": 62199, + "dice-4-fill": 62200, + "dice-4": 62201, + "dice-5-fill": 62202, + "dice-5": 62203, + "dice-6-fill": 62204, + "dice-6": 62205, + "disc-fill": 62206, + "disc": 62207, + "discord": 62208, + "display-fill": 62209, + "display": 62210, + "distribute-horizontal": 62211, + "distribute-vertical": 62212, + "door-closed-fill": 62213, + "door-closed": 62214, + "door-open-fill": 62215, + "door-open": 62216, + "dot": 62217, + "download": 62218, + "droplet-fill": 62219, + "droplet-half": 62220, + "droplet": 62221, + "earbuds": 62222, + "easel-fill": 62223, + "easel": 62224, + "egg-fill": 62225, + "egg-fried": 62226, + "egg": 62227, + "eject-fill": 62228, + "eject": 62229, + "emoji-angry-fill": 62230, + "emoji-angry": 62231, + "emoji-dizzy-fill": 62232, + "emoji-dizzy": 62233, + "emoji-expressionless-fill": 62234, + "emoji-expressionless": 62235, + "emoji-frown-fill": 62236, + "emoji-frown": 62237, + "emoji-heart-eyes-fill": 62238, + "emoji-heart-eyes": 62239, + "emoji-laughing-fill": 62240, + "emoji-laughing": 62241, + "emoji-neutral-fill": 62242, + "emoji-neutral": 62243, + "emoji-smile-fill": 62244, + "emoji-smile-upside-down-fill": 62245, + "emoji-smile-upside-down": 62246, + "emoji-smile": 62247, + "emoji-sunglasses-fill": 62248, + "emoji-sunglasses": 62249, + "emoji-wink-fill": 62250, + "emoji-wink": 62251, + "envelope-fill": 62252, + "envelope-open-fill": 62253, + "envelope-open": 62254, + "envelope": 62255, + "eraser-fill": 62256, + "eraser": 62257, + "exclamation-circle-fill": 62258, + "exclamation-circle": 62259, + "exclamation-diamond-fill": 62260, + "exclamation-diamond": 62261, + "exclamation-octagon-fill": 62262, + "exclamation-octagon": 62263, + "exclamation-square-fill": 62264, + "exclamation-square": 62265, + "exclamation-triangle-fill": 62266, + "exclamation-triangle": 62267, + "exclamation": 62268, + "exclude": 62269, + "eye-fill": 62270, + "eye-slash-fill": 62271, + "eye-slash": 62272, + "eye": 62273, + "eyedropper": 62274, + "eyeglasses": 62275, + "facebook": 62276, + "file-arrow-down-fill": 62277, + "file-arrow-down": 62278, + "file-arrow-up-fill": 62279, + "file-arrow-up": 62280, + "file-bar-graph-fill": 62281, + "file-bar-graph": 62282, + "file-binary-fill": 62283, + "file-binary": 62284, + "file-break-fill": 62285, + "file-break": 62286, + "file-check-fill": 62287, + "file-check": 62288, + "file-code-fill": 62289, + "file-code": 62290, + "file-diff-fill": 62291, + "file-diff": 62292, + "file-earmark-arrow-down-fill": 62293, + "file-earmark-arrow-down": 62294, + "file-earmark-arrow-up-fill": 62295, + "file-earmark-arrow-up": 62296, + "file-earmark-bar-graph-fill": 62297, + "file-earmark-bar-graph": 62298, + "file-earmark-binary-fill": 62299, + "file-earmark-binary": 62300, + "file-earmark-break-fill": 62301, + "file-earmark-break": 62302, + "file-earmark-check-fill": 62303, + "file-earmark-check": 62304, + "file-earmark-code-fill": 62305, + "file-earmark-code": 62306, + "file-earmark-diff-fill": 62307, + "file-earmark-diff": 62308, + "file-earmark-easel-fill": 62309, + "file-earmark-easel": 62310, + "file-earmark-excel-fill": 62311, + "file-earmark-excel": 62312, + "file-earmark-fill": 62313, + "file-earmark-font-fill": 62314, + "file-earmark-font": 62315, + "file-earmark-image-fill": 62316, + "file-earmark-image": 62317, + "file-earmark-lock-fill": 62318, + "file-earmark-lock": 62319, + "file-earmark-lock2-fill": 62320, + "file-earmark-lock2": 62321, + "file-earmark-medical-fill": 62322, + "file-earmark-medical": 62323, + "file-earmark-minus-fill": 62324, + "file-earmark-minus": 62325, + "file-earmark-music-fill": 62326, + "file-earmark-music": 62327, + "file-earmark-person-fill": 62328, + "file-earmark-person": 62329, + "file-earmark-play-fill": 62330, + "file-earmark-play": 62331, + "file-earmark-plus-fill": 62332, + "file-earmark-plus": 62333, + "file-earmark-post-fill": 62334, + "file-earmark-post": 62335, + "file-earmark-ppt-fill": 62336, + "file-earmark-ppt": 62337, + "file-earmark-richtext-fill": 62338, + "file-earmark-richtext": 62339, + "file-earmark-ruled-fill": 62340, + "file-earmark-ruled": 62341, + "file-earmark-slides-fill": 62342, + "file-earmark-slides": 62343, + "file-earmark-spreadsheet-fill": 62344, + "file-earmark-spreadsheet": 62345, + "file-earmark-text-fill": 62346, + "file-earmark-text": 62347, + "file-earmark-word-fill": 62348, + "file-earmark-word": 62349, + "file-earmark-x-fill": 62350, + "file-earmark-x": 62351, + "file-earmark-zip-fill": 62352, + "file-earmark-zip": 62353, + "file-earmark": 62354, + "file-easel-fill": 62355, + "file-easel": 62356, + "file-excel-fill": 62357, + "file-excel": 62358, + "file-fill": 62359, + "file-font-fill": 62360, + "file-font": 62361, + "file-image-fill": 62362, + "file-image": 62363, + "file-lock-fill": 62364, + "file-lock": 62365, + "file-lock2-fill": 62366, + "file-lock2": 62367, + "file-medical-fill": 62368, + "file-medical": 62369, + "file-minus-fill": 62370, + "file-minus": 62371, + "file-music-fill": 62372, + "file-music": 62373, + "file-person-fill": 62374, + "file-person": 62375, + "file-play-fill": 62376, + "file-play": 62377, + "file-plus-fill": 62378, + "file-plus": 62379, + "file-post-fill": 62380, + "file-post": 62381, + "file-ppt-fill": 62382, + "file-ppt": 62383, + "file-richtext-fill": 62384, + "file-richtext": 62385, + "file-ruled-fill": 62386, + "file-ruled": 62387, + "file-slides-fill": 62388, + "file-slides": 62389, + "file-spreadsheet-fill": 62390, + "file-spreadsheet": 62391, + "file-text-fill": 62392, + "file-text": 62393, + "file-word-fill": 62394, + "file-word": 62395, + "file-x-fill": 62396, + "file-x": 62397, + "file-zip-fill": 62398, + "file-zip": 62399, + "file": 62400, + "files-alt": 62401, + "files": 62402, + "film": 62403, + "filter-circle-fill": 62404, + "filter-circle": 62405, + "filter-left": 62406, + "filter-right": 62407, + "filter-square-fill": 62408, + "filter-square": 62409, + "filter": 62410, + "flag-fill": 62411, + "flag": 62412, + "flower1": 62413, + "flower2": 62414, + "flower3": 62415, + "folder-check": 62416, + "folder-fill": 62417, + "folder-minus": 62418, + "folder-plus": 62419, + "folder-symlink-fill": 62420, + "folder-symlink": 62421, + "folder-x": 62422, + "folder": 62423, + "folder2-open": 62424, + "folder2": 62425, + "fonts": 62426, + "forward-fill": 62427, + "forward": 62428, + "front": 62429, + "fullscreen-exit": 62430, + "fullscreen": 62431, + "funnel-fill": 62432, + "funnel": 62433, + "gear-fill": 62434, + "gear-wide-connected": 62435, + "gear-wide": 62436, + "gear": 62437, + "gem": 62438, + "geo-alt-fill": 62439, + "geo-alt": 62440, + "geo-fill": 62441, + "geo": 62442, + "gift-fill": 62443, + "gift": 62444, + "github": 62445, + "globe": 62446, + "globe2": 62447, + "google": 62448, + "graph-down": 62449, + "graph-up": 62450, + "grid-1x2-fill": 62451, + "grid-1x2": 62452, + "grid-3x2-gap-fill": 62453, + "grid-3x2-gap": 62454, + "grid-3x2": 62455, + "grid-3x3-gap-fill": 62456, + "grid-3x3-gap": 62457, + "grid-3x3": 62458, + "grid-fill": 62459, + "grid": 62460, + "grip-horizontal": 62461, + "grip-vertical": 62462, + "hammer": 62463, + "hand-index-fill": 62464, + "hand-index-thumb-fill": 62465, + "hand-index-thumb": 62466, + "hand-index": 62467, + "hand-thumbs-down-fill": 62468, + "hand-thumbs-down": 62469, + "hand-thumbs-up-fill": 62470, + "hand-thumbs-up": 62471, + "handbag-fill": 62472, + "handbag": 62473, + "hash": 62474, + "hdd-fill": 62475, + "hdd-network-fill": 62476, + "hdd-network": 62477, + "hdd-rack-fill": 62478, + "hdd-rack": 62479, + "hdd-stack-fill": 62480, + "hdd-stack": 62481, + "hdd": 62482, + "headphones": 62483, + "headset": 62484, + "heart-fill": 62485, + "heart-half": 62486, + "heart": 62487, + "heptagon-fill": 62488, + "heptagon-half": 62489, + "heptagon": 62490, + "hexagon-fill": 62491, + "hexagon-half": 62492, + "hexagon": 62493, + "hourglass-bottom": 62494, + "hourglass-split": 62495, + "hourglass-top": 62496, + "hourglass": 62497, + "house-door-fill": 62498, + "house-door": 62499, + "house-fill": 62500, + "house": 62501, + "hr": 62502, + "hurricane": 62503, + "image-alt": 62504, + "image-fill": 62505, + "image": 62506, + "images": 62507, + "inbox-fill": 62508, + "inbox": 62509, + "inboxes-fill": 62510, + "inboxes": 62511, + "info-circle-fill": 62512, + "info-circle": 62513, + "info-square-fill": 62514, + "info-square": 62515, + "info": 62516, + "input-cursor-text": 62517, + "input-cursor": 62518, + "instagram": 62519, + "intersect": 62520, + "journal-album": 62521, + "journal-arrow-down": 62522, + "journal-arrow-up": 62523, + "journal-bookmark-fill": 62524, + "journal-bookmark": 62525, + "journal-check": 62526, + "journal-code": 62527, + "journal-medical": 62528, + "journal-minus": 62529, + "journal-plus": 62530, + "journal-richtext": 62531, + "journal-text": 62532, + "journal-x": 62533, + "journal": 62534, + "journals": 62535, + "joystick": 62536, + "justify-left": 62537, + "justify-right": 62538, + "justify": 62539, + "kanban-fill": 62540, + "kanban": 62541, + "key-fill": 62542, + "key": 62543, + "keyboard-fill": 62544, + "keyboard": 62545, + "ladder": 62546, + "lamp-fill": 62547, + "lamp": 62548, + "laptop-fill": 62549, + "laptop": 62550, + "layer-backward": 62551, + "layer-forward": 62552, + "layers-fill": 62553, + "layers-half": 62554, + "layers": 62555, + "layout-sidebar-inset-reverse": 62556, + "layout-sidebar-inset": 62557, + "layout-sidebar-reverse": 62558, + "layout-sidebar": 62559, + "layout-split": 62560, + "layout-text-sidebar-reverse": 62561, + "layout-text-sidebar": 62562, + "layout-text-window-reverse": 62563, + "layout-text-window": 62564, + "layout-three-columns": 62565, + "layout-wtf": 62566, + "life-preserver": 62567, + "lightbulb-fill": 62568, + "lightbulb-off-fill": 62569, + "lightbulb-off": 62570, + "lightbulb": 62571, + "lightning-charge-fill": 62572, + "lightning-charge": 62573, + "lightning-fill": 62574, + "lightning": 62575, + "link-45deg": 62576, + "link": 62577, + "linkedin": 62578, + "list-check": 62579, + "list-nested": 62580, + "list-ol": 62581, + "list-stars": 62582, + "list-task": 62583, + "list-ul": 62584, + "list": 62585, + "lock-fill": 62586, + "lock": 62587, + "mailbox": 62588, + "mailbox2": 62589, + "map-fill": 62590, + "map": 62591, + "markdown-fill": 62592, + "markdown": 62593, + "mask": 62594, + "megaphone-fill": 62595, + "megaphone": 62596, + "menu-app-fill": 62597, + "menu-app": 62598, + "menu-button-fill": 62599, + "menu-button-wide-fill": 62600, + "menu-button-wide": 62601, + "menu-button": 62602, + "menu-down": 62603, + "menu-up": 62604, + "mic-fill": 62605, + "mic-mute-fill": 62606, + "mic-mute": 62607, + "mic": 62608, + "minecart-loaded": 62609, + "minecart": 62610, + "moisture": 62611, + "moon-fill": 62612, + "moon-stars-fill": 62613, + "moon-stars": 62614, + "moon": 62615, + "mouse-fill": 62616, + "mouse": 62617, + "mouse2-fill": 62618, + "mouse2": 62619, + "mouse3-fill": 62620, + "mouse3": 62621, + "music-note-beamed": 62622, + "music-note-list": 62623, + "music-note": 62624, + "music-player-fill": 62625, + "music-player": 62626, + "newspaper": 62627, + "node-minus-fill": 62628, + "node-minus": 62629, + "node-plus-fill": 62630, + "node-plus": 62631, + "nut-fill": 62632, + "nut": 62633, + "octagon-fill": 62634, + "octagon-half": 62635, + "octagon": 62636, + "option": 62637, + "outlet": 62638, + "paint-bucket": 62639, + "palette-fill": 62640, + "palette": 62641, + "palette2": 62642, + "paperclip": 62643, + "paragraph": 62644, + "patch-check-fill": 62645, + "patch-check": 62646, + "patch-exclamation-fill": 62647, + "patch-exclamation": 62648, + "patch-minus-fill": 62649, + "patch-minus": 62650, + "patch-plus-fill": 62651, + "patch-plus": 62652, + "patch-question-fill": 62653, + "patch-question": 62654, + "pause-btn-fill": 62655, + "pause-btn": 62656, + "pause-circle-fill": 62657, + "pause-circle": 62658, + "pause-fill": 62659, + "pause": 62660, + "peace-fill": 62661, + "peace": 62662, + "pen-fill": 62663, + "pen": 62664, + "pencil-fill": 62665, + "pencil-square": 62666, + "pencil": 62667, + "pentagon-fill": 62668, + "pentagon-half": 62669, + "pentagon": 62670, + "people-fill": 62671, + "people": 62672, + "percent": 62673, + "person-badge-fill": 62674, + "person-badge": 62675, + "person-bounding-box": 62676, + "person-check-fill": 62677, + "person-check": 62678, + "person-circle": 62679, + "person-dash-fill": 62680, + "person-dash": 62681, + "person-fill": 62682, + "person-lines-fill": 62683, + "person-plus-fill": 62684, + "person-plus": 62685, + "person-square": 62686, + "person-x-fill": 62687, + "person-x": 62688, + "person": 62689, + "phone-fill": 62690, + "phone-landscape-fill": 62691, + "phone-landscape": 62692, + "phone-vibrate-fill": 62693, + "phone-vibrate": 62694, + "phone": 62695, + "pie-chart-fill": 62696, + "pie-chart": 62697, + "pin-angle-fill": 62698, + "pin-angle": 62699, + "pin-fill": 62700, + "pin": 62701, + "pip-fill": 62702, + "pip": 62703, + "play-btn-fill": 62704, + "play-btn": 62705, + "play-circle-fill": 62706, + "play-circle": 62707, + "play-fill": 62708, + "play": 62709, + "plug-fill": 62710, + "plug": 62711, + "plus-circle-dotted": 62712, + "plus-circle-fill": 62713, + "plus-circle": 62714, + "plus-square-dotted": 62715, + "plus-square-fill": 62716, + "plus-square": 62717, + "plus": 62718, + "power": 62719, + "printer-fill": 62720, + "printer": 62721, + "puzzle-fill": 62722, + "puzzle": 62723, + "question-circle-fill": 62724, + "question-circle": 62725, + "question-diamond-fill": 62726, + "question-diamond": 62727, + "question-octagon-fill": 62728, + "question-octagon": 62729, + "question-square-fill": 62730, + "question-square": 62731, + "question": 62732, + "rainbow": 62733, + "receipt-cutoff": 62734, + "receipt": 62735, + "reception-0": 62736, + "reception-1": 62737, + "reception-2": 62738, + "reception-3": 62739, + "reception-4": 62740, + "record-btn-fill": 62741, + "record-btn": 62742, + "record-circle-fill": 62743, + "record-circle": 62744, + "record-fill": 62745, + "record": 62746, + "record2-fill": 62747, + "record2": 62748, + "reply-all-fill": 62749, + "reply-all": 62750, + "reply-fill": 62751, + "reply": 62752, + "rss-fill": 62753, + "rss": 62754, + "rulers": 62755, + "save-fill": 62756, + "save": 62757, + "save2-fill": 62758, + "save2": 62759, + "scissors": 62760, + "screwdriver": 62761, + "search": 62762, + "segmented-nav": 62763, + "server": 62764, + "share-fill": 62765, + "share": 62766, + "shield-check": 62767, + "shield-exclamation": 62768, + "shield-fill-check": 62769, + "shield-fill-exclamation": 62770, + "shield-fill-minus": 62771, + "shield-fill-plus": 62772, + "shield-fill-x": 62773, + "shield-fill": 62774, + "shield-lock-fill": 62775, + "shield-lock": 62776, + "shield-minus": 62777, + "shield-plus": 62778, + "shield-shaded": 62779, + "shield-slash-fill": 62780, + "shield-slash": 62781, + "shield-x": 62782, + "shield": 62783, + "shift-fill": 62784, + "shift": 62785, + "shop-window": 62786, + "shop": 62787, + "shuffle": 62788, + "signpost-2-fill": 62789, + "signpost-2": 62790, + "signpost-fill": 62791, + "signpost-split-fill": 62792, + "signpost-split": 62793, + "signpost": 62794, + "sim-fill": 62795, + "sim": 62796, + "skip-backward-btn-fill": 62797, + "skip-backward-btn": 62798, + "skip-backward-circle-fill": 62799, + "skip-backward-circle": 62800, + "skip-backward-fill": 62801, + "skip-backward": 62802, + "skip-end-btn-fill": 62803, + "skip-end-btn": 62804, + "skip-end-circle-fill": 62805, + "skip-end-circle": 62806, + "skip-end-fill": 62807, + "skip-end": 62808, + "skip-forward-btn-fill": 62809, + "skip-forward-btn": 62810, + "skip-forward-circle-fill": 62811, + "skip-forward-circle": 62812, + "skip-forward-fill": 62813, + "skip-forward": 62814, + "skip-start-btn-fill": 62815, + "skip-start-btn": 62816, + "skip-start-circle-fill": 62817, + "skip-start-circle": 62818, + "skip-start-fill": 62819, + "skip-start": 62820, + "slack": 62821, + "slash-circle-fill": 62822, + "slash-circle": 62823, + "slash-square-fill": 62824, + "slash-square": 62825, + "slash": 62826, + "sliders": 62827, + "smartwatch": 62828, + "snow": 62829, + "snow2": 62830, + "snow3": 62831, + "sort-alpha-down-alt": 62832, + "sort-alpha-down": 62833, + "sort-alpha-up-alt": 62834, + "sort-alpha-up": 62835, + "sort-down-alt": 62836, + "sort-down": 62837, + "sort-numeric-down-alt": 62838, + "sort-numeric-down": 62839, + "sort-numeric-up-alt": 62840, + "sort-numeric-up": 62841, + "sort-up-alt": 62842, + "sort-up": 62843, + "soundwave": 62844, + "speaker-fill": 62845, + "speaker": 62846, + "speedometer": 62847, + "speedometer2": 62848, + "spellcheck": 62849, + "square-fill": 62850, + "square-half": 62851, + "square": 62852, + "stack": 62853, + "star-fill": 62854, + "star-half": 62855, + "star": 62856, + "stars": 62857, + "stickies-fill": 62858, + "stickies": 62859, + "sticky-fill": 62860, + "sticky": 62861, + "stop-btn-fill": 62862, + "stop-btn": 62863, + "stop-circle-fill": 62864, + "stop-circle": 62865, + "stop-fill": 62866, + "stop": 62867, + "stoplights-fill": 62868, + "stoplights": 62869, + "stopwatch-fill": 62870, + "stopwatch": 62871, + "subtract": 62872, + "suit-club-fill": 62873, + "suit-club": 62874, + "suit-diamond-fill": 62875, + "suit-diamond": 62876, + "suit-heart-fill": 62877, + "suit-heart": 62878, + "suit-spade-fill": 62879, + "suit-spade": 62880, + "sun-fill": 62881, + "sun": 62882, + "sunglasses": 62883, + "sunrise-fill": 62884, + "sunrise": 62885, + "sunset-fill": 62886, + "sunset": 62887, + "symmetry-horizontal": 62888, + "symmetry-vertical": 62889, + "table": 62890, + "tablet-fill": 62891, + "tablet-landscape-fill": 62892, + "tablet-landscape": 62893, + "tablet": 62894, + "tag-fill": 62895, + "tag": 62896, + "tags-fill": 62897, + "tags": 62898, + "telegram": 62899, + "telephone-fill": 62900, + "telephone-forward-fill": 62901, + "telephone-forward": 62902, + "telephone-inbound-fill": 62903, + "telephone-inbound": 62904, + "telephone-minus-fill": 62905, + "telephone-minus": 62906, + "telephone-outbound-fill": 62907, + "telephone-outbound": 62908, + "telephone-plus-fill": 62909, + "telephone-plus": 62910, + "telephone-x-fill": 62911, + "telephone-x": 62912, + "telephone": 62913, + "terminal-fill": 62914, + "terminal": 62915, + "text-center": 62916, + "text-indent-left": 62917, + "text-indent-right": 62918, + "text-left": 62919, + "text-paragraph": 62920, + "text-right": 62921, + "textarea-resize": 62922, + "textarea-t": 62923, + "textarea": 62924, + "thermometer-half": 62925, + "thermometer-high": 62926, + "thermometer-low": 62927, + "thermometer-snow": 62928, + "thermometer-sun": 62929, + "thermometer": 62930, + "three-dots-vertical": 62931, + "three-dots": 62932, + "toggle-off": 62933, + "toggle-on": 62934, + "toggle2-off": 62935, + "toggle2-on": 62936, + "toggles": 62937, + "toggles2": 62938, + "tools": 62939, + "tornado": 62940, + "trash-fill": 62941, + "trash": 62942, + "trash2-fill": 62943, + "trash2": 62944, + "tree-fill": 62945, + "tree": 62946, + "triangle-fill": 62947, + "triangle-half": 62948, + "triangle": 62949, + "trophy-fill": 62950, + "trophy": 62951, + "tropical-storm": 62952, + "truck-flatbed": 62953, + "truck": 62954, + "tsunami": 62955, + "tv-fill": 62956, + "tv": 62957, + "twitch": 62958, + "twitter": 62959, + "type-bold": 62960, + "type-h1": 62961, + "type-h2": 62962, + "type-h3": 62963, + "type-italic": 62964, + "type-strikethrough": 62965, + "type-underline": 62966, + "type": 62967, + "ui-checks-grid": 62968, + "ui-checks": 62969, + "ui-radios-grid": 62970, + "ui-radios": 62971, + "umbrella-fill": 62972, + "umbrella": 62973, + "union": 62974, + "unlock-fill": 62975, + "unlock": 62976, + "upc-scan": 62977, + "upc": 62978, + "upload": 62979, + "vector-pen": 62980, + "view-list": 62981, + "view-stacked": 62982, + "vinyl-fill": 62983, + "vinyl": 62984, + "voicemail": 62985, + "volume-down-fill": 62986, + "volume-down": 62987, + "volume-mute-fill": 62988, + "volume-mute": 62989, + "volume-off-fill": 62990, + "volume-off": 62991, + "volume-up-fill": 62992, + "volume-up": 62993, + "vr": 62994, + "wallet-fill": 62995, + "wallet": 62996, + "wallet2": 62997, + "watch": 62998, + "water": 62999, + "whatsapp": 63000, + "wifi-1": 63001, + "wifi-2": 63002, + "wifi-off": 63003, + "wifi": 63004, + "wind": 63005, + "window-dock": 63006, + "window-sidebar": 63007, + "window": 63008, + "wrench": 63009, + "x-circle-fill": 63010, + "x-circle": 63011, + "x-diamond-fill": 63012, + "x-diamond": 63013, + "x-octagon-fill": 63014, + "x-octagon": 63015, + "x-square-fill": 63016, + "x-square": 63017, + "x": 63018, + "youtube": 63019, + "zoom-in": 63020, + "zoom-out": 63021, + "bank": 63022, + "bank2": 63023, + "bell-slash-fill": 63024, + "bell-slash": 63025, + "cash-coin": 63026, + "check-lg": 63027, + "coin": 63028, + "currency-bitcoin": 63029, + "currency-dollar": 63030, + "currency-euro": 63031, + "currency-exchange": 63032, + "currency-pound": 63033, + "currency-yen": 63034, + "dash-lg": 63035, + "exclamation-lg": 63036, + "file-earmark-pdf-fill": 63037, + "file-earmark-pdf": 63038, + "file-pdf-fill": 63039, + "file-pdf": 63040, + "gender-ambiguous": 63041, + "gender-female": 63042, + "gender-male": 63043, + "gender-trans": 63044, + "headset-vr": 63045, + "info-lg": 63046, + "mastodon": 63047, + "messenger": 63048, + "piggy-bank-fill": 63049, + "piggy-bank": 63050, + "pin-map-fill": 63051, + "pin-map": 63052, + "plus-lg": 63053, + "question-lg": 63054, + "recycle": 63055, + "reddit": 63056, + "safe-fill": 63057, + "safe2-fill": 63058, + "safe2": 63059, + "sd-card-fill": 63060, + "sd-card": 63061, + "skype": 63062, + "slash-lg": 63063, + "translate": 63064, + "x-lg": 63065, + "safe": 63066, + "apple": 63067, + "microsoft": 63069, + "windows": 63070, + "behance": 63068, + "dribbble": 63071, + "line": 63072, + "medium": 63073, + "paypal": 63074, + "pinterest": 63075, + "signal": 63076, + "snapchat": 63077, + "spotify": 63078, + "stack-overflow": 63079, + "strava": 63080, + "wordpress": 63081, + "vimeo": 63082, + "activity": 63083, + "easel2-fill": 63084, + "easel2": 63085, + "easel3-fill": 63086, + "easel3": 63087, + "fan": 63088, + "fingerprint": 63089, + "graph-down-arrow": 63090, + "graph-up-arrow": 63091, + "hypnotize": 63092, + "magic": 63093, + "person-rolodex": 63094, + "person-video": 63095, + "person-video2": 63096, + "person-video3": 63097, + "person-workspace": 63098, + "radioactive": 63099, + "webcam-fill": 63100, + "webcam": 63101, + "yin-yang": 63102, + "bandaid-fill": 63104, + "bandaid": 63105, + "bluetooth": 63106, + "body-text": 63107, + "boombox": 63108, + "boxes": 63109, + "dpad-fill": 63110, + "dpad": 63111, + "ear-fill": 63112, + "ear": 63113, + "envelope-check-fill": 63115, + "envelope-check": 63116, + "envelope-dash-fill": 63118, + "envelope-dash": 63119, + "envelope-exclamation-fill": 63121, + "envelope-exclamation": 63122, + "envelope-plus-fill": 63123, + "envelope-plus": 63124, + "envelope-slash-fill": 63126, + "envelope-slash": 63127, + "envelope-x-fill": 63129, + "envelope-x": 63130, + "explicit-fill": 63131, + "explicit": 63132, + "git": 63133, + "infinity": 63134, + "list-columns-reverse": 63135, + "list-columns": 63136, + "meta": 63137, + "nintendo-switch": 63140, + "pc-display-horizontal": 63141, + "pc-display": 63142, + "pc-horizontal": 63143, + "pc": 63144, + "playstation": 63145, + "plus-slash-minus": 63146, + "projector-fill": 63147, + "projector": 63148, + "qr-code-scan": 63149, + "qr-code": 63150, + "quora": 63151, + "quote": 63152, + "robot": 63153, + "send-check-fill": 63154, + "send-check": 63155, + "send-dash-fill": 63156, + "send-dash": 63157, + "send-exclamation-fill": 63159, + "send-exclamation": 63160, + "send-fill": 63161, + "send-plus-fill": 63162, + "send-plus": 63163, + "send-slash-fill": 63164, + "send-slash": 63165, + "send-x-fill": 63166, + "send-x": 63167, + "send": 63168, + "steam": 63169, + "terminal-dash": 63171, + "terminal-plus": 63172, + "terminal-split": 63173, + "ticket-detailed-fill": 63174, + "ticket-detailed": 63175, + "ticket-fill": 63176, + "ticket-perforated-fill": 63177, + "ticket-perforated": 63178, + "ticket": 63179, + "tiktok": 63180, + "window-dash": 63181, + "window-desktop": 63182, + "window-fullscreen": 63183, + "window-plus": 63184, + "window-split": 63185, + "window-stack": 63186, + "window-x": 63187, + "xbox": 63188, + "ethernet": 63189, + "hdmi-fill": 63190, + "hdmi": 63191, + "usb-c-fill": 63192, + "usb-c": 63193, + "usb-fill": 63194, + "usb-plug-fill": 63195, + "usb-plug": 63196, + "usb-symbol": 63197, + "usb": 63198, + "boombox-fill": 63199, + "displayport": 63201, + "gpu-card": 63202, + "memory": 63203, + "modem-fill": 63204, + "modem": 63205, + "motherboard-fill": 63206, + "motherboard": 63207, + "optical-audio-fill": 63208, + "optical-audio": 63209, + "pci-card": 63210, + "router-fill": 63211, + "router": 63212, + "thunderbolt-fill": 63215, + "thunderbolt": 63216, + "usb-drive-fill": 63217, + "usb-drive": 63218, + "usb-micro-fill": 63219, + "usb-micro": 63220, + "usb-mini-fill": 63221, + "usb-mini": 63222, + "cloud-haze2": 63223, + "device-hdd-fill": 63224, + "device-hdd": 63225, + "device-ssd-fill": 63226, + "device-ssd": 63227, + "displayport-fill": 63228, + "mortarboard-fill": 63229, + "mortarboard": 63230, + "terminal-x": 63231, + "arrow-through-heart-fill": 63232, + "arrow-through-heart": 63233, + "badge-sd-fill": 63234, + "badge-sd": 63235, + "bag-heart-fill": 63236, + "bag-heart": 63237, + "balloon-fill": 63238, + "balloon-heart-fill": 63239, + "balloon-heart": 63240, + "balloon": 63241, + "box2-fill": 63242, + "box2-heart-fill": 63243, + "box2-heart": 63244, + "box2": 63245, + "braces-asterisk": 63246, + "calendar-heart-fill": 63247, + "calendar-heart": 63248, + "calendar2-heart-fill": 63249, + "calendar2-heart": 63250, + "chat-heart-fill": 63251, + "chat-heart": 63252, + "chat-left-heart-fill": 63253, + "chat-left-heart": 63254, + "chat-right-heart-fill": 63255, + "chat-right-heart": 63256, + "chat-square-heart-fill": 63257, + "chat-square-heart": 63258, + "clipboard-check-fill": 63259, + "clipboard-data-fill": 63260, + "clipboard-fill": 63261, + "clipboard-heart-fill": 63262, + "clipboard-heart": 63263, + "clipboard-minus-fill": 63264, + "clipboard-plus-fill": 63265, + "clipboard-pulse": 63266, + "clipboard-x-fill": 63267, + "clipboard2-check-fill": 63268, + "clipboard2-check": 63269, + "clipboard2-data-fill": 63270, + "clipboard2-data": 63271, + "clipboard2-fill": 63272, + "clipboard2-heart-fill": 63273, + "clipboard2-heart": 63274, + "clipboard2-minus-fill": 63275, + "clipboard2-minus": 63276, + "clipboard2-plus-fill": 63277, + "clipboard2-plus": 63278, + "clipboard2-pulse-fill": 63279, + "clipboard2-pulse": 63280, + "clipboard2-x-fill": 63281, + "clipboard2-x": 63282, + "clipboard2": 63283, + "emoji-kiss-fill": 63284, + "emoji-kiss": 63285, + "envelope-heart-fill": 63286, + "envelope-heart": 63287, + "envelope-open-heart-fill": 63288, + "envelope-open-heart": 63289, + "envelope-paper-fill": 63290, + "envelope-paper-heart-fill": 63291, + "envelope-paper-heart": 63292, + "envelope-paper": 63293, + "filetype-aac": 63294, + "filetype-ai": 63295, + "filetype-bmp": 63296, + "filetype-cs": 63297, + "filetype-css": 63298, + "filetype-csv": 63299, + "filetype-doc": 63300, + "filetype-docx": 63301, + "filetype-exe": 63302, + "filetype-gif": 63303, + "filetype-heic": 63304, + "filetype-html": 63305, + "filetype-java": 63306, + "filetype-jpg": 63307, + "filetype-js": 63308, + "filetype-jsx": 63309, + "filetype-key": 63310, + "filetype-m4p": 63311, + "filetype-md": 63312, + "filetype-mdx": 63313, + "filetype-mov": 63314, + "filetype-mp3": 63315, + "filetype-mp4": 63316, + "filetype-otf": 63317, + "filetype-pdf": 63318, + "filetype-php": 63319, + "filetype-png": 63320, + "filetype-ppt": 63322, + "filetype-psd": 63323, + "filetype-py": 63324, + "filetype-raw": 63325, + "filetype-rb": 63326, + "filetype-sass": 63327, + "filetype-scss": 63328, + "filetype-sh": 63329, + "filetype-svg": 63330, + "filetype-tiff": 63331, + "filetype-tsx": 63332, + "filetype-ttf": 63333, + "filetype-txt": 63334, + "filetype-wav": 63335, + "filetype-woff": 63336, + "filetype-xls": 63338, + "filetype-xml": 63339, + "filetype-yml": 63340, + "heart-arrow": 63341, + "heart-pulse-fill": 63342, + "heart-pulse": 63343, + "heartbreak-fill": 63344, + "heartbreak": 63345, + "hearts": 63346, + "hospital-fill": 63347, + "hospital": 63348, + "house-heart-fill": 63349, + "house-heart": 63350, + "incognito": 63351, + "magnet-fill": 63352, + "magnet": 63353, + "person-heart": 63354, + "person-hearts": 63355, + "phone-flip": 63356, + "plugin": 63357, + "postage-fill": 63358, + "postage-heart-fill": 63359, + "postage-heart": 63360, + "postage": 63361, + "postcard-fill": 63362, + "postcard-heart-fill": 63363, + "postcard-heart": 63364, + "postcard": 63365, + "search-heart-fill": 63366, + "search-heart": 63367, + "sliders2-vertical": 63368, + "sliders2": 63369, + "trash3-fill": 63370, + "trash3": 63371, + "valentine": 63372, + "valentine2": 63373, + "wrench-adjustable-circle-fill": 63374, + "wrench-adjustable-circle": 63375, + "wrench-adjustable": 63376, + "filetype-json": 63377, + "filetype-pptx": 63378, + "filetype-xlsx": 63379, + "1-circle-fill": 63382, + "1-circle": 63383, + "1-square-fill": 63384, + "1-square": 63385, + "2-circle-fill": 63388, + "2-circle": 63389, + "2-square-fill": 63390, + "2-square": 63391, + "3-circle-fill": 63394, + "3-circle": 63395, + "3-square-fill": 63396, + "3-square": 63397, + "4-circle-fill": 63400, + "4-circle": 63401, + "4-square-fill": 63402, + "4-square": 63403, + "5-circle-fill": 63406, + "5-circle": 63407, + "5-square-fill": 63408, + "5-square": 63409, + "6-circle-fill": 63412, + "6-circle": 63413, + "6-square-fill": 63414, + "6-square": 63415, + "7-circle-fill": 63418, + "7-circle": 63419, + "7-square-fill": 63420, + "7-square": 63421, + "8-circle-fill": 63424, + "8-circle": 63425, + "8-square-fill": 63426, + "8-square": 63427, + "9-circle-fill": 63430, + "9-circle": 63431, + "9-square-fill": 63432, + "9-square": 63433, + "airplane-engines-fill": 63434, + "airplane-engines": 63435, + "airplane-fill": 63436, + "airplane": 63437, + "alexa": 63438, + "alipay": 63439, + "android": 63440, + "android2": 63441, + "box-fill": 63442, + "box-seam-fill": 63443, + "browser-chrome": 63444, + "browser-edge": 63445, + "browser-firefox": 63446, + "browser-safari": 63447, + "c-circle-fill": 63450, + "c-circle": 63451, + "c-square-fill": 63452, + "c-square": 63453, + "capsule-pill": 63454, + "capsule": 63455, + "car-front-fill": 63456, + "car-front": 63457, + "cassette-fill": 63458, + "cassette": 63459, + "cc-circle-fill": 63462, + "cc-circle": 63463, + "cc-square-fill": 63464, + "cc-square": 63465, + "cup-hot-fill": 63466, + "cup-hot": 63467, + "currency-rupee": 63468, + "dropbox": 63469, + "escape": 63470, + "fast-forward-btn-fill": 63471, + "fast-forward-btn": 63472, + "fast-forward-circle-fill": 63473, + "fast-forward-circle": 63474, + "fast-forward-fill": 63475, + "fast-forward": 63476, + "filetype-sql": 63477, + "fire": 63478, + "google-play": 63479, + "h-circle-fill": 63482, + "h-circle": 63483, + "h-square-fill": 63484, + "h-square": 63485, + "indent": 63486, + "lungs-fill": 63487, + "lungs": 63488, + "microsoft-teams": 63489, + "p-circle-fill": 63492, + "p-circle": 63493, + "p-square-fill": 63494, + "p-square": 63495, + "pass-fill": 63496, + "pass": 63497, + "prescription": 63498, + "prescription2": 63499, + "r-circle-fill": 63502, + "r-circle": 63503, + "r-square-fill": 63504, + "r-square": 63505, + "repeat-1": 63506, + "repeat": 63507, + "rewind-btn-fill": 63508, + "rewind-btn": 63509, + "rewind-circle-fill": 63510, + "rewind-circle": 63511, + "rewind-fill": 63512, + "rewind": 63513, + "train-freight-front-fill": 63514, + "train-freight-front": 63515, + "train-front-fill": 63516, + "train-front": 63517, + "train-lightrail-front-fill": 63518, + "train-lightrail-front": 63519, + "truck-front-fill": 63520, + "truck-front": 63521, + "ubuntu": 63522, + "unindent": 63523, + "unity": 63524, + "universal-access-circle": 63525, + "universal-access": 63526, + "virus": 63527, + "virus2": 63528, + "wechat": 63529, + "yelp": 63530, + "sign-stop-fill": 63531, + "sign-stop-lights-fill": 63532, + "sign-stop-lights": 63533, + "sign-stop": 63534, + "sign-turn-left-fill": 63535, + "sign-turn-left": 63536, + "sign-turn-right-fill": 63537, + "sign-turn-right": 63538, + "sign-turn-slight-left-fill": 63539, + "sign-turn-slight-left": 63540, + "sign-turn-slight-right-fill": 63541, + "sign-turn-slight-right": 63542, + "sign-yield-fill": 63543, + "sign-yield": 63544, + "ev-station-fill": 63545, + "ev-station": 63546, + "fuel-pump-diesel-fill": 63547, + "fuel-pump-diesel": 63548, + "fuel-pump-fill": 63549, + "fuel-pump": 63550, + "0-circle-fill": 63551, + "0-circle": 63552, + "0-square-fill": 63553, + "0-square": 63554, + "rocket-fill": 63555, + "rocket-takeoff-fill": 63556, + "rocket-takeoff": 63557, + "rocket": 63558, + "stripe": 63559, + "subscript": 63560, + "superscript": 63561, + "trello": 63562, + "envelope-at-fill": 63563, + "envelope-at": 63564, + "regex": 63565, + "text-wrap": 63566, + "sign-dead-end-fill": 63567, + "sign-dead-end": 63568, + "sign-do-not-enter-fill": 63569, + "sign-do-not-enter": 63570, + "sign-intersection-fill": 63571, + "sign-intersection-side-fill": 63572, + "sign-intersection-side": 63573, + "sign-intersection-t-fill": 63574, + "sign-intersection-t": 63575, + "sign-intersection-y-fill": 63576, + "sign-intersection-y": 63577, + "sign-intersection": 63578, + "sign-merge-left-fill": 63579, + "sign-merge-left": 63580, + "sign-merge-right-fill": 63581, + "sign-merge-right": 63582, + "sign-no-left-turn-fill": 63583, + "sign-no-left-turn": 63584, + "sign-no-parking-fill": 63585, + "sign-no-parking": 63586, + "sign-no-right-turn-fill": 63587, + "sign-no-right-turn": 63588, + "sign-railroad-fill": 63589, + "sign-railroad": 63590, + "building-add": 63591, + "building-check": 63592, + "building-dash": 63593, + "building-down": 63594, + "building-exclamation": 63595, + "building-fill-add": 63596, + "building-fill-check": 63597, + "building-fill-dash": 63598, + "building-fill-down": 63599, + "building-fill-exclamation": 63600, + "building-fill-gear": 63601, + "building-fill-lock": 63602, + "building-fill-slash": 63603, + "building-fill-up": 63604, + "building-fill-x": 63605, + "building-fill": 63606, + "building-gear": 63607, + "building-lock": 63608, + "building-slash": 63609, + "building-up": 63610, + "building-x": 63611, + "buildings-fill": 63612, + "buildings": 63613, + "bus-front-fill": 63614, + "bus-front": 63615, + "ev-front-fill": 63616, + "ev-front": 63617, + "globe-americas": 63618, + "globe-asia-australia": 63619, + "globe-central-south-asia": 63620, + "globe-europe-africa": 63621, + "house-add-fill": 63622, + "house-add": 63623, + "house-check-fill": 63624, + "house-check": 63625, + "house-dash-fill": 63626, + "house-dash": 63627, + "house-down-fill": 63628, + "house-down": 63629, + "house-exclamation-fill": 63630, + "house-exclamation": 63631, + "house-gear-fill": 63632, + "house-gear": 63633, + "house-lock-fill": 63634, + "house-lock": 63635, + "house-slash-fill": 63636, + "house-slash": 63637, + "house-up-fill": 63638, + "house-up": 63639, + "house-x-fill": 63640, + "house-x": 63641, + "person-add": 63642, + "person-down": 63643, + "person-exclamation": 63644, + "person-fill-add": 63645, + "person-fill-check": 63646, + "person-fill-dash": 63647, + "person-fill-down": 63648, + "person-fill-exclamation": 63649, + "person-fill-gear": 63650, + "person-fill-lock": 63651, + "person-fill-slash": 63652, + "person-fill-up": 63653, + "person-fill-x": 63654, + "person-gear": 63655, + "person-lock": 63656, + "person-slash": 63657, + "person-up": 63658, + "scooter": 63659, + "taxi-front-fill": 63660, + "taxi-front": 63661, + "amd": 63662, + "database-add": 63663, + "database-check": 63664, + "database-dash": 63665, + "database-down": 63666, + "database-exclamation": 63667, + "database-fill-add": 63668, + "database-fill-check": 63669, + "database-fill-dash": 63670, + "database-fill-down": 63671, + "database-fill-exclamation": 63672, + "database-fill-gear": 63673, + "database-fill-lock": 63674, + "database-fill-slash": 63675, + "database-fill-up": 63676, + "database-fill-x": 63677, + "database-fill": 63678, + "database-gear": 63679, + "database-lock": 63680, + "database-slash": 63681, + "database-up": 63682, + "database-x": 63683, + "database": 63684, + "houses-fill": 63685, + "houses": 63686, + "nvidia": 63687, + "person-vcard-fill": 63688, + "person-vcard": 63689, + "sina-weibo": 63690, + "tencent-qq": 63691, + "wikipedia": 63692, + "alphabet-uppercase": 62117, + "alphabet": 63114, + "amazon": 63117, + "arrows-collapse-vertical": 63120, + "arrows-expand-vertical": 63125, + "arrows-vertical": 63128, + "arrows": 63138, + "ban-fill": 63139, + "ban": 63158, + "bing": 63170, + "cake": 63200, + "cake2": 63213, + "cookie": 63214, + "copy": 63321, + "crosshair": 63337, + "crosshair2": 63380, + "emoji-astonished-fill": 63381, + "emoji-astonished": 63386, + "emoji-grimace-fill": 63387, + "emoji-grimace": 63392, + "emoji-grin-fill": 63393, + "emoji-grin": 63398, + "emoji-surprise-fill": 63399, + "emoji-surprise": 63404, + "emoji-tear-fill": 63405, + "emoji-tear": 63410, + "envelope-arrow-down-fill": 63411, + "envelope-arrow-down": 63416, + "envelope-arrow-up-fill": 63417, + "envelope-arrow-up": 63422, + "feather": 63423, + "feather2": 63428, + "floppy-fill": 63429, + "floppy": 63448, + "floppy2-fill": 63449, + "floppy2": 63460, + "gitlab": 63461, + "highlighter": 63480, + "marker-tip": 63490, + "nvme-fill": 63491, + "nvme": 63500, + "opencollective": 63501, + "pci-card-network": 63693, + "pci-card-sound": 63694, + "radar": 63695, + "send-arrow-down-fill": 63696, + "send-arrow-down": 63697, + "send-arrow-up-fill": 63698, + "send-arrow-up": 63699, + "sim-slash-fill": 63700, + "sim-slash": 63701, + "sourceforge": 63702, + "substack": 63703, + "threads-fill": 63704, + "threads": 63705, + "transparency": 63706, + "twitter-x": 63707, + "type-h4": 63708, + "type-h5": 63709, + "type-h6": 63710, + "backpack-fill": 63711, + "backpack": 63712, + "backpack2-fill": 63713, + "backpack2": 63714, + "backpack3-fill": 63715, + "backpack3": 63716, + "backpack4-fill": 63717, + "backpack4": 63718, + "brilliance": 63719, + "cake-fill": 63720, + "cake2-fill": 63721, + "duffle-fill": 63722, + "duffle": 63723, + "exposure": 63724, + "gender-neuter": 63725, + "highlights": 63726, + "luggage-fill": 63727, + "luggage": 63728, + "mailbox-flag": 63729, + "mailbox2-flag": 63730, + "noise-reduction": 63731, + "passport-fill": 63732, + "passport": 63733, + "person-arms-up": 63734, + "person-raised-hand": 63735, + "person-standing-dress": 63736, + "person-standing": 63737, + "person-walking": 63738, + "person-wheelchair": 63739, + "shadows": 63740, + "suitcase-fill": 63741, + "suitcase-lg-fill": 63742, + "suitcase-lg": 63743, + "suitcase": 63744, + "suitcase2-fill": 63745, + "suitcase2": 63746, + "vignette": 63747, + "bluesky": 63481, + "tux": 63748, + "beaker-fill": 63749, + "beaker": 63750, + "flask-fill": 63751, + "flask-florence-fill": 63752, + "flask-florence": 63753, + "flask": 63754, + "leaf-fill": 63755, + "leaf": 63756, + "measuring-cup-fill": 63757, + "measuring-cup": 63758, + "unlock2-fill": 63759, + "unlock2": 63760, + "battery-low": 63761, + "anthropic": 63762, + "apple-music": 63763, + "claude": 63764, + "openai": 63765, + "perplexity": 63766, + "css": 63767, + "javascript": 63768, + "typescript": 63769, + "fork-knife": 63770, + "globe-americas-fill": 63771, + "globe-asia-australia-fill": 63772, + "globe-central-south-asia-fill": 63773, + "globe-europe-africa-fill": 63774 +} \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.min.css b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.min.css new file mode 100644 index 00000000..706a5c8b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap Icons v1.13.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */@font-face{font-display:block;font-family:bootstrap-icons;src:url("fonts/bootstrap-icons.woff2?e34853135f9e39acf64315236852cd5a") format("woff2"),url("fonts/bootstrap-icons.woff?e34853135f9e39acf64315236852cd5a") format("woff")}.bi::before,[class*=" bi-"]::before,[class^=bi-]::before{display:inline-block;font-family:bootstrap-icons!important;font-style:normal;font-weight:400!important;font-variant:normal;text-transform:none;line-height:1;vertical-align:-.125em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.bi-123::before{content:"\f67f"}.bi-alarm-fill::before{content:"\f101"}.bi-alarm::before{content:"\f102"}.bi-align-bottom::before{content:"\f103"}.bi-align-center::before{content:"\f104"}.bi-align-end::before{content:"\f105"}.bi-align-middle::before{content:"\f106"}.bi-align-start::before{content:"\f107"}.bi-align-top::before{content:"\f108"}.bi-alt::before{content:"\f109"}.bi-app-indicator::before{content:"\f10a"}.bi-app::before{content:"\f10b"}.bi-archive-fill::before{content:"\f10c"}.bi-archive::before{content:"\f10d"}.bi-arrow-90deg-down::before{content:"\f10e"}.bi-arrow-90deg-left::before{content:"\f10f"}.bi-arrow-90deg-right::before{content:"\f110"}.bi-arrow-90deg-up::before{content:"\f111"}.bi-arrow-bar-down::before{content:"\f112"}.bi-arrow-bar-left::before{content:"\f113"}.bi-arrow-bar-right::before{content:"\f114"}.bi-arrow-bar-up::before{content:"\f115"}.bi-arrow-clockwise::before{content:"\f116"}.bi-arrow-counterclockwise::before{content:"\f117"}.bi-arrow-down-circle-fill::before{content:"\f118"}.bi-arrow-down-circle::before{content:"\f119"}.bi-arrow-down-left-circle-fill::before{content:"\f11a"}.bi-arrow-down-left-circle::before{content:"\f11b"}.bi-arrow-down-left-square-fill::before{content:"\f11c"}.bi-arrow-down-left-square::before{content:"\f11d"}.bi-arrow-down-left::before{content:"\f11e"}.bi-arrow-down-right-circle-fill::before{content:"\f11f"}.bi-arrow-down-right-circle::before{content:"\f120"}.bi-arrow-down-right-square-fill::before{content:"\f121"}.bi-arrow-down-right-square::before{content:"\f122"}.bi-arrow-down-right::before{content:"\f123"}.bi-arrow-down-short::before{content:"\f124"}.bi-arrow-down-square-fill::before{content:"\f125"}.bi-arrow-down-square::before{content:"\f126"}.bi-arrow-down-up::before{content:"\f127"}.bi-arrow-down::before{content:"\f128"}.bi-arrow-left-circle-fill::before{content:"\f129"}.bi-arrow-left-circle::before{content:"\f12a"}.bi-arrow-left-right::before{content:"\f12b"}.bi-arrow-left-short::before{content:"\f12c"}.bi-arrow-left-square-fill::before{content:"\f12d"}.bi-arrow-left-square::before{content:"\f12e"}.bi-arrow-left::before{content:"\f12f"}.bi-arrow-repeat::before{content:"\f130"}.bi-arrow-return-left::before{content:"\f131"}.bi-arrow-return-right::before{content:"\f132"}.bi-arrow-right-circle-fill::before{content:"\f133"}.bi-arrow-right-circle::before{content:"\f134"}.bi-arrow-right-short::before{content:"\f135"}.bi-arrow-right-square-fill::before{content:"\f136"}.bi-arrow-right-square::before{content:"\f137"}.bi-arrow-right::before{content:"\f138"}.bi-arrow-up-circle-fill::before{content:"\f139"}.bi-arrow-up-circle::before{content:"\f13a"}.bi-arrow-up-left-circle-fill::before{content:"\f13b"}.bi-arrow-up-left-circle::before{content:"\f13c"}.bi-arrow-up-left-square-fill::before{content:"\f13d"}.bi-arrow-up-left-square::before{content:"\f13e"}.bi-arrow-up-left::before{content:"\f13f"}.bi-arrow-up-right-circle-fill::before{content:"\f140"}.bi-arrow-up-right-circle::before{content:"\f141"}.bi-arrow-up-right-square-fill::before{content:"\f142"}.bi-arrow-up-right-square::before{content:"\f143"}.bi-arrow-up-right::before{content:"\f144"}.bi-arrow-up-short::before{content:"\f145"}.bi-arrow-up-square-fill::before{content:"\f146"}.bi-arrow-up-square::before{content:"\f147"}.bi-arrow-up::before{content:"\f148"}.bi-arrows-angle-contract::before{content:"\f149"}.bi-arrows-angle-expand::before{content:"\f14a"}.bi-arrows-collapse::before{content:"\f14b"}.bi-arrows-expand::before{content:"\f14c"}.bi-arrows-fullscreen::before{content:"\f14d"}.bi-arrows-move::before{content:"\f14e"}.bi-aspect-ratio-fill::before{content:"\f14f"}.bi-aspect-ratio::before{content:"\f150"}.bi-asterisk::before{content:"\f151"}.bi-at::before{content:"\f152"}.bi-award-fill::before{content:"\f153"}.bi-award::before{content:"\f154"}.bi-back::before{content:"\f155"}.bi-backspace-fill::before{content:"\f156"}.bi-backspace-reverse-fill::before{content:"\f157"}.bi-backspace-reverse::before{content:"\f158"}.bi-backspace::before{content:"\f159"}.bi-badge-3d-fill::before{content:"\f15a"}.bi-badge-3d::before{content:"\f15b"}.bi-badge-4k-fill::before{content:"\f15c"}.bi-badge-4k::before{content:"\f15d"}.bi-badge-8k-fill::before{content:"\f15e"}.bi-badge-8k::before{content:"\f15f"}.bi-badge-ad-fill::before{content:"\f160"}.bi-badge-ad::before{content:"\f161"}.bi-badge-ar-fill::before{content:"\f162"}.bi-badge-ar::before{content:"\f163"}.bi-badge-cc-fill::before{content:"\f164"}.bi-badge-cc::before{content:"\f165"}.bi-badge-hd-fill::before{content:"\f166"}.bi-badge-hd::before{content:"\f167"}.bi-badge-tm-fill::before{content:"\f168"}.bi-badge-tm::before{content:"\f169"}.bi-badge-vo-fill::before{content:"\f16a"}.bi-badge-vo::before{content:"\f16b"}.bi-badge-vr-fill::before{content:"\f16c"}.bi-badge-vr::before{content:"\f16d"}.bi-badge-wc-fill::before{content:"\f16e"}.bi-badge-wc::before{content:"\f16f"}.bi-bag-check-fill::before{content:"\f170"}.bi-bag-check::before{content:"\f171"}.bi-bag-dash-fill::before{content:"\f172"}.bi-bag-dash::before{content:"\f173"}.bi-bag-fill::before{content:"\f174"}.bi-bag-plus-fill::before{content:"\f175"}.bi-bag-plus::before{content:"\f176"}.bi-bag-x-fill::before{content:"\f177"}.bi-bag-x::before{content:"\f178"}.bi-bag::before{content:"\f179"}.bi-bar-chart-fill::before{content:"\f17a"}.bi-bar-chart-line-fill::before{content:"\f17b"}.bi-bar-chart-line::before{content:"\f17c"}.bi-bar-chart-steps::before{content:"\f17d"}.bi-bar-chart::before{content:"\f17e"}.bi-basket-fill::before{content:"\f17f"}.bi-basket::before{content:"\f180"}.bi-basket2-fill::before{content:"\f181"}.bi-basket2::before{content:"\f182"}.bi-basket3-fill::before{content:"\f183"}.bi-basket3::before{content:"\f184"}.bi-battery-charging::before{content:"\f185"}.bi-battery-full::before{content:"\f186"}.bi-battery-half::before{content:"\f187"}.bi-battery::before{content:"\f188"}.bi-bell-fill::before{content:"\f189"}.bi-bell::before{content:"\f18a"}.bi-bezier::before{content:"\f18b"}.bi-bezier2::before{content:"\f18c"}.bi-bicycle::before{content:"\f18d"}.bi-binoculars-fill::before{content:"\f18e"}.bi-binoculars::before{content:"\f18f"}.bi-blockquote-left::before{content:"\f190"}.bi-blockquote-right::before{content:"\f191"}.bi-book-fill::before{content:"\f192"}.bi-book-half::before{content:"\f193"}.bi-book::before{content:"\f194"}.bi-bookmark-check-fill::before{content:"\f195"}.bi-bookmark-check::before{content:"\f196"}.bi-bookmark-dash-fill::before{content:"\f197"}.bi-bookmark-dash::before{content:"\f198"}.bi-bookmark-fill::before{content:"\f199"}.bi-bookmark-heart-fill::before{content:"\f19a"}.bi-bookmark-heart::before{content:"\f19b"}.bi-bookmark-plus-fill::before{content:"\f19c"}.bi-bookmark-plus::before{content:"\f19d"}.bi-bookmark-star-fill::before{content:"\f19e"}.bi-bookmark-star::before{content:"\f19f"}.bi-bookmark-x-fill::before{content:"\f1a0"}.bi-bookmark-x::before{content:"\f1a1"}.bi-bookmark::before{content:"\f1a2"}.bi-bookmarks-fill::before{content:"\f1a3"}.bi-bookmarks::before{content:"\f1a4"}.bi-bookshelf::before{content:"\f1a5"}.bi-bootstrap-fill::before{content:"\f1a6"}.bi-bootstrap-reboot::before{content:"\f1a7"}.bi-bootstrap::before{content:"\f1a8"}.bi-border-all::before{content:"\f1a9"}.bi-border-bottom::before{content:"\f1aa"}.bi-border-center::before{content:"\f1ab"}.bi-border-inner::before{content:"\f1ac"}.bi-border-left::before{content:"\f1ad"}.bi-border-middle::before{content:"\f1ae"}.bi-border-outer::before{content:"\f1af"}.bi-border-right::before{content:"\f1b0"}.bi-border-style::before{content:"\f1b1"}.bi-border-top::before{content:"\f1b2"}.bi-border-width::before{content:"\f1b3"}.bi-border::before{content:"\f1b4"}.bi-bounding-box-circles::before{content:"\f1b5"}.bi-bounding-box::before{content:"\f1b6"}.bi-box-arrow-down-left::before{content:"\f1b7"}.bi-box-arrow-down-right::before{content:"\f1b8"}.bi-box-arrow-down::before{content:"\f1b9"}.bi-box-arrow-in-down-left::before{content:"\f1ba"}.bi-box-arrow-in-down-right::before{content:"\f1bb"}.bi-box-arrow-in-down::before{content:"\f1bc"}.bi-box-arrow-in-left::before{content:"\f1bd"}.bi-box-arrow-in-right::before{content:"\f1be"}.bi-box-arrow-in-up-left::before{content:"\f1bf"}.bi-box-arrow-in-up-right::before{content:"\f1c0"}.bi-box-arrow-in-up::before{content:"\f1c1"}.bi-box-arrow-left::before{content:"\f1c2"}.bi-box-arrow-right::before{content:"\f1c3"}.bi-box-arrow-up-left::before{content:"\f1c4"}.bi-box-arrow-up-right::before{content:"\f1c5"}.bi-box-arrow-up::before{content:"\f1c6"}.bi-box-seam::before{content:"\f1c7"}.bi-box::before{content:"\f1c8"}.bi-braces::before{content:"\f1c9"}.bi-bricks::before{content:"\f1ca"}.bi-briefcase-fill::before{content:"\f1cb"}.bi-briefcase::before{content:"\f1cc"}.bi-brightness-alt-high-fill::before{content:"\f1cd"}.bi-brightness-alt-high::before{content:"\f1ce"}.bi-brightness-alt-low-fill::before{content:"\f1cf"}.bi-brightness-alt-low::before{content:"\f1d0"}.bi-brightness-high-fill::before{content:"\f1d1"}.bi-brightness-high::before{content:"\f1d2"}.bi-brightness-low-fill::before{content:"\f1d3"}.bi-brightness-low::before{content:"\f1d4"}.bi-broadcast-pin::before{content:"\f1d5"}.bi-broadcast::before{content:"\f1d6"}.bi-brush-fill::before{content:"\f1d7"}.bi-brush::before{content:"\f1d8"}.bi-bucket-fill::before{content:"\f1d9"}.bi-bucket::before{content:"\f1da"}.bi-bug-fill::before{content:"\f1db"}.bi-bug::before{content:"\f1dc"}.bi-building::before{content:"\f1dd"}.bi-bullseye::before{content:"\f1de"}.bi-calculator-fill::before{content:"\f1df"}.bi-calculator::before{content:"\f1e0"}.bi-calendar-check-fill::before{content:"\f1e1"}.bi-calendar-check::before{content:"\f1e2"}.bi-calendar-date-fill::before{content:"\f1e3"}.bi-calendar-date::before{content:"\f1e4"}.bi-calendar-day-fill::before{content:"\f1e5"}.bi-calendar-day::before{content:"\f1e6"}.bi-calendar-event-fill::before{content:"\f1e7"}.bi-calendar-event::before{content:"\f1e8"}.bi-calendar-fill::before{content:"\f1e9"}.bi-calendar-minus-fill::before{content:"\f1ea"}.bi-calendar-minus::before{content:"\f1eb"}.bi-calendar-month-fill::before{content:"\f1ec"}.bi-calendar-month::before{content:"\f1ed"}.bi-calendar-plus-fill::before{content:"\f1ee"}.bi-calendar-plus::before{content:"\f1ef"}.bi-calendar-range-fill::before{content:"\f1f0"}.bi-calendar-range::before{content:"\f1f1"}.bi-calendar-week-fill::before{content:"\f1f2"}.bi-calendar-week::before{content:"\f1f3"}.bi-calendar-x-fill::before{content:"\f1f4"}.bi-calendar-x::before{content:"\f1f5"}.bi-calendar::before{content:"\f1f6"}.bi-calendar2-check-fill::before{content:"\f1f7"}.bi-calendar2-check::before{content:"\f1f8"}.bi-calendar2-date-fill::before{content:"\f1f9"}.bi-calendar2-date::before{content:"\f1fa"}.bi-calendar2-day-fill::before{content:"\f1fb"}.bi-calendar2-day::before{content:"\f1fc"}.bi-calendar2-event-fill::before{content:"\f1fd"}.bi-calendar2-event::before{content:"\f1fe"}.bi-calendar2-fill::before{content:"\f1ff"}.bi-calendar2-minus-fill::before{content:"\f200"}.bi-calendar2-minus::before{content:"\f201"}.bi-calendar2-month-fill::before{content:"\f202"}.bi-calendar2-month::before{content:"\f203"}.bi-calendar2-plus-fill::before{content:"\f204"}.bi-calendar2-plus::before{content:"\f205"}.bi-calendar2-range-fill::before{content:"\f206"}.bi-calendar2-range::before{content:"\f207"}.bi-calendar2-week-fill::before{content:"\f208"}.bi-calendar2-week::before{content:"\f209"}.bi-calendar2-x-fill::before{content:"\f20a"}.bi-calendar2-x::before{content:"\f20b"}.bi-calendar2::before{content:"\f20c"}.bi-calendar3-event-fill::before{content:"\f20d"}.bi-calendar3-event::before{content:"\f20e"}.bi-calendar3-fill::before{content:"\f20f"}.bi-calendar3-range-fill::before{content:"\f210"}.bi-calendar3-range::before{content:"\f211"}.bi-calendar3-week-fill::before{content:"\f212"}.bi-calendar3-week::before{content:"\f213"}.bi-calendar3::before{content:"\f214"}.bi-calendar4-event::before{content:"\f215"}.bi-calendar4-range::before{content:"\f216"}.bi-calendar4-week::before{content:"\f217"}.bi-calendar4::before{content:"\f218"}.bi-camera-fill::before{content:"\f219"}.bi-camera-reels-fill::before{content:"\f21a"}.bi-camera-reels::before{content:"\f21b"}.bi-camera-video-fill::before{content:"\f21c"}.bi-camera-video-off-fill::before{content:"\f21d"}.bi-camera-video-off::before{content:"\f21e"}.bi-camera-video::before{content:"\f21f"}.bi-camera::before{content:"\f220"}.bi-camera2::before{content:"\f221"}.bi-capslock-fill::before{content:"\f222"}.bi-capslock::before{content:"\f223"}.bi-card-checklist::before{content:"\f224"}.bi-card-heading::before{content:"\f225"}.bi-card-image::before{content:"\f226"}.bi-card-list::before{content:"\f227"}.bi-card-text::before{content:"\f228"}.bi-caret-down-fill::before{content:"\f229"}.bi-caret-down-square-fill::before{content:"\f22a"}.bi-caret-down-square::before{content:"\f22b"}.bi-caret-down::before{content:"\f22c"}.bi-caret-left-fill::before{content:"\f22d"}.bi-caret-left-square-fill::before{content:"\f22e"}.bi-caret-left-square::before{content:"\f22f"}.bi-caret-left::before{content:"\f230"}.bi-caret-right-fill::before{content:"\f231"}.bi-caret-right-square-fill::before{content:"\f232"}.bi-caret-right-square::before{content:"\f233"}.bi-caret-right::before{content:"\f234"}.bi-caret-up-fill::before{content:"\f235"}.bi-caret-up-square-fill::before{content:"\f236"}.bi-caret-up-square::before{content:"\f237"}.bi-caret-up::before{content:"\f238"}.bi-cart-check-fill::before{content:"\f239"}.bi-cart-check::before{content:"\f23a"}.bi-cart-dash-fill::before{content:"\f23b"}.bi-cart-dash::before{content:"\f23c"}.bi-cart-fill::before{content:"\f23d"}.bi-cart-plus-fill::before{content:"\f23e"}.bi-cart-plus::before{content:"\f23f"}.bi-cart-x-fill::before{content:"\f240"}.bi-cart-x::before{content:"\f241"}.bi-cart::before{content:"\f242"}.bi-cart2::before{content:"\f243"}.bi-cart3::before{content:"\f244"}.bi-cart4::before{content:"\f245"}.bi-cash-stack::before{content:"\f246"}.bi-cash::before{content:"\f247"}.bi-cast::before{content:"\f248"}.bi-chat-dots-fill::before{content:"\f249"}.bi-chat-dots::before{content:"\f24a"}.bi-chat-fill::before{content:"\f24b"}.bi-chat-left-dots-fill::before{content:"\f24c"}.bi-chat-left-dots::before{content:"\f24d"}.bi-chat-left-fill::before{content:"\f24e"}.bi-chat-left-quote-fill::before{content:"\f24f"}.bi-chat-left-quote::before{content:"\f250"}.bi-chat-left-text-fill::before{content:"\f251"}.bi-chat-left-text::before{content:"\f252"}.bi-chat-left::before{content:"\f253"}.bi-chat-quote-fill::before{content:"\f254"}.bi-chat-quote::before{content:"\f255"}.bi-chat-right-dots-fill::before{content:"\f256"}.bi-chat-right-dots::before{content:"\f257"}.bi-chat-right-fill::before{content:"\f258"}.bi-chat-right-quote-fill::before{content:"\f259"}.bi-chat-right-quote::before{content:"\f25a"}.bi-chat-right-text-fill::before{content:"\f25b"}.bi-chat-right-text::before{content:"\f25c"}.bi-chat-right::before{content:"\f25d"}.bi-chat-square-dots-fill::before{content:"\f25e"}.bi-chat-square-dots::before{content:"\f25f"}.bi-chat-square-fill::before{content:"\f260"}.bi-chat-square-quote-fill::before{content:"\f261"}.bi-chat-square-quote::before{content:"\f262"}.bi-chat-square-text-fill::before{content:"\f263"}.bi-chat-square-text::before{content:"\f264"}.bi-chat-square::before{content:"\f265"}.bi-chat-text-fill::before{content:"\f266"}.bi-chat-text::before{content:"\f267"}.bi-chat::before{content:"\f268"}.bi-check-all::before{content:"\f269"}.bi-check-circle-fill::before{content:"\f26a"}.bi-check-circle::before{content:"\f26b"}.bi-check-square-fill::before{content:"\f26c"}.bi-check-square::before{content:"\f26d"}.bi-check::before{content:"\f26e"}.bi-check2-all::before{content:"\f26f"}.bi-check2-circle::before{content:"\f270"}.bi-check2-square::before{content:"\f271"}.bi-check2::before{content:"\f272"}.bi-chevron-bar-contract::before{content:"\f273"}.bi-chevron-bar-down::before{content:"\f274"}.bi-chevron-bar-expand::before{content:"\f275"}.bi-chevron-bar-left::before{content:"\f276"}.bi-chevron-bar-right::before{content:"\f277"}.bi-chevron-bar-up::before{content:"\f278"}.bi-chevron-compact-down::before{content:"\f279"}.bi-chevron-compact-left::before{content:"\f27a"}.bi-chevron-compact-right::before{content:"\f27b"}.bi-chevron-compact-up::before{content:"\f27c"}.bi-chevron-contract::before{content:"\f27d"}.bi-chevron-double-down::before{content:"\f27e"}.bi-chevron-double-left::before{content:"\f27f"}.bi-chevron-double-right::before{content:"\f280"}.bi-chevron-double-up::before{content:"\f281"}.bi-chevron-down::before{content:"\f282"}.bi-chevron-expand::before{content:"\f283"}.bi-chevron-left::before{content:"\f284"}.bi-chevron-right::before{content:"\f285"}.bi-chevron-up::before{content:"\f286"}.bi-circle-fill::before{content:"\f287"}.bi-circle-half::before{content:"\f288"}.bi-circle-square::before{content:"\f289"}.bi-circle::before{content:"\f28a"}.bi-clipboard-check::before{content:"\f28b"}.bi-clipboard-data::before{content:"\f28c"}.bi-clipboard-minus::before{content:"\f28d"}.bi-clipboard-plus::before{content:"\f28e"}.bi-clipboard-x::before{content:"\f28f"}.bi-clipboard::before{content:"\f290"}.bi-clock-fill::before{content:"\f291"}.bi-clock-history::before{content:"\f292"}.bi-clock::before{content:"\f293"}.bi-cloud-arrow-down-fill::before{content:"\f294"}.bi-cloud-arrow-down::before{content:"\f295"}.bi-cloud-arrow-up-fill::before{content:"\f296"}.bi-cloud-arrow-up::before{content:"\f297"}.bi-cloud-check-fill::before{content:"\f298"}.bi-cloud-check::before{content:"\f299"}.bi-cloud-download-fill::before{content:"\f29a"}.bi-cloud-download::before{content:"\f29b"}.bi-cloud-drizzle-fill::before{content:"\f29c"}.bi-cloud-drizzle::before{content:"\f29d"}.bi-cloud-fill::before{content:"\f29e"}.bi-cloud-fog-fill::before{content:"\f29f"}.bi-cloud-fog::before{content:"\f2a0"}.bi-cloud-fog2-fill::before{content:"\f2a1"}.bi-cloud-fog2::before{content:"\f2a2"}.bi-cloud-hail-fill::before{content:"\f2a3"}.bi-cloud-hail::before{content:"\f2a4"}.bi-cloud-haze-fill::before{content:"\f2a6"}.bi-cloud-haze::before{content:"\f2a7"}.bi-cloud-haze2-fill::before{content:"\f2a8"}.bi-cloud-lightning-fill::before{content:"\f2a9"}.bi-cloud-lightning-rain-fill::before{content:"\f2aa"}.bi-cloud-lightning-rain::before{content:"\f2ab"}.bi-cloud-lightning::before{content:"\f2ac"}.bi-cloud-minus-fill::before{content:"\f2ad"}.bi-cloud-minus::before{content:"\f2ae"}.bi-cloud-moon-fill::before{content:"\f2af"}.bi-cloud-moon::before{content:"\f2b0"}.bi-cloud-plus-fill::before{content:"\f2b1"}.bi-cloud-plus::before{content:"\f2b2"}.bi-cloud-rain-fill::before{content:"\f2b3"}.bi-cloud-rain-heavy-fill::before{content:"\f2b4"}.bi-cloud-rain-heavy::before{content:"\f2b5"}.bi-cloud-rain::before{content:"\f2b6"}.bi-cloud-slash-fill::before{content:"\f2b7"}.bi-cloud-slash::before{content:"\f2b8"}.bi-cloud-sleet-fill::before{content:"\f2b9"}.bi-cloud-sleet::before{content:"\f2ba"}.bi-cloud-snow-fill::before{content:"\f2bb"}.bi-cloud-snow::before{content:"\f2bc"}.bi-cloud-sun-fill::before{content:"\f2bd"}.bi-cloud-sun::before{content:"\f2be"}.bi-cloud-upload-fill::before{content:"\f2bf"}.bi-cloud-upload::before{content:"\f2c0"}.bi-cloud::before{content:"\f2c1"}.bi-clouds-fill::before{content:"\f2c2"}.bi-clouds::before{content:"\f2c3"}.bi-cloudy-fill::before{content:"\f2c4"}.bi-cloudy::before{content:"\f2c5"}.bi-code-slash::before{content:"\f2c6"}.bi-code-square::before{content:"\f2c7"}.bi-code::before{content:"\f2c8"}.bi-collection-fill::before{content:"\f2c9"}.bi-collection-play-fill::before{content:"\f2ca"}.bi-collection-play::before{content:"\f2cb"}.bi-collection::before{content:"\f2cc"}.bi-columns-gap::before{content:"\f2cd"}.bi-columns::before{content:"\f2ce"}.bi-command::before{content:"\f2cf"}.bi-compass-fill::before{content:"\f2d0"}.bi-compass::before{content:"\f2d1"}.bi-cone-striped::before{content:"\f2d2"}.bi-cone::before{content:"\f2d3"}.bi-controller::before{content:"\f2d4"}.bi-cpu-fill::before{content:"\f2d5"}.bi-cpu::before{content:"\f2d6"}.bi-credit-card-2-back-fill::before{content:"\f2d7"}.bi-credit-card-2-back::before{content:"\f2d8"}.bi-credit-card-2-front-fill::before{content:"\f2d9"}.bi-credit-card-2-front::before{content:"\f2da"}.bi-credit-card-fill::before{content:"\f2db"}.bi-credit-card::before{content:"\f2dc"}.bi-crop::before{content:"\f2dd"}.bi-cup-fill::before{content:"\f2de"}.bi-cup-straw::before{content:"\f2df"}.bi-cup::before{content:"\f2e0"}.bi-cursor-fill::before{content:"\f2e1"}.bi-cursor-text::before{content:"\f2e2"}.bi-cursor::before{content:"\f2e3"}.bi-dash-circle-dotted::before{content:"\f2e4"}.bi-dash-circle-fill::before{content:"\f2e5"}.bi-dash-circle::before{content:"\f2e6"}.bi-dash-square-dotted::before{content:"\f2e7"}.bi-dash-square-fill::before{content:"\f2e8"}.bi-dash-square::before{content:"\f2e9"}.bi-dash::before{content:"\f2ea"}.bi-diagram-2-fill::before{content:"\f2eb"}.bi-diagram-2::before{content:"\f2ec"}.bi-diagram-3-fill::before{content:"\f2ed"}.bi-diagram-3::before{content:"\f2ee"}.bi-diamond-fill::before{content:"\f2ef"}.bi-diamond-half::before{content:"\f2f0"}.bi-diamond::before{content:"\f2f1"}.bi-dice-1-fill::before{content:"\f2f2"}.bi-dice-1::before{content:"\f2f3"}.bi-dice-2-fill::before{content:"\f2f4"}.bi-dice-2::before{content:"\f2f5"}.bi-dice-3-fill::before{content:"\f2f6"}.bi-dice-3::before{content:"\f2f7"}.bi-dice-4-fill::before{content:"\f2f8"}.bi-dice-4::before{content:"\f2f9"}.bi-dice-5-fill::before{content:"\f2fa"}.bi-dice-5::before{content:"\f2fb"}.bi-dice-6-fill::before{content:"\f2fc"}.bi-dice-6::before{content:"\f2fd"}.bi-disc-fill::before{content:"\f2fe"}.bi-disc::before{content:"\f2ff"}.bi-discord::before{content:"\f300"}.bi-display-fill::before{content:"\f301"}.bi-display::before{content:"\f302"}.bi-distribute-horizontal::before{content:"\f303"}.bi-distribute-vertical::before{content:"\f304"}.bi-door-closed-fill::before{content:"\f305"}.bi-door-closed::before{content:"\f306"}.bi-door-open-fill::before{content:"\f307"}.bi-door-open::before{content:"\f308"}.bi-dot::before{content:"\f309"}.bi-download::before{content:"\f30a"}.bi-droplet-fill::before{content:"\f30b"}.bi-droplet-half::before{content:"\f30c"}.bi-droplet::before{content:"\f30d"}.bi-earbuds::before{content:"\f30e"}.bi-easel-fill::before{content:"\f30f"}.bi-easel::before{content:"\f310"}.bi-egg-fill::before{content:"\f311"}.bi-egg-fried::before{content:"\f312"}.bi-egg::before{content:"\f313"}.bi-eject-fill::before{content:"\f314"}.bi-eject::before{content:"\f315"}.bi-emoji-angry-fill::before{content:"\f316"}.bi-emoji-angry::before{content:"\f317"}.bi-emoji-dizzy-fill::before{content:"\f318"}.bi-emoji-dizzy::before{content:"\f319"}.bi-emoji-expressionless-fill::before{content:"\f31a"}.bi-emoji-expressionless::before{content:"\f31b"}.bi-emoji-frown-fill::before{content:"\f31c"}.bi-emoji-frown::before{content:"\f31d"}.bi-emoji-heart-eyes-fill::before{content:"\f31e"}.bi-emoji-heart-eyes::before{content:"\f31f"}.bi-emoji-laughing-fill::before{content:"\f320"}.bi-emoji-laughing::before{content:"\f321"}.bi-emoji-neutral-fill::before{content:"\f322"}.bi-emoji-neutral::before{content:"\f323"}.bi-emoji-smile-fill::before{content:"\f324"}.bi-emoji-smile-upside-down-fill::before{content:"\f325"}.bi-emoji-smile-upside-down::before{content:"\f326"}.bi-emoji-smile::before{content:"\f327"}.bi-emoji-sunglasses-fill::before{content:"\f328"}.bi-emoji-sunglasses::before{content:"\f329"}.bi-emoji-wink-fill::before{content:"\f32a"}.bi-emoji-wink::before{content:"\f32b"}.bi-envelope-fill::before{content:"\f32c"}.bi-envelope-open-fill::before{content:"\f32d"}.bi-envelope-open::before{content:"\f32e"}.bi-envelope::before{content:"\f32f"}.bi-eraser-fill::before{content:"\f330"}.bi-eraser::before{content:"\f331"}.bi-exclamation-circle-fill::before{content:"\f332"}.bi-exclamation-circle::before{content:"\f333"}.bi-exclamation-diamond-fill::before{content:"\f334"}.bi-exclamation-diamond::before{content:"\f335"}.bi-exclamation-octagon-fill::before{content:"\f336"}.bi-exclamation-octagon::before{content:"\f337"}.bi-exclamation-square-fill::before{content:"\f338"}.bi-exclamation-square::before{content:"\f339"}.bi-exclamation-triangle-fill::before{content:"\f33a"}.bi-exclamation-triangle::before{content:"\f33b"}.bi-exclamation::before{content:"\f33c"}.bi-exclude::before{content:"\f33d"}.bi-eye-fill::before{content:"\f33e"}.bi-eye-slash-fill::before{content:"\f33f"}.bi-eye-slash::before{content:"\f340"}.bi-eye::before{content:"\f341"}.bi-eyedropper::before{content:"\f342"}.bi-eyeglasses::before{content:"\f343"}.bi-facebook::before{content:"\f344"}.bi-file-arrow-down-fill::before{content:"\f345"}.bi-file-arrow-down::before{content:"\f346"}.bi-file-arrow-up-fill::before{content:"\f347"}.bi-file-arrow-up::before{content:"\f348"}.bi-file-bar-graph-fill::before{content:"\f349"}.bi-file-bar-graph::before{content:"\f34a"}.bi-file-binary-fill::before{content:"\f34b"}.bi-file-binary::before{content:"\f34c"}.bi-file-break-fill::before{content:"\f34d"}.bi-file-break::before{content:"\f34e"}.bi-file-check-fill::before{content:"\f34f"}.bi-file-check::before{content:"\f350"}.bi-file-code-fill::before{content:"\f351"}.bi-file-code::before{content:"\f352"}.bi-file-diff-fill::before{content:"\f353"}.bi-file-diff::before{content:"\f354"}.bi-file-earmark-arrow-down-fill::before{content:"\f355"}.bi-file-earmark-arrow-down::before{content:"\f356"}.bi-file-earmark-arrow-up-fill::before{content:"\f357"}.bi-file-earmark-arrow-up::before{content:"\f358"}.bi-file-earmark-bar-graph-fill::before{content:"\f359"}.bi-file-earmark-bar-graph::before{content:"\f35a"}.bi-file-earmark-binary-fill::before{content:"\f35b"}.bi-file-earmark-binary::before{content:"\f35c"}.bi-file-earmark-break-fill::before{content:"\f35d"}.bi-file-earmark-break::before{content:"\f35e"}.bi-file-earmark-check-fill::before{content:"\f35f"}.bi-file-earmark-check::before{content:"\f360"}.bi-file-earmark-code-fill::before{content:"\f361"}.bi-file-earmark-code::before{content:"\f362"}.bi-file-earmark-diff-fill::before{content:"\f363"}.bi-file-earmark-diff::before{content:"\f364"}.bi-file-earmark-easel-fill::before{content:"\f365"}.bi-file-earmark-easel::before{content:"\f366"}.bi-file-earmark-excel-fill::before{content:"\f367"}.bi-file-earmark-excel::before{content:"\f368"}.bi-file-earmark-fill::before{content:"\f369"}.bi-file-earmark-font-fill::before{content:"\f36a"}.bi-file-earmark-font::before{content:"\f36b"}.bi-file-earmark-image-fill::before{content:"\f36c"}.bi-file-earmark-image::before{content:"\f36d"}.bi-file-earmark-lock-fill::before{content:"\f36e"}.bi-file-earmark-lock::before{content:"\f36f"}.bi-file-earmark-lock2-fill::before{content:"\f370"}.bi-file-earmark-lock2::before{content:"\f371"}.bi-file-earmark-medical-fill::before{content:"\f372"}.bi-file-earmark-medical::before{content:"\f373"}.bi-file-earmark-minus-fill::before{content:"\f374"}.bi-file-earmark-minus::before{content:"\f375"}.bi-file-earmark-music-fill::before{content:"\f376"}.bi-file-earmark-music::before{content:"\f377"}.bi-file-earmark-person-fill::before{content:"\f378"}.bi-file-earmark-person::before{content:"\f379"}.bi-file-earmark-play-fill::before{content:"\f37a"}.bi-file-earmark-play::before{content:"\f37b"}.bi-file-earmark-plus-fill::before{content:"\f37c"}.bi-file-earmark-plus::before{content:"\f37d"}.bi-file-earmark-post-fill::before{content:"\f37e"}.bi-file-earmark-post::before{content:"\f37f"}.bi-file-earmark-ppt-fill::before{content:"\f380"}.bi-file-earmark-ppt::before{content:"\f381"}.bi-file-earmark-richtext-fill::before{content:"\f382"}.bi-file-earmark-richtext::before{content:"\f383"}.bi-file-earmark-ruled-fill::before{content:"\f384"}.bi-file-earmark-ruled::before{content:"\f385"}.bi-file-earmark-slides-fill::before{content:"\f386"}.bi-file-earmark-slides::before{content:"\f387"}.bi-file-earmark-spreadsheet-fill::before{content:"\f388"}.bi-file-earmark-spreadsheet::before{content:"\f389"}.bi-file-earmark-text-fill::before{content:"\f38a"}.bi-file-earmark-text::before{content:"\f38b"}.bi-file-earmark-word-fill::before{content:"\f38c"}.bi-file-earmark-word::before{content:"\f38d"}.bi-file-earmark-x-fill::before{content:"\f38e"}.bi-file-earmark-x::before{content:"\f38f"}.bi-file-earmark-zip-fill::before{content:"\f390"}.bi-file-earmark-zip::before{content:"\f391"}.bi-file-earmark::before{content:"\f392"}.bi-file-easel-fill::before{content:"\f393"}.bi-file-easel::before{content:"\f394"}.bi-file-excel-fill::before{content:"\f395"}.bi-file-excel::before{content:"\f396"}.bi-file-fill::before{content:"\f397"}.bi-file-font-fill::before{content:"\f398"}.bi-file-font::before{content:"\f399"}.bi-file-image-fill::before{content:"\f39a"}.bi-file-image::before{content:"\f39b"}.bi-file-lock-fill::before{content:"\f39c"}.bi-file-lock::before{content:"\f39d"}.bi-file-lock2-fill::before{content:"\f39e"}.bi-file-lock2::before{content:"\f39f"}.bi-file-medical-fill::before{content:"\f3a0"}.bi-file-medical::before{content:"\f3a1"}.bi-file-minus-fill::before{content:"\f3a2"}.bi-file-minus::before{content:"\f3a3"}.bi-file-music-fill::before{content:"\f3a4"}.bi-file-music::before{content:"\f3a5"}.bi-file-person-fill::before{content:"\f3a6"}.bi-file-person::before{content:"\f3a7"}.bi-file-play-fill::before{content:"\f3a8"}.bi-file-play::before{content:"\f3a9"}.bi-file-plus-fill::before{content:"\f3aa"}.bi-file-plus::before{content:"\f3ab"}.bi-file-post-fill::before{content:"\f3ac"}.bi-file-post::before{content:"\f3ad"}.bi-file-ppt-fill::before{content:"\f3ae"}.bi-file-ppt::before{content:"\f3af"}.bi-file-richtext-fill::before{content:"\f3b0"}.bi-file-richtext::before{content:"\f3b1"}.bi-file-ruled-fill::before{content:"\f3b2"}.bi-file-ruled::before{content:"\f3b3"}.bi-file-slides-fill::before{content:"\f3b4"}.bi-file-slides::before{content:"\f3b5"}.bi-file-spreadsheet-fill::before{content:"\f3b6"}.bi-file-spreadsheet::before{content:"\f3b7"}.bi-file-text-fill::before{content:"\f3b8"}.bi-file-text::before{content:"\f3b9"}.bi-file-word-fill::before{content:"\f3ba"}.bi-file-word::before{content:"\f3bb"}.bi-file-x-fill::before{content:"\f3bc"}.bi-file-x::before{content:"\f3bd"}.bi-file-zip-fill::before{content:"\f3be"}.bi-file-zip::before{content:"\f3bf"}.bi-file::before{content:"\f3c0"}.bi-files-alt::before{content:"\f3c1"}.bi-files::before{content:"\f3c2"}.bi-film::before{content:"\f3c3"}.bi-filter-circle-fill::before{content:"\f3c4"}.bi-filter-circle::before{content:"\f3c5"}.bi-filter-left::before{content:"\f3c6"}.bi-filter-right::before{content:"\f3c7"}.bi-filter-square-fill::before{content:"\f3c8"}.bi-filter-square::before{content:"\f3c9"}.bi-filter::before{content:"\f3ca"}.bi-flag-fill::before{content:"\f3cb"}.bi-flag::before{content:"\f3cc"}.bi-flower1::before{content:"\f3cd"}.bi-flower2::before{content:"\f3ce"}.bi-flower3::before{content:"\f3cf"}.bi-folder-check::before{content:"\f3d0"}.bi-folder-fill::before{content:"\f3d1"}.bi-folder-minus::before{content:"\f3d2"}.bi-folder-plus::before{content:"\f3d3"}.bi-folder-symlink-fill::before{content:"\f3d4"}.bi-folder-symlink::before{content:"\f3d5"}.bi-folder-x::before{content:"\f3d6"}.bi-folder::before{content:"\f3d7"}.bi-folder2-open::before{content:"\f3d8"}.bi-folder2::before{content:"\f3d9"}.bi-fonts::before{content:"\f3da"}.bi-forward-fill::before{content:"\f3db"}.bi-forward::before{content:"\f3dc"}.bi-front::before{content:"\f3dd"}.bi-fullscreen-exit::before{content:"\f3de"}.bi-fullscreen::before{content:"\f3df"}.bi-funnel-fill::before{content:"\f3e0"}.bi-funnel::before{content:"\f3e1"}.bi-gear-fill::before{content:"\f3e2"}.bi-gear-wide-connected::before{content:"\f3e3"}.bi-gear-wide::before{content:"\f3e4"}.bi-gear::before{content:"\f3e5"}.bi-gem::before{content:"\f3e6"}.bi-geo-alt-fill::before{content:"\f3e7"}.bi-geo-alt::before{content:"\f3e8"}.bi-geo-fill::before{content:"\f3e9"}.bi-geo::before{content:"\f3ea"}.bi-gift-fill::before{content:"\f3eb"}.bi-gift::before{content:"\f3ec"}.bi-github::before{content:"\f3ed"}.bi-globe::before{content:"\f3ee"}.bi-globe2::before{content:"\f3ef"}.bi-google::before{content:"\f3f0"}.bi-graph-down::before{content:"\f3f1"}.bi-graph-up::before{content:"\f3f2"}.bi-grid-1x2-fill::before{content:"\f3f3"}.bi-grid-1x2::before{content:"\f3f4"}.bi-grid-3x2-gap-fill::before{content:"\f3f5"}.bi-grid-3x2-gap::before{content:"\f3f6"}.bi-grid-3x2::before{content:"\f3f7"}.bi-grid-3x3-gap-fill::before{content:"\f3f8"}.bi-grid-3x3-gap::before{content:"\f3f9"}.bi-grid-3x3::before{content:"\f3fa"}.bi-grid-fill::before{content:"\f3fb"}.bi-grid::before{content:"\f3fc"}.bi-grip-horizontal::before{content:"\f3fd"}.bi-grip-vertical::before{content:"\f3fe"}.bi-hammer::before{content:"\f3ff"}.bi-hand-index-fill::before{content:"\f400"}.bi-hand-index-thumb-fill::before{content:"\f401"}.bi-hand-index-thumb::before{content:"\f402"}.bi-hand-index::before{content:"\f403"}.bi-hand-thumbs-down-fill::before{content:"\f404"}.bi-hand-thumbs-down::before{content:"\f405"}.bi-hand-thumbs-up-fill::before{content:"\f406"}.bi-hand-thumbs-up::before{content:"\f407"}.bi-handbag-fill::before{content:"\f408"}.bi-handbag::before{content:"\f409"}.bi-hash::before{content:"\f40a"}.bi-hdd-fill::before{content:"\f40b"}.bi-hdd-network-fill::before{content:"\f40c"}.bi-hdd-network::before{content:"\f40d"}.bi-hdd-rack-fill::before{content:"\f40e"}.bi-hdd-rack::before{content:"\f40f"}.bi-hdd-stack-fill::before{content:"\f410"}.bi-hdd-stack::before{content:"\f411"}.bi-hdd::before{content:"\f412"}.bi-headphones::before{content:"\f413"}.bi-headset::before{content:"\f414"}.bi-heart-fill::before{content:"\f415"}.bi-heart-half::before{content:"\f416"}.bi-heart::before{content:"\f417"}.bi-heptagon-fill::before{content:"\f418"}.bi-heptagon-half::before{content:"\f419"}.bi-heptagon::before{content:"\f41a"}.bi-hexagon-fill::before{content:"\f41b"}.bi-hexagon-half::before{content:"\f41c"}.bi-hexagon::before{content:"\f41d"}.bi-hourglass-bottom::before{content:"\f41e"}.bi-hourglass-split::before{content:"\f41f"}.bi-hourglass-top::before{content:"\f420"}.bi-hourglass::before{content:"\f421"}.bi-house-door-fill::before{content:"\f422"}.bi-house-door::before{content:"\f423"}.bi-house-fill::before{content:"\f424"}.bi-house::before{content:"\f425"}.bi-hr::before{content:"\f426"}.bi-hurricane::before{content:"\f427"}.bi-image-alt::before{content:"\f428"}.bi-image-fill::before{content:"\f429"}.bi-image::before{content:"\f42a"}.bi-images::before{content:"\f42b"}.bi-inbox-fill::before{content:"\f42c"}.bi-inbox::before{content:"\f42d"}.bi-inboxes-fill::before{content:"\f42e"}.bi-inboxes::before{content:"\f42f"}.bi-info-circle-fill::before{content:"\f430"}.bi-info-circle::before{content:"\f431"}.bi-info-square-fill::before{content:"\f432"}.bi-info-square::before{content:"\f433"}.bi-info::before{content:"\f434"}.bi-input-cursor-text::before{content:"\f435"}.bi-input-cursor::before{content:"\f436"}.bi-instagram::before{content:"\f437"}.bi-intersect::before{content:"\f438"}.bi-journal-album::before{content:"\f439"}.bi-journal-arrow-down::before{content:"\f43a"}.bi-journal-arrow-up::before{content:"\f43b"}.bi-journal-bookmark-fill::before{content:"\f43c"}.bi-journal-bookmark::before{content:"\f43d"}.bi-journal-check::before{content:"\f43e"}.bi-journal-code::before{content:"\f43f"}.bi-journal-medical::before{content:"\f440"}.bi-journal-minus::before{content:"\f441"}.bi-journal-plus::before{content:"\f442"}.bi-journal-richtext::before{content:"\f443"}.bi-journal-text::before{content:"\f444"}.bi-journal-x::before{content:"\f445"}.bi-journal::before{content:"\f446"}.bi-journals::before{content:"\f447"}.bi-joystick::before{content:"\f448"}.bi-justify-left::before{content:"\f449"}.bi-justify-right::before{content:"\f44a"}.bi-justify::before{content:"\f44b"}.bi-kanban-fill::before{content:"\f44c"}.bi-kanban::before{content:"\f44d"}.bi-key-fill::before{content:"\f44e"}.bi-key::before{content:"\f44f"}.bi-keyboard-fill::before{content:"\f450"}.bi-keyboard::before{content:"\f451"}.bi-ladder::before{content:"\f452"}.bi-lamp-fill::before{content:"\f453"}.bi-lamp::before{content:"\f454"}.bi-laptop-fill::before{content:"\f455"}.bi-laptop::before{content:"\f456"}.bi-layer-backward::before{content:"\f457"}.bi-layer-forward::before{content:"\f458"}.bi-layers-fill::before{content:"\f459"}.bi-layers-half::before{content:"\f45a"}.bi-layers::before{content:"\f45b"}.bi-layout-sidebar-inset-reverse::before{content:"\f45c"}.bi-layout-sidebar-inset::before{content:"\f45d"}.bi-layout-sidebar-reverse::before{content:"\f45e"}.bi-layout-sidebar::before{content:"\f45f"}.bi-layout-split::before{content:"\f460"}.bi-layout-text-sidebar-reverse::before{content:"\f461"}.bi-layout-text-sidebar::before{content:"\f462"}.bi-layout-text-window-reverse::before{content:"\f463"}.bi-layout-text-window::before{content:"\f464"}.bi-layout-three-columns::before{content:"\f465"}.bi-layout-wtf::before{content:"\f466"}.bi-life-preserver::before{content:"\f467"}.bi-lightbulb-fill::before{content:"\f468"}.bi-lightbulb-off-fill::before{content:"\f469"}.bi-lightbulb-off::before{content:"\f46a"}.bi-lightbulb::before{content:"\f46b"}.bi-lightning-charge-fill::before{content:"\f46c"}.bi-lightning-charge::before{content:"\f46d"}.bi-lightning-fill::before{content:"\f46e"}.bi-lightning::before{content:"\f46f"}.bi-link-45deg::before{content:"\f470"}.bi-link::before{content:"\f471"}.bi-linkedin::before{content:"\f472"}.bi-list-check::before{content:"\f473"}.bi-list-nested::before{content:"\f474"}.bi-list-ol::before{content:"\f475"}.bi-list-stars::before{content:"\f476"}.bi-list-task::before{content:"\f477"}.bi-list-ul::before{content:"\f478"}.bi-list::before{content:"\f479"}.bi-lock-fill::before{content:"\f47a"}.bi-lock::before{content:"\f47b"}.bi-mailbox::before{content:"\f47c"}.bi-mailbox2::before{content:"\f47d"}.bi-map-fill::before{content:"\f47e"}.bi-map::before{content:"\f47f"}.bi-markdown-fill::before{content:"\f480"}.bi-markdown::before{content:"\f481"}.bi-mask::before{content:"\f482"}.bi-megaphone-fill::before{content:"\f483"}.bi-megaphone::before{content:"\f484"}.bi-menu-app-fill::before{content:"\f485"}.bi-menu-app::before{content:"\f486"}.bi-menu-button-fill::before{content:"\f487"}.bi-menu-button-wide-fill::before{content:"\f488"}.bi-menu-button-wide::before{content:"\f489"}.bi-menu-button::before{content:"\f48a"}.bi-menu-down::before{content:"\f48b"}.bi-menu-up::before{content:"\f48c"}.bi-mic-fill::before{content:"\f48d"}.bi-mic-mute-fill::before{content:"\f48e"}.bi-mic-mute::before{content:"\f48f"}.bi-mic::before{content:"\f490"}.bi-minecart-loaded::before{content:"\f491"}.bi-minecart::before{content:"\f492"}.bi-moisture::before{content:"\f493"}.bi-moon-fill::before{content:"\f494"}.bi-moon-stars-fill::before{content:"\f495"}.bi-moon-stars::before{content:"\f496"}.bi-moon::before{content:"\f497"}.bi-mouse-fill::before{content:"\f498"}.bi-mouse::before{content:"\f499"}.bi-mouse2-fill::before{content:"\f49a"}.bi-mouse2::before{content:"\f49b"}.bi-mouse3-fill::before{content:"\f49c"}.bi-mouse3::before{content:"\f49d"}.bi-music-note-beamed::before{content:"\f49e"}.bi-music-note-list::before{content:"\f49f"}.bi-music-note::before{content:"\f4a0"}.bi-music-player-fill::before{content:"\f4a1"}.bi-music-player::before{content:"\f4a2"}.bi-newspaper::before{content:"\f4a3"}.bi-node-minus-fill::before{content:"\f4a4"}.bi-node-minus::before{content:"\f4a5"}.bi-node-plus-fill::before{content:"\f4a6"}.bi-node-plus::before{content:"\f4a7"}.bi-nut-fill::before{content:"\f4a8"}.bi-nut::before{content:"\f4a9"}.bi-octagon-fill::before{content:"\f4aa"}.bi-octagon-half::before{content:"\f4ab"}.bi-octagon::before{content:"\f4ac"}.bi-option::before{content:"\f4ad"}.bi-outlet::before{content:"\f4ae"}.bi-paint-bucket::before{content:"\f4af"}.bi-palette-fill::before{content:"\f4b0"}.bi-palette::before{content:"\f4b1"}.bi-palette2::before{content:"\f4b2"}.bi-paperclip::before{content:"\f4b3"}.bi-paragraph::before{content:"\f4b4"}.bi-patch-check-fill::before{content:"\f4b5"}.bi-patch-check::before{content:"\f4b6"}.bi-patch-exclamation-fill::before{content:"\f4b7"}.bi-patch-exclamation::before{content:"\f4b8"}.bi-patch-minus-fill::before{content:"\f4b9"}.bi-patch-minus::before{content:"\f4ba"}.bi-patch-plus-fill::before{content:"\f4bb"}.bi-patch-plus::before{content:"\f4bc"}.bi-patch-question-fill::before{content:"\f4bd"}.bi-patch-question::before{content:"\f4be"}.bi-pause-btn-fill::before{content:"\f4bf"}.bi-pause-btn::before{content:"\f4c0"}.bi-pause-circle-fill::before{content:"\f4c1"}.bi-pause-circle::before{content:"\f4c2"}.bi-pause-fill::before{content:"\f4c3"}.bi-pause::before{content:"\f4c4"}.bi-peace-fill::before{content:"\f4c5"}.bi-peace::before{content:"\f4c6"}.bi-pen-fill::before{content:"\f4c7"}.bi-pen::before{content:"\f4c8"}.bi-pencil-fill::before{content:"\f4c9"}.bi-pencil-square::before{content:"\f4ca"}.bi-pencil::before{content:"\f4cb"}.bi-pentagon-fill::before{content:"\f4cc"}.bi-pentagon-half::before{content:"\f4cd"}.bi-pentagon::before{content:"\f4ce"}.bi-people-fill::before{content:"\f4cf"}.bi-people::before{content:"\f4d0"}.bi-percent::before{content:"\f4d1"}.bi-person-badge-fill::before{content:"\f4d2"}.bi-person-badge::before{content:"\f4d3"}.bi-person-bounding-box::before{content:"\f4d4"}.bi-person-check-fill::before{content:"\f4d5"}.bi-person-check::before{content:"\f4d6"}.bi-person-circle::before{content:"\f4d7"}.bi-person-dash-fill::before{content:"\f4d8"}.bi-person-dash::before{content:"\f4d9"}.bi-person-fill::before{content:"\f4da"}.bi-person-lines-fill::before{content:"\f4db"}.bi-person-plus-fill::before{content:"\f4dc"}.bi-person-plus::before{content:"\f4dd"}.bi-person-square::before{content:"\f4de"}.bi-person-x-fill::before{content:"\f4df"}.bi-person-x::before{content:"\f4e0"}.bi-person::before{content:"\f4e1"}.bi-phone-fill::before{content:"\f4e2"}.bi-phone-landscape-fill::before{content:"\f4e3"}.bi-phone-landscape::before{content:"\f4e4"}.bi-phone-vibrate-fill::before{content:"\f4e5"}.bi-phone-vibrate::before{content:"\f4e6"}.bi-phone::before{content:"\f4e7"}.bi-pie-chart-fill::before{content:"\f4e8"}.bi-pie-chart::before{content:"\f4e9"}.bi-pin-angle-fill::before{content:"\f4ea"}.bi-pin-angle::before{content:"\f4eb"}.bi-pin-fill::before{content:"\f4ec"}.bi-pin::before{content:"\f4ed"}.bi-pip-fill::before{content:"\f4ee"}.bi-pip::before{content:"\f4ef"}.bi-play-btn-fill::before{content:"\f4f0"}.bi-play-btn::before{content:"\f4f1"}.bi-play-circle-fill::before{content:"\f4f2"}.bi-play-circle::before{content:"\f4f3"}.bi-play-fill::before{content:"\f4f4"}.bi-play::before{content:"\f4f5"}.bi-plug-fill::before{content:"\f4f6"}.bi-plug::before{content:"\f4f7"}.bi-plus-circle-dotted::before{content:"\f4f8"}.bi-plus-circle-fill::before{content:"\f4f9"}.bi-plus-circle::before{content:"\f4fa"}.bi-plus-square-dotted::before{content:"\f4fb"}.bi-plus-square-fill::before{content:"\f4fc"}.bi-plus-square::before{content:"\f4fd"}.bi-plus::before{content:"\f4fe"}.bi-power::before{content:"\f4ff"}.bi-printer-fill::before{content:"\f500"}.bi-printer::before{content:"\f501"}.bi-puzzle-fill::before{content:"\f502"}.bi-puzzle::before{content:"\f503"}.bi-question-circle-fill::before{content:"\f504"}.bi-question-circle::before{content:"\f505"}.bi-question-diamond-fill::before{content:"\f506"}.bi-question-diamond::before{content:"\f507"}.bi-question-octagon-fill::before{content:"\f508"}.bi-question-octagon::before{content:"\f509"}.bi-question-square-fill::before{content:"\f50a"}.bi-question-square::before{content:"\f50b"}.bi-question::before{content:"\f50c"}.bi-rainbow::before{content:"\f50d"}.bi-receipt-cutoff::before{content:"\f50e"}.bi-receipt::before{content:"\f50f"}.bi-reception-0::before{content:"\f510"}.bi-reception-1::before{content:"\f511"}.bi-reception-2::before{content:"\f512"}.bi-reception-3::before{content:"\f513"}.bi-reception-4::before{content:"\f514"}.bi-record-btn-fill::before{content:"\f515"}.bi-record-btn::before{content:"\f516"}.bi-record-circle-fill::before{content:"\f517"}.bi-record-circle::before{content:"\f518"}.bi-record-fill::before{content:"\f519"}.bi-record::before{content:"\f51a"}.bi-record2-fill::before{content:"\f51b"}.bi-record2::before{content:"\f51c"}.bi-reply-all-fill::before{content:"\f51d"}.bi-reply-all::before{content:"\f51e"}.bi-reply-fill::before{content:"\f51f"}.bi-reply::before{content:"\f520"}.bi-rss-fill::before{content:"\f521"}.bi-rss::before{content:"\f522"}.bi-rulers::before{content:"\f523"}.bi-save-fill::before{content:"\f524"}.bi-save::before{content:"\f525"}.bi-save2-fill::before{content:"\f526"}.bi-save2::before{content:"\f527"}.bi-scissors::before{content:"\f528"}.bi-screwdriver::before{content:"\f529"}.bi-search::before{content:"\f52a"}.bi-segmented-nav::before{content:"\f52b"}.bi-server::before{content:"\f52c"}.bi-share-fill::before{content:"\f52d"}.bi-share::before{content:"\f52e"}.bi-shield-check::before{content:"\f52f"}.bi-shield-exclamation::before{content:"\f530"}.bi-shield-fill-check::before{content:"\f531"}.bi-shield-fill-exclamation::before{content:"\f532"}.bi-shield-fill-minus::before{content:"\f533"}.bi-shield-fill-plus::before{content:"\f534"}.bi-shield-fill-x::before{content:"\f535"}.bi-shield-fill::before{content:"\f536"}.bi-shield-lock-fill::before{content:"\f537"}.bi-shield-lock::before{content:"\f538"}.bi-shield-minus::before{content:"\f539"}.bi-shield-plus::before{content:"\f53a"}.bi-shield-shaded::before{content:"\f53b"}.bi-shield-slash-fill::before{content:"\f53c"}.bi-shield-slash::before{content:"\f53d"}.bi-shield-x::before{content:"\f53e"}.bi-shield::before{content:"\f53f"}.bi-shift-fill::before{content:"\f540"}.bi-shift::before{content:"\f541"}.bi-shop-window::before{content:"\f542"}.bi-shop::before{content:"\f543"}.bi-shuffle::before{content:"\f544"}.bi-signpost-2-fill::before{content:"\f545"}.bi-signpost-2::before{content:"\f546"}.bi-signpost-fill::before{content:"\f547"}.bi-signpost-split-fill::before{content:"\f548"}.bi-signpost-split::before{content:"\f549"}.bi-signpost::before{content:"\f54a"}.bi-sim-fill::before{content:"\f54b"}.bi-sim::before{content:"\f54c"}.bi-skip-backward-btn-fill::before{content:"\f54d"}.bi-skip-backward-btn::before{content:"\f54e"}.bi-skip-backward-circle-fill::before{content:"\f54f"}.bi-skip-backward-circle::before{content:"\f550"}.bi-skip-backward-fill::before{content:"\f551"}.bi-skip-backward::before{content:"\f552"}.bi-skip-end-btn-fill::before{content:"\f553"}.bi-skip-end-btn::before{content:"\f554"}.bi-skip-end-circle-fill::before{content:"\f555"}.bi-skip-end-circle::before{content:"\f556"}.bi-skip-end-fill::before{content:"\f557"}.bi-skip-end::before{content:"\f558"}.bi-skip-forward-btn-fill::before{content:"\f559"}.bi-skip-forward-btn::before{content:"\f55a"}.bi-skip-forward-circle-fill::before{content:"\f55b"}.bi-skip-forward-circle::before{content:"\f55c"}.bi-skip-forward-fill::before{content:"\f55d"}.bi-skip-forward::before{content:"\f55e"}.bi-skip-start-btn-fill::before{content:"\f55f"}.bi-skip-start-btn::before{content:"\f560"}.bi-skip-start-circle-fill::before{content:"\f561"}.bi-skip-start-circle::before{content:"\f562"}.bi-skip-start-fill::before{content:"\f563"}.bi-skip-start::before{content:"\f564"}.bi-slack::before{content:"\f565"}.bi-slash-circle-fill::before{content:"\f566"}.bi-slash-circle::before{content:"\f567"}.bi-slash-square-fill::before{content:"\f568"}.bi-slash-square::before{content:"\f569"}.bi-slash::before{content:"\f56a"}.bi-sliders::before{content:"\f56b"}.bi-smartwatch::before{content:"\f56c"}.bi-snow::before{content:"\f56d"}.bi-snow2::before{content:"\f56e"}.bi-snow3::before{content:"\f56f"}.bi-sort-alpha-down-alt::before{content:"\f570"}.bi-sort-alpha-down::before{content:"\f571"}.bi-sort-alpha-up-alt::before{content:"\f572"}.bi-sort-alpha-up::before{content:"\f573"}.bi-sort-down-alt::before{content:"\f574"}.bi-sort-down::before{content:"\f575"}.bi-sort-numeric-down-alt::before{content:"\f576"}.bi-sort-numeric-down::before{content:"\f577"}.bi-sort-numeric-up-alt::before{content:"\f578"}.bi-sort-numeric-up::before{content:"\f579"}.bi-sort-up-alt::before{content:"\f57a"}.bi-sort-up::before{content:"\f57b"}.bi-soundwave::before{content:"\f57c"}.bi-speaker-fill::before{content:"\f57d"}.bi-speaker::before{content:"\f57e"}.bi-speedometer::before{content:"\f57f"}.bi-speedometer2::before{content:"\f580"}.bi-spellcheck::before{content:"\f581"}.bi-square-fill::before{content:"\f582"}.bi-square-half::before{content:"\f583"}.bi-square::before{content:"\f584"}.bi-stack::before{content:"\f585"}.bi-star-fill::before{content:"\f586"}.bi-star-half::before{content:"\f587"}.bi-star::before{content:"\f588"}.bi-stars::before{content:"\f589"}.bi-stickies-fill::before{content:"\f58a"}.bi-stickies::before{content:"\f58b"}.bi-sticky-fill::before{content:"\f58c"}.bi-sticky::before{content:"\f58d"}.bi-stop-btn-fill::before{content:"\f58e"}.bi-stop-btn::before{content:"\f58f"}.bi-stop-circle-fill::before{content:"\f590"}.bi-stop-circle::before{content:"\f591"}.bi-stop-fill::before{content:"\f592"}.bi-stop::before{content:"\f593"}.bi-stoplights-fill::before{content:"\f594"}.bi-stoplights::before{content:"\f595"}.bi-stopwatch-fill::before{content:"\f596"}.bi-stopwatch::before{content:"\f597"}.bi-subtract::before{content:"\f598"}.bi-suit-club-fill::before{content:"\f599"}.bi-suit-club::before{content:"\f59a"}.bi-suit-diamond-fill::before{content:"\f59b"}.bi-suit-diamond::before{content:"\f59c"}.bi-suit-heart-fill::before{content:"\f59d"}.bi-suit-heart::before{content:"\f59e"}.bi-suit-spade-fill::before{content:"\f59f"}.bi-suit-spade::before{content:"\f5a0"}.bi-sun-fill::before{content:"\f5a1"}.bi-sun::before{content:"\f5a2"}.bi-sunglasses::before{content:"\f5a3"}.bi-sunrise-fill::before{content:"\f5a4"}.bi-sunrise::before{content:"\f5a5"}.bi-sunset-fill::before{content:"\f5a6"}.bi-sunset::before{content:"\f5a7"}.bi-symmetry-horizontal::before{content:"\f5a8"}.bi-symmetry-vertical::before{content:"\f5a9"}.bi-table::before{content:"\f5aa"}.bi-tablet-fill::before{content:"\f5ab"}.bi-tablet-landscape-fill::before{content:"\f5ac"}.bi-tablet-landscape::before{content:"\f5ad"}.bi-tablet::before{content:"\f5ae"}.bi-tag-fill::before{content:"\f5af"}.bi-tag::before{content:"\f5b0"}.bi-tags-fill::before{content:"\f5b1"}.bi-tags::before{content:"\f5b2"}.bi-telegram::before{content:"\f5b3"}.bi-telephone-fill::before{content:"\f5b4"}.bi-telephone-forward-fill::before{content:"\f5b5"}.bi-telephone-forward::before{content:"\f5b6"}.bi-telephone-inbound-fill::before{content:"\f5b7"}.bi-telephone-inbound::before{content:"\f5b8"}.bi-telephone-minus-fill::before{content:"\f5b9"}.bi-telephone-minus::before{content:"\f5ba"}.bi-telephone-outbound-fill::before{content:"\f5bb"}.bi-telephone-outbound::before{content:"\f5bc"}.bi-telephone-plus-fill::before{content:"\f5bd"}.bi-telephone-plus::before{content:"\f5be"}.bi-telephone-x-fill::before{content:"\f5bf"}.bi-telephone-x::before{content:"\f5c0"}.bi-telephone::before{content:"\f5c1"}.bi-terminal-fill::before{content:"\f5c2"}.bi-terminal::before{content:"\f5c3"}.bi-text-center::before{content:"\f5c4"}.bi-text-indent-left::before{content:"\f5c5"}.bi-text-indent-right::before{content:"\f5c6"}.bi-text-left::before{content:"\f5c7"}.bi-text-paragraph::before{content:"\f5c8"}.bi-text-right::before{content:"\f5c9"}.bi-textarea-resize::before{content:"\f5ca"}.bi-textarea-t::before{content:"\f5cb"}.bi-textarea::before{content:"\f5cc"}.bi-thermometer-half::before{content:"\f5cd"}.bi-thermometer-high::before{content:"\f5ce"}.bi-thermometer-low::before{content:"\f5cf"}.bi-thermometer-snow::before{content:"\f5d0"}.bi-thermometer-sun::before{content:"\f5d1"}.bi-thermometer::before{content:"\f5d2"}.bi-three-dots-vertical::before{content:"\f5d3"}.bi-three-dots::before{content:"\f5d4"}.bi-toggle-off::before{content:"\f5d5"}.bi-toggle-on::before{content:"\f5d6"}.bi-toggle2-off::before{content:"\f5d7"}.bi-toggle2-on::before{content:"\f5d8"}.bi-toggles::before{content:"\f5d9"}.bi-toggles2::before{content:"\f5da"}.bi-tools::before{content:"\f5db"}.bi-tornado::before{content:"\f5dc"}.bi-trash-fill::before{content:"\f5dd"}.bi-trash::before{content:"\f5de"}.bi-trash2-fill::before{content:"\f5df"}.bi-trash2::before{content:"\f5e0"}.bi-tree-fill::before{content:"\f5e1"}.bi-tree::before{content:"\f5e2"}.bi-triangle-fill::before{content:"\f5e3"}.bi-triangle-half::before{content:"\f5e4"}.bi-triangle::before{content:"\f5e5"}.bi-trophy-fill::before{content:"\f5e6"}.bi-trophy::before{content:"\f5e7"}.bi-tropical-storm::before{content:"\f5e8"}.bi-truck-flatbed::before{content:"\f5e9"}.bi-truck::before{content:"\f5ea"}.bi-tsunami::before{content:"\f5eb"}.bi-tv-fill::before{content:"\f5ec"}.bi-tv::before{content:"\f5ed"}.bi-twitch::before{content:"\f5ee"}.bi-twitter::before{content:"\f5ef"}.bi-type-bold::before{content:"\f5f0"}.bi-type-h1::before{content:"\f5f1"}.bi-type-h2::before{content:"\f5f2"}.bi-type-h3::before{content:"\f5f3"}.bi-type-italic::before{content:"\f5f4"}.bi-type-strikethrough::before{content:"\f5f5"}.bi-type-underline::before{content:"\f5f6"}.bi-type::before{content:"\f5f7"}.bi-ui-checks-grid::before{content:"\f5f8"}.bi-ui-checks::before{content:"\f5f9"}.bi-ui-radios-grid::before{content:"\f5fa"}.bi-ui-radios::before{content:"\f5fb"}.bi-umbrella-fill::before{content:"\f5fc"}.bi-umbrella::before{content:"\f5fd"}.bi-union::before{content:"\f5fe"}.bi-unlock-fill::before{content:"\f5ff"}.bi-unlock::before{content:"\f600"}.bi-upc-scan::before{content:"\f601"}.bi-upc::before{content:"\f602"}.bi-upload::before{content:"\f603"}.bi-vector-pen::before{content:"\f604"}.bi-view-list::before{content:"\f605"}.bi-view-stacked::before{content:"\f606"}.bi-vinyl-fill::before{content:"\f607"}.bi-vinyl::before{content:"\f608"}.bi-voicemail::before{content:"\f609"}.bi-volume-down-fill::before{content:"\f60a"}.bi-volume-down::before{content:"\f60b"}.bi-volume-mute-fill::before{content:"\f60c"}.bi-volume-mute::before{content:"\f60d"}.bi-volume-off-fill::before{content:"\f60e"}.bi-volume-off::before{content:"\f60f"}.bi-volume-up-fill::before{content:"\f610"}.bi-volume-up::before{content:"\f611"}.bi-vr::before{content:"\f612"}.bi-wallet-fill::before{content:"\f613"}.bi-wallet::before{content:"\f614"}.bi-wallet2::before{content:"\f615"}.bi-watch::before{content:"\f616"}.bi-water::before{content:"\f617"}.bi-whatsapp::before{content:"\f618"}.bi-wifi-1::before{content:"\f619"}.bi-wifi-2::before{content:"\f61a"}.bi-wifi-off::before{content:"\f61b"}.bi-wifi::before{content:"\f61c"}.bi-wind::before{content:"\f61d"}.bi-window-dock::before{content:"\f61e"}.bi-window-sidebar::before{content:"\f61f"}.bi-window::before{content:"\f620"}.bi-wrench::before{content:"\f621"}.bi-x-circle-fill::before{content:"\f622"}.bi-x-circle::before{content:"\f623"}.bi-x-diamond-fill::before{content:"\f624"}.bi-x-diamond::before{content:"\f625"}.bi-x-octagon-fill::before{content:"\f626"}.bi-x-octagon::before{content:"\f627"}.bi-x-square-fill::before{content:"\f628"}.bi-x-square::before{content:"\f629"}.bi-x::before{content:"\f62a"}.bi-youtube::before{content:"\f62b"}.bi-zoom-in::before{content:"\f62c"}.bi-zoom-out::before{content:"\f62d"}.bi-bank::before{content:"\f62e"}.bi-bank2::before{content:"\f62f"}.bi-bell-slash-fill::before{content:"\f630"}.bi-bell-slash::before{content:"\f631"}.bi-cash-coin::before{content:"\f632"}.bi-check-lg::before{content:"\f633"}.bi-coin::before{content:"\f634"}.bi-currency-bitcoin::before{content:"\f635"}.bi-currency-dollar::before{content:"\f636"}.bi-currency-euro::before{content:"\f637"}.bi-currency-exchange::before{content:"\f638"}.bi-currency-pound::before{content:"\f639"}.bi-currency-yen::before{content:"\f63a"}.bi-dash-lg::before{content:"\f63b"}.bi-exclamation-lg::before{content:"\f63c"}.bi-file-earmark-pdf-fill::before{content:"\f63d"}.bi-file-earmark-pdf::before{content:"\f63e"}.bi-file-pdf-fill::before{content:"\f63f"}.bi-file-pdf::before{content:"\f640"}.bi-gender-ambiguous::before{content:"\f641"}.bi-gender-female::before{content:"\f642"}.bi-gender-male::before{content:"\f643"}.bi-gender-trans::before{content:"\f644"}.bi-headset-vr::before{content:"\f645"}.bi-info-lg::before{content:"\f646"}.bi-mastodon::before{content:"\f647"}.bi-messenger::before{content:"\f648"}.bi-piggy-bank-fill::before{content:"\f649"}.bi-piggy-bank::before{content:"\f64a"}.bi-pin-map-fill::before{content:"\f64b"}.bi-pin-map::before{content:"\f64c"}.bi-plus-lg::before{content:"\f64d"}.bi-question-lg::before{content:"\f64e"}.bi-recycle::before{content:"\f64f"}.bi-reddit::before{content:"\f650"}.bi-safe-fill::before{content:"\f651"}.bi-safe2-fill::before{content:"\f652"}.bi-safe2::before{content:"\f653"}.bi-sd-card-fill::before{content:"\f654"}.bi-sd-card::before{content:"\f655"}.bi-skype::before{content:"\f656"}.bi-slash-lg::before{content:"\f657"}.bi-translate::before{content:"\f658"}.bi-x-lg::before{content:"\f659"}.bi-safe::before{content:"\f65a"}.bi-apple::before{content:"\f65b"}.bi-microsoft::before{content:"\f65d"}.bi-windows::before{content:"\f65e"}.bi-behance::before{content:"\f65c"}.bi-dribbble::before{content:"\f65f"}.bi-line::before{content:"\f660"}.bi-medium::before{content:"\f661"}.bi-paypal::before{content:"\f662"}.bi-pinterest::before{content:"\f663"}.bi-signal::before{content:"\f664"}.bi-snapchat::before{content:"\f665"}.bi-spotify::before{content:"\f666"}.bi-stack-overflow::before{content:"\f667"}.bi-strava::before{content:"\f668"}.bi-wordpress::before{content:"\f669"}.bi-vimeo::before{content:"\f66a"}.bi-activity::before{content:"\f66b"}.bi-easel2-fill::before{content:"\f66c"}.bi-easel2::before{content:"\f66d"}.bi-easel3-fill::before{content:"\f66e"}.bi-easel3::before{content:"\f66f"}.bi-fan::before{content:"\f670"}.bi-fingerprint::before{content:"\f671"}.bi-graph-down-arrow::before{content:"\f672"}.bi-graph-up-arrow::before{content:"\f673"}.bi-hypnotize::before{content:"\f674"}.bi-magic::before{content:"\f675"}.bi-person-rolodex::before{content:"\f676"}.bi-person-video::before{content:"\f677"}.bi-person-video2::before{content:"\f678"}.bi-person-video3::before{content:"\f679"}.bi-person-workspace::before{content:"\f67a"}.bi-radioactive::before{content:"\f67b"}.bi-webcam-fill::before{content:"\f67c"}.bi-webcam::before{content:"\f67d"}.bi-yin-yang::before{content:"\f67e"}.bi-bandaid-fill::before{content:"\f680"}.bi-bandaid::before{content:"\f681"}.bi-bluetooth::before{content:"\f682"}.bi-body-text::before{content:"\f683"}.bi-boombox::before{content:"\f684"}.bi-boxes::before{content:"\f685"}.bi-dpad-fill::before{content:"\f686"}.bi-dpad::before{content:"\f687"}.bi-ear-fill::before{content:"\f688"}.bi-ear::before{content:"\f689"}.bi-envelope-check-fill::before{content:"\f68b"}.bi-envelope-check::before{content:"\f68c"}.bi-envelope-dash-fill::before{content:"\f68e"}.bi-envelope-dash::before{content:"\f68f"}.bi-envelope-exclamation-fill::before{content:"\f691"}.bi-envelope-exclamation::before{content:"\f692"}.bi-envelope-plus-fill::before{content:"\f693"}.bi-envelope-plus::before{content:"\f694"}.bi-envelope-slash-fill::before{content:"\f696"}.bi-envelope-slash::before{content:"\f697"}.bi-envelope-x-fill::before{content:"\f699"}.bi-envelope-x::before{content:"\f69a"}.bi-explicit-fill::before{content:"\f69b"}.bi-explicit::before{content:"\f69c"}.bi-git::before{content:"\f69d"}.bi-infinity::before{content:"\f69e"}.bi-list-columns-reverse::before{content:"\f69f"}.bi-list-columns::before{content:"\f6a0"}.bi-meta::before{content:"\f6a1"}.bi-nintendo-switch::before{content:"\f6a4"}.bi-pc-display-horizontal::before{content:"\f6a5"}.bi-pc-display::before{content:"\f6a6"}.bi-pc-horizontal::before{content:"\f6a7"}.bi-pc::before{content:"\f6a8"}.bi-playstation::before{content:"\f6a9"}.bi-plus-slash-minus::before{content:"\f6aa"}.bi-projector-fill::before{content:"\f6ab"}.bi-projector::before{content:"\f6ac"}.bi-qr-code-scan::before{content:"\f6ad"}.bi-qr-code::before{content:"\f6ae"}.bi-quora::before{content:"\f6af"}.bi-quote::before{content:"\f6b0"}.bi-robot::before{content:"\f6b1"}.bi-send-check-fill::before{content:"\f6b2"}.bi-send-check::before{content:"\f6b3"}.bi-send-dash-fill::before{content:"\f6b4"}.bi-send-dash::before{content:"\f6b5"}.bi-send-exclamation-fill::before{content:"\f6b7"}.bi-send-exclamation::before{content:"\f6b8"}.bi-send-fill::before{content:"\f6b9"}.bi-send-plus-fill::before{content:"\f6ba"}.bi-send-plus::before{content:"\f6bb"}.bi-send-slash-fill::before{content:"\f6bc"}.bi-send-slash::before{content:"\f6bd"}.bi-send-x-fill::before{content:"\f6be"}.bi-send-x::before{content:"\f6bf"}.bi-send::before{content:"\f6c0"}.bi-steam::before{content:"\f6c1"}.bi-terminal-dash::before{content:"\f6c3"}.bi-terminal-plus::before{content:"\f6c4"}.bi-terminal-split::before{content:"\f6c5"}.bi-ticket-detailed-fill::before{content:"\f6c6"}.bi-ticket-detailed::before{content:"\f6c7"}.bi-ticket-fill::before{content:"\f6c8"}.bi-ticket-perforated-fill::before{content:"\f6c9"}.bi-ticket-perforated::before{content:"\f6ca"}.bi-ticket::before{content:"\f6cb"}.bi-tiktok::before{content:"\f6cc"}.bi-window-dash::before{content:"\f6cd"}.bi-window-desktop::before{content:"\f6ce"}.bi-window-fullscreen::before{content:"\f6cf"}.bi-window-plus::before{content:"\f6d0"}.bi-window-split::before{content:"\f6d1"}.bi-window-stack::before{content:"\f6d2"}.bi-window-x::before{content:"\f6d3"}.bi-xbox::before{content:"\f6d4"}.bi-ethernet::before{content:"\f6d5"}.bi-hdmi-fill::before{content:"\f6d6"}.bi-hdmi::before{content:"\f6d7"}.bi-usb-c-fill::before{content:"\f6d8"}.bi-usb-c::before{content:"\f6d9"}.bi-usb-fill::before{content:"\f6da"}.bi-usb-plug-fill::before{content:"\f6db"}.bi-usb-plug::before{content:"\f6dc"}.bi-usb-symbol::before{content:"\f6dd"}.bi-usb::before{content:"\f6de"}.bi-boombox-fill::before{content:"\f6df"}.bi-displayport::before{content:"\f6e1"}.bi-gpu-card::before{content:"\f6e2"}.bi-memory::before{content:"\f6e3"}.bi-modem-fill::before{content:"\f6e4"}.bi-modem::before{content:"\f6e5"}.bi-motherboard-fill::before{content:"\f6e6"}.bi-motherboard::before{content:"\f6e7"}.bi-optical-audio-fill::before{content:"\f6e8"}.bi-optical-audio::before{content:"\f6e9"}.bi-pci-card::before{content:"\f6ea"}.bi-router-fill::before{content:"\f6eb"}.bi-router::before{content:"\f6ec"}.bi-thunderbolt-fill::before{content:"\f6ef"}.bi-thunderbolt::before{content:"\f6f0"}.bi-usb-drive-fill::before{content:"\f6f1"}.bi-usb-drive::before{content:"\f6f2"}.bi-usb-micro-fill::before{content:"\f6f3"}.bi-usb-micro::before{content:"\f6f4"}.bi-usb-mini-fill::before{content:"\f6f5"}.bi-usb-mini::before{content:"\f6f6"}.bi-cloud-haze2::before{content:"\f6f7"}.bi-device-hdd-fill::before{content:"\f6f8"}.bi-device-hdd::before{content:"\f6f9"}.bi-device-ssd-fill::before{content:"\f6fa"}.bi-device-ssd::before{content:"\f6fb"}.bi-displayport-fill::before{content:"\f6fc"}.bi-mortarboard-fill::before{content:"\f6fd"}.bi-mortarboard::before{content:"\f6fe"}.bi-terminal-x::before{content:"\f6ff"}.bi-arrow-through-heart-fill::before{content:"\f700"}.bi-arrow-through-heart::before{content:"\f701"}.bi-badge-sd-fill::before{content:"\f702"}.bi-badge-sd::before{content:"\f703"}.bi-bag-heart-fill::before{content:"\f704"}.bi-bag-heart::before{content:"\f705"}.bi-balloon-fill::before{content:"\f706"}.bi-balloon-heart-fill::before{content:"\f707"}.bi-balloon-heart::before{content:"\f708"}.bi-balloon::before{content:"\f709"}.bi-box2-fill::before{content:"\f70a"}.bi-box2-heart-fill::before{content:"\f70b"}.bi-box2-heart::before{content:"\f70c"}.bi-box2::before{content:"\f70d"}.bi-braces-asterisk::before{content:"\f70e"}.bi-calendar-heart-fill::before{content:"\f70f"}.bi-calendar-heart::before{content:"\f710"}.bi-calendar2-heart-fill::before{content:"\f711"}.bi-calendar2-heart::before{content:"\f712"}.bi-chat-heart-fill::before{content:"\f713"}.bi-chat-heart::before{content:"\f714"}.bi-chat-left-heart-fill::before{content:"\f715"}.bi-chat-left-heart::before{content:"\f716"}.bi-chat-right-heart-fill::before{content:"\f717"}.bi-chat-right-heart::before{content:"\f718"}.bi-chat-square-heart-fill::before{content:"\f719"}.bi-chat-square-heart::before{content:"\f71a"}.bi-clipboard-check-fill::before{content:"\f71b"}.bi-clipboard-data-fill::before{content:"\f71c"}.bi-clipboard-fill::before{content:"\f71d"}.bi-clipboard-heart-fill::before{content:"\f71e"}.bi-clipboard-heart::before{content:"\f71f"}.bi-clipboard-minus-fill::before{content:"\f720"}.bi-clipboard-plus-fill::before{content:"\f721"}.bi-clipboard-pulse::before{content:"\f722"}.bi-clipboard-x-fill::before{content:"\f723"}.bi-clipboard2-check-fill::before{content:"\f724"}.bi-clipboard2-check::before{content:"\f725"}.bi-clipboard2-data-fill::before{content:"\f726"}.bi-clipboard2-data::before{content:"\f727"}.bi-clipboard2-fill::before{content:"\f728"}.bi-clipboard2-heart-fill::before{content:"\f729"}.bi-clipboard2-heart::before{content:"\f72a"}.bi-clipboard2-minus-fill::before{content:"\f72b"}.bi-clipboard2-minus::before{content:"\f72c"}.bi-clipboard2-plus-fill::before{content:"\f72d"}.bi-clipboard2-plus::before{content:"\f72e"}.bi-clipboard2-pulse-fill::before{content:"\f72f"}.bi-clipboard2-pulse::before{content:"\f730"}.bi-clipboard2-x-fill::before{content:"\f731"}.bi-clipboard2-x::before{content:"\f732"}.bi-clipboard2::before{content:"\f733"}.bi-emoji-kiss-fill::before{content:"\f734"}.bi-emoji-kiss::before{content:"\f735"}.bi-envelope-heart-fill::before{content:"\f736"}.bi-envelope-heart::before{content:"\f737"}.bi-envelope-open-heart-fill::before{content:"\f738"}.bi-envelope-open-heart::before{content:"\f739"}.bi-envelope-paper-fill::before{content:"\f73a"}.bi-envelope-paper-heart-fill::before{content:"\f73b"}.bi-envelope-paper-heart::before{content:"\f73c"}.bi-envelope-paper::before{content:"\f73d"}.bi-filetype-aac::before{content:"\f73e"}.bi-filetype-ai::before{content:"\f73f"}.bi-filetype-bmp::before{content:"\f740"}.bi-filetype-cs::before{content:"\f741"}.bi-filetype-css::before{content:"\f742"}.bi-filetype-csv::before{content:"\f743"}.bi-filetype-doc::before{content:"\f744"}.bi-filetype-docx::before{content:"\f745"}.bi-filetype-exe::before{content:"\f746"}.bi-filetype-gif::before{content:"\f747"}.bi-filetype-heic::before{content:"\f748"}.bi-filetype-html::before{content:"\f749"}.bi-filetype-java::before{content:"\f74a"}.bi-filetype-jpg::before{content:"\f74b"}.bi-filetype-js::before{content:"\f74c"}.bi-filetype-jsx::before{content:"\f74d"}.bi-filetype-key::before{content:"\f74e"}.bi-filetype-m4p::before{content:"\f74f"}.bi-filetype-md::before{content:"\f750"}.bi-filetype-mdx::before{content:"\f751"}.bi-filetype-mov::before{content:"\f752"}.bi-filetype-mp3::before{content:"\f753"}.bi-filetype-mp4::before{content:"\f754"}.bi-filetype-otf::before{content:"\f755"}.bi-filetype-pdf::before{content:"\f756"}.bi-filetype-php::before{content:"\f757"}.bi-filetype-png::before{content:"\f758"}.bi-filetype-ppt::before{content:"\f75a"}.bi-filetype-psd::before{content:"\f75b"}.bi-filetype-py::before{content:"\f75c"}.bi-filetype-raw::before{content:"\f75d"}.bi-filetype-rb::before{content:"\f75e"}.bi-filetype-sass::before{content:"\f75f"}.bi-filetype-scss::before{content:"\f760"}.bi-filetype-sh::before{content:"\f761"}.bi-filetype-svg::before{content:"\f762"}.bi-filetype-tiff::before{content:"\f763"}.bi-filetype-tsx::before{content:"\f764"}.bi-filetype-ttf::before{content:"\f765"}.bi-filetype-txt::before{content:"\f766"}.bi-filetype-wav::before{content:"\f767"}.bi-filetype-woff::before{content:"\f768"}.bi-filetype-xls::before{content:"\f76a"}.bi-filetype-xml::before{content:"\f76b"}.bi-filetype-yml::before{content:"\f76c"}.bi-heart-arrow::before{content:"\f76d"}.bi-heart-pulse-fill::before{content:"\f76e"}.bi-heart-pulse::before{content:"\f76f"}.bi-heartbreak-fill::before{content:"\f770"}.bi-heartbreak::before{content:"\f771"}.bi-hearts::before{content:"\f772"}.bi-hospital-fill::before{content:"\f773"}.bi-hospital::before{content:"\f774"}.bi-house-heart-fill::before{content:"\f775"}.bi-house-heart::before{content:"\f776"}.bi-incognito::before{content:"\f777"}.bi-magnet-fill::before{content:"\f778"}.bi-magnet::before{content:"\f779"}.bi-person-heart::before{content:"\f77a"}.bi-person-hearts::before{content:"\f77b"}.bi-phone-flip::before{content:"\f77c"}.bi-plugin::before{content:"\f77d"}.bi-postage-fill::before{content:"\f77e"}.bi-postage-heart-fill::before{content:"\f77f"}.bi-postage-heart::before{content:"\f780"}.bi-postage::before{content:"\f781"}.bi-postcard-fill::before{content:"\f782"}.bi-postcard-heart-fill::before{content:"\f783"}.bi-postcard-heart::before{content:"\f784"}.bi-postcard::before{content:"\f785"}.bi-search-heart-fill::before{content:"\f786"}.bi-search-heart::before{content:"\f787"}.bi-sliders2-vertical::before{content:"\f788"}.bi-sliders2::before{content:"\f789"}.bi-trash3-fill::before{content:"\f78a"}.bi-trash3::before{content:"\f78b"}.bi-valentine::before{content:"\f78c"}.bi-valentine2::before{content:"\f78d"}.bi-wrench-adjustable-circle-fill::before{content:"\f78e"}.bi-wrench-adjustable-circle::before{content:"\f78f"}.bi-wrench-adjustable::before{content:"\f790"}.bi-filetype-json::before{content:"\f791"}.bi-filetype-pptx::before{content:"\f792"}.bi-filetype-xlsx::before{content:"\f793"}.bi-1-circle-fill::before{content:"\f796"}.bi-1-circle::before{content:"\f797"}.bi-1-square-fill::before{content:"\f798"}.bi-1-square::before{content:"\f799"}.bi-2-circle-fill::before{content:"\f79c"}.bi-2-circle::before{content:"\f79d"}.bi-2-square-fill::before{content:"\f79e"}.bi-2-square::before{content:"\f79f"}.bi-3-circle-fill::before{content:"\f7a2"}.bi-3-circle::before{content:"\f7a3"}.bi-3-square-fill::before{content:"\f7a4"}.bi-3-square::before{content:"\f7a5"}.bi-4-circle-fill::before{content:"\f7a8"}.bi-4-circle::before{content:"\f7a9"}.bi-4-square-fill::before{content:"\f7aa"}.bi-4-square::before{content:"\f7ab"}.bi-5-circle-fill::before{content:"\f7ae"}.bi-5-circle::before{content:"\f7af"}.bi-5-square-fill::before{content:"\f7b0"}.bi-5-square::before{content:"\f7b1"}.bi-6-circle-fill::before{content:"\f7b4"}.bi-6-circle::before{content:"\f7b5"}.bi-6-square-fill::before{content:"\f7b6"}.bi-6-square::before{content:"\f7b7"}.bi-7-circle-fill::before{content:"\f7ba"}.bi-7-circle::before{content:"\f7bb"}.bi-7-square-fill::before{content:"\f7bc"}.bi-7-square::before{content:"\f7bd"}.bi-8-circle-fill::before{content:"\f7c0"}.bi-8-circle::before{content:"\f7c1"}.bi-8-square-fill::before{content:"\f7c2"}.bi-8-square::before{content:"\f7c3"}.bi-9-circle-fill::before{content:"\f7c6"}.bi-9-circle::before{content:"\f7c7"}.bi-9-square-fill::before{content:"\f7c8"}.bi-9-square::before{content:"\f7c9"}.bi-airplane-engines-fill::before{content:"\f7ca"}.bi-airplane-engines::before{content:"\f7cb"}.bi-airplane-fill::before{content:"\f7cc"}.bi-airplane::before{content:"\f7cd"}.bi-alexa::before{content:"\f7ce"}.bi-alipay::before{content:"\f7cf"}.bi-android::before{content:"\f7d0"}.bi-android2::before{content:"\f7d1"}.bi-box-fill::before{content:"\f7d2"}.bi-box-seam-fill::before{content:"\f7d3"}.bi-browser-chrome::before{content:"\f7d4"}.bi-browser-edge::before{content:"\f7d5"}.bi-browser-firefox::before{content:"\f7d6"}.bi-browser-safari::before{content:"\f7d7"}.bi-c-circle-fill::before{content:"\f7da"}.bi-c-circle::before{content:"\f7db"}.bi-c-square-fill::before{content:"\f7dc"}.bi-c-square::before{content:"\f7dd"}.bi-capsule-pill::before{content:"\f7de"}.bi-capsule::before{content:"\f7df"}.bi-car-front-fill::before{content:"\f7e0"}.bi-car-front::before{content:"\f7e1"}.bi-cassette-fill::before{content:"\f7e2"}.bi-cassette::before{content:"\f7e3"}.bi-cc-circle-fill::before{content:"\f7e6"}.bi-cc-circle::before{content:"\f7e7"}.bi-cc-square-fill::before{content:"\f7e8"}.bi-cc-square::before{content:"\f7e9"}.bi-cup-hot-fill::before{content:"\f7ea"}.bi-cup-hot::before{content:"\f7eb"}.bi-currency-rupee::before{content:"\f7ec"}.bi-dropbox::before{content:"\f7ed"}.bi-escape::before{content:"\f7ee"}.bi-fast-forward-btn-fill::before{content:"\f7ef"}.bi-fast-forward-btn::before{content:"\f7f0"}.bi-fast-forward-circle-fill::before{content:"\f7f1"}.bi-fast-forward-circle::before{content:"\f7f2"}.bi-fast-forward-fill::before{content:"\f7f3"}.bi-fast-forward::before{content:"\f7f4"}.bi-filetype-sql::before{content:"\f7f5"}.bi-fire::before{content:"\f7f6"}.bi-google-play::before{content:"\f7f7"}.bi-h-circle-fill::before{content:"\f7fa"}.bi-h-circle::before{content:"\f7fb"}.bi-h-square-fill::before{content:"\f7fc"}.bi-h-square::before{content:"\f7fd"}.bi-indent::before{content:"\f7fe"}.bi-lungs-fill::before{content:"\f7ff"}.bi-lungs::before{content:"\f800"}.bi-microsoft-teams::before{content:"\f801"}.bi-p-circle-fill::before{content:"\f804"}.bi-p-circle::before{content:"\f805"}.bi-p-square-fill::before{content:"\f806"}.bi-p-square::before{content:"\f807"}.bi-pass-fill::before{content:"\f808"}.bi-pass::before{content:"\f809"}.bi-prescription::before{content:"\f80a"}.bi-prescription2::before{content:"\f80b"}.bi-r-circle-fill::before{content:"\f80e"}.bi-r-circle::before{content:"\f80f"}.bi-r-square-fill::before{content:"\f810"}.bi-r-square::before{content:"\f811"}.bi-repeat-1::before{content:"\f812"}.bi-repeat::before{content:"\f813"}.bi-rewind-btn-fill::before{content:"\f814"}.bi-rewind-btn::before{content:"\f815"}.bi-rewind-circle-fill::before{content:"\f816"}.bi-rewind-circle::before{content:"\f817"}.bi-rewind-fill::before{content:"\f818"}.bi-rewind::before{content:"\f819"}.bi-train-freight-front-fill::before{content:"\f81a"}.bi-train-freight-front::before{content:"\f81b"}.bi-train-front-fill::before{content:"\f81c"}.bi-train-front::before{content:"\f81d"}.bi-train-lightrail-front-fill::before{content:"\f81e"}.bi-train-lightrail-front::before{content:"\f81f"}.bi-truck-front-fill::before{content:"\f820"}.bi-truck-front::before{content:"\f821"}.bi-ubuntu::before{content:"\f822"}.bi-unindent::before{content:"\f823"}.bi-unity::before{content:"\f824"}.bi-universal-access-circle::before{content:"\f825"}.bi-universal-access::before{content:"\f826"}.bi-virus::before{content:"\f827"}.bi-virus2::before{content:"\f828"}.bi-wechat::before{content:"\f829"}.bi-yelp::before{content:"\f82a"}.bi-sign-stop-fill::before{content:"\f82b"}.bi-sign-stop-lights-fill::before{content:"\f82c"}.bi-sign-stop-lights::before{content:"\f82d"}.bi-sign-stop::before{content:"\f82e"}.bi-sign-turn-left-fill::before{content:"\f82f"}.bi-sign-turn-left::before{content:"\f830"}.bi-sign-turn-right-fill::before{content:"\f831"}.bi-sign-turn-right::before{content:"\f832"}.bi-sign-turn-slight-left-fill::before{content:"\f833"}.bi-sign-turn-slight-left::before{content:"\f834"}.bi-sign-turn-slight-right-fill::before{content:"\f835"}.bi-sign-turn-slight-right::before{content:"\f836"}.bi-sign-yield-fill::before{content:"\f837"}.bi-sign-yield::before{content:"\f838"}.bi-ev-station-fill::before{content:"\f839"}.bi-ev-station::before{content:"\f83a"}.bi-fuel-pump-diesel-fill::before{content:"\f83b"}.bi-fuel-pump-diesel::before{content:"\f83c"}.bi-fuel-pump-fill::before{content:"\f83d"}.bi-fuel-pump::before{content:"\f83e"}.bi-0-circle-fill::before{content:"\f83f"}.bi-0-circle::before{content:"\f840"}.bi-0-square-fill::before{content:"\f841"}.bi-0-square::before{content:"\f842"}.bi-rocket-fill::before{content:"\f843"}.bi-rocket-takeoff-fill::before{content:"\f844"}.bi-rocket-takeoff::before{content:"\f845"}.bi-rocket::before{content:"\f846"}.bi-stripe::before{content:"\f847"}.bi-subscript::before{content:"\f848"}.bi-superscript::before{content:"\f849"}.bi-trello::before{content:"\f84a"}.bi-envelope-at-fill::before{content:"\f84b"}.bi-envelope-at::before{content:"\f84c"}.bi-regex::before{content:"\f84d"}.bi-text-wrap::before{content:"\f84e"}.bi-sign-dead-end-fill::before{content:"\f84f"}.bi-sign-dead-end::before{content:"\f850"}.bi-sign-do-not-enter-fill::before{content:"\f851"}.bi-sign-do-not-enter::before{content:"\f852"}.bi-sign-intersection-fill::before{content:"\f853"}.bi-sign-intersection-side-fill::before{content:"\f854"}.bi-sign-intersection-side::before{content:"\f855"}.bi-sign-intersection-t-fill::before{content:"\f856"}.bi-sign-intersection-t::before{content:"\f857"}.bi-sign-intersection-y-fill::before{content:"\f858"}.bi-sign-intersection-y::before{content:"\f859"}.bi-sign-intersection::before{content:"\f85a"}.bi-sign-merge-left-fill::before{content:"\f85b"}.bi-sign-merge-left::before{content:"\f85c"}.bi-sign-merge-right-fill::before{content:"\f85d"}.bi-sign-merge-right::before{content:"\f85e"}.bi-sign-no-left-turn-fill::before{content:"\f85f"}.bi-sign-no-left-turn::before{content:"\f860"}.bi-sign-no-parking-fill::before{content:"\f861"}.bi-sign-no-parking::before{content:"\f862"}.bi-sign-no-right-turn-fill::before{content:"\f863"}.bi-sign-no-right-turn::before{content:"\f864"}.bi-sign-railroad-fill::before{content:"\f865"}.bi-sign-railroad::before{content:"\f866"}.bi-building-add::before{content:"\f867"}.bi-building-check::before{content:"\f868"}.bi-building-dash::before{content:"\f869"}.bi-building-down::before{content:"\f86a"}.bi-building-exclamation::before{content:"\f86b"}.bi-building-fill-add::before{content:"\f86c"}.bi-building-fill-check::before{content:"\f86d"}.bi-building-fill-dash::before{content:"\f86e"}.bi-building-fill-down::before{content:"\f86f"}.bi-building-fill-exclamation::before{content:"\f870"}.bi-building-fill-gear::before{content:"\f871"}.bi-building-fill-lock::before{content:"\f872"}.bi-building-fill-slash::before{content:"\f873"}.bi-building-fill-up::before{content:"\f874"}.bi-building-fill-x::before{content:"\f875"}.bi-building-fill::before{content:"\f876"}.bi-building-gear::before{content:"\f877"}.bi-building-lock::before{content:"\f878"}.bi-building-slash::before{content:"\f879"}.bi-building-up::before{content:"\f87a"}.bi-building-x::before{content:"\f87b"}.bi-buildings-fill::before{content:"\f87c"}.bi-buildings::before{content:"\f87d"}.bi-bus-front-fill::before{content:"\f87e"}.bi-bus-front::before{content:"\f87f"}.bi-ev-front-fill::before{content:"\f880"}.bi-ev-front::before{content:"\f881"}.bi-globe-americas::before{content:"\f882"}.bi-globe-asia-australia::before{content:"\f883"}.bi-globe-central-south-asia::before{content:"\f884"}.bi-globe-europe-africa::before{content:"\f885"}.bi-house-add-fill::before{content:"\f886"}.bi-house-add::before{content:"\f887"}.bi-house-check-fill::before{content:"\f888"}.bi-house-check::before{content:"\f889"}.bi-house-dash-fill::before{content:"\f88a"}.bi-house-dash::before{content:"\f88b"}.bi-house-down-fill::before{content:"\f88c"}.bi-house-down::before{content:"\f88d"}.bi-house-exclamation-fill::before{content:"\f88e"}.bi-house-exclamation::before{content:"\f88f"}.bi-house-gear-fill::before{content:"\f890"}.bi-house-gear::before{content:"\f891"}.bi-house-lock-fill::before{content:"\f892"}.bi-house-lock::before{content:"\f893"}.bi-house-slash-fill::before{content:"\f894"}.bi-house-slash::before{content:"\f895"}.bi-house-up-fill::before{content:"\f896"}.bi-house-up::before{content:"\f897"}.bi-house-x-fill::before{content:"\f898"}.bi-house-x::before{content:"\f899"}.bi-person-add::before{content:"\f89a"}.bi-person-down::before{content:"\f89b"}.bi-person-exclamation::before{content:"\f89c"}.bi-person-fill-add::before{content:"\f89d"}.bi-person-fill-check::before{content:"\f89e"}.bi-person-fill-dash::before{content:"\f89f"}.bi-person-fill-down::before{content:"\f8a0"}.bi-person-fill-exclamation::before{content:"\f8a1"}.bi-person-fill-gear::before{content:"\f8a2"}.bi-person-fill-lock::before{content:"\f8a3"}.bi-person-fill-slash::before{content:"\f8a4"}.bi-person-fill-up::before{content:"\f8a5"}.bi-person-fill-x::before{content:"\f8a6"}.bi-person-gear::before{content:"\f8a7"}.bi-person-lock::before{content:"\f8a8"}.bi-person-slash::before{content:"\f8a9"}.bi-person-up::before{content:"\f8aa"}.bi-scooter::before{content:"\f8ab"}.bi-taxi-front-fill::before{content:"\f8ac"}.bi-taxi-front::before{content:"\f8ad"}.bi-amd::before{content:"\f8ae"}.bi-database-add::before{content:"\f8af"}.bi-database-check::before{content:"\f8b0"}.bi-database-dash::before{content:"\f8b1"}.bi-database-down::before{content:"\f8b2"}.bi-database-exclamation::before{content:"\f8b3"}.bi-database-fill-add::before{content:"\f8b4"}.bi-database-fill-check::before{content:"\f8b5"}.bi-database-fill-dash::before{content:"\f8b6"}.bi-database-fill-down::before{content:"\f8b7"}.bi-database-fill-exclamation::before{content:"\f8b8"}.bi-database-fill-gear::before{content:"\f8b9"}.bi-database-fill-lock::before{content:"\f8ba"}.bi-database-fill-slash::before{content:"\f8bb"}.bi-database-fill-up::before{content:"\f8bc"}.bi-database-fill-x::before{content:"\f8bd"}.bi-database-fill::before{content:"\f8be"}.bi-database-gear::before{content:"\f8bf"}.bi-database-lock::before{content:"\f8c0"}.bi-database-slash::before{content:"\f8c1"}.bi-database-up::before{content:"\f8c2"}.bi-database-x::before{content:"\f8c3"}.bi-database::before{content:"\f8c4"}.bi-houses-fill::before{content:"\f8c5"}.bi-houses::before{content:"\f8c6"}.bi-nvidia::before{content:"\f8c7"}.bi-person-vcard-fill::before{content:"\f8c8"}.bi-person-vcard::before{content:"\f8c9"}.bi-sina-weibo::before{content:"\f8ca"}.bi-tencent-qq::before{content:"\f8cb"}.bi-wikipedia::before{content:"\f8cc"}.bi-alphabet-uppercase::before{content:"\f2a5"}.bi-alphabet::before{content:"\f68a"}.bi-amazon::before{content:"\f68d"}.bi-arrows-collapse-vertical::before{content:"\f690"}.bi-arrows-expand-vertical::before{content:"\f695"}.bi-arrows-vertical::before{content:"\f698"}.bi-arrows::before{content:"\f6a2"}.bi-ban-fill::before{content:"\f6a3"}.bi-ban::before{content:"\f6b6"}.bi-bing::before{content:"\f6c2"}.bi-cake::before{content:"\f6e0"}.bi-cake2::before{content:"\f6ed"}.bi-cookie::before{content:"\f6ee"}.bi-copy::before{content:"\f759"}.bi-crosshair::before{content:"\f769"}.bi-crosshair2::before{content:"\f794"}.bi-emoji-astonished-fill::before{content:"\f795"}.bi-emoji-astonished::before{content:"\f79a"}.bi-emoji-grimace-fill::before{content:"\f79b"}.bi-emoji-grimace::before{content:"\f7a0"}.bi-emoji-grin-fill::before{content:"\f7a1"}.bi-emoji-grin::before{content:"\f7a6"}.bi-emoji-surprise-fill::before{content:"\f7a7"}.bi-emoji-surprise::before{content:"\f7ac"}.bi-emoji-tear-fill::before{content:"\f7ad"}.bi-emoji-tear::before{content:"\f7b2"}.bi-envelope-arrow-down-fill::before{content:"\f7b3"}.bi-envelope-arrow-down::before{content:"\f7b8"}.bi-envelope-arrow-up-fill::before{content:"\f7b9"}.bi-envelope-arrow-up::before{content:"\f7be"}.bi-feather::before{content:"\f7bf"}.bi-feather2::before{content:"\f7c4"}.bi-floppy-fill::before{content:"\f7c5"}.bi-floppy::before{content:"\f7d8"}.bi-floppy2-fill::before{content:"\f7d9"}.bi-floppy2::before{content:"\f7e4"}.bi-gitlab::before{content:"\f7e5"}.bi-highlighter::before{content:"\f7f8"}.bi-marker-tip::before{content:"\f802"}.bi-nvme-fill::before{content:"\f803"}.bi-nvme::before{content:"\f80c"}.bi-opencollective::before{content:"\f80d"}.bi-pci-card-network::before{content:"\f8cd"}.bi-pci-card-sound::before{content:"\f8ce"}.bi-radar::before{content:"\f8cf"}.bi-send-arrow-down-fill::before{content:"\f8d0"}.bi-send-arrow-down::before{content:"\f8d1"}.bi-send-arrow-up-fill::before{content:"\f8d2"}.bi-send-arrow-up::before{content:"\f8d3"}.bi-sim-slash-fill::before{content:"\f8d4"}.bi-sim-slash::before{content:"\f8d5"}.bi-sourceforge::before{content:"\f8d6"}.bi-substack::before{content:"\f8d7"}.bi-threads-fill::before{content:"\f8d8"}.bi-threads::before{content:"\f8d9"}.bi-transparency::before{content:"\f8da"}.bi-twitter-x::before{content:"\f8db"}.bi-type-h4::before{content:"\f8dc"}.bi-type-h5::before{content:"\f8dd"}.bi-type-h6::before{content:"\f8de"}.bi-backpack-fill::before{content:"\f8df"}.bi-backpack::before{content:"\f8e0"}.bi-backpack2-fill::before{content:"\f8e1"}.bi-backpack2::before{content:"\f8e2"}.bi-backpack3-fill::before{content:"\f8e3"}.bi-backpack3::before{content:"\f8e4"}.bi-backpack4-fill::before{content:"\f8e5"}.bi-backpack4::before{content:"\f8e6"}.bi-brilliance::before{content:"\f8e7"}.bi-cake-fill::before{content:"\f8e8"}.bi-cake2-fill::before{content:"\f8e9"}.bi-duffle-fill::before{content:"\f8ea"}.bi-duffle::before{content:"\f8eb"}.bi-exposure::before{content:"\f8ec"}.bi-gender-neuter::before{content:"\f8ed"}.bi-highlights::before{content:"\f8ee"}.bi-luggage-fill::before{content:"\f8ef"}.bi-luggage::before{content:"\f8f0"}.bi-mailbox-flag::before{content:"\f8f1"}.bi-mailbox2-flag::before{content:"\f8f2"}.bi-noise-reduction::before{content:"\f8f3"}.bi-passport-fill::before{content:"\f8f4"}.bi-passport::before{content:"\f8f5"}.bi-person-arms-up::before{content:"\f8f6"}.bi-person-raised-hand::before{content:"\f8f7"}.bi-person-standing-dress::before{content:"\f8f8"}.bi-person-standing::before{content:"\f8f9"}.bi-person-walking::before{content:"\f8fa"}.bi-person-wheelchair::before{content:"\f8fb"}.bi-shadows::before{content:"\f8fc"}.bi-suitcase-fill::before{content:"\f8fd"}.bi-suitcase-lg-fill::before{content:"\f8fe"}.bi-suitcase-lg::before{content:"\f8ff"}.bi-suitcase::before{content:"\f900"}.bi-suitcase2-fill::before{content:"\f901"}.bi-suitcase2::before{content:"\f902"}.bi-vignette::before{content:"\f903"}.bi-bluesky::before{content:"\f7f9"}.bi-tux::before{content:"\f904"}.bi-beaker-fill::before{content:"\f905"}.bi-beaker::before{content:"\f906"}.bi-flask-fill::before{content:"\f907"}.bi-flask-florence-fill::before{content:"\f908"}.bi-flask-florence::before{content:"\f909"}.bi-flask::before{content:"\f90a"}.bi-leaf-fill::before{content:"\f90b"}.bi-leaf::before{content:"\f90c"}.bi-measuring-cup-fill::before{content:"\f90d"}.bi-measuring-cup::before{content:"\f90e"}.bi-unlock2-fill::before{content:"\f90f"}.bi-unlock2::before{content:"\f910"}.bi-battery-low::before{content:"\f911"}.bi-anthropic::before{content:"\f912"}.bi-apple-music::before{content:"\f913"}.bi-claude::before{content:"\f914"}.bi-openai::before{content:"\f915"}.bi-perplexity::before{content:"\f916"}.bi-css::before{content:"\f917"}.bi-javascript::before{content:"\f918"}.bi-typescript::before{content:"\f919"}.bi-fork-knife::before{content:"\f91a"}.bi-globe-americas-fill::before{content:"\f91b"}.bi-globe-asia-australia-fill::before{content:"\f91c"}.bi-globe-central-south-asia-fill::before{content:"\f91d"}.bi-globe-europe-africa-fill::before{content:"\f91e"} \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.scss b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.scss new file mode 100644 index 00000000..19735c42 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.scss @@ -0,0 +1,2118 @@ +/*! + * Bootstrap Icons v1.13.1 (https://icons.getbootstrap.com/) + * Copyright 2019-2024 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/icons/blob/main/LICENSE) + */ + +$bootstrap-icons-font: "bootstrap-icons" !default; +$bootstrap-icons-font-dir: "./fonts" !default; +$bootstrap-icons-font-file: "#{$bootstrap-icons-font-dir}/#{$bootstrap-icons-font}" !default; +$bootstrap-icons-font-hash: "24e3eb84d0bcaf83d77f904c78ac1f47" !default; +$bootstrap-icons-font-src: url("#{$bootstrap-icons-font-file}.woff2?#{$bootstrap-icons-font-hash}") format("woff2"), + url("#{$bootstrap-icons-font-file}.woff?#{$bootstrap-icons-font-hash}") format("woff") !default; + +@font-face { + font-display: block; + font-family: $bootstrap-icons-font; + src: $bootstrap-icons-font-src; +} + +.bi::before, +[class^="bi-"]::before, +[class*=" bi-"]::before { + display: inline-block; + font-family: $bootstrap-icons-font !important; + font-style: normal; + font-weight: normal !important; + font-variant: normal; + text-transform: none; + line-height: 1; + vertical-align: -.125em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +$bootstrap-icons-map: ( + "123": "\f67f", + "alarm-fill": "\f101", + "alarm": "\f102", + "align-bottom": "\f103", + "align-center": "\f104", + "align-end": "\f105", + "align-middle": "\f106", + "align-start": "\f107", + "align-top": "\f108", + "alt": "\f109", + "app-indicator": "\f10a", + "app": "\f10b", + "archive-fill": "\f10c", + "archive": "\f10d", + "arrow-90deg-down": "\f10e", + "arrow-90deg-left": "\f10f", + "arrow-90deg-right": "\f110", + "arrow-90deg-up": "\f111", + "arrow-bar-down": "\f112", + "arrow-bar-left": "\f113", + "arrow-bar-right": "\f114", + "arrow-bar-up": "\f115", + "arrow-clockwise": "\f116", + "arrow-counterclockwise": "\f117", + "arrow-down-circle-fill": "\f118", + "arrow-down-circle": "\f119", + "arrow-down-left-circle-fill": "\f11a", + "arrow-down-left-circle": "\f11b", + "arrow-down-left-square-fill": "\f11c", + "arrow-down-left-square": "\f11d", + "arrow-down-left": "\f11e", + "arrow-down-right-circle-fill": "\f11f", + "arrow-down-right-circle": "\f120", + "arrow-down-right-square-fill": "\f121", + "arrow-down-right-square": "\f122", + "arrow-down-right": "\f123", + "arrow-down-short": "\f124", + "arrow-down-square-fill": "\f125", + "arrow-down-square": "\f126", + "arrow-down-up": "\f127", + "arrow-down": "\f128", + "arrow-left-circle-fill": "\f129", + "arrow-left-circle": "\f12a", + "arrow-left-right": "\f12b", + "arrow-left-short": "\f12c", + "arrow-left-square-fill": "\f12d", + "arrow-left-square": "\f12e", + "arrow-left": "\f12f", + "arrow-repeat": "\f130", + "arrow-return-left": "\f131", + "arrow-return-right": "\f132", + "arrow-right-circle-fill": "\f133", + "arrow-right-circle": "\f134", + "arrow-right-short": "\f135", + "arrow-right-square-fill": "\f136", + "arrow-right-square": "\f137", + "arrow-right": "\f138", + "arrow-up-circle-fill": "\f139", + "arrow-up-circle": "\f13a", + "arrow-up-left-circle-fill": "\f13b", + "arrow-up-left-circle": "\f13c", + "arrow-up-left-square-fill": "\f13d", + "arrow-up-left-square": "\f13e", + "arrow-up-left": "\f13f", + "arrow-up-right-circle-fill": "\f140", + "arrow-up-right-circle": "\f141", + "arrow-up-right-square-fill": "\f142", + "arrow-up-right-square": "\f143", + "arrow-up-right": "\f144", + "arrow-up-short": "\f145", + "arrow-up-square-fill": "\f146", + "arrow-up-square": "\f147", + "arrow-up": "\f148", + "arrows-angle-contract": "\f149", + "arrows-angle-expand": "\f14a", + "arrows-collapse": "\f14b", + "arrows-expand": "\f14c", + "arrows-fullscreen": "\f14d", + "arrows-move": "\f14e", + "aspect-ratio-fill": "\f14f", + "aspect-ratio": "\f150", + "asterisk": "\f151", + "at": "\f152", + "award-fill": "\f153", + "award": "\f154", + "back": "\f155", + "backspace-fill": "\f156", + "backspace-reverse-fill": "\f157", + "backspace-reverse": "\f158", + "backspace": "\f159", + "badge-3d-fill": "\f15a", + "badge-3d": "\f15b", + "badge-4k-fill": "\f15c", + "badge-4k": "\f15d", + "badge-8k-fill": "\f15e", + "badge-8k": "\f15f", + "badge-ad-fill": "\f160", + "badge-ad": "\f161", + "badge-ar-fill": "\f162", + "badge-ar": "\f163", + "badge-cc-fill": "\f164", + "badge-cc": "\f165", + "badge-hd-fill": "\f166", + "badge-hd": "\f167", + "badge-tm-fill": "\f168", + "badge-tm": "\f169", + "badge-vo-fill": "\f16a", + "badge-vo": "\f16b", + "badge-vr-fill": "\f16c", + "badge-vr": "\f16d", + "badge-wc-fill": "\f16e", + "badge-wc": "\f16f", + "bag-check-fill": "\f170", + "bag-check": "\f171", + "bag-dash-fill": "\f172", + "bag-dash": "\f173", + "bag-fill": "\f174", + "bag-plus-fill": "\f175", + "bag-plus": "\f176", + "bag-x-fill": "\f177", + "bag-x": "\f178", + "bag": "\f179", + "bar-chart-fill": "\f17a", + "bar-chart-line-fill": "\f17b", + "bar-chart-line": "\f17c", + "bar-chart-steps": "\f17d", + "bar-chart": "\f17e", + "basket-fill": "\f17f", + "basket": "\f180", + "basket2-fill": "\f181", + "basket2": "\f182", + "basket3-fill": "\f183", + "basket3": "\f184", + "battery-charging": "\f185", + "battery-full": "\f186", + "battery-half": "\f187", + "battery": "\f188", + "bell-fill": "\f189", + "bell": "\f18a", + "bezier": "\f18b", + "bezier2": "\f18c", + "bicycle": "\f18d", + "binoculars-fill": "\f18e", + "binoculars": "\f18f", + "blockquote-left": "\f190", + "blockquote-right": "\f191", + "book-fill": "\f192", + "book-half": "\f193", + "book": "\f194", + "bookmark-check-fill": "\f195", + "bookmark-check": "\f196", + "bookmark-dash-fill": "\f197", + "bookmark-dash": "\f198", + "bookmark-fill": "\f199", + "bookmark-heart-fill": "\f19a", + "bookmark-heart": "\f19b", + "bookmark-plus-fill": "\f19c", + "bookmark-plus": "\f19d", + "bookmark-star-fill": "\f19e", + "bookmark-star": "\f19f", + "bookmark-x-fill": "\f1a0", + "bookmark-x": "\f1a1", + "bookmark": "\f1a2", + "bookmarks-fill": "\f1a3", + "bookmarks": "\f1a4", + "bookshelf": "\f1a5", + "bootstrap-fill": "\f1a6", + "bootstrap-reboot": "\f1a7", + "bootstrap": "\f1a8", + "border-all": "\f1a9", + "border-bottom": "\f1aa", + "border-center": "\f1ab", + "border-inner": "\f1ac", + "border-left": "\f1ad", + "border-middle": "\f1ae", + "border-outer": "\f1af", + "border-right": "\f1b0", + "border-style": "\f1b1", + "border-top": "\f1b2", + "border-width": "\f1b3", + "border": "\f1b4", + "bounding-box-circles": "\f1b5", + "bounding-box": "\f1b6", + "box-arrow-down-left": "\f1b7", + "box-arrow-down-right": "\f1b8", + "box-arrow-down": "\f1b9", + "box-arrow-in-down-left": "\f1ba", + "box-arrow-in-down-right": "\f1bb", + "box-arrow-in-down": "\f1bc", + "box-arrow-in-left": "\f1bd", + "box-arrow-in-right": "\f1be", + "box-arrow-in-up-left": "\f1bf", + "box-arrow-in-up-right": "\f1c0", + "box-arrow-in-up": "\f1c1", + "box-arrow-left": "\f1c2", + "box-arrow-right": "\f1c3", + "box-arrow-up-left": "\f1c4", + "box-arrow-up-right": "\f1c5", + "box-arrow-up": "\f1c6", + "box-seam": "\f1c7", + "box": "\f1c8", + "braces": "\f1c9", + "bricks": "\f1ca", + "briefcase-fill": "\f1cb", + "briefcase": "\f1cc", + "brightness-alt-high-fill": "\f1cd", + "brightness-alt-high": "\f1ce", + "brightness-alt-low-fill": "\f1cf", + "brightness-alt-low": "\f1d0", + "brightness-high-fill": "\f1d1", + "brightness-high": "\f1d2", + "brightness-low-fill": "\f1d3", + "brightness-low": "\f1d4", + "broadcast-pin": "\f1d5", + "broadcast": "\f1d6", + "brush-fill": "\f1d7", + "brush": "\f1d8", + "bucket-fill": "\f1d9", + "bucket": "\f1da", + "bug-fill": "\f1db", + "bug": "\f1dc", + "building": "\f1dd", + "bullseye": "\f1de", + "calculator-fill": "\f1df", + "calculator": "\f1e0", + "calendar-check-fill": "\f1e1", + "calendar-check": "\f1e2", + "calendar-date-fill": "\f1e3", + "calendar-date": "\f1e4", + "calendar-day-fill": "\f1e5", + "calendar-day": "\f1e6", + "calendar-event-fill": "\f1e7", + "calendar-event": "\f1e8", + "calendar-fill": "\f1e9", + "calendar-minus-fill": "\f1ea", + "calendar-minus": "\f1eb", + "calendar-month-fill": "\f1ec", + "calendar-month": "\f1ed", + "calendar-plus-fill": "\f1ee", + "calendar-plus": "\f1ef", + "calendar-range-fill": "\f1f0", + "calendar-range": "\f1f1", + "calendar-week-fill": "\f1f2", + "calendar-week": "\f1f3", + "calendar-x-fill": "\f1f4", + "calendar-x": "\f1f5", + "calendar": "\f1f6", + "calendar2-check-fill": "\f1f7", + "calendar2-check": "\f1f8", + "calendar2-date-fill": "\f1f9", + "calendar2-date": "\f1fa", + "calendar2-day-fill": "\f1fb", + "calendar2-day": "\f1fc", + "calendar2-event-fill": "\f1fd", + "calendar2-event": "\f1fe", + "calendar2-fill": "\f1ff", + "calendar2-minus-fill": "\f200", + "calendar2-minus": "\f201", + "calendar2-month-fill": "\f202", + "calendar2-month": "\f203", + "calendar2-plus-fill": "\f204", + "calendar2-plus": "\f205", + "calendar2-range-fill": "\f206", + "calendar2-range": "\f207", + "calendar2-week-fill": "\f208", + "calendar2-week": "\f209", + "calendar2-x-fill": "\f20a", + "calendar2-x": "\f20b", + "calendar2": "\f20c", + "calendar3-event-fill": "\f20d", + "calendar3-event": "\f20e", + "calendar3-fill": "\f20f", + "calendar3-range-fill": "\f210", + "calendar3-range": "\f211", + "calendar3-week-fill": "\f212", + "calendar3-week": "\f213", + "calendar3": "\f214", + "calendar4-event": "\f215", + "calendar4-range": "\f216", + "calendar4-week": "\f217", + "calendar4": "\f218", + "camera-fill": "\f219", + "camera-reels-fill": "\f21a", + "camera-reels": "\f21b", + "camera-video-fill": "\f21c", + "camera-video-off-fill": "\f21d", + "camera-video-off": "\f21e", + "camera-video": "\f21f", + "camera": "\f220", + "camera2": "\f221", + "capslock-fill": "\f222", + "capslock": "\f223", + "card-checklist": "\f224", + "card-heading": "\f225", + "card-image": "\f226", + "card-list": "\f227", + "card-text": "\f228", + "caret-down-fill": "\f229", + "caret-down-square-fill": "\f22a", + "caret-down-square": "\f22b", + "caret-down": "\f22c", + "caret-left-fill": "\f22d", + "caret-left-square-fill": "\f22e", + "caret-left-square": "\f22f", + "caret-left": "\f230", + "caret-right-fill": "\f231", + "caret-right-square-fill": "\f232", + "caret-right-square": "\f233", + "caret-right": "\f234", + "caret-up-fill": "\f235", + "caret-up-square-fill": "\f236", + "caret-up-square": "\f237", + "caret-up": "\f238", + "cart-check-fill": "\f239", + "cart-check": "\f23a", + "cart-dash-fill": "\f23b", + "cart-dash": "\f23c", + "cart-fill": "\f23d", + "cart-plus-fill": "\f23e", + "cart-plus": "\f23f", + "cart-x-fill": "\f240", + "cart-x": "\f241", + "cart": "\f242", + "cart2": "\f243", + "cart3": "\f244", + "cart4": "\f245", + "cash-stack": "\f246", + "cash": "\f247", + "cast": "\f248", + "chat-dots-fill": "\f249", + "chat-dots": "\f24a", + "chat-fill": "\f24b", + "chat-left-dots-fill": "\f24c", + "chat-left-dots": "\f24d", + "chat-left-fill": "\f24e", + "chat-left-quote-fill": "\f24f", + "chat-left-quote": "\f250", + "chat-left-text-fill": "\f251", + "chat-left-text": "\f252", + "chat-left": "\f253", + "chat-quote-fill": "\f254", + "chat-quote": "\f255", + "chat-right-dots-fill": "\f256", + "chat-right-dots": "\f257", + "chat-right-fill": "\f258", + "chat-right-quote-fill": "\f259", + "chat-right-quote": "\f25a", + "chat-right-text-fill": "\f25b", + "chat-right-text": "\f25c", + "chat-right": "\f25d", + "chat-square-dots-fill": "\f25e", + "chat-square-dots": "\f25f", + "chat-square-fill": "\f260", + "chat-square-quote-fill": "\f261", + "chat-square-quote": "\f262", + "chat-square-text-fill": "\f263", + "chat-square-text": "\f264", + "chat-square": "\f265", + "chat-text-fill": "\f266", + "chat-text": "\f267", + "chat": "\f268", + "check-all": "\f269", + "check-circle-fill": "\f26a", + "check-circle": "\f26b", + "check-square-fill": "\f26c", + "check-square": "\f26d", + "check": "\f26e", + "check2-all": "\f26f", + "check2-circle": "\f270", + "check2-square": "\f271", + "check2": "\f272", + "chevron-bar-contract": "\f273", + "chevron-bar-down": "\f274", + "chevron-bar-expand": "\f275", + "chevron-bar-left": "\f276", + "chevron-bar-right": "\f277", + "chevron-bar-up": "\f278", + "chevron-compact-down": "\f279", + "chevron-compact-left": "\f27a", + "chevron-compact-right": "\f27b", + "chevron-compact-up": "\f27c", + "chevron-contract": "\f27d", + "chevron-double-down": "\f27e", + "chevron-double-left": "\f27f", + "chevron-double-right": "\f280", + "chevron-double-up": "\f281", + "chevron-down": "\f282", + "chevron-expand": "\f283", + "chevron-left": "\f284", + "chevron-right": "\f285", + "chevron-up": "\f286", + "circle-fill": "\f287", + "circle-half": "\f288", + "circle-square": "\f289", + "circle": "\f28a", + "clipboard-check": "\f28b", + "clipboard-data": "\f28c", + "clipboard-minus": "\f28d", + "clipboard-plus": "\f28e", + "clipboard-x": "\f28f", + "clipboard": "\f290", + "clock-fill": "\f291", + "clock-history": "\f292", + "clock": "\f293", + "cloud-arrow-down-fill": "\f294", + "cloud-arrow-down": "\f295", + "cloud-arrow-up-fill": "\f296", + "cloud-arrow-up": "\f297", + "cloud-check-fill": "\f298", + "cloud-check": "\f299", + "cloud-download-fill": "\f29a", + "cloud-download": "\f29b", + "cloud-drizzle-fill": "\f29c", + "cloud-drizzle": "\f29d", + "cloud-fill": "\f29e", + "cloud-fog-fill": "\f29f", + "cloud-fog": "\f2a0", + "cloud-fog2-fill": "\f2a1", + "cloud-fog2": "\f2a2", + "cloud-hail-fill": "\f2a3", + "cloud-hail": "\f2a4", + "cloud-haze-fill": "\f2a6", + "cloud-haze": "\f2a7", + "cloud-haze2-fill": "\f2a8", + "cloud-lightning-fill": "\f2a9", + "cloud-lightning-rain-fill": "\f2aa", + "cloud-lightning-rain": "\f2ab", + "cloud-lightning": "\f2ac", + "cloud-minus-fill": "\f2ad", + "cloud-minus": "\f2ae", + "cloud-moon-fill": "\f2af", + "cloud-moon": "\f2b0", + "cloud-plus-fill": "\f2b1", + "cloud-plus": "\f2b2", + "cloud-rain-fill": "\f2b3", + "cloud-rain-heavy-fill": "\f2b4", + "cloud-rain-heavy": "\f2b5", + "cloud-rain": "\f2b6", + "cloud-slash-fill": "\f2b7", + "cloud-slash": "\f2b8", + "cloud-sleet-fill": "\f2b9", + "cloud-sleet": "\f2ba", + "cloud-snow-fill": "\f2bb", + "cloud-snow": "\f2bc", + "cloud-sun-fill": "\f2bd", + "cloud-sun": "\f2be", + "cloud-upload-fill": "\f2bf", + "cloud-upload": "\f2c0", + "cloud": "\f2c1", + "clouds-fill": "\f2c2", + "clouds": "\f2c3", + "cloudy-fill": "\f2c4", + "cloudy": "\f2c5", + "code-slash": "\f2c6", + "code-square": "\f2c7", + "code": "\f2c8", + "collection-fill": "\f2c9", + "collection-play-fill": "\f2ca", + "collection-play": "\f2cb", + "collection": "\f2cc", + "columns-gap": "\f2cd", + "columns": "\f2ce", + "command": "\f2cf", + "compass-fill": "\f2d0", + "compass": "\f2d1", + "cone-striped": "\f2d2", + "cone": "\f2d3", + "controller": "\f2d4", + "cpu-fill": "\f2d5", + "cpu": "\f2d6", + "credit-card-2-back-fill": "\f2d7", + "credit-card-2-back": "\f2d8", + "credit-card-2-front-fill": "\f2d9", + "credit-card-2-front": "\f2da", + "credit-card-fill": "\f2db", + "credit-card": "\f2dc", + "crop": "\f2dd", + "cup-fill": "\f2de", + "cup-straw": "\f2df", + "cup": "\f2e0", + "cursor-fill": "\f2e1", + "cursor-text": "\f2e2", + "cursor": "\f2e3", + "dash-circle-dotted": "\f2e4", + "dash-circle-fill": "\f2e5", + "dash-circle": "\f2e6", + "dash-square-dotted": "\f2e7", + "dash-square-fill": "\f2e8", + "dash-square": "\f2e9", + "dash": "\f2ea", + "diagram-2-fill": "\f2eb", + "diagram-2": "\f2ec", + "diagram-3-fill": "\f2ed", + "diagram-3": "\f2ee", + "diamond-fill": "\f2ef", + "diamond-half": "\f2f0", + "diamond": "\f2f1", + "dice-1-fill": "\f2f2", + "dice-1": "\f2f3", + "dice-2-fill": "\f2f4", + "dice-2": "\f2f5", + "dice-3-fill": "\f2f6", + "dice-3": "\f2f7", + "dice-4-fill": "\f2f8", + "dice-4": "\f2f9", + "dice-5-fill": "\f2fa", + "dice-5": "\f2fb", + "dice-6-fill": "\f2fc", + "dice-6": "\f2fd", + "disc-fill": "\f2fe", + "disc": "\f2ff", + "discord": "\f300", + "display-fill": "\f301", + "display": "\f302", + "distribute-horizontal": "\f303", + "distribute-vertical": "\f304", + "door-closed-fill": "\f305", + "door-closed": "\f306", + "door-open-fill": "\f307", + "door-open": "\f308", + "dot": "\f309", + "download": "\f30a", + "droplet-fill": "\f30b", + "droplet-half": "\f30c", + "droplet": "\f30d", + "earbuds": "\f30e", + "easel-fill": "\f30f", + "easel": "\f310", + "egg-fill": "\f311", + "egg-fried": "\f312", + "egg": "\f313", + "eject-fill": "\f314", + "eject": "\f315", + "emoji-angry-fill": "\f316", + "emoji-angry": "\f317", + "emoji-dizzy-fill": "\f318", + "emoji-dizzy": "\f319", + "emoji-expressionless-fill": "\f31a", + "emoji-expressionless": "\f31b", + "emoji-frown-fill": "\f31c", + "emoji-frown": "\f31d", + "emoji-heart-eyes-fill": "\f31e", + "emoji-heart-eyes": "\f31f", + "emoji-laughing-fill": "\f320", + "emoji-laughing": "\f321", + "emoji-neutral-fill": "\f322", + "emoji-neutral": "\f323", + "emoji-smile-fill": "\f324", + "emoji-smile-upside-down-fill": "\f325", + "emoji-smile-upside-down": "\f326", + "emoji-smile": "\f327", + "emoji-sunglasses-fill": "\f328", + "emoji-sunglasses": "\f329", + "emoji-wink-fill": "\f32a", + "emoji-wink": "\f32b", + "envelope-fill": "\f32c", + "envelope-open-fill": "\f32d", + "envelope-open": "\f32e", + "envelope": "\f32f", + "eraser-fill": "\f330", + "eraser": "\f331", + "exclamation-circle-fill": "\f332", + "exclamation-circle": "\f333", + "exclamation-diamond-fill": "\f334", + "exclamation-diamond": "\f335", + "exclamation-octagon-fill": "\f336", + "exclamation-octagon": "\f337", + "exclamation-square-fill": "\f338", + "exclamation-square": "\f339", + "exclamation-triangle-fill": "\f33a", + "exclamation-triangle": "\f33b", + "exclamation": "\f33c", + "exclude": "\f33d", + "eye-fill": "\f33e", + "eye-slash-fill": "\f33f", + "eye-slash": "\f340", + "eye": "\f341", + "eyedropper": "\f342", + "eyeglasses": "\f343", + "facebook": "\f344", + "file-arrow-down-fill": "\f345", + "file-arrow-down": "\f346", + "file-arrow-up-fill": "\f347", + "file-arrow-up": "\f348", + "file-bar-graph-fill": "\f349", + "file-bar-graph": "\f34a", + "file-binary-fill": "\f34b", + "file-binary": "\f34c", + "file-break-fill": "\f34d", + "file-break": "\f34e", + "file-check-fill": "\f34f", + "file-check": "\f350", + "file-code-fill": "\f351", + "file-code": "\f352", + "file-diff-fill": "\f353", + "file-diff": "\f354", + "file-earmark-arrow-down-fill": "\f355", + "file-earmark-arrow-down": "\f356", + "file-earmark-arrow-up-fill": "\f357", + "file-earmark-arrow-up": "\f358", + "file-earmark-bar-graph-fill": "\f359", + "file-earmark-bar-graph": "\f35a", + "file-earmark-binary-fill": "\f35b", + "file-earmark-binary": "\f35c", + "file-earmark-break-fill": "\f35d", + "file-earmark-break": "\f35e", + "file-earmark-check-fill": "\f35f", + "file-earmark-check": "\f360", + "file-earmark-code-fill": "\f361", + "file-earmark-code": "\f362", + "file-earmark-diff-fill": "\f363", + "file-earmark-diff": "\f364", + "file-earmark-easel-fill": "\f365", + "file-earmark-easel": "\f366", + "file-earmark-excel-fill": "\f367", + "file-earmark-excel": "\f368", + "file-earmark-fill": "\f369", + "file-earmark-font-fill": "\f36a", + "file-earmark-font": "\f36b", + "file-earmark-image-fill": "\f36c", + "file-earmark-image": "\f36d", + "file-earmark-lock-fill": "\f36e", + "file-earmark-lock": "\f36f", + "file-earmark-lock2-fill": "\f370", + "file-earmark-lock2": "\f371", + "file-earmark-medical-fill": "\f372", + "file-earmark-medical": "\f373", + "file-earmark-minus-fill": "\f374", + "file-earmark-minus": "\f375", + "file-earmark-music-fill": "\f376", + "file-earmark-music": "\f377", + "file-earmark-person-fill": "\f378", + "file-earmark-person": "\f379", + "file-earmark-play-fill": "\f37a", + "file-earmark-play": "\f37b", + "file-earmark-plus-fill": "\f37c", + "file-earmark-plus": "\f37d", + "file-earmark-post-fill": "\f37e", + "file-earmark-post": "\f37f", + "file-earmark-ppt-fill": "\f380", + "file-earmark-ppt": "\f381", + "file-earmark-richtext-fill": "\f382", + "file-earmark-richtext": "\f383", + "file-earmark-ruled-fill": "\f384", + "file-earmark-ruled": "\f385", + "file-earmark-slides-fill": "\f386", + "file-earmark-slides": "\f387", + "file-earmark-spreadsheet-fill": "\f388", + "file-earmark-spreadsheet": "\f389", + "file-earmark-text-fill": "\f38a", + "file-earmark-text": "\f38b", + "file-earmark-word-fill": "\f38c", + "file-earmark-word": "\f38d", + "file-earmark-x-fill": "\f38e", + "file-earmark-x": "\f38f", + "file-earmark-zip-fill": "\f390", + "file-earmark-zip": "\f391", + "file-earmark": "\f392", + "file-easel-fill": "\f393", + "file-easel": "\f394", + "file-excel-fill": "\f395", + "file-excel": "\f396", + "file-fill": "\f397", + "file-font-fill": "\f398", + "file-font": "\f399", + "file-image-fill": "\f39a", + "file-image": "\f39b", + "file-lock-fill": "\f39c", + "file-lock": "\f39d", + "file-lock2-fill": "\f39e", + "file-lock2": "\f39f", + "file-medical-fill": "\f3a0", + "file-medical": "\f3a1", + "file-minus-fill": "\f3a2", + "file-minus": "\f3a3", + "file-music-fill": "\f3a4", + "file-music": "\f3a5", + "file-person-fill": "\f3a6", + "file-person": "\f3a7", + "file-play-fill": "\f3a8", + "file-play": "\f3a9", + "file-plus-fill": "\f3aa", + "file-plus": "\f3ab", + "file-post-fill": "\f3ac", + "file-post": "\f3ad", + "file-ppt-fill": "\f3ae", + "file-ppt": "\f3af", + "file-richtext-fill": "\f3b0", + "file-richtext": "\f3b1", + "file-ruled-fill": "\f3b2", + "file-ruled": "\f3b3", + "file-slides-fill": "\f3b4", + "file-slides": "\f3b5", + "file-spreadsheet-fill": "\f3b6", + "file-spreadsheet": "\f3b7", + "file-text-fill": "\f3b8", + "file-text": "\f3b9", + "file-word-fill": "\f3ba", + "file-word": "\f3bb", + "file-x-fill": "\f3bc", + "file-x": "\f3bd", + "file-zip-fill": "\f3be", + "file-zip": "\f3bf", + "file": "\f3c0", + "files-alt": "\f3c1", + "files": "\f3c2", + "film": "\f3c3", + "filter-circle-fill": "\f3c4", + "filter-circle": "\f3c5", + "filter-left": "\f3c6", + "filter-right": "\f3c7", + "filter-square-fill": "\f3c8", + "filter-square": "\f3c9", + "filter": "\f3ca", + "flag-fill": "\f3cb", + "flag": "\f3cc", + "flower1": "\f3cd", + "flower2": "\f3ce", + "flower3": "\f3cf", + "folder-check": "\f3d0", + "folder-fill": "\f3d1", + "folder-minus": "\f3d2", + "folder-plus": "\f3d3", + "folder-symlink-fill": "\f3d4", + "folder-symlink": "\f3d5", + "folder-x": "\f3d6", + "folder": "\f3d7", + "folder2-open": "\f3d8", + "folder2": "\f3d9", + "fonts": "\f3da", + "forward-fill": "\f3db", + "forward": "\f3dc", + "front": "\f3dd", + "fullscreen-exit": "\f3de", + "fullscreen": "\f3df", + "funnel-fill": "\f3e0", + "funnel": "\f3e1", + "gear-fill": "\f3e2", + "gear-wide-connected": "\f3e3", + "gear-wide": "\f3e4", + "gear": "\f3e5", + "gem": "\f3e6", + "geo-alt-fill": "\f3e7", + "geo-alt": "\f3e8", + "geo-fill": "\f3e9", + "geo": "\f3ea", + "gift-fill": "\f3eb", + "gift": "\f3ec", + "github": "\f3ed", + "globe": "\f3ee", + "globe2": "\f3ef", + "google": "\f3f0", + "graph-down": "\f3f1", + "graph-up": "\f3f2", + "grid-1x2-fill": "\f3f3", + "grid-1x2": "\f3f4", + "grid-3x2-gap-fill": "\f3f5", + "grid-3x2-gap": "\f3f6", + "grid-3x2": "\f3f7", + "grid-3x3-gap-fill": "\f3f8", + "grid-3x3-gap": "\f3f9", + "grid-3x3": "\f3fa", + "grid-fill": "\f3fb", + "grid": "\f3fc", + "grip-horizontal": "\f3fd", + "grip-vertical": "\f3fe", + "hammer": "\f3ff", + "hand-index-fill": "\f400", + "hand-index-thumb-fill": "\f401", + "hand-index-thumb": "\f402", + "hand-index": "\f403", + "hand-thumbs-down-fill": "\f404", + "hand-thumbs-down": "\f405", + "hand-thumbs-up-fill": "\f406", + "hand-thumbs-up": "\f407", + "handbag-fill": "\f408", + "handbag": "\f409", + "hash": "\f40a", + "hdd-fill": "\f40b", + "hdd-network-fill": "\f40c", + "hdd-network": "\f40d", + "hdd-rack-fill": "\f40e", + "hdd-rack": "\f40f", + "hdd-stack-fill": "\f410", + "hdd-stack": "\f411", + "hdd": "\f412", + "headphones": "\f413", + "headset": "\f414", + "heart-fill": "\f415", + "heart-half": "\f416", + "heart": "\f417", + "heptagon-fill": "\f418", + "heptagon-half": "\f419", + "heptagon": "\f41a", + "hexagon-fill": "\f41b", + "hexagon-half": "\f41c", + "hexagon": "\f41d", + "hourglass-bottom": "\f41e", + "hourglass-split": "\f41f", + "hourglass-top": "\f420", + "hourglass": "\f421", + "house-door-fill": "\f422", + "house-door": "\f423", + "house-fill": "\f424", + "house": "\f425", + "hr": "\f426", + "hurricane": "\f427", + "image-alt": "\f428", + "image-fill": "\f429", + "image": "\f42a", + "images": "\f42b", + "inbox-fill": "\f42c", + "inbox": "\f42d", + "inboxes-fill": "\f42e", + "inboxes": "\f42f", + "info-circle-fill": "\f430", + "info-circle": "\f431", + "info-square-fill": "\f432", + "info-square": "\f433", + "info": "\f434", + "input-cursor-text": "\f435", + "input-cursor": "\f436", + "instagram": "\f437", + "intersect": "\f438", + "journal-album": "\f439", + "journal-arrow-down": "\f43a", + "journal-arrow-up": "\f43b", + "journal-bookmark-fill": "\f43c", + "journal-bookmark": "\f43d", + "journal-check": "\f43e", + "journal-code": "\f43f", + "journal-medical": "\f440", + "journal-minus": "\f441", + "journal-plus": "\f442", + "journal-richtext": "\f443", + "journal-text": "\f444", + "journal-x": "\f445", + "journal": "\f446", + "journals": "\f447", + "joystick": "\f448", + "justify-left": "\f449", + "justify-right": "\f44a", + "justify": "\f44b", + "kanban-fill": "\f44c", + "kanban": "\f44d", + "key-fill": "\f44e", + "key": "\f44f", + "keyboard-fill": "\f450", + "keyboard": "\f451", + "ladder": "\f452", + "lamp-fill": "\f453", + "lamp": "\f454", + "laptop-fill": "\f455", + "laptop": "\f456", + "layer-backward": "\f457", + "layer-forward": "\f458", + "layers-fill": "\f459", + "layers-half": "\f45a", + "layers": "\f45b", + "layout-sidebar-inset-reverse": "\f45c", + "layout-sidebar-inset": "\f45d", + "layout-sidebar-reverse": "\f45e", + "layout-sidebar": "\f45f", + "layout-split": "\f460", + "layout-text-sidebar-reverse": "\f461", + "layout-text-sidebar": "\f462", + "layout-text-window-reverse": "\f463", + "layout-text-window": "\f464", + "layout-three-columns": "\f465", + "layout-wtf": "\f466", + "life-preserver": "\f467", + "lightbulb-fill": "\f468", + "lightbulb-off-fill": "\f469", + "lightbulb-off": "\f46a", + "lightbulb": "\f46b", + "lightning-charge-fill": "\f46c", + "lightning-charge": "\f46d", + "lightning-fill": "\f46e", + "lightning": "\f46f", + "link-45deg": "\f470", + "link": "\f471", + "linkedin": "\f472", + "list-check": "\f473", + "list-nested": "\f474", + "list-ol": "\f475", + "list-stars": "\f476", + "list-task": "\f477", + "list-ul": "\f478", + "list": "\f479", + "lock-fill": "\f47a", + "lock": "\f47b", + "mailbox": "\f47c", + "mailbox2": "\f47d", + "map-fill": "\f47e", + "map": "\f47f", + "markdown-fill": "\f480", + "markdown": "\f481", + "mask": "\f482", + "megaphone-fill": "\f483", + "megaphone": "\f484", + "menu-app-fill": "\f485", + "menu-app": "\f486", + "menu-button-fill": "\f487", + "menu-button-wide-fill": "\f488", + "menu-button-wide": "\f489", + "menu-button": "\f48a", + "menu-down": "\f48b", + "menu-up": "\f48c", + "mic-fill": "\f48d", + "mic-mute-fill": "\f48e", + "mic-mute": "\f48f", + "mic": "\f490", + "minecart-loaded": "\f491", + "minecart": "\f492", + "moisture": "\f493", + "moon-fill": "\f494", + "moon-stars-fill": "\f495", + "moon-stars": "\f496", + "moon": "\f497", + "mouse-fill": "\f498", + "mouse": "\f499", + "mouse2-fill": "\f49a", + "mouse2": "\f49b", + "mouse3-fill": "\f49c", + "mouse3": "\f49d", + "music-note-beamed": "\f49e", + "music-note-list": "\f49f", + "music-note": "\f4a0", + "music-player-fill": "\f4a1", + "music-player": "\f4a2", + "newspaper": "\f4a3", + "node-minus-fill": "\f4a4", + "node-minus": "\f4a5", + "node-plus-fill": "\f4a6", + "node-plus": "\f4a7", + "nut-fill": "\f4a8", + "nut": "\f4a9", + "octagon-fill": "\f4aa", + "octagon-half": "\f4ab", + "octagon": "\f4ac", + "option": "\f4ad", + "outlet": "\f4ae", + "paint-bucket": "\f4af", + "palette-fill": "\f4b0", + "palette": "\f4b1", + "palette2": "\f4b2", + "paperclip": "\f4b3", + "paragraph": "\f4b4", + "patch-check-fill": "\f4b5", + "patch-check": "\f4b6", + "patch-exclamation-fill": "\f4b7", + "patch-exclamation": "\f4b8", + "patch-minus-fill": "\f4b9", + "patch-minus": "\f4ba", + "patch-plus-fill": "\f4bb", + "patch-plus": "\f4bc", + "patch-question-fill": "\f4bd", + "patch-question": "\f4be", + "pause-btn-fill": "\f4bf", + "pause-btn": "\f4c0", + "pause-circle-fill": "\f4c1", + "pause-circle": "\f4c2", + "pause-fill": "\f4c3", + "pause": "\f4c4", + "peace-fill": "\f4c5", + "peace": "\f4c6", + "pen-fill": "\f4c7", + "pen": "\f4c8", + "pencil-fill": "\f4c9", + "pencil-square": "\f4ca", + "pencil": "\f4cb", + "pentagon-fill": "\f4cc", + "pentagon-half": "\f4cd", + "pentagon": "\f4ce", + "people-fill": "\f4cf", + "people": "\f4d0", + "percent": "\f4d1", + "person-badge-fill": "\f4d2", + "person-badge": "\f4d3", + "person-bounding-box": "\f4d4", + "person-check-fill": "\f4d5", + "person-check": "\f4d6", + "person-circle": "\f4d7", + "person-dash-fill": "\f4d8", + "person-dash": "\f4d9", + "person-fill": "\f4da", + "person-lines-fill": "\f4db", + "person-plus-fill": "\f4dc", + "person-plus": "\f4dd", + "person-square": "\f4de", + "person-x-fill": "\f4df", + "person-x": "\f4e0", + "person": "\f4e1", + "phone-fill": "\f4e2", + "phone-landscape-fill": "\f4e3", + "phone-landscape": "\f4e4", + "phone-vibrate-fill": "\f4e5", + "phone-vibrate": "\f4e6", + "phone": "\f4e7", + "pie-chart-fill": "\f4e8", + "pie-chart": "\f4e9", + "pin-angle-fill": "\f4ea", + "pin-angle": "\f4eb", + "pin-fill": "\f4ec", + "pin": "\f4ed", + "pip-fill": "\f4ee", + "pip": "\f4ef", + "play-btn-fill": "\f4f0", + "play-btn": "\f4f1", + "play-circle-fill": "\f4f2", + "play-circle": "\f4f3", + "play-fill": "\f4f4", + "play": "\f4f5", + "plug-fill": "\f4f6", + "plug": "\f4f7", + "plus-circle-dotted": "\f4f8", + "plus-circle-fill": "\f4f9", + "plus-circle": "\f4fa", + "plus-square-dotted": "\f4fb", + "plus-square-fill": "\f4fc", + "plus-square": "\f4fd", + "plus": "\f4fe", + "power": "\f4ff", + "printer-fill": "\f500", + "printer": "\f501", + "puzzle-fill": "\f502", + "puzzle": "\f503", + "question-circle-fill": "\f504", + "question-circle": "\f505", + "question-diamond-fill": "\f506", + "question-diamond": "\f507", + "question-octagon-fill": "\f508", + "question-octagon": "\f509", + "question-square-fill": "\f50a", + "question-square": "\f50b", + "question": "\f50c", + "rainbow": "\f50d", + "receipt-cutoff": "\f50e", + "receipt": "\f50f", + "reception-0": "\f510", + "reception-1": "\f511", + "reception-2": "\f512", + "reception-3": "\f513", + "reception-4": "\f514", + "record-btn-fill": "\f515", + "record-btn": "\f516", + "record-circle-fill": "\f517", + "record-circle": "\f518", + "record-fill": "\f519", + "record": "\f51a", + "record2-fill": "\f51b", + "record2": "\f51c", + "reply-all-fill": "\f51d", + "reply-all": "\f51e", + "reply-fill": "\f51f", + "reply": "\f520", + "rss-fill": "\f521", + "rss": "\f522", + "rulers": "\f523", + "save-fill": "\f524", + "save": "\f525", + "save2-fill": "\f526", + "save2": "\f527", + "scissors": "\f528", + "screwdriver": "\f529", + "search": "\f52a", + "segmented-nav": "\f52b", + "server": "\f52c", + "share-fill": "\f52d", + "share": "\f52e", + "shield-check": "\f52f", + "shield-exclamation": "\f530", + "shield-fill-check": "\f531", + "shield-fill-exclamation": "\f532", + "shield-fill-minus": "\f533", + "shield-fill-plus": "\f534", + "shield-fill-x": "\f535", + "shield-fill": "\f536", + "shield-lock-fill": "\f537", + "shield-lock": "\f538", + "shield-minus": "\f539", + "shield-plus": "\f53a", + "shield-shaded": "\f53b", + "shield-slash-fill": "\f53c", + "shield-slash": "\f53d", + "shield-x": "\f53e", + "shield": "\f53f", + "shift-fill": "\f540", + "shift": "\f541", + "shop-window": "\f542", + "shop": "\f543", + "shuffle": "\f544", + "signpost-2-fill": "\f545", + "signpost-2": "\f546", + "signpost-fill": "\f547", + "signpost-split-fill": "\f548", + "signpost-split": "\f549", + "signpost": "\f54a", + "sim-fill": "\f54b", + "sim": "\f54c", + "skip-backward-btn-fill": "\f54d", + "skip-backward-btn": "\f54e", + "skip-backward-circle-fill": "\f54f", + "skip-backward-circle": "\f550", + "skip-backward-fill": "\f551", + "skip-backward": "\f552", + "skip-end-btn-fill": "\f553", + "skip-end-btn": "\f554", + "skip-end-circle-fill": "\f555", + "skip-end-circle": "\f556", + "skip-end-fill": "\f557", + "skip-end": "\f558", + "skip-forward-btn-fill": "\f559", + "skip-forward-btn": "\f55a", + "skip-forward-circle-fill": "\f55b", + "skip-forward-circle": "\f55c", + "skip-forward-fill": "\f55d", + "skip-forward": "\f55e", + "skip-start-btn-fill": "\f55f", + "skip-start-btn": "\f560", + "skip-start-circle-fill": "\f561", + "skip-start-circle": "\f562", + "skip-start-fill": "\f563", + "skip-start": "\f564", + "slack": "\f565", + "slash-circle-fill": "\f566", + "slash-circle": "\f567", + "slash-square-fill": "\f568", + "slash-square": "\f569", + "slash": "\f56a", + "sliders": "\f56b", + "smartwatch": "\f56c", + "snow": "\f56d", + "snow2": "\f56e", + "snow3": "\f56f", + "sort-alpha-down-alt": "\f570", + "sort-alpha-down": "\f571", + "sort-alpha-up-alt": "\f572", + "sort-alpha-up": "\f573", + "sort-down-alt": "\f574", + "sort-down": "\f575", + "sort-numeric-down-alt": "\f576", + "sort-numeric-down": "\f577", + "sort-numeric-up-alt": "\f578", + "sort-numeric-up": "\f579", + "sort-up-alt": "\f57a", + "sort-up": "\f57b", + "soundwave": "\f57c", + "speaker-fill": "\f57d", + "speaker": "\f57e", + "speedometer": "\f57f", + "speedometer2": "\f580", + "spellcheck": "\f581", + "square-fill": "\f582", + "square-half": "\f583", + "square": "\f584", + "stack": "\f585", + "star-fill": "\f586", + "star-half": "\f587", + "star": "\f588", + "stars": "\f589", + "stickies-fill": "\f58a", + "stickies": "\f58b", + "sticky-fill": "\f58c", + "sticky": "\f58d", + "stop-btn-fill": "\f58e", + "stop-btn": "\f58f", + "stop-circle-fill": "\f590", + "stop-circle": "\f591", + "stop-fill": "\f592", + "stop": "\f593", + "stoplights-fill": "\f594", + "stoplights": "\f595", + "stopwatch-fill": "\f596", + "stopwatch": "\f597", + "subtract": "\f598", + "suit-club-fill": "\f599", + "suit-club": "\f59a", + "suit-diamond-fill": "\f59b", + "suit-diamond": "\f59c", + "suit-heart-fill": "\f59d", + "suit-heart": "\f59e", + "suit-spade-fill": "\f59f", + "suit-spade": "\f5a0", + "sun-fill": "\f5a1", + "sun": "\f5a2", + "sunglasses": "\f5a3", + "sunrise-fill": "\f5a4", + "sunrise": "\f5a5", + "sunset-fill": "\f5a6", + "sunset": "\f5a7", + "symmetry-horizontal": "\f5a8", + "symmetry-vertical": "\f5a9", + "table": "\f5aa", + "tablet-fill": "\f5ab", + "tablet-landscape-fill": "\f5ac", + "tablet-landscape": "\f5ad", + "tablet": "\f5ae", + "tag-fill": "\f5af", + "tag": "\f5b0", + "tags-fill": "\f5b1", + "tags": "\f5b2", + "telegram": "\f5b3", + "telephone-fill": "\f5b4", + "telephone-forward-fill": "\f5b5", + "telephone-forward": "\f5b6", + "telephone-inbound-fill": "\f5b7", + "telephone-inbound": "\f5b8", + "telephone-minus-fill": "\f5b9", + "telephone-minus": "\f5ba", + "telephone-outbound-fill": "\f5bb", + "telephone-outbound": "\f5bc", + "telephone-plus-fill": "\f5bd", + "telephone-plus": "\f5be", + "telephone-x-fill": "\f5bf", + "telephone-x": "\f5c0", + "telephone": "\f5c1", + "terminal-fill": "\f5c2", + "terminal": "\f5c3", + "text-center": "\f5c4", + "text-indent-left": "\f5c5", + "text-indent-right": "\f5c6", + "text-left": "\f5c7", + "text-paragraph": "\f5c8", + "text-right": "\f5c9", + "textarea-resize": "\f5ca", + "textarea-t": "\f5cb", + "textarea": "\f5cc", + "thermometer-half": "\f5cd", + "thermometer-high": "\f5ce", + "thermometer-low": "\f5cf", + "thermometer-snow": "\f5d0", + "thermometer-sun": "\f5d1", + "thermometer": "\f5d2", + "three-dots-vertical": "\f5d3", + "three-dots": "\f5d4", + "toggle-off": "\f5d5", + "toggle-on": "\f5d6", + "toggle2-off": "\f5d7", + "toggle2-on": "\f5d8", + "toggles": "\f5d9", + "toggles2": "\f5da", + "tools": "\f5db", + "tornado": "\f5dc", + "trash-fill": "\f5dd", + "trash": "\f5de", + "trash2-fill": "\f5df", + "trash2": "\f5e0", + "tree-fill": "\f5e1", + "tree": "\f5e2", + "triangle-fill": "\f5e3", + "triangle-half": "\f5e4", + "triangle": "\f5e5", + "trophy-fill": "\f5e6", + "trophy": "\f5e7", + "tropical-storm": "\f5e8", + "truck-flatbed": "\f5e9", + "truck": "\f5ea", + "tsunami": "\f5eb", + "tv-fill": "\f5ec", + "tv": "\f5ed", + "twitch": "\f5ee", + "twitter": "\f5ef", + "type-bold": "\f5f0", + "type-h1": "\f5f1", + "type-h2": "\f5f2", + "type-h3": "\f5f3", + "type-italic": "\f5f4", + "type-strikethrough": "\f5f5", + "type-underline": "\f5f6", + "type": "\f5f7", + "ui-checks-grid": "\f5f8", + "ui-checks": "\f5f9", + "ui-radios-grid": "\f5fa", + "ui-radios": "\f5fb", + "umbrella-fill": "\f5fc", + "umbrella": "\f5fd", + "union": "\f5fe", + "unlock-fill": "\f5ff", + "unlock": "\f600", + "upc-scan": "\f601", + "upc": "\f602", + "upload": "\f603", + "vector-pen": "\f604", + "view-list": "\f605", + "view-stacked": "\f606", + "vinyl-fill": "\f607", + "vinyl": "\f608", + "voicemail": "\f609", + "volume-down-fill": "\f60a", + "volume-down": "\f60b", + "volume-mute-fill": "\f60c", + "volume-mute": "\f60d", + "volume-off-fill": "\f60e", + "volume-off": "\f60f", + "volume-up-fill": "\f610", + "volume-up": "\f611", + "vr": "\f612", + "wallet-fill": "\f613", + "wallet": "\f614", + "wallet2": "\f615", + "watch": "\f616", + "water": "\f617", + "whatsapp": "\f618", + "wifi-1": "\f619", + "wifi-2": "\f61a", + "wifi-off": "\f61b", + "wifi": "\f61c", + "wind": "\f61d", + "window-dock": "\f61e", + "window-sidebar": "\f61f", + "window": "\f620", + "wrench": "\f621", + "x-circle-fill": "\f622", + "x-circle": "\f623", + "x-diamond-fill": "\f624", + "x-diamond": "\f625", + "x-octagon-fill": "\f626", + "x-octagon": "\f627", + "x-square-fill": "\f628", + "x-square": "\f629", + "x": "\f62a", + "youtube": "\f62b", + "zoom-in": "\f62c", + "zoom-out": "\f62d", + "bank": "\f62e", + "bank2": "\f62f", + "bell-slash-fill": "\f630", + "bell-slash": "\f631", + "cash-coin": "\f632", + "check-lg": "\f633", + "coin": "\f634", + "currency-bitcoin": "\f635", + "currency-dollar": "\f636", + "currency-euro": "\f637", + "currency-exchange": "\f638", + "currency-pound": "\f639", + "currency-yen": "\f63a", + "dash-lg": "\f63b", + "exclamation-lg": "\f63c", + "file-earmark-pdf-fill": "\f63d", + "file-earmark-pdf": "\f63e", + "file-pdf-fill": "\f63f", + "file-pdf": "\f640", + "gender-ambiguous": "\f641", + "gender-female": "\f642", + "gender-male": "\f643", + "gender-trans": "\f644", + "headset-vr": "\f645", + "info-lg": "\f646", + "mastodon": "\f647", + "messenger": "\f648", + "piggy-bank-fill": "\f649", + "piggy-bank": "\f64a", + "pin-map-fill": "\f64b", + "pin-map": "\f64c", + "plus-lg": "\f64d", + "question-lg": "\f64e", + "recycle": "\f64f", + "reddit": "\f650", + "safe-fill": "\f651", + "safe2-fill": "\f652", + "safe2": "\f653", + "sd-card-fill": "\f654", + "sd-card": "\f655", + "skype": "\f656", + "slash-lg": "\f657", + "translate": "\f658", + "x-lg": "\f659", + "safe": "\f65a", + "apple": "\f65b", + "microsoft": "\f65d", + "windows": "\f65e", + "behance": "\f65c", + "dribbble": "\f65f", + "line": "\f660", + "medium": "\f661", + "paypal": "\f662", + "pinterest": "\f663", + "signal": "\f664", + "snapchat": "\f665", + "spotify": "\f666", + "stack-overflow": "\f667", + "strava": "\f668", + "wordpress": "\f669", + "vimeo": "\f66a", + "activity": "\f66b", + "easel2-fill": "\f66c", + "easel2": "\f66d", + "easel3-fill": "\f66e", + "easel3": "\f66f", + "fan": "\f670", + "fingerprint": "\f671", + "graph-down-arrow": "\f672", + "graph-up-arrow": "\f673", + "hypnotize": "\f674", + "magic": "\f675", + "person-rolodex": "\f676", + "person-video": "\f677", + "person-video2": "\f678", + "person-video3": "\f679", + "person-workspace": "\f67a", + "radioactive": "\f67b", + "webcam-fill": "\f67c", + "webcam": "\f67d", + "yin-yang": "\f67e", + "bandaid-fill": "\f680", + "bandaid": "\f681", + "bluetooth": "\f682", + "body-text": "\f683", + "boombox": "\f684", + "boxes": "\f685", + "dpad-fill": "\f686", + "dpad": "\f687", + "ear-fill": "\f688", + "ear": "\f689", + "envelope-check-fill": "\f68b", + "envelope-check": "\f68c", + "envelope-dash-fill": "\f68e", + "envelope-dash": "\f68f", + "envelope-exclamation-fill": "\f691", + "envelope-exclamation": "\f692", + "envelope-plus-fill": "\f693", + "envelope-plus": "\f694", + "envelope-slash-fill": "\f696", + "envelope-slash": "\f697", + "envelope-x-fill": "\f699", + "envelope-x": "\f69a", + "explicit-fill": "\f69b", + "explicit": "\f69c", + "git": "\f69d", + "infinity": "\f69e", + "list-columns-reverse": "\f69f", + "list-columns": "\f6a0", + "meta": "\f6a1", + "nintendo-switch": "\f6a4", + "pc-display-horizontal": "\f6a5", + "pc-display": "\f6a6", + "pc-horizontal": "\f6a7", + "pc": "\f6a8", + "playstation": "\f6a9", + "plus-slash-minus": "\f6aa", + "projector-fill": "\f6ab", + "projector": "\f6ac", + "qr-code-scan": "\f6ad", + "qr-code": "\f6ae", + "quora": "\f6af", + "quote": "\f6b0", + "robot": "\f6b1", + "send-check-fill": "\f6b2", + "send-check": "\f6b3", + "send-dash-fill": "\f6b4", + "send-dash": "\f6b5", + "send-exclamation-fill": "\f6b7", + "send-exclamation": "\f6b8", + "send-fill": "\f6b9", + "send-plus-fill": "\f6ba", + "send-plus": "\f6bb", + "send-slash-fill": "\f6bc", + "send-slash": "\f6bd", + "send-x-fill": "\f6be", + "send-x": "\f6bf", + "send": "\f6c0", + "steam": "\f6c1", + "terminal-dash": "\f6c3", + "terminal-plus": "\f6c4", + "terminal-split": "\f6c5", + "ticket-detailed-fill": "\f6c6", + "ticket-detailed": "\f6c7", + "ticket-fill": "\f6c8", + "ticket-perforated-fill": "\f6c9", + "ticket-perforated": "\f6ca", + "ticket": "\f6cb", + "tiktok": "\f6cc", + "window-dash": "\f6cd", + "window-desktop": "\f6ce", + "window-fullscreen": "\f6cf", + "window-plus": "\f6d0", + "window-split": "\f6d1", + "window-stack": "\f6d2", + "window-x": "\f6d3", + "xbox": "\f6d4", + "ethernet": "\f6d5", + "hdmi-fill": "\f6d6", + "hdmi": "\f6d7", + "usb-c-fill": "\f6d8", + "usb-c": "\f6d9", + "usb-fill": "\f6da", + "usb-plug-fill": "\f6db", + "usb-plug": "\f6dc", + "usb-symbol": "\f6dd", + "usb": "\f6de", + "boombox-fill": "\f6df", + "displayport": "\f6e1", + "gpu-card": "\f6e2", + "memory": "\f6e3", + "modem-fill": "\f6e4", + "modem": "\f6e5", + "motherboard-fill": "\f6e6", + "motherboard": "\f6e7", + "optical-audio-fill": "\f6e8", + "optical-audio": "\f6e9", + "pci-card": "\f6ea", + "router-fill": "\f6eb", + "router": "\f6ec", + "thunderbolt-fill": "\f6ef", + "thunderbolt": "\f6f0", + "usb-drive-fill": "\f6f1", + "usb-drive": "\f6f2", + "usb-micro-fill": "\f6f3", + "usb-micro": "\f6f4", + "usb-mini-fill": "\f6f5", + "usb-mini": "\f6f6", + "cloud-haze2": "\f6f7", + "device-hdd-fill": "\f6f8", + "device-hdd": "\f6f9", + "device-ssd-fill": "\f6fa", + "device-ssd": "\f6fb", + "displayport-fill": "\f6fc", + "mortarboard-fill": "\f6fd", + "mortarboard": "\f6fe", + "terminal-x": "\f6ff", + "arrow-through-heart-fill": "\f700", + "arrow-through-heart": "\f701", + "badge-sd-fill": "\f702", + "badge-sd": "\f703", + "bag-heart-fill": "\f704", + "bag-heart": "\f705", + "balloon-fill": "\f706", + "balloon-heart-fill": "\f707", + "balloon-heart": "\f708", + "balloon": "\f709", + "box2-fill": "\f70a", + "box2-heart-fill": "\f70b", + "box2-heart": "\f70c", + "box2": "\f70d", + "braces-asterisk": "\f70e", + "calendar-heart-fill": "\f70f", + "calendar-heart": "\f710", + "calendar2-heart-fill": "\f711", + "calendar2-heart": "\f712", + "chat-heart-fill": "\f713", + "chat-heart": "\f714", + "chat-left-heart-fill": "\f715", + "chat-left-heart": "\f716", + "chat-right-heart-fill": "\f717", + "chat-right-heart": "\f718", + "chat-square-heart-fill": "\f719", + "chat-square-heart": "\f71a", + "clipboard-check-fill": "\f71b", + "clipboard-data-fill": "\f71c", + "clipboard-fill": "\f71d", + "clipboard-heart-fill": "\f71e", + "clipboard-heart": "\f71f", + "clipboard-minus-fill": "\f720", + "clipboard-plus-fill": "\f721", + "clipboard-pulse": "\f722", + "clipboard-x-fill": "\f723", + "clipboard2-check-fill": "\f724", + "clipboard2-check": "\f725", + "clipboard2-data-fill": "\f726", + "clipboard2-data": "\f727", + "clipboard2-fill": "\f728", + "clipboard2-heart-fill": "\f729", + "clipboard2-heart": "\f72a", + "clipboard2-minus-fill": "\f72b", + "clipboard2-minus": "\f72c", + "clipboard2-plus-fill": "\f72d", + "clipboard2-plus": "\f72e", + "clipboard2-pulse-fill": "\f72f", + "clipboard2-pulse": "\f730", + "clipboard2-x-fill": "\f731", + "clipboard2-x": "\f732", + "clipboard2": "\f733", + "emoji-kiss-fill": "\f734", + "emoji-kiss": "\f735", + "envelope-heart-fill": "\f736", + "envelope-heart": "\f737", + "envelope-open-heart-fill": "\f738", + "envelope-open-heart": "\f739", + "envelope-paper-fill": "\f73a", + "envelope-paper-heart-fill": "\f73b", + "envelope-paper-heart": "\f73c", + "envelope-paper": "\f73d", + "filetype-aac": "\f73e", + "filetype-ai": "\f73f", + "filetype-bmp": "\f740", + "filetype-cs": "\f741", + "filetype-css": "\f742", + "filetype-csv": "\f743", + "filetype-doc": "\f744", + "filetype-docx": "\f745", + "filetype-exe": "\f746", + "filetype-gif": "\f747", + "filetype-heic": "\f748", + "filetype-html": "\f749", + "filetype-java": "\f74a", + "filetype-jpg": "\f74b", + "filetype-js": "\f74c", + "filetype-jsx": "\f74d", + "filetype-key": "\f74e", + "filetype-m4p": "\f74f", + "filetype-md": "\f750", + "filetype-mdx": "\f751", + "filetype-mov": "\f752", + "filetype-mp3": "\f753", + "filetype-mp4": "\f754", + "filetype-otf": "\f755", + "filetype-pdf": "\f756", + "filetype-php": "\f757", + "filetype-png": "\f758", + "filetype-ppt": "\f75a", + "filetype-psd": "\f75b", + "filetype-py": "\f75c", + "filetype-raw": "\f75d", + "filetype-rb": "\f75e", + "filetype-sass": "\f75f", + "filetype-scss": "\f760", + "filetype-sh": "\f761", + "filetype-svg": "\f762", + "filetype-tiff": "\f763", + "filetype-tsx": "\f764", + "filetype-ttf": "\f765", + "filetype-txt": "\f766", + "filetype-wav": "\f767", + "filetype-woff": "\f768", + "filetype-xls": "\f76a", + "filetype-xml": "\f76b", + "filetype-yml": "\f76c", + "heart-arrow": "\f76d", + "heart-pulse-fill": "\f76e", + "heart-pulse": "\f76f", + "heartbreak-fill": "\f770", + "heartbreak": "\f771", + "hearts": "\f772", + "hospital-fill": "\f773", + "hospital": "\f774", + "house-heart-fill": "\f775", + "house-heart": "\f776", + "incognito": "\f777", + "magnet-fill": "\f778", + "magnet": "\f779", + "person-heart": "\f77a", + "person-hearts": "\f77b", + "phone-flip": "\f77c", + "plugin": "\f77d", + "postage-fill": "\f77e", + "postage-heart-fill": "\f77f", + "postage-heart": "\f780", + "postage": "\f781", + "postcard-fill": "\f782", + "postcard-heart-fill": "\f783", + "postcard-heart": "\f784", + "postcard": "\f785", + "search-heart-fill": "\f786", + "search-heart": "\f787", + "sliders2-vertical": "\f788", + "sliders2": "\f789", + "trash3-fill": "\f78a", + "trash3": "\f78b", + "valentine": "\f78c", + "valentine2": "\f78d", + "wrench-adjustable-circle-fill": "\f78e", + "wrench-adjustable-circle": "\f78f", + "wrench-adjustable": "\f790", + "filetype-json": "\f791", + "filetype-pptx": "\f792", + "filetype-xlsx": "\f793", + "1-circle-fill": "\f796", + "1-circle": "\f797", + "1-square-fill": "\f798", + "1-square": "\f799", + "2-circle-fill": "\f79c", + "2-circle": "\f79d", + "2-square-fill": "\f79e", + "2-square": "\f79f", + "3-circle-fill": "\f7a2", + "3-circle": "\f7a3", + "3-square-fill": "\f7a4", + "3-square": "\f7a5", + "4-circle-fill": "\f7a8", + "4-circle": "\f7a9", + "4-square-fill": "\f7aa", + "4-square": "\f7ab", + "5-circle-fill": "\f7ae", + "5-circle": "\f7af", + "5-square-fill": "\f7b0", + "5-square": "\f7b1", + "6-circle-fill": "\f7b4", + "6-circle": "\f7b5", + "6-square-fill": "\f7b6", + "6-square": "\f7b7", + "7-circle-fill": "\f7ba", + "7-circle": "\f7bb", + "7-square-fill": "\f7bc", + "7-square": "\f7bd", + "8-circle-fill": "\f7c0", + "8-circle": "\f7c1", + "8-square-fill": "\f7c2", + "8-square": "\f7c3", + "9-circle-fill": "\f7c6", + "9-circle": "\f7c7", + "9-square-fill": "\f7c8", + "9-square": "\f7c9", + "airplane-engines-fill": "\f7ca", + "airplane-engines": "\f7cb", + "airplane-fill": "\f7cc", + "airplane": "\f7cd", + "alexa": "\f7ce", + "alipay": "\f7cf", + "android": "\f7d0", + "android2": "\f7d1", + "box-fill": "\f7d2", + "box-seam-fill": "\f7d3", + "browser-chrome": "\f7d4", + "browser-edge": "\f7d5", + "browser-firefox": "\f7d6", + "browser-safari": "\f7d7", + "c-circle-fill": "\f7da", + "c-circle": "\f7db", + "c-square-fill": "\f7dc", + "c-square": "\f7dd", + "capsule-pill": "\f7de", + "capsule": "\f7df", + "car-front-fill": "\f7e0", + "car-front": "\f7e1", + "cassette-fill": "\f7e2", + "cassette": "\f7e3", + "cc-circle-fill": "\f7e6", + "cc-circle": "\f7e7", + "cc-square-fill": "\f7e8", + "cc-square": "\f7e9", + "cup-hot-fill": "\f7ea", + "cup-hot": "\f7eb", + "currency-rupee": "\f7ec", + "dropbox": "\f7ed", + "escape": "\f7ee", + "fast-forward-btn-fill": "\f7ef", + "fast-forward-btn": "\f7f0", + "fast-forward-circle-fill": "\f7f1", + "fast-forward-circle": "\f7f2", + "fast-forward-fill": "\f7f3", + "fast-forward": "\f7f4", + "filetype-sql": "\f7f5", + "fire": "\f7f6", + "google-play": "\f7f7", + "h-circle-fill": "\f7fa", + "h-circle": "\f7fb", + "h-square-fill": "\f7fc", + "h-square": "\f7fd", + "indent": "\f7fe", + "lungs-fill": "\f7ff", + "lungs": "\f800", + "microsoft-teams": "\f801", + "p-circle-fill": "\f804", + "p-circle": "\f805", + "p-square-fill": "\f806", + "p-square": "\f807", + "pass-fill": "\f808", + "pass": "\f809", + "prescription": "\f80a", + "prescription2": "\f80b", + "r-circle-fill": "\f80e", + "r-circle": "\f80f", + "r-square-fill": "\f810", + "r-square": "\f811", + "repeat-1": "\f812", + "repeat": "\f813", + "rewind-btn-fill": "\f814", + "rewind-btn": "\f815", + "rewind-circle-fill": "\f816", + "rewind-circle": "\f817", + "rewind-fill": "\f818", + "rewind": "\f819", + "train-freight-front-fill": "\f81a", + "train-freight-front": "\f81b", + "train-front-fill": "\f81c", + "train-front": "\f81d", + "train-lightrail-front-fill": "\f81e", + "train-lightrail-front": "\f81f", + "truck-front-fill": "\f820", + "truck-front": "\f821", + "ubuntu": "\f822", + "unindent": "\f823", + "unity": "\f824", + "universal-access-circle": "\f825", + "universal-access": "\f826", + "virus": "\f827", + "virus2": "\f828", + "wechat": "\f829", + "yelp": "\f82a", + "sign-stop-fill": "\f82b", + "sign-stop-lights-fill": "\f82c", + "sign-stop-lights": "\f82d", + "sign-stop": "\f82e", + "sign-turn-left-fill": "\f82f", + "sign-turn-left": "\f830", + "sign-turn-right-fill": "\f831", + "sign-turn-right": "\f832", + "sign-turn-slight-left-fill": "\f833", + "sign-turn-slight-left": "\f834", + "sign-turn-slight-right-fill": "\f835", + "sign-turn-slight-right": "\f836", + "sign-yield-fill": "\f837", + "sign-yield": "\f838", + "ev-station-fill": "\f839", + "ev-station": "\f83a", + "fuel-pump-diesel-fill": "\f83b", + "fuel-pump-diesel": "\f83c", + "fuel-pump-fill": "\f83d", + "fuel-pump": "\f83e", + "0-circle-fill": "\f83f", + "0-circle": "\f840", + "0-square-fill": "\f841", + "0-square": "\f842", + "rocket-fill": "\f843", + "rocket-takeoff-fill": "\f844", + "rocket-takeoff": "\f845", + "rocket": "\f846", + "stripe": "\f847", + "subscript": "\f848", + "superscript": "\f849", + "trello": "\f84a", + "envelope-at-fill": "\f84b", + "envelope-at": "\f84c", + "regex": "\f84d", + "text-wrap": "\f84e", + "sign-dead-end-fill": "\f84f", + "sign-dead-end": "\f850", + "sign-do-not-enter-fill": "\f851", + "sign-do-not-enter": "\f852", + "sign-intersection-fill": "\f853", + "sign-intersection-side-fill": "\f854", + "sign-intersection-side": "\f855", + "sign-intersection-t-fill": "\f856", + "sign-intersection-t": "\f857", + "sign-intersection-y-fill": "\f858", + "sign-intersection-y": "\f859", + "sign-intersection": "\f85a", + "sign-merge-left-fill": "\f85b", + "sign-merge-left": "\f85c", + "sign-merge-right-fill": "\f85d", + "sign-merge-right": "\f85e", + "sign-no-left-turn-fill": "\f85f", + "sign-no-left-turn": "\f860", + "sign-no-parking-fill": "\f861", + "sign-no-parking": "\f862", + "sign-no-right-turn-fill": "\f863", + "sign-no-right-turn": "\f864", + "sign-railroad-fill": "\f865", + "sign-railroad": "\f866", + "building-add": "\f867", + "building-check": "\f868", + "building-dash": "\f869", + "building-down": "\f86a", + "building-exclamation": "\f86b", + "building-fill-add": "\f86c", + "building-fill-check": "\f86d", + "building-fill-dash": "\f86e", + "building-fill-down": "\f86f", + "building-fill-exclamation": "\f870", + "building-fill-gear": "\f871", + "building-fill-lock": "\f872", + "building-fill-slash": "\f873", + "building-fill-up": "\f874", + "building-fill-x": "\f875", + "building-fill": "\f876", + "building-gear": "\f877", + "building-lock": "\f878", + "building-slash": "\f879", + "building-up": "\f87a", + "building-x": "\f87b", + "buildings-fill": "\f87c", + "buildings": "\f87d", + "bus-front-fill": "\f87e", + "bus-front": "\f87f", + "ev-front-fill": "\f880", + "ev-front": "\f881", + "globe-americas": "\f882", + "globe-asia-australia": "\f883", + "globe-central-south-asia": "\f884", + "globe-europe-africa": "\f885", + "house-add-fill": "\f886", + "house-add": "\f887", + "house-check-fill": "\f888", + "house-check": "\f889", + "house-dash-fill": "\f88a", + "house-dash": "\f88b", + "house-down-fill": "\f88c", + "house-down": "\f88d", + "house-exclamation-fill": "\f88e", + "house-exclamation": "\f88f", + "house-gear-fill": "\f890", + "house-gear": "\f891", + "house-lock-fill": "\f892", + "house-lock": "\f893", + "house-slash-fill": "\f894", + "house-slash": "\f895", + "house-up-fill": "\f896", + "house-up": "\f897", + "house-x-fill": "\f898", + "house-x": "\f899", + "person-add": "\f89a", + "person-down": "\f89b", + "person-exclamation": "\f89c", + "person-fill-add": "\f89d", + "person-fill-check": "\f89e", + "person-fill-dash": "\f89f", + "person-fill-down": "\f8a0", + "person-fill-exclamation": "\f8a1", + "person-fill-gear": "\f8a2", + "person-fill-lock": "\f8a3", + "person-fill-slash": "\f8a4", + "person-fill-up": "\f8a5", + "person-fill-x": "\f8a6", + "person-gear": "\f8a7", + "person-lock": "\f8a8", + "person-slash": "\f8a9", + "person-up": "\f8aa", + "scooter": "\f8ab", + "taxi-front-fill": "\f8ac", + "taxi-front": "\f8ad", + "amd": "\f8ae", + "database-add": "\f8af", + "database-check": "\f8b0", + "database-dash": "\f8b1", + "database-down": "\f8b2", + "database-exclamation": "\f8b3", + "database-fill-add": "\f8b4", + "database-fill-check": "\f8b5", + "database-fill-dash": "\f8b6", + "database-fill-down": "\f8b7", + "database-fill-exclamation": "\f8b8", + "database-fill-gear": "\f8b9", + "database-fill-lock": "\f8ba", + "database-fill-slash": "\f8bb", + "database-fill-up": "\f8bc", + "database-fill-x": "\f8bd", + "database-fill": "\f8be", + "database-gear": "\f8bf", + "database-lock": "\f8c0", + "database-slash": "\f8c1", + "database-up": "\f8c2", + "database-x": "\f8c3", + "database": "\f8c4", + "houses-fill": "\f8c5", + "houses": "\f8c6", + "nvidia": "\f8c7", + "person-vcard-fill": "\f8c8", + "person-vcard": "\f8c9", + "sina-weibo": "\f8ca", + "tencent-qq": "\f8cb", + "wikipedia": "\f8cc", + "alphabet-uppercase": "\f2a5", + "alphabet": "\f68a", + "amazon": "\f68d", + "arrows-collapse-vertical": "\f690", + "arrows-expand-vertical": "\f695", + "arrows-vertical": "\f698", + "arrows": "\f6a2", + "ban-fill": "\f6a3", + "ban": "\f6b6", + "bing": "\f6c2", + "cake": "\f6e0", + "cake2": "\f6ed", + "cookie": "\f6ee", + "copy": "\f759", + "crosshair": "\f769", + "crosshair2": "\f794", + "emoji-astonished-fill": "\f795", + "emoji-astonished": "\f79a", + "emoji-grimace-fill": "\f79b", + "emoji-grimace": "\f7a0", + "emoji-grin-fill": "\f7a1", + "emoji-grin": "\f7a6", + "emoji-surprise-fill": "\f7a7", + "emoji-surprise": "\f7ac", + "emoji-tear-fill": "\f7ad", + "emoji-tear": "\f7b2", + "envelope-arrow-down-fill": "\f7b3", + "envelope-arrow-down": "\f7b8", + "envelope-arrow-up-fill": "\f7b9", + "envelope-arrow-up": "\f7be", + "feather": "\f7bf", + "feather2": "\f7c4", + "floppy-fill": "\f7c5", + "floppy": "\f7d8", + "floppy2-fill": "\f7d9", + "floppy2": "\f7e4", + "gitlab": "\f7e5", + "highlighter": "\f7f8", + "marker-tip": "\f802", + "nvme-fill": "\f803", + "nvme": "\f80c", + "opencollective": "\f80d", + "pci-card-network": "\f8cd", + "pci-card-sound": "\f8ce", + "radar": "\f8cf", + "send-arrow-down-fill": "\f8d0", + "send-arrow-down": "\f8d1", + "send-arrow-up-fill": "\f8d2", + "send-arrow-up": "\f8d3", + "sim-slash-fill": "\f8d4", + "sim-slash": "\f8d5", + "sourceforge": "\f8d6", + "substack": "\f8d7", + "threads-fill": "\f8d8", + "threads": "\f8d9", + "transparency": "\f8da", + "twitter-x": "\f8db", + "type-h4": "\f8dc", + "type-h5": "\f8dd", + "type-h6": "\f8de", + "backpack-fill": "\f8df", + "backpack": "\f8e0", + "backpack2-fill": "\f8e1", + "backpack2": "\f8e2", + "backpack3-fill": "\f8e3", + "backpack3": "\f8e4", + "backpack4-fill": "\f8e5", + "backpack4": "\f8e6", + "brilliance": "\f8e7", + "cake-fill": "\f8e8", + "cake2-fill": "\f8e9", + "duffle-fill": "\f8ea", + "duffle": "\f8eb", + "exposure": "\f8ec", + "gender-neuter": "\f8ed", + "highlights": "\f8ee", + "luggage-fill": "\f8ef", + "luggage": "\f8f0", + "mailbox-flag": "\f8f1", + "mailbox2-flag": "\f8f2", + "noise-reduction": "\f8f3", + "passport-fill": "\f8f4", + "passport": "\f8f5", + "person-arms-up": "\f8f6", + "person-raised-hand": "\f8f7", + "person-standing-dress": "\f8f8", + "person-standing": "\f8f9", + "person-walking": "\f8fa", + "person-wheelchair": "\f8fb", + "shadows": "\f8fc", + "suitcase-fill": "\f8fd", + "suitcase-lg-fill": "\f8fe", + "suitcase-lg": "\f8ff", + "suitcase": "\f900", + "suitcase2-fill": "\f901", + "suitcase2": "\f902", + "vignette": "\f903", + "bluesky": "\f7f9", + "tux": "\f904", + "beaker-fill": "\f905", + "beaker": "\f906", + "flask-fill": "\f907", + "flask-florence-fill": "\f908", + "flask-florence": "\f909", + "flask": "\f90a", + "leaf-fill": "\f90b", + "leaf": "\f90c", + "measuring-cup-fill": "\f90d", + "measuring-cup": "\f90e", + "unlock2-fill": "\f90f", + "unlock2": "\f910", + "battery-low": "\f911", + "anthropic": "\f912", + "apple-music": "\f913", + "claude": "\f914", + "openai": "\f915", + "perplexity": "\f916", + "css": "\f917", + "javascript": "\f918", + "typescript": "\f919", + "fork-knife": "\f91a", + "globe-americas-fill": "\f91b", + "globe-asia-australia-fill": "\f91c", + "globe-central-south-asia-fill": "\f91d", + "globe-europe-africa-fill": "\f91e", +); + +@each $icon, $codepoint in $bootstrap-icons-map { + .bi-#{$icon}::before { content: $codepoint; } +} diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.svg new file mode 100644 index 00000000..fa7e6203 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-icons.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-reboot.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-reboot.svg new file mode 100644 index 00000000..14e08033 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap-reboot.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap.svg new file mode 100644 index 00000000..1fa9b570 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bootstrap.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-all.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-all.svg new file mode 100644 index 00000000..b54e1d98 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-all.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-bottom.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-bottom.svg new file mode 100644 index 00000000..5d8ddc25 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-bottom.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-center.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-center.svg new file mode 100644 index 00000000..15eb06e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-center.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-inner.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-inner.svg new file mode 100644 index 00000000..047ad0d3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-inner.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-left.svg new file mode 100644 index 00000000..5e1f5ce4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-middle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-middle.svg new file mode 100644 index 00000000..808cb6f9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-middle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-outer.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-outer.svg new file mode 100644 index 00000000..a2df853e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-outer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-right.svg new file mode 100644 index 00000000..151f0046 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-style.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-style.svg new file mode 100644 index 00000000..5dd22e8c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-style.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-top.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-top.svg new file mode 100644 index 00000000..fcbbdc35 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-top.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border-width.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-width.svg new file mode 100644 index 00000000..24a320de --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border-width.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/border.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/border.svg new file mode 100644 index 00000000..60b861ab --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/border.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bounding-box-circles.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bounding-box-circles.svg new file mode 100644 index 00000000..8e75142a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bounding-box-circles.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bounding-box.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bounding-box.svg new file mode 100644 index 00000000..e83c49d7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bounding-box.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down-left.svg new file mode 100644 index 00000000..4892efcf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down-right.svg new file mode 100644 index 00000000..97e982da --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down.svg new file mode 100644 index 00000000..2a22ebbf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down-left.svg new file mode 100644 index 00000000..b403ec98 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down-right.svg new file mode 100644 index 00000000..c838b073 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down.svg new file mode 100644 index 00000000..dc69a506 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-left.svg new file mode 100644 index 00000000..04bdf09c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-right.svg new file mode 100644 index 00000000..7d28872e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up-left.svg new file mode 100644 index 00000000..06ac0e2d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up-right.svg new file mode 100644 index 00000000..e9a770e6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up.svg new file mode 100644 index 00000000..88664cd0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-in-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-left.svg new file mode 100644 index 00000000..e4375f2d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-right.svg new file mode 100644 index 00000000..e4b88d16 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up-left.svg new file mode 100644 index 00000000..9359bcf1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up-right.svg new file mode 100644 index 00000000..25149c5d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up.svg new file mode 100644 index 00000000..9a05ea8a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-fill.svg new file mode 100644 index 00000000..c3e46ae7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-seam-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-seam-fill.svg new file mode 100644 index 00000000..5ca92bc4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-seam-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box-seam.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-seam.svg new file mode 100644 index 00000000..e1509400 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box-seam.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box.svg new file mode 100644 index 00000000..5ca8d162 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-fill.svg new file mode 100644 index 00000000..1b9f226c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-heart-fill.svg new file mode 100644 index 00000000..d3ee4817 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-heart.svg new file mode 100644 index 00000000..fefb98d5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box2-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/box2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/box2.svg new file mode 100644 index 00000000..fe2d9f53 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/box2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/boxes.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/boxes.svg new file mode 100644 index 00000000..fbc84a6c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/boxes.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/braces-asterisk.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/braces-asterisk.svg new file mode 100644 index 00000000..45f87162 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/braces-asterisk.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/braces.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/braces.svg new file mode 100644 index 00000000..5614720b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/braces.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bricks.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bricks.svg new file mode 100644 index 00000000..78a4c8ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bricks.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/briefcase-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/briefcase-fill.svg new file mode 100644 index 00000000..4d7fadb5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/briefcase-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/briefcase.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/briefcase.svg new file mode 100644 index 00000000..c5bcde0c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/briefcase.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-high-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-high-fill.svg new file mode 100644 index 00000000..1fa22311 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-high-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-high.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-high.svg new file mode 100644 index 00000000..33e19d01 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-high.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-low-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-low-fill.svg new file mode 100644 index 00000000..0d427a89 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-low-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-low.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-low.svg new file mode 100644 index 00000000..153199b8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-alt-low.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-high-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-high-fill.svg new file mode 100644 index 00000000..6130b6cd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-high-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-high.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-high.svg new file mode 100644 index 00000000..3def0ddb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-high.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-low-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-low-fill.svg new file mode 100644 index 00000000..c473ca7e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-low-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-low.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-low.svg new file mode 100644 index 00000000..18a87bfe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brightness-low.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brilliance.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brilliance.svg new file mode 100644 index 00000000..b2dd8e5e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brilliance.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/broadcast-pin.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/broadcast-pin.svg new file mode 100644 index 00000000..37e571bc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/broadcast-pin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/broadcast.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/broadcast.svg new file mode 100644 index 00000000..f554b40f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/broadcast.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-chrome.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-chrome.svg new file mode 100644 index 00000000..68596d02 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-chrome.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-edge.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-edge.svg new file mode 100644 index 00000000..fb6e9434 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-edge.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-firefox.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-firefox.svg new file mode 100644 index 00000000..7a100e35 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-firefox.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-safari.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-safari.svg new file mode 100644 index 00000000..e8454e3c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/browser-safari.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brush-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brush-fill.svg new file mode 100644 index 00000000..33a4500a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brush-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/brush.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/brush.svg new file mode 100644 index 00000000..a8485969 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/brush.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bucket-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bucket-fill.svg new file mode 100644 index 00000000..d90878fe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bucket-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bucket.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bucket.svg new file mode 100644 index 00000000..70b3d133 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bucket.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bug-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bug-fill.svg new file mode 100644 index 00000000..ec3f6052 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bug-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bug.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bug.svg new file mode 100644 index 00000000..2d9d1e8d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bug.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-add.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-add.svg new file mode 100644 index 00000000..2208c9ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-add.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-check.svg new file mode 100644 index 00000000..fb682fcd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-dash.svg new file mode 100644 index 00000000..77ce4c6a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-dash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-down.svg new file mode 100644 index 00000000..4db08e9c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-down.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-exclamation.svg new file mode 100644 index 00000000..6165c6a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-add.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-add.svg new file mode 100644 index 00000000..c7bd588e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-check.svg new file mode 100644 index 00000000..19cfc595 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-dash.svg new file mode 100644 index 00000000..2c4aad06 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-down.svg new file mode 100644 index 00000000..d1dea024 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-exclamation.svg new file mode 100644 index 00000000..7990ecb4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-gear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-gear.svg new file mode 100644 index 00000000..ff16c9db --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-lock.svg new file mode 100644 index 00000000..b9fde69c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-slash.svg new file mode 100644 index 00000000..8d8be4dd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-up.svg new file mode 100644 index 00000000..5f7f5370 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-x.svg new file mode 100644 index 00000000..ee28c3a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill.svg new file mode 100644 index 00000000..357c61b5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-gear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-gear.svg new file mode 100644 index 00000000..423bde05 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-lock.svg new file mode 100644 index 00000000..2f949c7d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-slash.svg new file mode 100644 index 00000000..b495936e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-slash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-up.svg new file mode 100644 index 00000000..8c7ad9fe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-up.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-x.svg new file mode 100644 index 00000000..8d761aac --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/building.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/building.svg new file mode 100644 index 00000000..55ded2dc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/building.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/buildings-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/buildings-fill.svg new file mode 100644 index 00000000..76b070c5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/buildings-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/buildings.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/buildings.svg new file mode 100644 index 00000000..c7634757 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/buildings.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bullseye.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bullseye.svg new file mode 100644 index 00000000..748b6e27 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bullseye.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bus-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bus-front-fill.svg new file mode 100644 index 00000000..f2caa1b2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bus-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/bus-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/bus-front.svg new file mode 100644 index 00000000..19aaa238 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/bus-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/c-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/c-circle-fill.svg new file mode 100644 index 00000000..3cbadbef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/c-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/c-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/c-circle.svg new file mode 100644 index 00000000..4632807a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/c-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/c-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/c-square-fill.svg new file mode 100644 index 00000000..7dad0796 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/c-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/c-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/c-square.svg new file mode 100644 index 00000000..4c857402 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/c-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cake-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cake-fill.svg new file mode 100644 index 00000000..dc2899a9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cake-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cake.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cake.svg new file mode 100644 index 00000000..f6c3899e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cake.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cake2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cake2-fill.svg new file mode 100644 index 00000000..c5f36633 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cake2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cake2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cake2.svg new file mode 100644 index 00000000..8bc96d4b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cake2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calculator-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calculator-fill.svg new file mode 100644 index 00000000..bdd0b9f3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calculator-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calculator.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calculator.svg new file mode 100644 index 00000000..d2143f1d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calculator.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-check-fill.svg new file mode 100644 index 00000000..decfb3f3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-check.svg new file mode 100644 index 00000000..9aeffbea --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-date-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-date-fill.svg new file mode 100644 index 00000000..f796e575 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-date-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-date.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-date.svg new file mode 100644 index 00000000..2f659281 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-date.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-day-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-day-fill.svg new file mode 100644 index 00000000..94a699c6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-day-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-day.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-day.svg new file mode 100644 index 00000000..ce4eb287 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-day.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-event-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-event-fill.svg new file mode 100644 index 00000000..659278bb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-event-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-event.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-event.svg new file mode 100644 index 00000000..451e7680 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-event.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-fill.svg new file mode 100644 index 00000000..76c7536b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-heart-fill.svg new file mode 100644 index 00000000..a4a254f8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-heart.svg new file mode 100644 index 00000000..07d0f942 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-minus-fill.svg new file mode 100644 index 00000000..a43d5318 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-minus.svg new file mode 100644 index 00000000..04299e20 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-month-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-month-fill.svg new file mode 100644 index 00000000..feda7121 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-month-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-month.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-month.svg new file mode 100644 index 00000000..d452105d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-month.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-plus-fill.svg new file mode 100644 index 00000000..a250d8e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-plus.svg new file mode 100644 index 00000000..d9e8fdd1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-range-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-range-fill.svg new file mode 100644 index 00000000..2b2dfcc8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-range-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-range.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-range.svg new file mode 100644 index 00000000..40c85b47 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-range.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-week-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-week-fill.svg new file mode 100644 index 00000000..ba06206f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-week-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-week.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-week.svg new file mode 100644 index 00000000..bba866c8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-week.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-x-fill.svg new file mode 100644 index 00000000..bc1c519f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-x.svg new file mode 100644 index 00000000..89de321b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar.svg new file mode 100644 index 00000000..f19331c5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-check-fill.svg new file mode 100644 index 00000000..83592eef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-check.svg new file mode 100644 index 00000000..c96c4219 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-date-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-date-fill.svg new file mode 100644 index 00000000..7d149e9d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-date-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-date.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-date.svg new file mode 100644 index 00000000..3997f23b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-date.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-day-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-day-fill.svg new file mode 100644 index 00000000..aefdc5fd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-day-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-day.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-day.svg new file mode 100644 index 00000000..b5d68150 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-day.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-event-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-event-fill.svg new file mode 100644 index 00000000..1219bf19 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-event-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-event.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-event.svg new file mode 100644 index 00000000..bc0c4a28 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-event.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-fill.svg new file mode 100644 index 00000000..2a66d984 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-heart-fill.svg new file mode 100644 index 00000000..ca803daa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-heart.svg new file mode 100644 index 00000000..11195abb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-minus-fill.svg new file mode 100644 index 00000000..b5db63d5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-minus.svg new file mode 100644 index 00000000..6cb395df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-minus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-month-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-month-fill.svg new file mode 100644 index 00000000..ab5f022b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-month-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-month.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-month.svg new file mode 100644 index 00000000..270494c2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-month.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-plus-fill.svg new file mode 100644 index 00000000..68d6b812 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-plus.svg new file mode 100644 index 00000000..6da40eb5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-range-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-range-fill.svg new file mode 100644 index 00000000..e06ce8d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-range-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-range.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-range.svg new file mode 100644 index 00000000..f480d84c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-range.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-week-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-week-fill.svg new file mode 100644 index 00000000..7d736b96 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-week-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-week.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-week.svg new file mode 100644 index 00000000..90720a0f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-week.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-x-fill.svg new file mode 100644 index 00000000..ce7e325b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-x.svg new file mode 100644 index 00000000..a4e46aec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2.svg new file mode 100644 index 00000000..46d5922e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-event-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-event-fill.svg new file mode 100644 index 00000000..5052d10c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-event-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-event.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-event.svg new file mode 100644 index 00000000..b164ddf2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-event.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-fill.svg new file mode 100644 index 00000000..1857b044 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-range-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-range-fill.svg new file mode 100644 index 00000000..415d24eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-range-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-range.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-range.svg new file mode 100644 index 00000000..631ba4d5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-range.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-week-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-week-fill.svg new file mode 100644 index 00000000..d214220d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-week-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-week.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-week.svg new file mode 100644 index 00000000..0836df41 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3-week.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3.svg new file mode 100644 index 00000000..d9a60912 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-event.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-event.svg new file mode 100644 index 00000000..cb83cf35 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-event.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-range.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-range.svg new file mode 100644 index 00000000..2d85a813 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-range.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-week.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-week.svg new file mode 100644 index 00000000..4adf34d2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4-week.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4.svg new file mode 100644 index 00000000..c545638c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/calendar4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-fill.svg new file mode 100644 index 00000000..ddf669a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-reels-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-reels-fill.svg new file mode 100644 index 00000000..fd5cc669 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-reels-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-reels.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-reels.svg new file mode 100644 index 00000000..ef886e61 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-reels.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-fill.svg new file mode 100644 index 00000000..60228c2f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-off-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-off-fill.svg new file mode 100644 index 00000000..60454c62 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-off-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-off.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-off.svg new file mode 100644 index 00000000..15ec07cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video.svg new file mode 100644 index 00000000..215c047d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera-video.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera.svg new file mode 100644 index 00000000..d78e612d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/camera2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera2.svg new file mode 100644 index 00000000..0cc1adef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/camera2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/capslock-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/capslock-fill.svg new file mode 100644 index 00000000..5f6671bb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/capslock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/capslock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/capslock.svg new file mode 100644 index 00000000..067b96d9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/capslock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/capsule-pill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/capsule-pill.svg new file mode 100644 index 00000000..9753f445 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/capsule-pill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/capsule.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/capsule.svg new file mode 100644 index 00000000..f4529cfa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/capsule.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/car-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/car-front-fill.svg new file mode 100644 index 00000000..005c9c98 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/car-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/car-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/car-front.svg new file mode 100644 index 00000000..1ca898a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/car-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/card-checklist.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-checklist.svg new file mode 100644 index 00000000..353d355d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-checklist.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/card-heading.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-heading.svg new file mode 100644 index 00000000..71b5b5e2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-heading.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/card-image.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-image.svg new file mode 100644 index 00000000..21a994f9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/card-list.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-list.svg new file mode 100644 index 00000000..c4ce1bf9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-list.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/card-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-text.svg new file mode 100644 index 00000000..4308a847 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/card-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-fill.svg new file mode 100644 index 00000000..858c977c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-square-fill.svg new file mode 100644 index 00000000..bfbf2ad4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-square.svg new file mode 100644 index 00000000..829d359c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down.svg new file mode 100644 index 00000000..3941331d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-fill.svg new file mode 100644 index 00000000..6a0516e3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-square-fill.svg new file mode 100644 index 00000000..eb236fff --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-square.svg new file mode 100644 index 00000000..4684818c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left.svg new file mode 100644 index 00000000..72a876b5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-fill.svg new file mode 100644 index 00000000..ab4126ae --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-square-fill.svg new file mode 100644 index 00000000..c89c9842 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-square.svg new file mode 100644 index 00000000..36674e38 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right.svg new file mode 100644 index 00000000..a67b120a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-fill.svg new file mode 100644 index 00000000..590dcadd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-square-fill.svg new file mode 100644 index 00000000..e2a2c32a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-square.svg new file mode 100644 index 00000000..01e225d3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up.svg new file mode 100644 index 00000000..7717f922 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/caret-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-check-fill.svg new file mode 100644 index 00000000..945f4a79 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-check.svg new file mode 100644 index 00000000..201db0cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-dash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-dash-fill.svg new file mode 100644 index 00000000..95bbff68 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-dash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-dash.svg new file mode 100644 index 00000000..49f4d87f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-fill.svg new file mode 100644 index 00000000..be4b70c8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-plus-fill.svg new file mode 100644 index 00000000..fa03ccb9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-plus.svg new file mode 100644 index 00000000..cd59dea2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-x-fill.svg new file mode 100644 index 00000000..a30bb6f3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-x.svg new file mode 100644 index 00000000..26ed84b2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart.svg new file mode 100644 index 00000000..20286d92 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart2.svg new file mode 100644 index 00000000..d83596b0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart3.svg new file mode 100644 index 00000000..ad2f7504 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cart4.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart4.svg new file mode 100644 index 00000000..7225d157 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cart4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cash-coin.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cash-coin.svg new file mode 100644 index 00000000..4e6e96ec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cash-coin.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cash-stack.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cash-stack.svg new file mode 100644 index 00000000..f469075c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cash-stack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cash.svg new file mode 100644 index 00000000..11dc3ec9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cassette-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cassette-fill.svg new file mode 100644 index 00000000..5c524452 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cassette-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cassette.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cassette.svg new file mode 100644 index 00000000..c6d20434 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cassette.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cast.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cast.svg new file mode 100644 index 00000000..166fc67f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cast.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-circle-fill.svg new file mode 100644 index 00000000..5371b8d6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-circle.svg new file mode 100644 index 00000000..2f0a7245 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-square-fill.svg new file mode 100644 index 00000000..c66eda27 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-square.svg new file mode 100644 index 00000000..949ff516 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cc-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-dots-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-dots-fill.svg new file mode 100644 index 00000000..c77ca6ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-dots-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-dots.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-dots.svg new file mode 100644 index 00000000..41f9f4fa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-dots.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-fill.svg new file mode 100644 index 00000000..33de8b2d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-heart-fill.svg new file mode 100644 index 00000000..3278c028 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-heart.svg new file mode 100644 index 00000000..d6f6fd77 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-dots-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-dots-fill.svg new file mode 100644 index 00000000..1d9c47db --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-dots-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-dots.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-dots.svg new file mode 100644 index 00000000..0c6fe2c4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-dots.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-fill.svg new file mode 100644 index 00000000..db32f54c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-heart-fill.svg new file mode 100644 index 00000000..ea3a81cd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-heart.svg new file mode 100644 index 00000000..99375346 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-quote-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-quote-fill.svg new file mode 100644 index 00000000..89e5a0d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-quote-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-quote.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-quote.svg new file mode 100644 index 00000000..8be4a33e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-quote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-text-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-text-fill.svg new file mode 100644 index 00000000..86d17cb4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-text.svg new file mode 100644 index 00000000..5055e398 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left.svg new file mode 100644 index 00000000..c1bf82bc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-quote-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-quote-fill.svg new file mode 100644 index 00000000..448c5b0d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-quote-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-quote.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-quote.svg new file mode 100644 index 00000000..635dbecd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-quote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-dots-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-dots-fill.svg new file mode 100644 index 00000000..320e1767 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-dots-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-dots.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-dots.svg new file mode 100644 index 00000000..7be9b5bf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-dots.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-fill.svg new file mode 100644 index 00000000..3c8c3cd9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-heart-fill.svg new file mode 100644 index 00000000..4384503f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-heart.svg new file mode 100644 index 00000000..81c6db13 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-quote-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-quote-fill.svg new file mode 100644 index 00000000..f537056a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-quote-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-quote.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-quote.svg new file mode 100644 index 00000000..3065100f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-quote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-text-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-text-fill.svg new file mode 100644 index 00000000..bcf97b0d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-text.svg new file mode 100644 index 00000000..ff7ce2a6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right.svg new file mode 100644 index 00000000..b8a2357a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-dots-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-dots-fill.svg new file mode 100644 index 00000000..2f6c1f4c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-dots-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-dots.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-dots.svg new file mode 100644 index 00000000..1495b930 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-dots.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-fill.svg new file mode 100644 index 00000000..0013fa47 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-heart-fill.svg new file mode 100644 index 00000000..02bf7b7c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-heart.svg new file mode 100644 index 00000000..315b8377 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-quote-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-quote-fill.svg new file mode 100644 index 00000000..8e80e232 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-quote-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-quote.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-quote.svg new file mode 100644 index 00000000..14b51c52 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-quote.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-text-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-text-fill.svg new file mode 100644 index 00000000..87cecdb4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-text.svg new file mode 100644 index 00000000..1d9a359c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square.svg new file mode 100644 index 00000000..f77c2be1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-text-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-text-fill.svg new file mode 100644 index 00000000..f6add9f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-text.svg new file mode 100644 index 00000000..89786ca0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chat.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat.svg new file mode 100644 index 00000000..7154a0e5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chat.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check-all.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-all.svg new file mode 100644 index 00000000..8abe30e2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-all.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-circle-fill.svg new file mode 100644 index 00000000..f24df1b7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-circle.svg new file mode 100644 index 00000000..4a6916c8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-lg.svg new file mode 100644 index 00000000..1682c5e6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-square-fill.svg new file mode 100644 index 00000000..160726ba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-square.svg new file mode 100644 index 00000000..5fdae93a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check.svg new file mode 100644 index 00000000..e187a15f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-all.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-all.svg new file mode 100644 index 00000000..49f8b10d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-all.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-circle.svg new file mode 100644 index 00000000..c3943eb5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-square.svg new file mode 100644 index 00000000..03ea4513 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check2-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/check2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/check2.svg new file mode 100644 index 00000000..07ea4452 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/check2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-contract.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-contract.svg new file mode 100644 index 00000000..a7113d74 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-contract.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-down.svg new file mode 100644 index 00000000..59bfeec6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-expand.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-expand.svg new file mode 100644 index 00000000..c717c969 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-expand.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-left.svg new file mode 100644 index 00000000..9719adb0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-right.svg new file mode 100644 index 00000000..d894417a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-up.svg new file mode 100644 index 00000000..32cf1966 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-bar-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-down.svg new file mode 100644 index 00000000..0ddee55a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-left.svg new file mode 100644 index 00000000..523d5dab --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-right.svg new file mode 100644 index 00000000..7240fd37 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-up.svg new file mode 100644 index 00000000..ffa680bd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-compact-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-contract.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-contract.svg new file mode 100644 index 00000000..041bcf9a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-contract.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-down.svg new file mode 100644 index 00000000..043e0803 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-left.svg new file mode 100644 index 00000000..0e0a8761 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-right.svg new file mode 100644 index 00000000..d6601dfb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-up.svg new file mode 100644 index 00000000..93014ae1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-double-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-down.svg new file mode 100644 index 00000000..7a955095 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-expand.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-expand.svg new file mode 100644 index 00000000..2a7619e5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-expand.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-left.svg new file mode 100644 index 00000000..9a631cfb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-right.svg new file mode 100644 index 00000000..1fbcea4b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-up.svg new file mode 100644 index 00000000..b62d77c9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/chevron-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-fill.svg new file mode 100644 index 00000000..3b35841f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-half.svg new file mode 100644 index 00000000..f7df10fa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-square.svg new file mode 100644 index 00000000..e2c04c42 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/circle-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/circle.svg new file mode 100644 index 00000000..0c591f6e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/claude.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/claude.svg new file mode 100644 index 00000000..99f86d48 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/claude.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-check-fill.svg new file mode 100644 index 00000000..ed665241 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-check.svg new file mode 100644 index 00000000..1efdad80 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-data-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-data-fill.svg new file mode 100644 index 00000000..c8bc02fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-data-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-data.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-data.svg new file mode 100644 index 00000000..708c21b8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-data.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-fill.svg new file mode 100644 index 00000000..e8c8e78d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-heart-fill.svg new file mode 100644 index 00000000..c8815e00 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-heart.svg new file mode 100644 index 00000000..897be92f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-heart.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-minus-fill.svg new file mode 100644 index 00000000..c56c0925 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-minus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-minus.svg new file mode 100644 index 00000000..1b36d3d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-minus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-plus-fill.svg new file mode 100644 index 00000000..e4ad26a8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-plus.svg new file mode 100644 index 00000000..de9bae10 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-pulse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-pulse.svg new file mode 100644 index 00000000..7891093c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-pulse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-x-fill.svg new file mode 100644 index 00000000..7a0011ac --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-x-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-x.svg new file mode 100644 index 00000000..75adb261 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard.svg new file mode 100644 index 00000000..cca45eb6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-check-fill.svg new file mode 100644 index 00000000..0f7657d8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-check.svg new file mode 100644 index 00000000..b026b80e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-data-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-data-fill.svg new file mode 100644 index 00000000..dce3785f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-data-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-data.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-data.svg new file mode 100644 index 00000000..933d6d84 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-data.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-fill.svg new file mode 100644 index 00000000..b9124ddd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-heart-fill.svg new file mode 100644 index 00000000..9694cd21 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-heart.svg new file mode 100644 index 00000000..c2381cd6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-heart.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-minus-fill.svg new file mode 100644 index 00000000..6a5ba9e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-minus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-minus.svg new file mode 100644 index 00000000..78a47560 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-minus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-plus-fill.svg new file mode 100644 index 00000000..9221823b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-plus.svg new file mode 100644 index 00000000..d8b30707 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-pulse-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-pulse-fill.svg new file mode 100644 index 00000000..4087f19a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-pulse-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-pulse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-pulse.svg new file mode 100644 index 00000000..3662bc23 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-pulse.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-x-fill.svg new file mode 100644 index 00000000..ac443d2a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-x-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-x.svg new file mode 100644 index 00000000..750f4cb0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2.svg new file mode 100644 index 00000000..3f549687 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clipboard2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clock-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clock-fill.svg new file mode 100644 index 00000000..109be162 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clock-history.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clock-history.svg new file mode 100644 index 00000000..7342b0a9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clock-history.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clock.svg new file mode 100644 index 00000000..e210180c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-down-fill.svg new file mode 100644 index 00000000..20b546a6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-down.svg new file mode 100644 index 00000000..8b0033ac --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-up-fill.svg new file mode 100644 index 00000000..8bb7abcf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-up.svg new file mode 100644 index 00000000..d48d6a4a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-check-fill.svg new file mode 100644 index 00000000..58f5ee5e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-check.svg new file mode 100644 index 00000000..bf751c2d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-download-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-download-fill.svg new file mode 100644 index 00000000..e75765f5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-download-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-download.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-download.svg new file mode 100644 index 00000000..23d7027f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-download.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-drizzle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-drizzle-fill.svg new file mode 100644 index 00000000..0b1c6dca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-drizzle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-drizzle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-drizzle.svg new file mode 100644 index 00000000..edf9deac --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-drizzle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fill.svg new file mode 100644 index 00000000..cef7cace --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog-fill.svg new file mode 100644 index 00000000..e8f6b50b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog.svg new file mode 100644 index 00000000..7d4abc2f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog2-fill.svg new file mode 100644 index 00000000..08daeefd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog2.svg new file mode 100644 index 00000000..0597aea9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-fog2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-hail-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-hail-fill.svg new file mode 100644 index 00000000..71020cfb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-hail-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-hail.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-hail.svg new file mode 100644 index 00000000..33539801 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-hail.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze-fill.svg new file mode 100644 index 00000000..bca757b8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze.svg new file mode 100644 index 00000000..40754fb4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze2-fill.svg new file mode 100644 index 00000000..0c7c8c61 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze2.svg new file mode 100644 index 00000000..8e28430f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-haze2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-fill.svg new file mode 100644 index 00000000..40a047fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-rain-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-rain-fill.svg new file mode 100644 index 00000000..f9586462 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-rain-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-rain.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-rain.svg new file mode 100644 index 00000000..c2e31381 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning-rain.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning.svg new file mode 100644 index 00000000..247fb423 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-lightning.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-minus-fill.svg new file mode 100644 index 00000000..bc391965 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-minus.svg new file mode 100644 index 00000000..0834442c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-moon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-moon-fill.svg new file mode 100644 index 00000000..356e4102 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-moon-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-moon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-moon.svg new file mode 100644 index 00000000..5ea2e2eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-moon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-plus-fill.svg new file mode 100644 index 00000000..21dae384 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-plus.svg new file mode 100644 index 00000000..ded12a4d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-fill.svg new file mode 100644 index 00000000..67d5901e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-heavy-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-heavy-fill.svg new file mode 100644 index 00000000..fa039cde --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-heavy-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-heavy.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-heavy.svg new file mode 100644 index 00000000..76b27ce3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain-heavy.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain.svg new file mode 100644 index 00000000..7d3d6dbb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-rain.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-slash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-slash-fill.svg new file mode 100644 index 00000000..5ef39d16 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-slash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-slash.svg new file mode 100644 index 00000000..e6072e4c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sleet-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sleet-fill.svg new file mode 100644 index 00000000..44ecfcb7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sleet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sleet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sleet.svg new file mode 100644 index 00000000..b04c9e83 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sleet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-snow-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-snow-fill.svg new file mode 100644 index 00000000..c12f3e1e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-snow-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-snow.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-snow.svg new file mode 100644 index 00000000..6273ad9b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-snow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sun-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sun-fill.svg new file mode 100644 index 00000000..a6f81cfe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sun-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sun.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sun.svg new file mode 100644 index 00000000..29aee9bb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-sun.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-upload-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-upload-fill.svg new file mode 100644 index 00000000..9434e356 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-upload-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-upload.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-upload.svg new file mode 100644 index 00000000..0c41b568 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud-upload.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud.svg new file mode 100644 index 00000000..c5b14ebf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloud.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clouds-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clouds-fill.svg new file mode 100644 index 00000000..b5feceee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clouds-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/clouds.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/clouds.svg new file mode 100644 index 00000000..37b040a7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/clouds.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloudy-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloudy-fill.svg new file mode 100644 index 00000000..41c02138 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloudy-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cloudy.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloudy.svg new file mode 100644 index 00000000..828ff5b7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cloudy.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/code-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/code-slash.svg new file mode 100644 index 00000000..4f54e1e8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/code-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/code-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/code-square.svg new file mode 100644 index 00000000..6e8b7174 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/code-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/code.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/code.svg new file mode 100644 index 00000000..f797d6a5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/code.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/coin.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/coin.svg new file mode 100644 index 00000000..1cf4e315 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/coin.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-fill.svg new file mode 100644 index 00000000..e3e3b9ea --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-play-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-play-fill.svg new file mode 100644 index 00000000..399cd088 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-play-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-play.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-play.svg new file mode 100644 index 00000000..23e29d34 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/collection-play.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/collection.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/collection.svg new file mode 100644 index 00000000..dee267d6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/collection.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/columns-gap.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/columns-gap.svg new file mode 100644 index 00000000..a1054290 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/columns-gap.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/columns.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/columns.svg new file mode 100644 index 00000000..cfeebbd9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/columns.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/command.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/command.svg new file mode 100644 index 00000000..12dc1ff5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/command.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/compass-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/compass-fill.svg new file mode 100644 index 00000000..99c5db09 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/compass-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/compass.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/compass.svg new file mode 100644 index 00000000..57671977 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/compass.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cone-striped.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cone-striped.svg new file mode 100644 index 00000000..476de8b1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cone-striped.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cone.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cone.svg new file mode 100644 index 00000000..5286d347 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cone.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/controller.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/controller.svg new file mode 100644 index 00000000..ee9426c5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/controller.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cookie.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cookie.svg new file mode 100644 index 00000000..685ed5e0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cookie.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/copy.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/copy.svg new file mode 100644 index 00000000..5246858c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/copy.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cpu-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cpu-fill.svg new file mode 100644 index 00000000..eb817c62 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cpu-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cpu.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cpu.svg new file mode 100644 index 00000000..02a5a504 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cpu.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-back-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-back-fill.svg new file mode 100644 index 00000000..062c2362 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-back-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-back.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-back.svg new file mode 100644 index 00000000..886baaba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-back.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-front-fill.svg new file mode 100644 index 00000000..deb6206d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-front.svg new file mode 100644 index 00000000..554298f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-2-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-fill.svg new file mode 100644 index 00000000..4621b90e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card.svg new file mode 100644 index 00000000..d0179fba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/credit-card.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/crop.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/crop.svg new file mode 100644 index 00000000..72d60436 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/crop.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/crosshair.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/crosshair.svg new file mode 100644 index 00000000..e0637510 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/crosshair.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/crosshair2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/crosshair2.svg new file mode 100644 index 00000000..e014f0bb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/crosshair2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/css.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/css.svg new file mode 100644 index 00000000..7ab7bc21 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/css.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-fill.svg new file mode 100644 index 00000000..dcaf39a4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-hot-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-hot-fill.svg new file mode 100644 index 00000000..afc1f2b1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-hot-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-hot.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-hot.svg new file mode 100644 index 00000000..fb8988ed --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-hot.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-straw.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-straw.svg new file mode 100644 index 00000000..80c4cabe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup-straw.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cup.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup.svg new file mode 100644 index 00000000..33d16624 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cup.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-bitcoin.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-bitcoin.svg new file mode 100644 index 00000000..7957db91 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-bitcoin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-dollar.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-dollar.svg new file mode 100644 index 00000000..e0bfb5e8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-dollar.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-euro.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-euro.svg new file mode 100644 index 00000000..5183beb0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-euro.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-exchange.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-exchange.svg new file mode 100644 index 00000000..0f0f31d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-exchange.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-pound.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-pound.svg new file mode 100644 index 00000000..0495178e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-pound.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-rupee.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-rupee.svg new file mode 100644 index 00000000..39054796 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-rupee.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-yen.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-yen.svg new file mode 100644 index 00000000..f17f1d55 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/currency-yen.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor-fill.svg new file mode 100644 index 00000000..b8416937 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor-text.svg new file mode 100644 index 00000000..a10c49a8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor-text.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor.svg new file mode 100644 index 00000000..8cede99b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/cursor.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle-dotted.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle-dotted.svg new file mode 100644 index 00000000..78dd897e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle-dotted.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle-fill.svg new file mode 100644 index 00000000..8bf35b0e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle.svg new file mode 100644 index 00000000..f73d0122 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-lg.svg new file mode 100644 index 00000000..7a315e25 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square-dotted.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square-dotted.svg new file mode 100644 index 00000000..892355b6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square-dotted.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square-fill.svg new file mode 100644 index 00000000..d59b7494 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square.svg new file mode 100644 index 00000000..eb0de725 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash.svg new file mode 100644 index 00000000..3f38f65e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-add.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-add.svg new file mode 100644 index 00000000..3b4af52d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-check.svg new file mode 100644 index 00000000..06b14b67 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-dash.svg new file mode 100644 index 00000000..58a6e3c3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-down.svg new file mode 100644 index 00000000..8671e71e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-exclamation.svg new file mode 100644 index 00000000..70a766e2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-add.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-add.svg new file mode 100644 index 00000000..889aed92 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-check.svg new file mode 100644 index 00000000..34c6f822 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-dash.svg new file mode 100644 index 00000000..2f84510e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-down.svg new file mode 100644 index 00000000..fd45dac9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-exclamation.svg new file mode 100644 index 00000000..daf40d6c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-exclamation.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-gear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-gear.svg new file mode 100644 index 00000000..33bf3f61 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-lock.svg new file mode 100644 index 00000000..9fb764fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-lock.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-slash.svg new file mode 100644 index 00000000..00b2208f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-up.svg new file mode 100644 index 00000000..99183127 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-x.svg new file mode 100644 index 00000000..3e89ef82 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill.svg new file mode 100644 index 00000000..834e9125 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-fill.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-gear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-gear.svg new file mode 100644 index 00000000..408c6871 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-lock.svg new file mode 100644 index 00000000..10e1189b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-slash.svg new file mode 100644 index 00000000..35fccf59 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-up.svg new file mode 100644 index 00000000..d497048f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-x.svg new file mode 100644 index 00000000..0ac750b6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/database.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/database.svg new file mode 100644 index 00000000..6586741c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/database.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/device-hdd-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/device-hdd-fill.svg new file mode 100644 index 00000000..25295e46 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/device-hdd-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/device-hdd.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/device-hdd.svg new file mode 100644 index 00000000..ecc9e50f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/device-hdd.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/device-ssd-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/device-ssd-fill.svg new file mode 100644 index 00000000..ed23318d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/device-ssd-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/device-ssd.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/device-ssd.svg new file mode 100644 index 00000000..6bedbd5f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/device-ssd.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-2-fill.svg new file mode 100644 index 00000000..7879ef6b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-2.svg new file mode 100644 index 00000000..31f990ed --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-3-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-3-fill.svg new file mode 100644 index 00000000..3326357c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-3.svg new file mode 100644 index 00000000..5ed4479f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/diagram-3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond-fill.svg new file mode 100644 index 00000000..bc4bf2f8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond-half.svg new file mode 100644 index 00000000..7c2ac0ff --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond.svg new file mode 100644 index 00000000..8217aac7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/diamond.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-1-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-1-fill.svg new file mode 100644 index 00000000..b0c7d226 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-1-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-1.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-1.svg new file mode 100644 index 00000000..ab490ea4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-1.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-2-fill.svg new file mode 100644 index 00000000..119f3db2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-2.svg new file mode 100644 index 00000000..16235ff6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-3-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-3-fill.svg new file mode 100644 index 00000000..bfcb505a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-3.svg new file mode 100644 index 00000000..b300de48 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-4-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-4-fill.svg new file mode 100644 index 00000000..df35bb8a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-4-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-4.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-4.svg new file mode 100644 index 00000000..8f029c06 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-4.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-5-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-5-fill.svg new file mode 100644 index 00000000..5aee8ab7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-5-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-5.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-5.svg new file mode 100644 index 00000000..b6537d0a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-5.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-6-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-6-fill.svg new file mode 100644 index 00000000..893ba987 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-6-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-6.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-6.svg new file mode 100644 index 00000000..7951fd8a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dice-6.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/disc-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/disc-fill.svg new file mode 100644 index 00000000..894afd7e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/disc-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/disc.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/disc.svg new file mode 100644 index 00000000..6f34164d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/disc.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/discord.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/discord.svg new file mode 100644 index 00000000..336f0742 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/discord.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/display-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/display-fill.svg new file mode 100644 index 00000000..74bb3453 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/display-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/display.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/display.svg new file mode 100644 index 00000000..02fada9e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/display.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/displayport-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/displayport-fill.svg new file mode 100644 index 00000000..20d62b66 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/displayport-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/displayport.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/displayport.svg new file mode 100644 index 00000000..23d40242 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/displayport.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/distribute-horizontal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/distribute-horizontal.svg new file mode 100644 index 00000000..f9b2a763 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/distribute-horizontal.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/distribute-vertical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/distribute-vertical.svg new file mode 100644 index 00000000..3581aacb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/distribute-vertical.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/door-closed-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/door-closed-fill.svg new file mode 100644 index 00000000..dbe79f99 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/door-closed-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/door-closed.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/door-closed.svg new file mode 100644 index 00000000..248a3119 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/door-closed.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/door-open-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/door-open-fill.svg new file mode 100644 index 00000000..80b5aa82 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/door-open-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/door-open.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/door-open.svg new file mode 100644 index 00000000..9d91c618 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/door-open.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dot.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dot.svg new file mode 100644 index 00000000..7fd6d746 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dot.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/download.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/download.svg new file mode 100644 index 00000000..48521962 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/download.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dpad-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dpad-fill.svg new file mode 100644 index 00000000..ad2c72e7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dpad-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dpad.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dpad.svg new file mode 100644 index 00000000..92b1d81b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dpad.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dribbble.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dribbble.svg new file mode 100644 index 00000000..13a3fd96 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dribbble.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/dropbox.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/dropbox.svg new file mode 100644 index 00000000..a3fe91cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/dropbox.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet-fill.svg new file mode 100644 index 00000000..a9c43403 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet-half.svg new file mode 100644 index 00000000..315c84c2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet-half.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet.svg new file mode 100644 index 00000000..0d2cc20f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/droplet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/duffle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/duffle-fill.svg new file mode 100644 index 00000000..d1cc5861 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/duffle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/duffle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/duffle.svg new file mode 100644 index 00000000..ba4bb9c9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/duffle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ear-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ear-fill.svg new file mode 100644 index 00000000..b0bd553d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ear-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ear.svg new file mode 100644 index 00000000..0313233e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ear.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/earbuds.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/earbuds.svg new file mode 100644 index 00000000..a7cb730e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/earbuds.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/easel-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel-fill.svg new file mode 100644 index 00000000..7dcff1d2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/easel.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel.svg new file mode 100644 index 00000000..efe2aa0b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/easel2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel2-fill.svg new file mode 100644 index 00000000..dcc33f34 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/easel2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel2.svg new file mode 100644 index 00000000..23a73db9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/easel3-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel3-fill.svg new file mode 100644 index 00000000..d4ae7354 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/easel3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel3.svg new file mode 100644 index 00000000..27a43d60 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/easel3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/egg-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/egg-fill.svg new file mode 100644 index 00000000..4e951888 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/egg-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/egg-fried.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/egg-fried.svg new file mode 100644 index 00000000..03753184 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/egg-fried.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/egg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/egg.svg new file mode 100644 index 00000000..664535d3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/egg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eject-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eject-fill.svg new file mode 100644 index 00000000..87378f92 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eject-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eject.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eject.svg new file mode 100644 index 00000000..c2d6dde5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eject.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-angry-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-angry-fill.svg new file mode 100644 index 00000000..535e7c6f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-angry-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-angry.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-angry.svg new file mode 100644 index 00000000..88768fd0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-angry.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-astonished-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-astonished-fill.svg new file mode 100644 index 00000000..67974cb8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-astonished-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-astonished.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-astonished.svg new file mode 100644 index 00000000..f30aaaf9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-astonished.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-dizzy-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-dizzy-fill.svg new file mode 100644 index 00000000..271e0311 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-dizzy-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-dizzy.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-dizzy.svg new file mode 100644 index 00000000..15cd8e74 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-dizzy.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-expressionless-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-expressionless-fill.svg new file mode 100644 index 00000000..cd311cf6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-expressionless-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-expressionless.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-expressionless.svg new file mode 100644 index 00000000..6dbd1ebb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-expressionless.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-frown-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-frown-fill.svg new file mode 100644 index 00000000..7e420e22 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-frown-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-frown.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-frown.svg new file mode 100644 index 00000000..98a3bff9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-frown.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grimace-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grimace-fill.svg new file mode 100644 index 00000000..2a1d7382 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grimace-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grimace.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grimace.svg new file mode 100644 index 00000000..f1118af8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grimace.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grin-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grin-fill.svg new file mode 100644 index 00000000..5f113908 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grin-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grin.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grin.svg new file mode 100644 index 00000000..31354adf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-grin.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-heart-eyes-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-heart-eyes-fill.svg new file mode 100644 index 00000000..1436d762 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-heart-eyes-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-heart-eyes.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-heart-eyes.svg new file mode 100644 index 00000000..8eadfc6c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-heart-eyes.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-kiss-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-kiss-fill.svg new file mode 100644 index 00000000..31d5056d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-kiss-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-kiss.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-kiss.svg new file mode 100644 index 00000000..dd3fd4b0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-kiss.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-laughing-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-laughing-fill.svg new file mode 100644 index 00000000..2c81386b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-laughing-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-laughing.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-laughing.svg new file mode 100644 index 00000000..eed9f847 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-laughing.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-neutral-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-neutral-fill.svg new file mode 100644 index 00000000..6e1f05db --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-neutral-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-neutral.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-neutral.svg new file mode 100644 index 00000000..509e9d1e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-neutral.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-fill.svg new file mode 100644 index 00000000..f267edf1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-upside-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-upside-down-fill.svg new file mode 100644 index 00000000..e88567a4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-upside-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-upside-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-upside-down.svg new file mode 100644 index 00000000..f0eedc29 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile-upside-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile.svg new file mode 100644 index 00000000..c35f1a18 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-smile.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-sunglasses-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-sunglasses-fill.svg new file mode 100644 index 00000000..44e9cb81 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-sunglasses-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-sunglasses.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-sunglasses.svg new file mode 100644 index 00000000..ee910dce --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-sunglasses.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-surprise-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-surprise-fill.svg new file mode 100644 index 00000000..d5e76523 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-surprise-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-surprise.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-surprise.svg new file mode 100644 index 00000000..cbb0a94f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-surprise.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-tear-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-tear-fill.svg new file mode 100644 index 00000000..6fdf98ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-tear-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-tear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-tear.svg new file mode 100644 index 00000000..fc724551 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-tear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-wink-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-wink-fill.svg new file mode 100644 index 00000000..bba38004 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-wink-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-wink.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-wink.svg new file mode 100644 index 00000000..8d8f764f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/emoji-wink.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-down-fill.svg new file mode 100644 index 00000000..abc8e0d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-down-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-down.svg new file mode 100644 index 00000000..65dd4c6b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-up-fill.svg new file mode 100644 index 00000000..9d276c2f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-up-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-up.svg new file mode 100644 index 00000000..2ebe82c2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-at-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-at-fill.svg new file mode 100644 index 00000000..2a1d4923 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-at-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-at.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-at.svg new file mode 100644 index 00000000..7a31442a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-at.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-check-fill.svg new file mode 100644 index 00000000..261f7b3f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-check.svg new file mode 100644 index 00000000..aa4bf8b8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-dash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-dash-fill.svg new file mode 100644 index 00000000..dd1cc6ad --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-dash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-dash.svg new file mode 100644 index 00000000..6e1c3fc2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-exclamation-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-exclamation-fill.svg new file mode 100644 index 00000000..89ab3529 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-exclamation-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-exclamation.svg new file mode 100644 index 00000000..86423d8d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-fill.svg new file mode 100644 index 00000000..bda5ad12 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-heart-fill.svg new file mode 100644 index 00000000..4a30e409 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-heart.svg new file mode 100644 index 00000000..bec48583 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-fill.svg new file mode 100644 index 00000000..f15f28e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-heart-fill.svg new file mode 100644 index 00000000..fee0dc82 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-heart.svg new file mode 100644 index 00000000..0a038da1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open.svg new file mode 100644 index 00000000..1882d9f8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-open.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-fill.svg new file mode 100644 index 00000000..6d47d0cb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-heart-fill.svg new file mode 100644 index 00000000..15e5a254 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-heart.svg new file mode 100644 index 00000000..363a32e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper.svg new file mode 100644 index 00000000..6f2609f5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-paper.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-plus-fill.svg new file mode 100644 index 00000000..f71b6c1b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-plus.svg new file mode 100644 index 00000000..53905284 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-slash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-slash-fill.svg new file mode 100644 index 00000000..9535d6b9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-slash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-slash.svg new file mode 100644 index 00000000..f3890923 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-x-fill.svg new file mode 100644 index 00000000..4342bdc4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-x-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-x.svg new file mode 100644 index 00000000..3da0e722 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope.svg new file mode 100644 index 00000000..a007ad24 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/envelope.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eraser-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eraser-fill.svg new file mode 100644 index 00000000..7cf55ddb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eraser-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eraser.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eraser.svg new file mode 100644 index 00000000..266b769d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eraser.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/error.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/error.svg new file mode 100644 index 00000000..25547844 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/error.svg @@ -0,0 +1,4 @@ + + + + diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/escape.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/escape.svg new file mode 100644 index 00000000..34093a15 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/escape.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ethernet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ethernet.svg new file mode 100644 index 00000000..66b2e742 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ethernet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-front-fill.svg new file mode 100644 index 00000000..d55d1cb5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-front.svg new file mode 100644 index 00000000..c50c0ab4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-station-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-station-fill.svg new file mode 100644 index 00000000..9187f78b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-station-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-station.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-station.svg new file mode 100644 index 00000000..56a0ba00 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ev-station.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-circle-fill.svg new file mode 100644 index 00000000..4b06ee70 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-circle.svg new file mode 100644 index 00000000..052a224e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-diamond-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-diamond-fill.svg new file mode 100644 index 00000000..ceea6412 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-diamond.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-diamond.svg new file mode 100644 index 00000000..affc7220 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-diamond.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-lg.svg new file mode 100644 index 00000000..8d60bd43 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-octagon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-octagon-fill.svg new file mode 100644 index 00000000..e712c7b1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-octagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-octagon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-octagon.svg new file mode 100644 index 00000000..e3784405 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-octagon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-square-fill.svg new file mode 100644 index 00000000..7850fdb0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-square.svg new file mode 100644 index 00000000..ede05a28 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-triangle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-triangle-fill.svg new file mode 100644 index 00000000..b5779676 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-triangle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-triangle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-triangle.svg new file mode 100644 index 00000000..8a446a92 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation-triangle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation.svg new file mode 100644 index 00000000..44b6c6ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclamation.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exclude.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclude.svg new file mode 100644 index 00000000..488e25b1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exclude.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/explicit-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/explicit-fill.svg new file mode 100644 index 00000000..da66b73b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/explicit-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/explicit.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/explicit.svg new file mode 100644 index 00000000..dc77a976 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/explicit.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/exposure.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/exposure.svg new file mode 100644 index 00000000..44211f95 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/exposure.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-fill.svg new file mode 100644 index 00000000..41a537fd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-slash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-slash-fill.svg new file mode 100644 index 00000000..7a1b0691 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-slash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-slash.svg new file mode 100644 index 00000000..6d6b01e2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eye-slash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eye.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eye.svg new file mode 100644 index 00000000..5c18be17 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eye.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eyedropper.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eyedropper.svg new file mode 100644 index 00000000..e1518083 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eyedropper.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/eyeglasses.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/eyeglasses.svg new file mode 100644 index 00000000..cfd2e86a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/eyeglasses.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/facebook.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/facebook.svg new file mode 100644 index 00000000..0c62bfe3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/facebook.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fan.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fan.svg new file mode 100644 index 00000000..eebf25c5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fan.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-btn-fill.svg new file mode 100644 index 00000000..29e272fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-btn.svg new file mode 100644 index 00000000..0f5c88a9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-circle-fill.svg new file mode 100644 index 00000000..ed127c2b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-circle.svg new file mode 100644 index 00000000..1144ae26 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-fill.svg new file mode 100644 index 00000000..79db4a7b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward.svg new file mode 100644 index 00000000..bacaf150 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fast-forward.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/feather.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/feather.svg new file mode 100644 index 00000000..606e7504 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/feather.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/feather2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/feather2.svg new file mode 100644 index 00000000..3df4a826 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/feather2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-down-fill.svg new file mode 100644 index 00000000..634b3b73 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-down.svg new file mode 100644 index 00000000..fca01f6d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-up-fill.svg new file mode 100644 index 00000000..3ccae5a6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-up.svg new file mode 100644 index 00000000..3426ae1e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-bar-graph-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-bar-graph-fill.svg new file mode 100644 index 00000000..61ea5305 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-bar-graph-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-bar-graph.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-bar-graph.svg new file mode 100644 index 00000000..073d1122 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-bar-graph.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-binary-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-binary-fill.svg new file mode 100644 index 00000000..7b95ff49 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-binary-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-binary.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-binary.svg new file mode 100644 index 00000000..a5d48251 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-binary.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-break-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-break-fill.svg new file mode 100644 index 00000000..6a40d8a0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-break-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-break.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-break.svg new file mode 100644 index 00000000..f65b897b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-break.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-check-fill.svg new file mode 100644 index 00000000..c972d822 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-check.svg new file mode 100644 index 00000000..57a2e39e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-code-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-code-fill.svg new file mode 100644 index 00000000..c90f6f30 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-code-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-code.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-code.svg new file mode 100644 index 00000000..e49ca8c1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-code.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-diff-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-diff-fill.svg new file mode 100644 index 00000000..54ea881a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-diff-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-diff.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-diff.svg new file mode 100644 index 00000000..2cb7fe40 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-diff.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-down-fill.svg new file mode 100644 index 00000000..dd152730 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-down.svg new file mode 100644 index 00000000..906884e0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-up-fill.svg new file mode 100644 index 00000000..3d3119ec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-up.svg new file mode 100644 index 00000000..73e6de2a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-bar-graph-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-bar-graph-fill.svg new file mode 100644 index 00000000..9cba979d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-bar-graph-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-bar-graph.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-bar-graph.svg new file mode 100644 index 00000000..5bd274d6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-bar-graph.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-binary-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-binary-fill.svg new file mode 100644 index 00000000..813be71f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-binary-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-binary.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-binary.svg new file mode 100644 index 00000000..68c4fcc7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-binary.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-break-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-break-fill.svg new file mode 100644 index 00000000..e045834c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-break-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-break.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-break.svg new file mode 100644 index 00000000..45a38e96 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-break.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-check-fill.svg new file mode 100644 index 00000000..daf36eb7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-check.svg new file mode 100644 index 00000000..514caf37 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-code-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-code-fill.svg new file mode 100644 index 00000000..689ad4e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-code-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-code.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-code.svg new file mode 100644 index 00000000..8751019e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-code.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-diff-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-diff-fill.svg new file mode 100644 index 00000000..9aeb2117 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-diff-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-diff.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-diff.svg new file mode 100644 index 00000000..14d6b7c9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-diff.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-easel-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-easel-fill.svg new file mode 100644 index 00000000..82b21ace --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-easel-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-easel.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-easel.svg new file mode 100644 index 00000000..a76b14fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-easel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-excel-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-excel-fill.svg new file mode 100644 index 00000000..57937252 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-excel-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-excel.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-excel.svg new file mode 100644 index 00000000..81237c5b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-excel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-fill.svg new file mode 100644 index 00000000..caf37371 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-font-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-font-fill.svg new file mode 100644 index 00000000..1c29751b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-font-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-font.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-font.svg new file mode 100644 index 00000000..2ba19e14 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-font.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-image-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-image-fill.svg new file mode 100644 index 00000000..02a8318c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-image-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-image.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-image.svg new file mode 100644 index 00000000..40a6b4ad --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock-fill.svg new file mode 100644 index 00000000..8836a82b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock.svg new file mode 100644 index 00000000..fa1455ba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock2-fill.svg new file mode 100644 index 00000000..2be3fd6c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock2.svg new file mode 100644 index 00000000..ce87e8e0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-lock2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-medical-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-medical-fill.svg new file mode 100644 index 00000000..b93cb85a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-medical-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-medical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-medical.svg new file mode 100644 index 00000000..56ca0054 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-medical.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-minus-fill.svg new file mode 100644 index 00000000..bee9808c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-minus.svg new file mode 100644 index 00000000..d56a6822 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-music-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-music-fill.svg new file mode 100644 index 00000000..96585322 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-music-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-music.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-music.svg new file mode 100644 index 00000000..ab7e02eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-music.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-pdf-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-pdf-fill.svg new file mode 100644 index 00000000..9f796cb2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-pdf-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-pdf.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-pdf.svg new file mode 100644 index 00000000..839d6bc4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-pdf.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-person-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-person-fill.svg new file mode 100644 index 00000000..7504d217 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-person-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-person.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-person.svg new file mode 100644 index 00000000..7397ceb9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-person.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-play-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-play-fill.svg new file mode 100644 index 00000000..3a6ad9ba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-play-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-play.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-play.svg new file mode 100644 index 00000000..ac5df5ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-play.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-plus-fill.svg new file mode 100644 index 00000000..3139b310 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-plus.svg new file mode 100644 index 00000000..d9f4c9b0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-post-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-post-fill.svg new file mode 100644 index 00000000..7934a440 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-post-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-post.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-post.svg new file mode 100644 index 00000000..cb1507cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-post.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ppt-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ppt-fill.svg new file mode 100644 index 00000000..3b8efa99 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ppt-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ppt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ppt.svg new file mode 100644 index 00000000..9cefb5e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ppt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-richtext-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-richtext-fill.svg new file mode 100644 index 00000000..71f8e0b4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-richtext-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-richtext.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-richtext.svg new file mode 100644 index 00000000..7a2081ae --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-richtext.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ruled-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ruled-fill.svg new file mode 100644 index 00000000..e5e52aa7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ruled-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ruled.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ruled.svg new file mode 100644 index 00000000..3777fdd2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-ruled.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-slides-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-slides-fill.svg new file mode 100644 index 00000000..92a07158 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-slides-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-slides.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-slides.svg new file mode 100644 index 00000000..dca4246b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-slides.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-spreadsheet-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-spreadsheet-fill.svg new file mode 100644 index 00000000..57b9a9bb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-spreadsheet-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-spreadsheet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-spreadsheet.svg new file mode 100644 index 00000000..530400f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-spreadsheet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-text-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-text-fill.svg new file mode 100644 index 00000000..f3e19fce --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-text.svg new file mode 100644 index 00000000..e8c822a5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-word-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-word-fill.svg new file mode 100644 index 00000000..ce8feb51 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-word-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-word.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-word.svg new file mode 100644 index 00000000..084460dd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-word.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-x-fill.svg new file mode 100644 index 00000000..87440cd2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-x.svg new file mode 100644 index 00000000..cd3e03a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-zip-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-zip-fill.svg new file mode 100644 index 00000000..7260f7c1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-zip-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-zip.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-zip.svg new file mode 100644 index 00000000..0bd3bef5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark-zip.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark.svg new file mode 100644 index 00000000..6b3016f1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-earmark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-easel-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-easel-fill.svg new file mode 100644 index 00000000..89bef306 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-easel-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-easel.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-easel.svg new file mode 100644 index 00000000..b9484af8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-easel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-excel-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-excel-fill.svg new file mode 100644 index 00000000..cb64546f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-excel-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-excel.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-excel.svg new file mode 100644 index 00000000..d88a5a50 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-excel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-fill.svg new file mode 100644 index 00000000..edeeebe8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-font-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-font-fill.svg new file mode 100644 index 00000000..4405d2be --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-font-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-font.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-font.svg new file mode 100644 index 00000000..e45a9069 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-font.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-image-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-image-fill.svg new file mode 100644 index 00000000..66a6b14a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-image-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-image.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-image.svg new file mode 100644 index 00000000..54af5f1f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock-fill.svg new file mode 100644 index 00000000..e549c40f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock.svg new file mode 100644 index 00000000..a9d45c85 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock2-fill.svg new file mode 100644 index 00000000..f02b9998 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock2.svg new file mode 100644 index 00000000..500453ad --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-lock2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-medical-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-medical-fill.svg new file mode 100644 index 00000000..3e6b2088 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-medical-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-medical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-medical.svg new file mode 100644 index 00000000..d1a1147b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-medical.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-minus-fill.svg new file mode 100644 index 00000000..43a55582 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-minus.svg new file mode 100644 index 00000000..97a81b8e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-music-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-music-fill.svg new file mode 100644 index 00000000..55eb8418 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-music-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-music.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-music.svg new file mode 100644 index 00000000..d9cebb81 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-music.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-pdf-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-pdf-fill.svg new file mode 100644 index 00000000..8113eb84 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-pdf-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-pdf.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-pdf.svg new file mode 100644 index 00000000..52651123 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-pdf.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-person-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-person-fill.svg new file mode 100644 index 00000000..b48e7b2e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-person-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-person.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-person.svg new file mode 100644 index 00000000..c0a90bb4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-person.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-play-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-play-fill.svg new file mode 100644 index 00000000..58f570de --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-play-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-play.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-play.svg new file mode 100644 index 00000000..60629ee3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-play.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-plus-fill.svg new file mode 100644 index 00000000..bdc48781 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-plus.svg new file mode 100644 index 00000000..b500d7a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-post-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-post-fill.svg new file mode 100644 index 00000000..4ebb9542 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-post-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-post.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-post.svg new file mode 100644 index 00000000..4b0dc1a0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-post.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ppt-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ppt-fill.svg new file mode 100644 index 00000000..9b84c050 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ppt-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ppt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ppt.svg new file mode 100644 index 00000000..9f6302e6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ppt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-richtext-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-richtext-fill.svg new file mode 100644 index 00000000..8f4f90df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-richtext-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-richtext.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-richtext.svg new file mode 100644 index 00000000..277b00db --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-richtext.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ruled-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ruled-fill.svg new file mode 100644 index 00000000..c90b2648 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ruled-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ruled.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ruled.svg new file mode 100644 index 00000000..ebf2df2a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-ruled.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-slides-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-slides-fill.svg new file mode 100644 index 00000000..fcba9632 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-slides-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-slides.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-slides.svg new file mode 100644 index 00000000..0b5a8716 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-slides.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-spreadsheet-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-spreadsheet-fill.svg new file mode 100644 index 00000000..2ce68734 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-spreadsheet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-spreadsheet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-spreadsheet.svg new file mode 100644 index 00000000..36ee79fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-spreadsheet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-text-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-text-fill.svg new file mode 100644 index 00000000..5e25373a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-text-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-text.svg new file mode 100644 index 00000000..10277208 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-word-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-word-fill.svg new file mode 100644 index 00000000..41a5ad45 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-word-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-word.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-word.svg new file mode 100644 index 00000000..1cb7ab83 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-word.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-x-fill.svg new file mode 100644 index 00000000..4c5b5b39 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-x.svg new file mode 100644 index 00000000..fc27740c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-zip-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-zip-fill.svg new file mode 100644 index 00000000..33f6c82e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-zip-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file-zip.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-zip.svg new file mode 100644 index 00000000..7860a4ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file-zip.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/file.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/file.svg new file mode 100644 index 00000000..6504fd45 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/file.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/files-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/files-alt.svg new file mode 100644 index 00000000..a019ec03 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/files-alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/files.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/files.svg new file mode 100644 index 00000000..e08eb2fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/files.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-aac.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-aac.svg new file mode 100644 index 00000000..a5e58d50 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-aac.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ai.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ai.svg new file mode 100644 index 00000000..5116a7d1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ai.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-bmp.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-bmp.svg new file mode 100644 index 00000000..41f8dde7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-bmp.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-cs.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-cs.svg new file mode 100644 index 00000000..2f9d98d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-cs.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-css.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-css.svg new file mode 100644 index 00000000..69e00c3f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-css.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-csv.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-csv.svg new file mode 100644 index 00000000..a800f151 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-csv.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-doc.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-doc.svg new file mode 100644 index 00000000..035795fe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-doc.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-docx.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-docx.svg new file mode 100644 index 00000000..6186a5ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-docx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-exe.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-exe.svg new file mode 100644 index 00000000..eb53980d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-exe.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-gif.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-gif.svg new file mode 100644 index 00000000..a9db28f2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-gif.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-heic.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-heic.svg new file mode 100644 index 00000000..29278528 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-heic.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-html.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-html.svg new file mode 100644 index 00000000..4f6a3325 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-html.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-java.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-java.svg new file mode 100644 index 00000000..907504cd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-java.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-jpg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-jpg.svg new file mode 100644 index 00000000..17c9c519 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-jpg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-js.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-js.svg new file mode 100644 index 00000000..2b56f006 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-js.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-json.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-json.svg new file mode 100644 index 00000000..47582ba8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-json.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-jsx.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-jsx.svg new file mode 100644 index 00000000..34e2401e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-jsx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-key.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-key.svg new file mode 100644 index 00000000..53c98730 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-key.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-m4p.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-m4p.svg new file mode 100644 index 00000000..61856a2e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-m4p.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-md.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-md.svg new file mode 100644 index 00000000..cacd0ae2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-md.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mdx.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mdx.svg new file mode 100644 index 00000000..154017ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mdx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mov.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mov.svg new file mode 100644 index 00000000..ccaea6d7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mov.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mp3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mp3.svg new file mode 100644 index 00000000..611cda84 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mp3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mp4.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mp4.svg new file mode 100644 index 00000000..ea2d9518 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-mp4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-otf.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-otf.svg new file mode 100644 index 00000000..ef991ffb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-otf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-pdf.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-pdf.svg new file mode 100644 index 00000000..093affe7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-pdf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-php.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-php.svg new file mode 100644 index 00000000..22da3d4f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-php.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-png.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-png.svg new file mode 100644 index 00000000..f1232306 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-png.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ppt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ppt.svg new file mode 100644 index 00000000..9c852717 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ppt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-pptx.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-pptx.svg new file mode 100644 index 00000000..7ae9adea --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-pptx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-psd.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-psd.svg new file mode 100644 index 00000000..3b66c801 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-psd.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-py.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-py.svg new file mode 100644 index 00000000..bf490ff7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-py.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-raw.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-raw.svg new file mode 100644 index 00000000..6e3abdc2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-raw.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-rb.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-rb.svg new file mode 100644 index 00000000..5b4b09fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-rb.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sass.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sass.svg new file mode 100644 index 00000000..f377204e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sass.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-scss.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-scss.svg new file mode 100644 index 00000000..b9ddfb82 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-scss.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sh.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sh.svg new file mode 100644 index 00000000..a99f8291 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sh.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sql.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sql.svg new file mode 100644 index 00000000..37ecdf76 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-sql.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-svg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-svg.svg new file mode 100644 index 00000000..31eef0bf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-svg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-tiff.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-tiff.svg new file mode 100644 index 00000000..df5f8974 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-tiff.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-tsx.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-tsx.svg new file mode 100644 index 00000000..fd60cff0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-tsx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ttf.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ttf.svg new file mode 100644 index 00000000..4f66f1d7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-ttf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-txt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-txt.svg new file mode 100644 index 00000000..24a98ba3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-txt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-wav.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-wav.svg new file mode 100644 index 00000000..539e73c0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-wav.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-woff.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-woff.svg new file mode 100644 index 00000000..2db38ac2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-woff.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xls.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xls.svg new file mode 100644 index 00000000..7c3669c4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xls.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xlsx.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xlsx.svg new file mode 100644 index 00000000..73925540 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xlsx.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xml.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xml.svg new file mode 100644 index 00000000..80edbfd0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-xml.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-yml.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-yml.svg new file mode 100644 index 00000000..c0c6e79b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filetype-yml.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/film.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/film.svg new file mode 100644 index 00000000..fa8ba5fe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/film.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-circle-fill.svg new file mode 100644 index 00000000..338c54f8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-circle.svg new file mode 100644 index 00000000..096eeaa5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-left.svg new file mode 100644 index 00000000..6ca2224c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-right.svg new file mode 100644 index 00000000..724f248d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-square-fill.svg new file mode 100644 index 00000000..bcab13eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-square.svg new file mode 100644 index 00000000..5fa1698f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/filter.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter.svg new file mode 100644 index 00000000..fc1ae38a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/filter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fingerprint.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fingerprint.svg new file mode 100644 index 00000000..5b9375f2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fingerprint.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fire.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fire.svg new file mode 100644 index 00000000..889eaf16 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fire.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flag-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flag-fill.svg new file mode 100644 index 00000000..1387cb20 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flag-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flag.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flag.svg new file mode 100644 index 00000000..980008f5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flag.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-fill.svg new file mode 100644 index 00000000..a907fb95 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-florence-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-florence-fill.svg new file mode 100644 index 00000000..6d163c98 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-florence-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-florence.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-florence.svg new file mode 100644 index 00000000..f68452d3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flask-florence.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flask.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flask.svg new file mode 100644 index 00000000..d310ba73 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flask.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy-fill.svg new file mode 100644 index 00000000..273238fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy.svg new file mode 100644 index 00000000..a43865fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy2-fill.svg new file mode 100644 index 00000000..fa2800f9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy2.svg new file mode 100644 index 00000000..08c29780 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/floppy2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flower1.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flower1.svg new file mode 100644 index 00000000..4328ee38 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flower1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flower2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flower2.svg new file mode 100644 index 00000000..c53a3cc6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flower2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/flower3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/flower3.svg new file mode 100644 index 00000000..c7dbe5a8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/flower3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-check.svg new file mode 100644 index 00000000..a0e0e6df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-fill.svg new file mode 100644 index 00000000..1fcf91e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-minus.svg new file mode 100644 index 00000000..54d3de75 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-plus.svg new file mode 100644 index 00000000..2cb0d18b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-symlink-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-symlink-fill.svg new file mode 100644 index 00000000..b82da98f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-symlink-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-symlink.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-symlink.svg new file mode 100644 index 00000000..583fa1aa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-symlink.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-x.svg new file mode 100644 index 00000000..e0009bdd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder.svg new file mode 100644 index 00000000..667f5a6b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder2-open.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder2-open.svg new file mode 100644 index 00000000..bc9e1a79 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder2-open.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/folder2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder2.svg new file mode 100644 index 00000000..39f8911c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/folder2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts.svg new file mode 100644 index 00000000..7f7b4faf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts/bootstrap-icons.woff b/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts/bootstrap-icons.woff new file mode 100644 index 00000000..a4fa4f02 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts/bootstrap-icons.woff differ diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts/bootstrap-icons.woff2 b/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts/bootstrap-icons.woff2 new file mode 100644 index 00000000..4d8c490e Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/core/icons/fonts/bootstrap-icons.woff2 differ diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fork-knife.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fork-knife.svg new file mode 100644 index 00000000..8ec2a066 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fork-knife.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/forward-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/forward-fill.svg new file mode 100644 index 00000000..6413d7dd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/forward-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/forward.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/forward.svg new file mode 100644 index 00000000..20cc05d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/forward.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/front.svg new file mode 100644 index 00000000..c64f3aa5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/front.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-diesel-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-diesel-fill.svg new file mode 100644 index 00000000..c3038ed7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-diesel-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-diesel.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-diesel.svg new file mode 100644 index 00000000..3ea136e3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-diesel.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-fill.svg new file mode 100644 index 00000000..3dcb7a2f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump.svg new file mode 100644 index 00000000..eb98a976 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fuel-pump.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fullscreen-exit.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fullscreen-exit.svg new file mode 100644 index 00000000..3fb6655c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fullscreen-exit.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/fullscreen.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/fullscreen.svg new file mode 100644 index 00000000..f1701ee3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/fullscreen.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/funnel-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/funnel-fill.svg new file mode 100644 index 00000000..440cd285 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/funnel-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/funnel.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/funnel.svg new file mode 100644 index 00000000..f8906a59 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/funnel.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-fill.svg new file mode 100644 index 00000000..a0e88a05 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-wide-connected.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-wide-connected.svg new file mode 100644 index 00000000..88e6ff7b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-wide-connected.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-wide.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-wide.svg new file mode 100644 index 00000000..f962f34b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gear-wide.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gear.svg new file mode 100644 index 00000000..6cd0bc84 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gem.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gem.svg new file mode 100644 index 00000000..30e15990 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gem.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-ambiguous.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-ambiguous.svg new file mode 100644 index 00000000..f6737d61 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-ambiguous.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-female.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-female.svg new file mode 100644 index 00000000..d152bdd2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-female.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-male.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-male.svg new file mode 100644 index 00000000..838ad00c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-male.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-neuter.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-neuter.svg new file mode 100644 index 00000000..5d175acf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-neuter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-trans.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-trans.svg new file mode 100644 index 00000000..6d2369ba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gender-trans.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-alt-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-alt-fill.svg new file mode 100644 index 00000000..ba95e33d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-alt-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-alt.svg new file mode 100644 index 00000000..046251c8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-alt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-fill.svg new file mode 100644 index 00000000..64faefe2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/geo-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/geo.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/geo.svg new file mode 100644 index 00000000..178caaed --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/geo.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gift-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gift-fill.svg new file mode 100644 index 00000000..3d831129 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gift-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gift.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gift.svg new file mode 100644 index 00000000..ceec17cc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gift.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/git.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/git.svg new file mode 100644 index 00000000..abf5db37 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/git.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/github.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/github.svg new file mode 100644 index 00000000..b3e91c88 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/github.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gitlab.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gitlab.svg new file mode 100644 index 00000000..51d36d58 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gitlab.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-americas-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-americas-fill.svg new file mode 100644 index 00000000..df4740fa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-americas-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-americas.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-americas.svg new file mode 100644 index 00000000..4acda64b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-americas.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-asia-australia-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-asia-australia-fill.svg new file mode 100644 index 00000000..63411998 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-asia-australia-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-asia-australia.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-asia-australia.svg new file mode 100644 index 00000000..e9cd1e4d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-asia-australia.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-central-south-asia-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-central-south-asia-fill.svg new file mode 100644 index 00000000..7956ccd6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-central-south-asia-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-central-south-asia.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-central-south-asia.svg new file mode 100644 index 00000000..1f70d7f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-central-south-asia.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-europe-africa-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-europe-africa-fill.svg new file mode 100644 index 00000000..621bc566 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-europe-africa-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-europe-africa.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-europe-africa.svg new file mode 100644 index 00000000..4e5a5e1f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe-europe-africa.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe.svg new file mode 100644 index 00000000..4fdbb1f1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/globe2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe2.svg new file mode 100644 index 00000000..e2b07880 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/globe2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/google-play.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/google-play.svg new file mode 100644 index 00000000..10c6649f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/google-play.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/google.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/google.svg new file mode 100644 index 00000000..be86f6e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/google.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/gpu-card.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/gpu-card.svg new file mode 100644 index 00000000..41663050 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/gpu-card.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-down-arrow.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-down-arrow.svg new file mode 100644 index 00000000..3fee3999 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-down-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-down.svg new file mode 100644 index 00000000..a78d2f15 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-up-arrow.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-up-arrow.svg new file mode 100644 index 00000000..90980fd5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-up-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-up.svg new file mode 100644 index 00000000..6c6203d6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/graph-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-1x2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-1x2-fill.svg new file mode 100644 index 00000000..5424db93 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-1x2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-1x2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-1x2.svg new file mode 100644 index 00000000..14b3381e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-1x2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2-gap-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2-gap-fill.svg new file mode 100644 index 00000000..6b4ccab0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2-gap-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2-gap.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2-gap.svg new file mode 100644 index 00000000..705ea842 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2-gap.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2.svg new file mode 100644 index 00000000..7191c9fe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3-gap-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3-gap-fill.svg new file mode 100644 index 00000000..1af175d4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3-gap-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3-gap.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3-gap.svg new file mode 100644 index 00000000..4c010dda --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3-gap.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3.svg new file mode 100644 index 00000000..67d1ed5c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-3x3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-fill.svg new file mode 100644 index 00000000..2ae61efd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grid.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid.svg new file mode 100644 index 00000000..0174fbf2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grid.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grip-horizontal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grip-horizontal.svg new file mode 100644 index 00000000..faca8516 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grip-horizontal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/grip-vertical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/grip-vertical.svg new file mode 100644 index 00000000..b84346f6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/grip-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/h-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/h-circle-fill.svg new file mode 100644 index 00000000..6b6760a0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/h-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/h-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/h-circle.svg new file mode 100644 index 00000000..93803be6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/h-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/h-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/h-square-fill.svg new file mode 100644 index 00000000..071904aa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/h-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/h-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/h-square.svg new file mode 100644 index 00000000..19933fdc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/h-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hammer.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hammer.svg new file mode 100644 index 00000000..d1f5ecfd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hammer.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-fill.svg new file mode 100644 index 00000000..234e3cfb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-thumb-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-thumb-fill.svg new file mode 100644 index 00000000..cd37f39a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-thumb-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-thumb.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-thumb.svg new file mode 100644 index 00000000..b96dea55 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index-thumb.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index.svg new file mode 100644 index 00000000..3532e65c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-index.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-down-fill.svg new file mode 100644 index 00000000..156f8f13 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-down.svg new file mode 100644 index 00000000..50bb0af7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-up-fill.svg new file mode 100644 index 00000000..da08e560 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-up-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-up.svg new file mode 100644 index 00000000..2f1e3bf6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hand-thumbs-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/handbag-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/handbag-fill.svg new file mode 100644 index 00000000..caf651f5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/handbag-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/handbag.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/handbag.svg new file mode 100644 index 00000000..be7699a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/handbag.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hash.svg new file mode 100644 index 00000000..0388f214 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-fill.svg new file mode 100644 index 00000000..682f2bc1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-network-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-network-fill.svg new file mode 100644 index 00000000..8adf6484 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-network-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-network.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-network.svg new file mode 100644 index 00000000..690bc0fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-network.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-rack-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-rack-fill.svg new file mode 100644 index 00000000..06966949 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-rack-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-rack.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-rack.svg new file mode 100644 index 00000000..c98d8e20 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-rack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-stack-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-stack-fill.svg new file mode 100644 index 00000000..4d67e5e8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-stack-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-stack.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-stack.svg new file mode 100644 index 00000000..3b4fbab3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd-stack.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd.svg new file mode 100644 index 00000000..596dc38c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdd.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdmi-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdmi-fill.svg new file mode 100644 index 00000000..1929b1be --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdmi-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hdmi.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdmi.svg new file mode 100644 index 00000000..2427a9ce --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hdmi.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/headphones.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/headphones.svg new file mode 100644 index 00000000..1696ead9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/headphones.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/headset-vr.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/headset-vr.svg new file mode 100644 index 00000000..ca8e7300 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/headset-vr.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/headset.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/headset.svg new file mode 100644 index 00000000..82e2634b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/headset.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-arrow.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-arrow.svg new file mode 100644 index 00000000..1bc2b95a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-arrow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-fill.svg new file mode 100644 index 00000000..e2eb9807 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-half.svg new file mode 100644 index 00000000..09517d44 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-pulse-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-pulse-fill.svg new file mode 100644 index 00000000..75a00f34 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-pulse-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-pulse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-pulse.svg new file mode 100644 index 00000000..77e966a7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart-pulse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart.svg new file mode 100644 index 00000000..f0fdd80f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heartbreak-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heartbreak-fill.svg new file mode 100644 index 00000000..14228096 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heartbreak-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heartbreak.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heartbreak.svg new file mode 100644 index 00000000..7b654ca1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heartbreak.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hearts.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hearts.svg new file mode 100644 index 00000000..2bb9b77d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hearts.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon-fill.svg new file mode 100644 index 00000000..863928d3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon-half.svg new file mode 100644 index 00000000..59f08166 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon.svg new file mode 100644 index 00000000..bd97be8c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/heptagon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon-fill.svg new file mode 100644 index 00000000..0b217f83 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon-half.svg new file mode 100644 index 00000000..c61e536d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon.svg new file mode 100644 index 00000000..febd0929 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hexagon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/highlighter.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/highlighter.svg new file mode 100644 index 00000000..f73c070c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/highlighter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/highlights.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/highlights.svg new file mode 100644 index 00000000..ae39ba9b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/highlights.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hospital-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hospital-fill.svg new file mode 100644 index 00000000..dc5a3989 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hospital-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hospital.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hospital.svg new file mode 100644 index 00000000..c03e7bd8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hospital.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-bottom.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-bottom.svg new file mode 100644 index 00000000..43bcc948 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-bottom.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-split.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-split.svg new file mode 100644 index 00000000..3f2bf1a4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-split.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-top.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-top.svg new file mode 100644 index 00000000..744689e7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass-top.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass.svg new file mode 100644 index 00000000..391344af --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hourglass.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-add-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-add-fill.svg new file mode 100644 index 00000000..791e1c5d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-add-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-add.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-add.svg new file mode 100644 index 00000000..32e9933c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-check-fill.svg new file mode 100644 index 00000000..b55c22cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-check-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-check.svg new file mode 100644 index 00000000..89cb7b1c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-dash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-dash-fill.svg new file mode 100644 index 00000000..23e6239e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-dash-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-dash.svg new file mode 100644 index 00000000..a9f43a57 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-door-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-door-fill.svg new file mode 100644 index 00000000..6bf50cab --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-door-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-door.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-door.svg new file mode 100644 index 00000000..1805cb18 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-door.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-down-fill.svg new file mode 100644 index 00000000..c442663f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-down-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-down.svg new file mode 100644 index 00000000..1434079b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-exclamation-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-exclamation-fill.svg new file mode 100644 index 00000000..fabbef4b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-exclamation-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-exclamation.svg new file mode 100644 index 00000000..fe624631 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-fill.svg new file mode 100644 index 00000000..78600749 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-gear-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-gear-fill.svg new file mode 100644 index 00000000..6d713d27 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-gear-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-gear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-gear.svg new file mode 100644 index 00000000..4816aba9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-gear.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-heart-fill.svg new file mode 100644 index 00000000..a9a59524 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-heart.svg new file mode 100644 index 00000000..b71f191c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-lock-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-lock-fill.svg new file mode 100644 index 00000000..9a52b5bf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-lock-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-lock.svg new file mode 100644 index 00000000..b85f0533 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-slash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-slash-fill.svg new file mode 100644 index 00000000..1978aeef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-slash-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-slash.svg new file mode 100644 index 00000000..81f51b4f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-up-fill.svg new file mode 100644 index 00000000..4583df29 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-up-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-up.svg new file mode 100644 index 00000000..a6dc1f05 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-x-fill.svg new file mode 100644 index 00000000..843fe3cb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-x-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-x.svg new file mode 100644 index 00000000..b131fd71 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/house.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/house.svg new file mode 100644 index 00000000..0441f47c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/house.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/houses-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/houses-fill.svg new file mode 100644 index 00000000..180daabe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/houses-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/houses.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/houses.svg new file mode 100644 index 00000000..55072a67 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/houses.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hr.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hr.svg new file mode 100644 index 00000000..449a959e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hr.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hurricane.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hurricane.svg new file mode 100644 index 00000000..3fb068e4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hurricane.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/hypnotize.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/hypnotize.svg new file mode 100644 index 00000000..ac4857ac --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/hypnotize.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/image-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/image-alt.svg new file mode 100644 index 00000000..d0d3360d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/image-alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/image-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/image-fill.svg new file mode 100644 index 00000000..c7f206da --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/image-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/image.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/image.svg new file mode 100644 index 00000000..b72aa821 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/image.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/images.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/images.svg new file mode 100644 index 00000000..096a178b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/images.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/inbox-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/inbox-fill.svg new file mode 100644 index 00000000..e26d5e0a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/inbox-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/inbox.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/inbox.svg new file mode 100644 index 00000000..ac018f26 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/inbox.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/inboxes-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/inboxes-fill.svg new file mode 100644 index 00000000..621e6fa7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/inboxes-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/inboxes.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/inboxes.svg new file mode 100644 index 00000000..2a5ed7b4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/inboxes.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/incognito.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/incognito.svg new file mode 100644 index 00000000..b2ebb921 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/incognito.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/indent.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/indent.svg new file mode 100644 index 00000000..735978a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/indent.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/infinity.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/infinity.svg new file mode 100644 index 00000000..897c5c4a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/infinity.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/info-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-circle-fill.svg new file mode 100644 index 00000000..f5679410 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/info-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-circle.svg new file mode 100644 index 00000000..4a82b5eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/info-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-lg.svg new file mode 100644 index 00000000..c42d7cdf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/info-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-square-fill.svg new file mode 100644 index 00000000..fe74563e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/info-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-square.svg new file mode 100644 index 00000000..50650fba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/info-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/info.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/info.svg new file mode 100644 index 00000000..40bc6dec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/info.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/input-cursor-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/input-cursor-text.svg new file mode 100644 index 00000000..408da037 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/input-cursor-text.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/input-cursor.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/input-cursor.svg new file mode 100644 index 00000000..2aae276e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/input-cursor.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/instagram.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/instagram.svg new file mode 100644 index 00000000..3e852866 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/instagram.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/intersect.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/intersect.svg new file mode 100644 index 00000000..3a5568c9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/intersect.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/javascript.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/javascript.svg new file mode 100644 index 00000000..ea1a3e54 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/javascript.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-album.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-album.svg new file mode 100644 index 00000000..34fd21ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-album.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-arrow-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-arrow-down.svg new file mode 100644 index 00000000..aed79bdf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-arrow-down.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-arrow-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-arrow-up.svg new file mode 100644 index 00000000..5276fe53 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-arrow-up.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-bookmark-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-bookmark-fill.svg new file mode 100644 index 00000000..d4eae576 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-bookmark-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-bookmark.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-bookmark.svg new file mode 100644 index 00000000..db4129fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-bookmark.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-check.svg new file mode 100644 index 00000000..f7663346 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-check.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-code.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-code.svg new file mode 100644 index 00000000..97704cb2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-code.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-medical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-medical.svg new file mode 100644 index 00000000..90579a74 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-medical.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-minus.svg new file mode 100644 index 00000000..ea541e1f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-minus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-plus.svg new file mode 100644 index 00000000..0710e3fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-richtext.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-richtext.svg new file mode 100644 index 00000000..d3449133 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-richtext.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-text.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-text.svg new file mode 100644 index 00000000..44e8bc08 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-text.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-x.svg new file mode 100644 index 00000000..9ede12cd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal.svg new file mode 100644 index 00000000..3516aa04 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journal.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/journals.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/journals.svg new file mode 100644 index 00000000..a3d2b425 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/journals.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/joystick.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/joystick.svg new file mode 100644 index 00000000..bea38879 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/joystick.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/justify-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/justify-left.svg new file mode 100644 index 00000000..58572b00 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/justify-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/justify-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/justify-right.svg new file mode 100644 index 00000000..3183a645 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/justify-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/justify.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/justify.svg new file mode 100644 index 00000000..7513201c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/justify.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/kanban-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/kanban-fill.svg new file mode 100644 index 00000000..d4746784 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/kanban-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/kanban.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/kanban.svg new file mode 100644 index 00000000..2b362880 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/kanban.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/key-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/key-fill.svg new file mode 100644 index 00000000..c75ff769 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/key-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/key.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/key.svg new file mode 100644 index 00000000..1f8f002f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/key.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/keyboard-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/keyboard-fill.svg new file mode 100644 index 00000000..c1449709 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/keyboard-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/keyboard.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/keyboard.svg new file mode 100644 index 00000000..970b5c28 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/keyboard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ladder.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ladder.svg new file mode 100644 index 00000000..d2d6d248 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ladder.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lamp-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lamp-fill.svg new file mode 100644 index 00000000..1703462b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lamp-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lamp.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lamp.svg new file mode 100644 index 00000000..01e4a116 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lamp.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/laptop-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/laptop-fill.svg new file mode 100644 index 00000000..b2cbcd22 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/laptop-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/laptop.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/laptop.svg new file mode 100644 index 00000000..81f02d43 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/laptop.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layer-backward.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layer-backward.svg new file mode 100644 index 00000000..15604afe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layer-backward.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layer-forward.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layer-forward.svg new file mode 100644 index 00000000..9721632f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layer-forward.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layers-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layers-fill.svg new file mode 100644 index 00000000..ad6bdbc8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layers-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layers-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layers-half.svg new file mode 100644 index 00000000..6e6a5d9c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layers-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layers.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layers.svg new file mode 100644 index 00000000..aaeb5d29 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layers.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-inset-reverse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-inset-reverse.svg new file mode 100644 index 00000000..7d936c8e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-inset-reverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-inset.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-inset.svg new file mode 100644 index 00000000..029169cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-inset.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-reverse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-reverse.svg new file mode 100644 index 00000000..0f891d41 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar-reverse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar.svg new file mode 100644 index 00000000..09dcd0ef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-sidebar.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-split.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-split.svg new file mode 100644 index 00000000..4e4a1181 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-split.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-sidebar-reverse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-sidebar-reverse.svg new file mode 100644 index 00000000..4cfa0b55 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-sidebar-reverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-sidebar.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-sidebar.svg new file mode 100644 index 00000000..a8452e6f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-sidebar.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-window-reverse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-window-reverse.svg new file mode 100644 index 00000000..bc6d53a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-window-reverse.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-window.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-window.svg new file mode 100644 index 00000000..3197a45e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-text-window.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-three-columns.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-three-columns.svg new file mode 100644 index 00000000..0015852a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-three-columns.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-wtf.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-wtf.svg new file mode 100644 index 00000000..349396df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/layout-wtf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/leaf-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/leaf-fill.svg new file mode 100644 index 00000000..9aec52f7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/leaf-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/leaf.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/leaf.svg new file mode 100644 index 00000000..4499411c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/leaf.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/life-preserver.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/life-preserver.svg new file mode 100644 index 00000000..d27e1f4c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/life-preserver.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-fill.svg new file mode 100644 index 00000000..74c071c0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-off-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-off-fill.svg new file mode 100644 index 00000000..757ca59f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-off-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-off.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-off.svg new file mode 100644 index 00000000..2d2d14a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb.svg new file mode 100644 index 00000000..bea8b867 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightbulb.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-charge-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-charge-fill.svg new file mode 100644 index 00000000..7021f2da --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-charge-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-charge.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-charge.svg new file mode 100644 index 00000000..45a8397c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-charge.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-fill.svg new file mode 100644 index 00000000..2e4d6850 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning.svg new file mode 100644 index 00000000..003e8bed --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lightning.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/line.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/line.svg new file mode 100644 index 00000000..c477de7a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/line.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/link-45deg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/link-45deg.svg new file mode 100644 index 00000000..1ce37411 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/link-45deg.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/link.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/link.svg new file mode 100644 index 00000000..fdc879d5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/link.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/linkedin.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/linkedin.svg new file mode 100644 index 00000000..d740ffa5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/linkedin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-check.svg new file mode 100644 index 00000000..27d500f4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list-columns-reverse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-columns-reverse.svg new file mode 100644 index 00000000..3d530915 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-columns-reverse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list-columns.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-columns.svg new file mode 100644 index 00000000..7f290d2a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-columns.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list-nested.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-nested.svg new file mode 100644 index 00000000..99b526b8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-nested.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list-ol.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-ol.svg new file mode 100644 index 00000000..15b29441 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-ol.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list-stars.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-stars.svg new file mode 100644 index 00000000..9bfc5f09 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-stars.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list-task.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-task.svg new file mode 100644 index 00000000..c13e1d71 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-task.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list-ul.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-ul.svg new file mode 100644 index 00000000..7e7b28b2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list-ul.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/list.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/list.svg new file mode 100644 index 00000000..ce9e86b0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/list.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lock-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lock-fill.svg new file mode 100644 index 00000000..deef2bae --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lock.svg new file mode 100644 index 00000000..602a5afb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/luggage-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/luggage-fill.svg new file mode 100644 index 00000000..833aa318 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/luggage-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/luggage.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/luggage.svg new file mode 100644 index 00000000..e2b86ef7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/luggage.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lungs-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lungs-fill.svg new file mode 100644 index 00000000..af4edf1b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lungs-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/lungs.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/lungs.svg new file mode 100644 index 00000000..b53a3c45 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/lungs.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/magic.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/magic.svg new file mode 100644 index 00000000..c67996cc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/magic.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/magnet-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/magnet-fill.svg new file mode 100644 index 00000000..31ca4e55 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/magnet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/magnet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/magnet.svg new file mode 100644 index 00000000..fef8fd0b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/magnet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox-flag.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox-flag.svg new file mode 100644 index 00000000..1211ab9a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox-flag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox.svg new file mode 100644 index 00000000..5dce6a39 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox2-flag.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox2-flag.svg new file mode 100644 index 00000000..560dc03b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox2-flag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox2.svg new file mode 100644 index 00000000..44c090d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mailbox2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/map-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/map-fill.svg new file mode 100644 index 00000000..73031ff9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/map-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/map.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/map.svg new file mode 100644 index 00000000..351042e8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/map.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/markdown-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/markdown-fill.svg new file mode 100644 index 00000000..4a22f840 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/markdown-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/markdown.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/markdown.svg new file mode 100644 index 00000000..bac4ecb0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/markdown.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/marker-tip.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/marker-tip.svg new file mode 100644 index 00000000..8770cc82 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/marker-tip.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mask.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mask.svg new file mode 100644 index 00000000..99e06187 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mask.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mastodon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mastodon.svg new file mode 100644 index 00000000..437b2144 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mastodon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/measuring-cup-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/measuring-cup-fill.svg new file mode 100644 index 00000000..d4f4b861 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/measuring-cup-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/measuring-cup.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/measuring-cup.svg new file mode 100644 index 00000000..8d9e56a2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/measuring-cup.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/medium.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/medium.svg new file mode 100644 index 00000000..55c79b28 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/medium.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/megaphone-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/megaphone-fill.svg new file mode 100644 index 00000000..1ce52280 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/megaphone-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/megaphone.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/megaphone.svg new file mode 100644 index 00000000..8ae2587c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/megaphone.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/memory.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/memory.svg new file mode 100644 index 00000000..fb0cba82 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/memory.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-app-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-app-fill.svg new file mode 100644 index 00000000..826e4405 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-app-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-app.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-app.svg new file mode 100644 index 00000000..c1ebe2b2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-app.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-fill.svg new file mode 100644 index 00000000..b9ffcfd8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-wide-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-wide-fill.svg new file mode 100644 index 00000000..7733cef6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-wide-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-wide.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-wide.svg new file mode 100644 index 00000000..118dad33 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button-wide.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button.svg new file mode 100644 index 00000000..17de9912 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-button.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-down.svg new file mode 100644 index 00000000..bf709e6d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-up.svg new file mode 100644 index 00000000..23c4a820 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/menu-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/messenger.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/messenger.svg new file mode 100644 index 00000000..ceee32f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/messenger.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/meta.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/meta.svg new file mode 100644 index 00000000..cb082c10 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/meta.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-fill.svg new file mode 100644 index 00000000..e18f419d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-mute-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-mute-fill.svg new file mode 100644 index 00000000..3ff86309 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-mute-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-mute.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-mute.svg new file mode 100644 index 00000000..23ddb03f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mic-mute.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mic.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mic.svg new file mode 100644 index 00000000..5792f8e8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mic.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/microsoft-teams.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/microsoft-teams.svg new file mode 100644 index 00000000..c7f99ac9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/microsoft-teams.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/microsoft.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/microsoft.svg new file mode 100644 index 00000000..ca7379b5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/microsoft.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/minecart-loaded.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/minecart-loaded.svg new file mode 100644 index 00000000..07fe80cb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/minecart-loaded.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/minecart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/minecart.svg new file mode 100644 index 00000000..8de1f1ce --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/minecart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/modem-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/modem-fill.svg new file mode 100644 index 00000000..7d512c22 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/modem-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/modem.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/modem.svg new file mode 100644 index 00000000..b9266bfe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/modem.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/moisture.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/moisture.svg new file mode 100644 index 00000000..8867b3c4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/moisture.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-fill.svg new file mode 100644 index 00000000..a9d2e158 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-stars-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-stars-fill.svg new file mode 100644 index 00000000..89ea0db1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-stars-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-stars.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-stars.svg new file mode 100644 index 00000000..2e25448f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/moon-stars.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/moon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/moon.svg new file mode 100644 index 00000000..dbbe637d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/moon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mortarboard-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mortarboard-fill.svg new file mode 100644 index 00000000..3f9a8fe9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mortarboard-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mortarboard.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mortarboard.svg new file mode 100644 index 00000000..f9e41242 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mortarboard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/motherboard-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/motherboard-fill.svg new file mode 100644 index 00000000..89c68ba5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/motherboard-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/motherboard.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/motherboard.svg new file mode 100644 index 00000000..d904e525 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/motherboard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse-fill.svg new file mode 100644 index 00000000..716f73dc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse.svg new file mode 100644 index 00000000..becf38b4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse2-fill.svg new file mode 100644 index 00000000..d8c5b9e7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse2.svg new file mode 100644 index 00000000..7848c2bf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse3-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse3-fill.svg new file mode 100644 index 00000000..a726d0d2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse3.svg new file mode 100644 index 00000000..52f6912a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/mouse3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note-beamed.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note-beamed.svg new file mode 100644 index 00000000..718e5073 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note-beamed.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note-list.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note-list.svg new file mode 100644 index 00000000..f65e230b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note-list.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note.svg new file mode 100644 index 00000000..b2aedb52 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-note.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/music-player-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-player-fill.svg new file mode 100644 index 00000000..6f703d03 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-player-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/music-player.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-player.svg new file mode 100644 index 00000000..fdca6047 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/music-player.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/newspaper.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/newspaper.svg new file mode 100644 index 00000000..ab7fc7b9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/newspaper.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/nintendo-switch.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/nintendo-switch.svg new file mode 100644 index 00000000..54311d7d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/nintendo-switch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/node-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/node-minus-fill.svg new file mode 100644 index 00000000..690b7ac0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/node-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/node-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/node-minus.svg new file mode 100644 index 00000000..b021918e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/node-minus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/node-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/node-plus-fill.svg new file mode 100644 index 00000000..6f98a60e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/node-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/node-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/node-plus.svg new file mode 100644 index 00000000..4eb1ef1d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/node-plus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/noise-reduction.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/noise-reduction.svg new file mode 100644 index 00000000..21462a8e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/noise-reduction.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/nut-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/nut-fill.svg new file mode 100644 index 00000000..ae49fc89 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/nut-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/nut.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/nut.svg new file mode 100644 index 00000000..1266e5ec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/nut.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/nvidia.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/nvidia.svg new file mode 100644 index 00000000..d13952a5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/nvidia.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/nvme-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/nvme-fill.svg new file mode 100644 index 00000000..71b360c6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/nvme-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/nvme.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/nvme.svg new file mode 100644 index 00000000..1f614c35 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/nvme.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon-fill.svg new file mode 100644 index 00000000..722a5a59 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon-half.svg new file mode 100644 index 00000000..07822481 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon.svg new file mode 100644 index 00000000..98a86af2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/octagon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/openai.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/openai.svg new file mode 100644 index 00000000..fe7c602f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/openai.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/opencollective.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/opencollective.svg new file mode 100644 index 00000000..0113a922 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/opencollective.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/optical-audio-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/optical-audio-fill.svg new file mode 100644 index 00000000..055c5fe7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/optical-audio-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/optical-audio.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/optical-audio.svg new file mode 100644 index 00000000..aa431b3e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/optical-audio.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/option.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/option.svg new file mode 100644 index 00000000..ba10d25d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/option.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/outlet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/outlet.svg new file mode 100644 index 00000000..473dc1e6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/outlet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/p-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/p-circle-fill.svg new file mode 100644 index 00000000..cfc4347d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/p-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/p-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/p-circle.svg new file mode 100644 index 00000000..89048864 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/p-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/p-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/p-square-fill.svg new file mode 100644 index 00000000..09db5b83 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/p-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/p-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/p-square.svg new file mode 100644 index 00000000..12274fbb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/p-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/paint-bucket.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/paint-bucket.svg new file mode 100644 index 00000000..f1f6c97c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/paint-bucket.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/palette-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/palette-fill.svg new file mode 100644 index 00000000..7f47cf6c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/palette-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/palette.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/palette.svg new file mode 100644 index 00000000..941a7e44 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/palette.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/palette2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/palette2.svg new file mode 100644 index 00000000..29436e3e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/palette2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/paperclip.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/paperclip.svg new file mode 100644 index 00000000..087fb329 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/paperclip.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/paragraph.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/paragraph.svg new file mode 100644 index 00000000..6f694d0e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/paragraph.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pass-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pass-fill.svg new file mode 100644 index 00000000..41d11ee8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pass-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pass.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pass.svg new file mode 100644 index 00000000..283198e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pass.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/passport-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/passport-fill.svg new file mode 100644 index 00000000..a7a38e33 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/passport-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/passport.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/passport.svg new file mode 100644 index 00000000..0b541bff --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/passport.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-check-fill.svg new file mode 100644 index 00000000..0c090725 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-check-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-check.svg new file mode 100644 index 00000000..c2909f54 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-exclamation-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-exclamation-fill.svg new file mode 100644 index 00000000..e0545529 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-exclamation-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-exclamation.svg new file mode 100644 index 00000000..7cd27af3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-minus-fill.svg new file mode 100644 index 00000000..d230be0d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-minus.svg new file mode 100644 index 00000000..5e871d7d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-plus-fill.svg new file mode 100644 index 00000000..0022e971 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-plus.svg new file mode 100644 index 00000000..2b35e9ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-question-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-question-fill.svg new file mode 100644 index 00000000..108157a2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-question-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-question.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-question.svg new file mode 100644 index 00000000..8ccf8804 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/patch-question.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-btn-fill.svg new file mode 100644 index 00000000..b6c90b83 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-btn.svg new file mode 100644 index 00000000..6daf1cda --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-circle-fill.svg new file mode 100644 index 00000000..970ce484 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-circle.svg new file mode 100644 index 00000000..7387a254 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-fill.svg new file mode 100644 index 00000000..e817993c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pause.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause.svg new file mode 100644 index 00000000..90f59b94 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pause.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/paypal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/paypal.svg new file mode 100644 index 00000000..a8b189b5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/paypal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-display-horizontal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-display-horizontal.svg new file mode 100644 index 00000000..99c04b49 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-display-horizontal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-display.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-display.svg new file mode 100644 index 00000000..edb76c12 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-display.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-horizontal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-horizontal.svg new file mode 100644 index 00000000..e4769f67 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pc-horizontal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pc.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pc.svg new file mode 100644 index 00000000..eb4ae795 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pc.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card-network.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card-network.svg new file mode 100644 index 00000000..ed42fd50 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card-network.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card-sound.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card-sound.svg new file mode 100644 index 00000000..93fc5242 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card-sound.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card.svg new file mode 100644 index 00000000..2d66ad00 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pci-card.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/peace-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/peace-fill.svg new file mode 100644 index 00000000..731c78b6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/peace-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/peace.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/peace.svg new file mode 100644 index 00000000..7f6343fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/peace.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pen-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pen-fill.svg new file mode 100644 index 00000000..b8909165 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pen-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pen.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pen.svg new file mode 100644 index 00000000..6efa5a54 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pen.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil-fill.svg new file mode 100644 index 00000000..a39b0cd7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil-square.svg new file mode 100644 index 00000000..a0da03ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil.svg new file mode 100644 index 00000000..b863138d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pencil.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon-fill.svg new file mode 100644 index 00000000..bf27f66c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon-half.svg new file mode 100644 index 00000000..42018d15 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon.svg new file mode 100644 index 00000000..52e85a56 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pentagon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/people-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/people-fill.svg new file mode 100644 index 00000000..57e3b54d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/people-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/people.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/people.svg new file mode 100644 index 00000000..9308209a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/people.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/percent.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/percent.svg new file mode 100644 index 00000000..aed6ab4c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/percent.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/perplexity.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/perplexity.svg new file mode 100644 index 00000000..9b9002cb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/perplexity.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-add.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-add.svg new file mode 100644 index 00000000..252a9edd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-arms-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-arms-up.svg new file mode 100644 index 00000000..5f6d8427 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-arms-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-badge-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-badge-fill.svg new file mode 100644 index 00000000..1d3cc0ef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-badge-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-badge.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-badge.svg new file mode 100644 index 00000000..51871708 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-badge.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-bounding-box.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-bounding-box.svg new file mode 100644 index 00000000..123d4504 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-bounding-box.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-check-fill.svg new file mode 100644 index 00000000..a223b5c9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-check.svg new file mode 100644 index 00000000..9cbfcb26 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-circle.svg new file mode 100644 index 00000000..087050a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-dash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-dash-fill.svg new file mode 100644 index 00000000..08042e13 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-dash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-dash.svg new file mode 100644 index 00000000..402c58ef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-down.svg new file mode 100644 index 00000000..11977579 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-exclamation.svg new file mode 100644 index 00000000..7ccba549 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-add.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-add.svg new file mode 100644 index 00000000..08b843c2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-add.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-check.svg new file mode 100644 index 00000000..f60bcbfa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-dash.svg new file mode 100644 index 00000000..8704b9ed --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-down.svg new file mode 100644 index 00000000..cf950a7a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-exclamation.svg new file mode 100644 index 00000000..5007532e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-gear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-gear.svg new file mode 100644 index 00000000..e9be1d16 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-gear.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-lock.svg new file mode 100644 index 00000000..7f9cfd99 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-lock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-slash.svg new file mode 100644 index 00000000..980edde3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-up.svg new file mode 100644 index 00000000..a9b8d505 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-x.svg new file mode 100644 index 00000000..7d48cf22 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill.svg new file mode 100644 index 00000000..45a37930 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-gear.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-gear.svg new file mode 100644 index 00000000..b0acb1c1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-gear.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-heart.svg new file mode 100644 index 00000000..3d734680 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-hearts.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-hearts.svg new file mode 100644 index 00000000..cf9d17d5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-hearts.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-lines-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-lines-fill.svg new file mode 100644 index 00000000..403e503c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-lines-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-lock.svg new file mode 100644 index 00000000..69cfea59 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-lock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-plus-fill.svg new file mode 100644 index 00000000..c35194b1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-plus.svg new file mode 100644 index 00000000..3be8a9f9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-raised-hand.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-raised-hand.svg new file mode 100644 index 00000000..41ba2714 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-raised-hand.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-rolodex.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-rolodex.svg new file mode 100644 index 00000000..c380e91b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-rolodex.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-slash.svg new file mode 100644 index 00000000..4be54164 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-square.svg new file mode 100644 index 00000000..b4404ebf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-standing-dress.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-standing-dress.svg new file mode 100644 index 00000000..4801868c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-standing-dress.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-standing.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-standing.svg new file mode 100644 index 00000000..67f2c7c7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-standing.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-up.svg new file mode 100644 index 00000000..c431fced --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-vcard-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-vcard-fill.svg new file mode 100644 index 00000000..cfed2696 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-vcard-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-vcard.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-vcard.svg new file mode 100644 index 00000000..88a7e98a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-vcard.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video.svg new file mode 100644 index 00000000..fe2f39e8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video2.svg new file mode 100644 index 00000000..f1d6d341 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video3.svg new file mode 100644 index 00000000..7468a920 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-video3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-walking.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-walking.svg new file mode 100644 index 00000000..d9c110c6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-walking.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-wheelchair.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-wheelchair.svg new file mode 100644 index 00000000..016118c2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-wheelchair.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-workspace.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-workspace.svg new file mode 100644 index 00000000..829574c2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-workspace.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-x-fill.svg new file mode 100644 index 00000000..c2982caa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-x.svg new file mode 100644 index 00000000..a9869858 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/person.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/person.svg new file mode 100644 index 00000000..fe025814 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/person.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-fill.svg new file mode 100644 index 00000000..5d3c1599 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-flip.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-flip.svg new file mode 100644 index 00000000..b1b6457d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-flip.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-landscape-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-landscape-fill.svg new file mode 100644 index 00000000..52a0e724 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-landscape-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-landscape.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-landscape.svg new file mode 100644 index 00000000..23e00a03 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-landscape.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-vibrate-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-vibrate-fill.svg new file mode 100644 index 00000000..2a3cbc54 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-vibrate-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-vibrate.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-vibrate.svg new file mode 100644 index 00000000..91878d12 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone-vibrate.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/phone.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone.svg new file mode 100644 index 00000000..ae87d935 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/phone.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pie-chart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pie-chart-fill.svg new file mode 100644 index 00000000..a60814a7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pie-chart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pie-chart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pie-chart.svg new file mode 100644 index 00000000..5863ac1e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pie-chart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/piggy-bank-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/piggy-bank-fill.svg new file mode 100644 index 00000000..13812f0c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/piggy-bank-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/piggy-bank.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/piggy-bank.svg new file mode 100644 index 00000000..5526df20 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/piggy-bank.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-angle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-angle-fill.svg new file mode 100644 index 00000000..3463f0a4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-angle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-angle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-angle.svg new file mode 100644 index 00000000..4c227338 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-angle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-fill.svg new file mode 100644 index 00000000..8b2d6e36 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-map-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-map-fill.svg new file mode 100644 index 00000000..e081d46a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-map-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-map.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-map.svg new file mode 100644 index 00000000..2a5ae62d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin-map.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pin.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin.svg new file mode 100644 index 00000000..9946219f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pinterest.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pinterest.svg new file mode 100644 index 00000000..109f30bf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pinterest.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pip-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pip-fill.svg new file mode 100644 index 00000000..ff0dae7c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pip-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/pip.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/pip.svg new file mode 100644 index 00000000..a0850086 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/pip.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/play-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-btn-fill.svg new file mode 100644 index 00000000..473884a0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/play-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-btn.svg new file mode 100644 index 00000000..0aa0db68 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/play-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-circle-fill.svg new file mode 100644 index 00000000..fd2fd724 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/play-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-circle.svg new file mode 100644 index 00000000..dba4b622 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/play-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-fill.svg new file mode 100644 index 00000000..b8d41baf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/play-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/play.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/play.svg new file mode 100644 index 00000000..668ea669 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/play.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/playstation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/playstation.svg new file mode 100644 index 00000000..a62a2b84 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/playstation.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plug-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plug-fill.svg new file mode 100644 index 00000000..c268eab4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plug-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plug.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plug.svg new file mode 100644 index 00000000..24b65084 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plug.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plugin.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plugin.svg new file mode 100644 index 00000000..414547c6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plugin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle-dotted.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle-dotted.svg new file mode 100644 index 00000000..b4a689b6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle-dotted.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle-fill.svg new file mode 100644 index 00000000..c32e677a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle.svg new file mode 100644 index 00000000..fe99ebbb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-lg.svg new file mode 100644 index 00000000..5ebf3d9b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-slash-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-slash-minus.svg new file mode 100644 index 00000000..565fb89f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-slash-minus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square-dotted.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square-dotted.svg new file mode 100644 index 00000000..fd0fe3de --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square-dotted.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square-fill.svg new file mode 100644 index 00000000..8147bac1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square.svg new file mode 100644 index 00000000..8a34b8b7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus.svg new file mode 100644 index 00000000..15d2b327 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/plus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-fill.svg new file mode 100644 index 00000000..2e16e121 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-heart-fill.svg new file mode 100644 index 00000000..5df10ff0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-heart-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-heart.svg new file mode 100644 index 00000000..2398a22f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/postage-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/postage.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/postage.svg new file mode 100644 index 00000000..43bb3104 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/postage.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-fill.svg new file mode 100644 index 00000000..12eb76ed --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-heart-fill.svg new file mode 100644 index 00000000..155dddfc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-heart.svg new file mode 100644 index 00000000..d96b49e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard.svg new file mode 100644 index 00000000..afdc2e4b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/postcard.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/power.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/power.svg new file mode 100644 index 00000000..f940b370 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/power.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/prescription.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/prescription.svg new file mode 100644 index 00000000..75b82272 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/prescription.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/prescription2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/prescription2.svg new file mode 100644 index 00000000..512f7553 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/prescription2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/printer-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/printer-fill.svg new file mode 100644 index 00000000..0fe977b6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/printer-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/printer.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/printer.svg new file mode 100644 index 00000000..6ef0f8ba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/printer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/projector-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/projector-fill.svg new file mode 100644 index 00000000..ee6bee8c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/projector-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/projector.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/projector.svg new file mode 100644 index 00000000..c5f0f98e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/projector.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/puzzle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/puzzle-fill.svg new file mode 100644 index 00000000..e629e93d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/puzzle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/puzzle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/puzzle.svg new file mode 100644 index 00000000..afa67b91 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/puzzle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/qr-code-scan.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/qr-code-scan.svg new file mode 100644 index 00000000..f887bced --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/qr-code-scan.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/qr-code.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/qr-code.svg new file mode 100644 index 00000000..961bab19 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/qr-code.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-circle-fill.svg new file mode 100644 index 00000000..0ad62bc7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-circle.svg new file mode 100644 index 00000000..26ab0700 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-diamond-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-diamond-fill.svg new file mode 100644 index 00000000..1ec85dc3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-diamond.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-diamond.svg new file mode 100644 index 00000000..202bacb8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-diamond.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-lg.svg new file mode 100644 index 00000000..ed408cc0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-octagon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-octagon-fill.svg new file mode 100644 index 00000000..d0fa3c8f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-octagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-octagon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-octagon.svg new file mode 100644 index 00000000..15ec4e70 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-octagon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-square-fill.svg new file mode 100644 index 00000000..519bfbaa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-square.svg new file mode 100644 index 00000000..6d634689 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/question.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/question.svg new file mode 100644 index 00000000..e63ac325 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/question.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/quora.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/quora.svg new file mode 100644 index 00000000..f1778a63 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/quora.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/quote.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/quote.svg new file mode 100644 index 00000000..e82e43dd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/quote.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/r-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/r-circle-fill.svg new file mode 100644 index 00000000..c6aaf9d4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/r-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/r-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/r-circle.svg new file mode 100644 index 00000000..94134047 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/r-circle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/r-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/r-square-fill.svg new file mode 100644 index 00000000..5f417738 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/r-square-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/r-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/r-square.svg new file mode 100644 index 00000000..5bf5622e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/r-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/radar.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/radar.svg new file mode 100644 index 00000000..0dfcc7f4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/radar.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/radioactive.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/radioactive.svg new file mode 100644 index 00000000..df9af279 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/radioactive.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rainbow.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rainbow.svg new file mode 100644 index 00000000..7c57b2b2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rainbow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/receipt-cutoff.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/receipt-cutoff.svg new file mode 100644 index 00000000..3ebe01f8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/receipt-cutoff.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/receipt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/receipt.svg new file mode 100644 index 00000000..8c8da0d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/receipt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-0.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-0.svg new file mode 100644 index 00000000..cca1a18f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-0.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-1.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-1.svg new file mode 100644 index 00000000..e8926a04 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-2.svg new file mode 100644 index 00000000..e53906c6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-3.svg new file mode 100644 index 00000000..8470e9ec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-4.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-4.svg new file mode 100644 index 00000000..87da1c7f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reception-4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/record-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-btn-fill.svg new file mode 100644 index 00000000..42fcdbe9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/record-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-btn.svg new file mode 100644 index 00000000..154e9281 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/record-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-circle-fill.svg new file mode 100644 index 00000000..f7b0956e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/record-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-circle.svg new file mode 100644 index 00000000..04b3c918 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/record-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-fill.svg new file mode 100644 index 00000000..f2d619f2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/record-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/record.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/record.svg new file mode 100644 index 00000000..bbb8c614 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/record.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/record2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/record2-fill.svg new file mode 100644 index 00000000..2a704018 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/record2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/record2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/record2.svg new file mode 100644 index 00000000..61da17b3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/record2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/recycle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/recycle.svg new file mode 100644 index 00000000..8cc7a4b7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/recycle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reddit.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reddit.svg new file mode 100644 index 00000000..62e7255e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reddit.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/regex.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/regex.svg new file mode 100644 index 00000000..4ddcea80 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/regex.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/repeat-1.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/repeat-1.svg new file mode 100644 index 00000000..8f4f6a6f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/repeat-1.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/repeat.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/repeat.svg new file mode 100644 index 00000000..9729e28c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/repeat.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-all-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-all-fill.svg new file mode 100644 index 00000000..b3d4768e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-all-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-all.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-all.svg new file mode 100644 index 00000000..2ca3f9df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-all.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-fill.svg new file mode 100644 index 00000000..bd0e72df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reply-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/reply.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/reply.svg new file mode 100644 index 00000000..10583c83 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/reply.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-btn-fill.svg new file mode 100644 index 00000000..b2ba3661 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-btn.svg new file mode 100644 index 00000000..f2d5ad4f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-circle-fill.svg new file mode 100644 index 00000000..9af9e6ad --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-circle.svg new file mode 100644 index 00000000..cbaa5d1e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-fill.svg new file mode 100644 index 00000000..8f73ae29 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind.svg new file mode 100644 index 00000000..f3773654 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rewind.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/robot.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/robot.svg new file mode 100644 index 00000000..58d0f614 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/robot.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-fill.svg new file mode 100644 index 00000000..a89bef00 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-takeoff-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-takeoff-fill.svg new file mode 100644 index 00000000..adbd3152 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-takeoff-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-takeoff.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-takeoff.svg new file mode 100644 index 00000000..a6622b46 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket-takeoff.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket.svg new file mode 100644 index 00000000..8dd9bd09 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rocket.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/router-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/router-fill.svg new file mode 100644 index 00000000..33250986 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/router-fill.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/router.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/router.svg new file mode 100644 index 00000000..436946d0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/router.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rss-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rss-fill.svg new file mode 100644 index 00000000..ecd7f6dd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rss-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rss.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rss.svg new file mode 100644 index 00000000..8986a907 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rss.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/rulers.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/rulers.svg new file mode 100644 index 00000000..2a2012f6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/rulers.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/safe-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/safe-fill.svg new file mode 100644 index 00000000..e3f4cd8b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/safe-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/safe.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/safe.svg new file mode 100644 index 00000000..579d4fbc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/safe.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/safe2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/safe2-fill.svg new file mode 100644 index 00000000..bf98ee7d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/safe2-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/safe2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/safe2.svg new file mode 100644 index 00000000..57f45985 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/safe2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/save-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/save-fill.svg new file mode 100644 index 00000000..a4ccc663 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/save-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/save.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/save.svg new file mode 100644 index 00000000..401e0994 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/save.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/save2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/save2-fill.svg new file mode 100644 index 00000000..f8bcfcbb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/save2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/save2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/save2.svg new file mode 100644 index 00000000..17777946 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/save2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/scissors.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/scissors.svg new file mode 100644 index 00000000..abab05a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/scissors.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/scooter.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/scooter.svg new file mode 100644 index 00000000..94434afa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/scooter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/screwdriver.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/screwdriver.svg new file mode 100644 index 00000000..f06d6306 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/screwdriver.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sd-card-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sd-card-fill.svg new file mode 100644 index 00000000..f17886d7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sd-card-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sd-card.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sd-card.svg new file mode 100644 index 00000000..a123f40d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sd-card.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/search-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/search-heart-fill.svg new file mode 100644 index 00000000..71a099e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/search-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/search-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/search-heart.svg new file mode 100644 index 00000000..630a7a0b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/search-heart.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/search.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/search.svg new file mode 100644 index 00000000..9798fc43 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/search.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/segmented-nav.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/segmented-nav.svg new file mode 100644 index 00000000..dbe519e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/segmented-nav.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-down-fill.svg new file mode 100644 index 00000000..cfa6f75d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-down-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-down.svg new file mode 100644 index 00000000..65401a45 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-up-fill.svg new file mode 100644 index 00000000..5d67d2b4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-up-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-up.svg new file mode 100644 index 00000000..d51f9692 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-arrow-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-check-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-check-fill.svg new file mode 100644 index 00000000..7c7dccfb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-check-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-check.svg new file mode 100644 index 00000000..b212bcdc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-dash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-dash-fill.svg new file mode 100644 index 00000000..72a61b43 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-dash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-dash.svg new file mode 100644 index 00000000..1b1a86e2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-exclamation-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-exclamation-fill.svg new file mode 100644 index 00000000..19717e19 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-exclamation-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-exclamation.svg new file mode 100644 index 00000000..7932e746 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-fill.svg new file mode 100644 index 00000000..dfe4c2bf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-plus-fill.svg new file mode 100644 index 00000000..fbaa48e2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-plus-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-plus.svg new file mode 100644 index 00000000..ab92d6e3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-slash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-slash-fill.svg new file mode 100644 index 00000000..b70ff7b8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-slash-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-slash.svg new file mode 100644 index 00000000..871975b5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-slash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-x-fill.svg new file mode 100644 index 00000000..fd92beca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-x-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-x.svg new file mode 100644 index 00000000..6b12a323 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/send.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/send.svg new file mode 100644 index 00000000..6bc7761f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/send.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/server.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/server.svg new file mode 100644 index 00000000..4f07ad73 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/server.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shadows.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shadows.svg new file mode 100644 index 00000000..d78db1eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shadows.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/share-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/share-fill.svg new file mode 100644 index 00000000..ee432ecb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/share-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/share.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/share.svg new file mode 100644 index 00000000..9d9718ec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/share.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-check.svg new file mode 100644 index 00000000..efac2af5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-exclamation.svg new file mode 100644 index 00000000..60aaafd6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-exclamation.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-check.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-check.svg new file mode 100644 index 00000000..4ad83226 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-check.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-exclamation.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-exclamation.svg new file mode 100644 index 00000000..f8312c1a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-exclamation.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-minus.svg new file mode 100644 index 00000000..6c5abc51 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-minus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-plus.svg new file mode 100644 index 00000000..0e4dc325 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-plus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-x.svg new file mode 100644 index 00000000..75815db2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill-x.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill.svg new file mode 100644 index 00000000..2b7dc114 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-lock-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-lock-fill.svg new file mode 100644 index 00000000..9d2b94f4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-lock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-lock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-lock.svg new file mode 100644 index 00000000..b1eb415c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-minus.svg new file mode 100644 index 00000000..61a513a0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-plus.svg new file mode 100644 index 00000000..9c7a962a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-shaded.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-shaded.svg new file mode 100644 index 00000000..2acba875 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-shaded.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-slash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-slash-fill.svg new file mode 100644 index 00000000..a11b0c21 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-slash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-slash.svg new file mode 100644 index 00000000..abfbbd6c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-x.svg new file mode 100644 index 00000000..038263ea --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shield.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield.svg new file mode 100644 index 00000000..97d95c08 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shield.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shift-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shift-fill.svg new file mode 100644 index 00000000..2146340f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shift-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shift.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shift.svg new file mode 100644 index 00000000..dfef17ad --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shift.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shop-window.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shop-window.svg new file mode 100644 index 00000000..d135934f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shop-window.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shop.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shop.svg new file mode 100644 index 00000000..73fb3d03 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shop.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/shuffle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/shuffle.svg new file mode 100644 index 00000000..3a0716fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/shuffle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-dead-end-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-dead-end-fill.svg new file mode 100644 index 00000000..665a938c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-dead-end-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-dead-end.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-dead-end.svg new file mode 100644 index 00000000..9de2e968 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-dead-end.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-do-not-enter-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-do-not-enter-fill.svg new file mode 100644 index 00000000..8d9d39fc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-do-not-enter-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-do-not-enter.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-do-not-enter.svg new file mode 100644 index 00000000..78c9b89a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-do-not-enter.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-fill.svg new file mode 100644 index 00000000..4e990dc0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-side-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-side-fill.svg new file mode 100644 index 00000000..4b75b789 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-side-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-side.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-side.svg new file mode 100644 index 00000000..d5a9bd96 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-side.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-t-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-t-fill.svg new file mode 100644 index 00000000..6fb9f617 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-t-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-t.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-t.svg new file mode 100644 index 00000000..130866f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-t.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-y-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-y-fill.svg new file mode 100644 index 00000000..316d16e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-y-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-y.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-y.svg new file mode 100644 index 00000000..ca1d26a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection-y.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection.svg new file mode 100644 index 00000000..5403c901 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-intersection.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-left-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-left-fill.svg new file mode 100644 index 00000000..6f1a2d3a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-left.svg new file mode 100644 index 00000000..e1378213 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-right-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-right-fill.svg new file mode 100644 index 00000000..d84a22f4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-right.svg new file mode 100644 index 00000000..bb5992e5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-merge-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-left-turn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-left-turn-fill.svg new file mode 100644 index 00000000..2a74d7d2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-left-turn-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-left-turn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-left-turn.svg new file mode 100644 index 00000000..658f5160 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-left-turn.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-parking-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-parking-fill.svg new file mode 100644 index 00000000..db8a80a2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-parking-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-parking.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-parking.svg new file mode 100644 index 00000000..559e73ef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-parking.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-right-turn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-right-turn-fill.svg new file mode 100644 index 00000000..05dd6667 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-right-turn-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-right-turn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-right-turn.svg new file mode 100644 index 00000000..f55cd9a5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-no-right-turn.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-railroad-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-railroad-fill.svg new file mode 100644 index 00000000..b51b8e9e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-railroad-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-railroad.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-railroad.svg new file mode 100644 index 00000000..2c4065d8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-railroad.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-fill.svg new file mode 100644 index 00000000..76ad911a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-lights-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-lights-fill.svg new file mode 100644 index 00000000..6c1470a9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-lights-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-lights.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-lights.svg new file mode 100644 index 00000000..5465d815 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop-lights.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop.svg new file mode 100644 index 00000000..5dae2e30 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-stop.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-left-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-left-fill.svg new file mode 100644 index 00000000..e001fd58 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-left.svg new file mode 100644 index 00000000..20bcd3a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-right-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-right-fill.svg new file mode 100644 index 00000000..ce68a34a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-right.svg new file mode 100644 index 00000000..3d0e3d60 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-left-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-left-fill.svg new file mode 100644 index 00000000..e891308f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-left-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-left.svg new file mode 100644 index 00000000..9f97ba05 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-left.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-right-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-right-fill.svg new file mode 100644 index 00000000..e7acbb2a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-right-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-right.svg new file mode 100644 index 00000000..7e105fa4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-turn-slight-right.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-yield-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-yield-fill.svg new file mode 100644 index 00000000..31e65d15 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-yield-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-yield.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-yield.svg new file mode 100644 index 00000000..6b1d6b90 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sign-yield.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/signal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/signal.svg new file mode 100644 index 00000000..a1720c08 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/signal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-2-fill.svg new file mode 100644 index 00000000..acf0243b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-2.svg new file mode 100644 index 00000000..b4e92f11 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-fill.svg new file mode 100644 index 00000000..bb8e97b1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-split-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-split-fill.svg new file mode 100644 index 00000000..bc164a7e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-split-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-split.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-split.svg new file mode 100644 index 00000000..431ed7d7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost-split.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost.svg new file mode 100644 index 00000000..be4623ec --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/signpost.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-fill.svg new file mode 100644 index 00000000..5ef90796 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-slash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-slash-fill.svg new file mode 100644 index 00000000..46fa2a41 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-slash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-slash.svg new file mode 100644 index 00000000..f58ba052 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sim-slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sim.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sim.svg new file mode 100644 index 00000000..d5d26ad0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sim.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sina-weibo.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sina-weibo.svg new file mode 100644 index 00000000..a150dff5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sina-weibo.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-btn-fill.svg new file mode 100644 index 00000000..69495300 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-btn.svg new file mode 100644 index 00000000..079e453d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-circle-fill.svg new file mode 100644 index 00000000..d069136d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-circle.svg new file mode 100644 index 00000000..6afde382 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-fill.svg new file mode 100644 index 00000000..f0813b54 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward.svg new file mode 100644 index 00000000..1322cabb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-backward.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-btn-fill.svg new file mode 100644 index 00000000..aaf2b54b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-btn.svg new file mode 100644 index 00000000..86e88807 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-circle-fill.svg new file mode 100644 index 00000000..a45aa192 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-circle.svg new file mode 100644 index 00000000..565d2050 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-fill.svg new file mode 100644 index 00000000..122d4bde --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end.svg new file mode 100644 index 00000000..ecf7d569 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-end.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-btn-fill.svg new file mode 100644 index 00000000..99d51ab9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-btn.svg new file mode 100644 index 00000000..8b97dc47 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-circle-fill.svg new file mode 100644 index 00000000..c9a8fd7d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-circle.svg new file mode 100644 index 00000000..9dacaedc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-fill.svg new file mode 100644 index 00000000..20534ece --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward.svg new file mode 100644 index 00000000..16d6a82c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-forward.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-btn-fill.svg new file mode 100644 index 00000000..09230dde --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-btn.svg new file mode 100644 index 00000000..ca8ced25 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-circle-fill.svg new file mode 100644 index 00000000..8aa2ef96 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-circle.svg new file mode 100644 index 00000000..65e67c84 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-fill.svg new file mode 100644 index 00000000..930c664a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start.svg new file mode 100644 index 00000000..d953a15c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skip-start.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/skype.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/skype.svg new file mode 100644 index 00000000..97d85ba2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/skype.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/slack.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/slack.svg new file mode 100644 index 00000000..69c3febe --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/slack.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-circle-fill.svg new file mode 100644 index 00000000..ed608226 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-circle.svg new file mode 100644 index 00000000..f6756f82 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-lg.svg new file mode 100644 index 00000000..b75b776f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-square-fill.svg new file mode 100644 index 00000000..0f31d482 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-square.svg new file mode 100644 index 00000000..c85b1ccc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/slash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash.svg new file mode 100644 index 00000000..586a92ac --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/slash.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders.svg new file mode 100644 index 00000000..beff9e40 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders2-vertical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders2-vertical.svg new file mode 100644 index 00000000..bdc828d5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders2-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders2.svg new file mode 100644 index 00000000..0adce19b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sliders2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/smartwatch.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/smartwatch.svg new file mode 100644 index 00000000..9e4a0247 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/smartwatch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/snapchat.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/snapchat.svg new file mode 100644 index 00000000..b175731d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/snapchat.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/snow.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/snow.svg new file mode 100644 index 00000000..70bc89c3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/snow.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/snow2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/snow2.svg new file mode 100644 index 00000000..ac4706a1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/snow2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/snow3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/snow3.svg new file mode 100644 index 00000000..62fd5150 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/snow3.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-down-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-down-alt.svg new file mode 100644 index 00000000..ebf01eda --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-down-alt.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-down.svg new file mode 100644 index 00000000..869f880f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-down.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-up-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-up-alt.svg new file mode 100644 index 00000000..588e058f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-up-alt.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-up.svg new file mode 100644 index 00000000..199766f8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-alpha-up.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-down-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-down-alt.svg new file mode 100644 index 00000000..5ff1617e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-down-alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-down.svg new file mode 100644 index 00000000..91ffd736 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-down-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-down-alt.svg new file mode 100644 index 00000000..74d6122d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-down-alt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-down.svg new file mode 100644 index 00000000..49637c5c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-down.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-up-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-up-alt.svg new file mode 100644 index 00000000..307ced49 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-up-alt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-up.svg new file mode 100644 index 00000000..2758ee97 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-numeric-up.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-up-alt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-up-alt.svg new file mode 100644 index 00000000..6ac5260b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-up-alt.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-up.svg new file mode 100644 index 00000000..06a991f6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sort-up.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/soundwave.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/soundwave.svg new file mode 100644 index 00000000..e48a5e43 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/soundwave.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sourceforge.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sourceforge.svg new file mode 100644 index 00000000..b0f2a09b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sourceforge.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/speaker-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/speaker-fill.svg new file mode 100644 index 00000000..79f4739e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/speaker-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/speaker.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/speaker.svg new file mode 100644 index 00000000..5e4e33d8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/speaker.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/speedometer.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/speedometer.svg new file mode 100644 index 00000000..7ca71ad1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/speedometer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/speedometer2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/speedometer2.svg new file mode 100644 index 00000000..7ff7e212 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/speedometer2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/spellcheck.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/spellcheck.svg new file mode 100644 index 00000000..ca37840c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/spellcheck.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/spinner.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/spinner.svg new file mode 100644 index 00000000..b8944ac5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/spinner.svg @@ -0,0 +1,3 @@ + + + diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/spotify.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/spotify.svg new file mode 100644 index 00000000..3ba29744 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/spotify.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/square-fill.svg new file mode 100644 index 00000000..32c32498 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/square-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/square-half.svg new file mode 100644 index 00000000..789eb614 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/square-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/square.svg new file mode 100644 index 00000000..d1ca3c58 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/square.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stack-overflow.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stack-overflow.svg new file mode 100644 index 00000000..e3e149c4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stack-overflow.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stack.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stack.svg new file mode 100644 index 00000000..a689b21e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/star-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/star-fill.svg new file mode 100644 index 00000000..3252816e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/star-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/star-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/star-half.svg new file mode 100644 index 00000000..5a7fa242 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/star-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/star.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/star.svg new file mode 100644 index 00000000..73296f30 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/star.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stars.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stars.svg new file mode 100644 index 00000000..a8ded4df --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stars.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/steam.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/steam.svg new file mode 100644 index 00000000..6db96878 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/steam.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stickies-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stickies-fill.svg new file mode 100644 index 00000000..568326ef --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stickies-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stickies.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stickies.svg new file mode 100644 index 00000000..034440e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stickies.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sticky-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sticky-fill.svg new file mode 100644 index 00000000..83140742 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sticky-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sticky.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sticky.svg new file mode 100644 index 00000000..9a087806 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sticky.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-btn-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-btn-fill.svg new file mode 100644 index 00000000..20352df3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-btn-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-btn.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-btn.svg new file mode 100644 index 00000000..a3b87433 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-btn.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-circle-fill.svg new file mode 100644 index 00000000..8b4aba1d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-circle.svg new file mode 100644 index 00000000..819ab288 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-fill.svg new file mode 100644 index 00000000..510ca14d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stop.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop.svg new file mode 100644 index 00000000..28c9ca1e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stop.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stoplights-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stoplights-fill.svg new file mode 100644 index 00000000..0d4fbeaa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stoplights-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stoplights.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stoplights.svg new file mode 100644 index 00000000..8845ed48 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stoplights.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stopwatch-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stopwatch-fill.svg new file mode 100644 index 00000000..d286a50c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stopwatch-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stopwatch.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stopwatch.svg new file mode 100644 index 00000000..d20fc8e7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stopwatch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/strava.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/strava.svg new file mode 100644 index 00000000..7f1f9fbc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/strava.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/stripe.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/stripe.svg new file mode 100644 index 00000000..4b69c80d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/stripe.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/subscript.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/subscript.svg new file mode 100644 index 00000000..8492a335 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/subscript.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/substack.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/substack.svg new file mode 100644 index 00000000..266d00a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/substack.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/subtract.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/subtract.svg new file mode 100644 index 00000000..b5314c4a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/subtract.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/success.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/success.svg new file mode 100644 index 00000000..85dad728 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/success.svg @@ -0,0 +1,4 @@ + + + + diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-club-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-club-fill.svg new file mode 100644 index 00000000..413575d6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-club-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-club.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-club.svg new file mode 100644 index 00000000..2ef4205a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-club.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-diamond-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-diamond-fill.svg new file mode 100644 index 00000000..cfb4a203 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-diamond.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-diamond.svg new file mode 100644 index 00000000..ef69774c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-diamond.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-heart-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-heart-fill.svg new file mode 100644 index 00000000..ce197506 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-heart-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-heart.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-heart.svg new file mode 100644 index 00000000..7a4328f9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-heart.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-spade-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-spade-fill.svg new file mode 100644 index 00000000..3651b53e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-spade-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-spade.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-spade.svg new file mode 100644 index 00000000..d29ac58a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suit-spade.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-fill.svg new file mode 100644 index 00000000..04667c45 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-lg-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-lg-fill.svg new file mode 100644 index 00000000..a6ccef38 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-lg-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-lg.svg new file mode 100644 index 00000000..e68b21f4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase.svg new file mode 100644 index 00000000..6bb4744a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase2-fill.svg new file mode 100644 index 00000000..e678003f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase2.svg new file mode 100644 index 00000000..6126c821 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/suitcase2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sun-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sun-fill.svg new file mode 100644 index 00000000..10ef7aee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sun-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sun.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sun.svg new file mode 100644 index 00000000..35088f68 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sun.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sunglasses.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunglasses.svg new file mode 100644 index 00000000..83417d7b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunglasses.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sunrise-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunrise-fill.svg new file mode 100644 index 00000000..6f33f8e1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunrise-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sunrise.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunrise.svg new file mode 100644 index 00000000..4136e195 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunrise.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sunset-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunset-fill.svg new file mode 100644 index 00000000..0cc2ac7a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunset-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/sunset.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunset.svg new file mode 100644 index 00000000..cc83e155 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/sunset.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/superscript.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/superscript.svg new file mode 100644 index 00000000..36095d3c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/superscript.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/symmetry-horizontal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/symmetry-horizontal.svg new file mode 100644 index 00000000..bb1742ba --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/symmetry-horizontal.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/symmetry-vertical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/symmetry-vertical.svg new file mode 100644 index 00000000..a89412b6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/symmetry-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/table.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/table.svg new file mode 100644 index 00000000..9de46f13 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/table.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-fill.svg new file mode 100644 index 00000000..d2b65f3a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-landscape-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-landscape-fill.svg new file mode 100644 index 00000000..8e2bac5d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-landscape-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-landscape.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-landscape.svg new file mode 100644 index 00000000..fd0efac9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet-landscape.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet.svg new file mode 100644 index 00000000..05b9d8ee --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tablet.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tag-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tag-fill.svg new file mode 100644 index 00000000..5871f00f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tag-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tag.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tag.svg new file mode 100644 index 00000000..192c0e23 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tag.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tags-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tags-fill.svg new file mode 100644 index 00000000..9d45e3b0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tags-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tags.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tags.svg new file mode 100644 index 00000000..493a20da --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tags.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/taxi-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/taxi-front-fill.svg new file mode 100644 index 00000000..3425346f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/taxi-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/taxi-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/taxi-front.svg new file mode 100644 index 00000000..f87d0faf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/taxi-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telegram.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telegram.svg new file mode 100644 index 00000000..f16eace5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telegram.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-fill.svg new file mode 100644 index 00000000..9882b232 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-forward-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-forward-fill.svg new file mode 100644 index 00000000..20ac8d3a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-forward-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-forward.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-forward.svg new file mode 100644 index 00000000..cb58fcdf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-forward.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-inbound-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-inbound-fill.svg new file mode 100644 index 00000000..fef3e264 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-inbound-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-inbound.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-inbound.svg new file mode 100644 index 00000000..4a86476b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-inbound.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-minus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-minus-fill.svg new file mode 100644 index 00000000..277cae8e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-minus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-minus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-minus.svg new file mode 100644 index 00000000..254b6332 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-minus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-outbound-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-outbound-fill.svg new file mode 100644 index 00000000..0530d649 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-outbound-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-outbound.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-outbound.svg new file mode 100644 index 00000000..da39faae --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-outbound.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-plus-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-plus-fill.svg new file mode 100644 index 00000000..25742d9c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-plus-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-plus.svg new file mode 100644 index 00000000..ed0f6012 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-x-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-x-fill.svg new file mode 100644 index 00000000..a7e881c2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-x-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-x.svg new file mode 100644 index 00000000..e21c6620 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone.svg new file mode 100644 index 00000000..201bcff4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/telephone.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tencent-qq.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tencent-qq.svg new file mode 100644 index 00000000..f11f5e4d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tencent-qq.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-dash.svg new file mode 100644 index 00000000..bd0b3db6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-dash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-fill.svg new file mode 100644 index 00000000..a06303f0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-plus.svg new file mode 100644 index 00000000..c53fdffa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-plus.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-split.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-split.svg new file mode 100644 index 00000000..4b959756 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-split.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-x.svg new file mode 100644 index 00000000..ca799a4a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal-x.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal.svg new file mode 100644 index 00000000..44b39e53 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/terminal.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/text-center.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-center.svg new file mode 100644 index 00000000..057abc43 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-center.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/text-indent-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-indent-left.svg new file mode 100644 index 00000000..3a226612 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-indent-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/text-indent-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-indent-right.svg new file mode 100644 index 00000000..09512d3f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-indent-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/text-left.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-left.svg new file mode 100644 index 00000000..615db68b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-left.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/text-paragraph.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-paragraph.svg new file mode 100644 index 00000000..ba6296db --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-paragraph.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/text-right.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-right.svg new file mode 100644 index 00000000..b6148f88 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-right.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/text-wrap.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-wrap.svg new file mode 100644 index 00000000..6bf272cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/text-wrap.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea-resize.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea-resize.svg new file mode 100644 index 00000000..9872a784 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea-resize.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea-t.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea-t.svg new file mode 100644 index 00000000..2a04d25f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea-t.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea.svg new file mode 100644 index 00000000..b9823b23 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/textarea.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-half.svg new file mode 100644 index 00000000..0c878152 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-half.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-high.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-high.svg new file mode 100644 index 00000000..4b23a489 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-high.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-low.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-low.svg new file mode 100644 index 00000000..7f2f5b9c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-low.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-snow.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-snow.svg new file mode 100644 index 00000000..509c79dc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-snow.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-sun.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-sun.svg new file mode 100644 index 00000000..a0289760 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer-sun.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer.svg new file mode 100644 index 00000000..26a0b829 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/thermometer.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/threads-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/threads-fill.svg new file mode 100644 index 00000000..5125e60b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/threads-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/threads.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/threads.svg new file mode 100644 index 00000000..aaff8406 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/threads.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/three-dots-vertical.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/three-dots-vertical.svg new file mode 100644 index 00000000..66f2528e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/three-dots-vertical.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/three-dots.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/three-dots.svg new file mode 100644 index 00000000..9f7667a3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/three-dots.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/thunderbolt-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/thunderbolt-fill.svg new file mode 100644 index 00000000..6bea1f51 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/thunderbolt-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/thunderbolt.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/thunderbolt.svg new file mode 100644 index 00000000..86c0d1dc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/thunderbolt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-detailed-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-detailed-fill.svg new file mode 100644 index 00000000..ecde8579 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-detailed-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-detailed.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-detailed.svg new file mode 100644 index 00000000..21f6d5e4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-detailed.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-fill.svg new file mode 100644 index 00000000..26b0dd34 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-perforated-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-perforated-fill.svg new file mode 100644 index 00000000..d41dfc90 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-perforated-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-perforated.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-perforated.svg new file mode 100644 index 00000000..d84999c7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket-perforated.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket.svg new file mode 100644 index 00000000..547b83d3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ticket.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tiktok.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tiktok.svg new file mode 100644 index 00000000..6332ae6a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tiktok.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle-off.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle-off.svg new file mode 100644 index 00000000..299ede31 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle-on.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle-on.svg new file mode 100644 index 00000000..a18b2c02 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle-on.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle2-off.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle2-off.svg new file mode 100644 index 00000000..bbfe3fd2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle2-off.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle2-on.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle2-on.svg new file mode 100644 index 00000000..ab47a954 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggle2-on.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/toggles.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggles.svg new file mode 100644 index 00000000..3e782a19 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggles.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/toggles2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggles2.svg new file mode 100644 index 00000000..c3e7f3d7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/toggles2.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tools.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tools.svg new file mode 100644 index 00000000..1e0d2796 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tools.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tornado.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tornado.svg new file mode 100644 index 00000000..cf0c66b4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tornado.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/train-freight-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-freight-front-fill.svg new file mode 100644 index 00000000..336c3b36 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-freight-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/train-freight-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-freight-front.svg new file mode 100644 index 00000000..b54986d8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-freight-front.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/train-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-front-fill.svg new file mode 100644 index 00000000..44d40231 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/train-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-front.svg new file mode 100644 index 00000000..14155d8c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-front.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/train-lightrail-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-lightrail-front-fill.svg new file mode 100644 index 00000000..09c8ad2e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-lightrail-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/train-lightrail-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-lightrail-front.svg new file mode 100644 index 00000000..9e129105 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/train-lightrail-front.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/translate.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/translate.svg new file mode 100644 index 00000000..4654968f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/translate.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/transparency.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/transparency.svg new file mode 100644 index 00000000..2d0429bf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/transparency.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trash-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash-fill.svg new file mode 100644 index 00000000..de5eb645 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash.svg new file mode 100644 index 00000000..94b98b5e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trash2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash2-fill.svg new file mode 100644 index 00000000..466e1c9d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trash2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash2.svg new file mode 100644 index 00000000..17d6ed80 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trash3-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash3-fill.svg new file mode 100644 index 00000000..4874933d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash3-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trash3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash3.svg new file mode 100644 index 00000000..496ed18d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trash3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tree-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tree-fill.svg new file mode 100644 index 00000000..9cbf3b11 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tree-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tree.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tree.svg new file mode 100644 index 00000000..c22a39da --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tree.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trello.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trello.svg new file mode 100644 index 00000000..5d95b849 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trello.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle-fill.svg new file mode 100644 index 00000000..cb21f60f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle-half.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle-half.svg new file mode 100644 index 00000000..6a8dac37 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle-half.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle.svg new file mode 100644 index 00000000..d3d7312c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/triangle.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trophy-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trophy-fill.svg new file mode 100644 index 00000000..38c9ef5a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trophy-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/trophy.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/trophy.svg new file mode 100644 index 00000000..84c369f6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/trophy.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tropical-storm.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tropical-storm.svg new file mode 100644 index 00000000..6bfaa11d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tropical-storm.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-flatbed.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-flatbed.svg new file mode 100644 index 00000000..5d99cfe0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-flatbed.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-front-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-front-fill.svg new file mode 100644 index 00000000..f9746836 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-front-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-front.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-front.svg new file mode 100644 index 00000000..fb6abd15 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/truck-front.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/truck.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/truck.svg new file mode 100644 index 00000000..7b313c91 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/truck.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tsunami.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tsunami.svg new file mode 100644 index 00000000..7f8ee166 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tsunami.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tux.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tux.svg new file mode 100644 index 00000000..59e505eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tux.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tv-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tv-fill.svg new file mode 100644 index 00000000..ac56fc2c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tv-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/tv.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/tv.svg new file mode 100644 index 00000000..126d3423 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/tv.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/twitch.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/twitch.svg new file mode 100644 index 00000000..e7107d99 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/twitch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/twitter-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/twitter-x.svg new file mode 100644 index 00000000..1af978c9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/twitter-x.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/twitter.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/twitter.svg new file mode 100644 index 00000000..0bee5dbc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/twitter.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-bold.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-bold.svg new file mode 100644 index 00000000..9ca85bcc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-bold.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h1.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h1.svg new file mode 100644 index 00000000..924bc1f5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h2.svg new file mode 100644 index 00000000..4b1df696 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h3.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h3.svg new file mode 100644 index 00000000..d97df9e7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h3.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h4.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h4.svg new file mode 100644 index 00000000..037d7fa2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h4.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h5.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h5.svg new file mode 100644 index 00000000..9cc56e96 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h5.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h6.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h6.svg new file mode 100644 index 00000000..b3437818 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-h6.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-italic.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-italic.svg new file mode 100644 index 00000000..9fa7a863 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-italic.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-strikethrough.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-strikethrough.svg new file mode 100644 index 00000000..441beebf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-strikethrough.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type-underline.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-underline.svg new file mode 100644 index 00000000..6390c75b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type-underline.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/type.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/type.svg new file mode 100644 index 00000000..c0803cc3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/type.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/typescript.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/typescript.svg new file mode 100644 index 00000000..b9ca36bd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/typescript.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ubuntu.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ubuntu.svg new file mode 100644 index 00000000..6e5c37b7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ubuntu.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-checks-grid.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-checks-grid.svg new file mode 100644 index 00000000..b0a2ea4e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-checks-grid.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-checks.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-checks.svg new file mode 100644 index 00000000..32b30533 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-checks.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-radios-grid.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-radios-grid.svg new file mode 100644 index 00000000..f9ac229d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-radios-grid.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-radios.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-radios.svg new file mode 100644 index 00000000..0f50bfc1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/ui-radios.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/umbrella-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/umbrella-fill.svg new file mode 100644 index 00000000..0a13fe93 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/umbrella-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/umbrella.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/umbrella.svg new file mode 100644 index 00000000..3c77651e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/umbrella.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/unindent.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/unindent.svg new file mode 100644 index 00000000..1ac0b986 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/unindent.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/union.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/union.svg new file mode 100644 index 00000000..ab9bce3b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/union.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/unity.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/unity.svg new file mode 100644 index 00000000..8ddd5ef9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/unity.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/universal-access-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/universal-access-circle.svg new file mode 100644 index 00000000..0621ebd6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/universal-access-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/universal-access.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/universal-access.svg new file mode 100644 index 00000000..71975509 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/universal-access.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock-fill.svg new file mode 100644 index 00000000..3b490676 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock.svg new file mode 100644 index 00000000..30d0a938 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock2-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock2-fill.svg new file mode 100644 index 00000000..ed59ca6c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock2-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock2.svg new file mode 100644 index 00000000..510ef053 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/unlock2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/upc-scan.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/upc-scan.svg new file mode 100644 index 00000000..9d3ac1b4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/upc-scan.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/upc.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/upc.svg new file mode 100644 index 00000000..fb00bc52 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/upc.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/upload.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/upload.svg new file mode 100644 index 00000000..17e71248 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/upload.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-c-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-c-fill.svg new file mode 100644 index 00000000..7dd9851f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-c-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-c.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-c.svg new file mode 100644 index 00000000..a693d4e0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-c.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-drive-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-drive-fill.svg new file mode 100644 index 00000000..f181bb6f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-drive-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-drive.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-drive.svg new file mode 100644 index 00000000..6eaa6ef9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-drive.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-fill.svg new file mode 100644 index 00000000..98214c4d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-micro-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-micro-fill.svg new file mode 100644 index 00000000..7f396486 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-micro-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-micro.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-micro.svg new file mode 100644 index 00000000..4f4803f1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-micro.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-mini-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-mini-fill.svg new file mode 100644 index 00000000..a1dd7580 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-mini-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-mini.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-mini.svg new file mode 100644 index 00000000..2f80c6fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-mini.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-plug-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-plug-fill.svg new file mode 100644 index 00000000..9231bcf0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-plug-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-plug.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-plug.svg new file mode 100644 index 00000000..0f107765 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-plug.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-symbol.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-symbol.svg new file mode 100644 index 00000000..86730acb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb-symbol.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/usb.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb.svg new file mode 100644 index 00000000..76964053 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/usb.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/valentine.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/valentine.svg new file mode 100644 index 00000000..7e3276cf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/valentine.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/valentine2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/valentine2.svg new file mode 100644 index 00000000..91ed70bb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/valentine2.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/vector-pen.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/vector-pen.svg new file mode 100644 index 00000000..f0bb0905 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/vector-pen.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/view-list.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/view-list.svg new file mode 100644 index 00000000..41f4421a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/view-list.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/view-stacked.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/view-stacked.svg new file mode 100644 index 00000000..51cc0d3b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/view-stacked.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/vignette.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/vignette.svg new file mode 100644 index 00000000..cac04cfb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/vignette.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/vimeo.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/vimeo.svg new file mode 100644 index 00000000..18436f0a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/vimeo.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/vinyl-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/vinyl-fill.svg new file mode 100644 index 00000000..6652047c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/vinyl-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/vinyl.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/vinyl.svg new file mode 100644 index 00000000..d4be3d2c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/vinyl.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/virus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/virus.svg new file mode 100644 index 00000000..1cb12307 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/virus.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/virus2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/virus2.svg new file mode 100644 index 00000000..f58d7ac7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/virus2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/voicemail.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/voicemail.svg new file mode 100644 index 00000000..67e18e10 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/voicemail.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-down-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-down-fill.svg new file mode 100644 index 00000000..28051899 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-down-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-down.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-down.svg new file mode 100644 index 00000000..f539e3bf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-mute-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-mute-fill.svg new file mode 100644 index 00000000..4fd27486 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-mute-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-mute.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-mute.svg new file mode 100644 index 00000000..1c3bf64d --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-mute.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-off-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-off-fill.svg new file mode 100644 index 00000000..2dacfa73 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-off-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-off.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-off.svg new file mode 100644 index 00000000..ccaf7be5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-up-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-up-fill.svg new file mode 100644 index 00000000..59100c2c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-up-fill.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-up.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-up.svg new file mode 100644 index 00000000..ad8163b6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/volume-up.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/vr.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/vr.svg new file mode 100644 index 00000000..e32863af --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/vr.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet-fill.svg new file mode 100644 index 00000000..916c91ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet.svg new file mode 100644 index 00000000..046e4c1b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet2.svg new file mode 100644 index 00000000..7dba9c08 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wallet2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/warning.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/warning.svg new file mode 100644 index 00000000..586a83c4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/warning.svg @@ -0,0 +1,4 @@ + + + + diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/watch.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/watch.svg new file mode 100644 index 00000000..f42ff67c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/watch.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/water.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/water.svg new file mode 100644 index 00000000..583b4c6a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/water.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/webcam-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/webcam-fill.svg new file mode 100644 index 00000000..b6039bb2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/webcam-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/webcam.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/webcam.svg new file mode 100644 index 00000000..b5a706a6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/webcam.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wechat.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wechat.svg new file mode 100644 index 00000000..8fb4871e --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wechat.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/whatsapp.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/whatsapp.svg new file mode 100644 index 00000000..d39e47f4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/whatsapp.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-1.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-1.svg new file mode 100644 index 00000000..98e7d482 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-1.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-2.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-2.svg new file mode 100644 index 00000000..850826c7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-2.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-off.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-off.svg new file mode 100644 index 00000000..6915c9dc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi-off.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi.svg new file mode 100644 index 00000000..f1671063 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wifi.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wikipedia.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wikipedia.svg new file mode 100644 index 00000000..a0c567ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wikipedia.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wind.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wind.svg new file mode 100644 index 00000000..a32f78e7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wind.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-dash.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-dash.svg new file mode 100644 index 00000000..46436fd6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-dash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-desktop.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-desktop.svg new file mode 100644 index 00000000..d62148aa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-desktop.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-dock.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-dock.svg new file mode 100644 index 00000000..279064dd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-dock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-fullscreen.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-fullscreen.svg new file mode 100644 index 00000000..309aded3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-fullscreen.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-plus.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-plus.svg new file mode 100644 index 00000000..8bdca678 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-plus.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-sidebar.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-sidebar.svg new file mode 100644 index 00000000..d2c593fb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-sidebar.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-split.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-split.svg new file mode 100644 index 00000000..ce50bd0b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-split.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-stack.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-stack.svg new file mode 100644 index 00000000..77fcb8a4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-stack.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window-x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-x.svg new file mode 100644 index 00000000..744fcd13 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window-x.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/window.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/window.svg new file mode 100644 index 00000000..c7c5b0e9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/window.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/windows.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/windows.svg new file mode 100644 index 00000000..b52dd477 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/windows.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wordpress.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wordpress.svg new file mode 100644 index 00000000..f36f5959 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wordpress.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable-circle-fill.svg new file mode 100644 index 00000000..19bf7c87 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable-circle-fill.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable-circle.svg new file mode 100644 index 00000000..b3de78d3 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable.svg new file mode 100644 index 00000000..4e2ec5eb --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench-adjustable.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench.svg new file mode 100644 index 00000000..652f4fb5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/wrench.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-circle-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-circle-fill.svg new file mode 100644 index 00000000..33b90e8c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-circle-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-circle.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-circle.svg new file mode 100644 index 00000000..dbf7eff0 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-circle.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-diamond-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-diamond-fill.svg new file mode 100644 index 00000000..6307e2ce --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-diamond-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-diamond.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-diamond.svg new file mode 100644 index 00000000..004a709b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-diamond.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-lg.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-lg.svg new file mode 100644 index 00000000..8b8027ca --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-lg.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-octagon-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-octagon-fill.svg new file mode 100644 index 00000000..8337450a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-octagon-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-octagon.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-octagon.svg new file mode 100644 index 00000000..de6b88bc --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-octagon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-square-fill.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-square-fill.svg new file mode 100644 index 00000000..79aeb6d4 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-square-fill.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x-square.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-square.svg new file mode 100644 index 00000000..f05e3b0a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x-square.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/x.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/x.svg new file mode 100644 index 00000000..d4312c8a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/x.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/xbox.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/xbox.svg new file mode 100644 index 00000000..00082cbf --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/xbox.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/yelp.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/yelp.svg new file mode 100644 index 00000000..2053e86f --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/yelp.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/yin-yang.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/yin-yang.svg new file mode 100644 index 00000000..7bf06f8b --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/yin-yang.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/youtube.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/youtube.svg new file mode 100644 index 00000000..a5d76742 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/youtube.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/zoom-in.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/zoom-in.svg new file mode 100644 index 00000000..61ea3871 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/zoom-in.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/icons/zoom-out.svg b/dist/macos/Replicator.app/Contents/Resources/core/icons/zoom-out.svg new file mode 100644 index 00000000..98d474c5 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/icons/zoom-out.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/core/log.py b/dist/macos/Replicator.app/Contents/Resources/core/log.py new file mode 100644 index 00000000..bf178f17 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/log.py @@ -0,0 +1,459 @@ +#!/usr/bin/env python3 +# src/core/log.py +import os +import re +import threading +from datetime import datetime +from collections import defaultdict +from typing import Iterable, Optional, TYPE_CHECKING + +from PyQt5.QtCore import Qt, QRegExp +from PyQt5.QtGui import QTextCharFormat, QColor +from PyQt5.QtWidgets import ( + QDialog, QTextEdit, QLineEdit, QPushButton, QHBoxLayout, + QVBoxLayout, QFileDialog, QWidget, QComboBox, QApplication +) + +from .helper import Helper +from .ui import MsgBox + +if TYPE_CHECKING: + # For type hints only, avoids circular import at runtime + try: + from .application import Application + from .configuration import Configuration + except ImportError: + from application import Application + from configuration import Configuration + +class Log: + + def __init__(self, helper: Helper | None = None): + + # Retrieve the application instance (may be None in CLI usage) + self._app: Application | None = QApplication.instance() # type: ignore[valid-type] + + # Ensure we have either an Application or an explicit Helper + if self._app is None and helper is None: + raise RuntimeError( + "Configuration must be created after QApplication/Application or with an explicit Helper." + ) + + # --- auto-wire from QApplication if not provided --- + if helper is None and self._app is not None: + helper = self._app.helper # type: ignore[attr-defined] + + # Helper + self._helper: Helper = helper + + # Configuration + self._configuration: Configuration = self._app.configuration + self._configuration.add("log.level", "info", "select", choices=["debug", "info", "warning", "error", "none"]) + self._configuration.add("log.enabled", True, "checkbox") + self._configuration.add("log.open", None, "button", label="Open Log", action=self.show) + self._configuration.add("log.clear", False, "checkbox", label="Allow clearing log") + self._configuration.add("log.verbose", False, "checkbox", label="Verbose logging") + + # Save any new defaults + self._configuration.save() + + # Parent + self._parent = None + + # Channel + self._channel = None + + # Core storage + self._lock = threading.Lock() + self._buffers: dict[str, list[str]] = defaultdict(list) + + # ---------- file persistence ---------- + # Save log lines to disk under /log/ + self._log_dir = self._helper.get_data_path("log",scope="system") + try: + os.makedirs(self._log_dir, exist_ok=True) + except Exception: + # If the directory cannot be created, we keep logging in memory. + pass + + # Optional configuration toggle for file logging + self._configuration.add("log.persist", True, "checkbox", label="Save log to file") + self._configuration.save() + + # Track currently used daily log file + self._current_log_path: str | None = None + + # ---------- file persistence helpers ---------- + + def _safe_filename(self, name: str) -> str: + name = (name or "app").strip() + # Keep only safe characters for filenames + name = re.sub(r"[^A-Za-z0-9._-]+", "_", name) + return name or "app" + + def _get_log_path(self) -> str | None: + # If directory creation failed earlier, bail out + if not os.path.isdir(self._log_dir): + return None + + app_name = "app" + if self._app is not None: + # Prefer application name when available + app_name = getattr(self._app, "name", None) or getattr(self._app, "applicationName", None) or "app" + + app_name = self._safe_filename(str(app_name)) + date_str = datetime.now().strftime("%Y-%m-%d") + return os.path.join(self._log_dir, f"{app_name}-{date_str}.log") + + def _append_to_file(self, lines: list[str]) -> None: + if not lines: + return + if not self._configuration.get("log.persist"): + return + + path = self._get_log_path() + if not path: + return + + # Write is protected by the same lock as in-memory buffers to keep ordering + try: + with open(path, "a", encoding="utf-8") as f: + for ln in lines: + f.write(ln) + if not ln.endswith("\n"): + f.write("\n") + self._current_log_path = path + except Exception: + # Never crash the app because file logging failed + return + + # ---------- core storage ---------- + + def append(self, message: str, channel: str = "default", level: str = "info") -> None: + + # Check if logging is enabled and level is sufficient + if not self._configuration.get("log.enabled"): + return + if self._configuration.get("log.level") == "none": + return + if self._configuration.get("log.level") == "error" and level != "error": + return + if self._configuration.get("log.level") == "warning" and level not in ("warning", "error"): + return + if self._configuration.get("log.level") == "info" and level not in ("info", "warning", "error"): + return + if self._configuration.get("log.level") == "debug" and level not in ("debug", "info", "warning", "error"): + return + if not message: + return + + # Normalize to individual lines + raw_lines = message.splitlines() or [message] + + # Format each line with timestamp, level, channel + lines: list[str] = [] + now = self._helper.get_now() + for ln in raw_lines: + line = f"[{now}][{level.upper()}][{channel}] {ln}" + lines.append(line) + + # Check if verbose logging is enabled and print to console + if self._configuration.get("log.verbose"): + print(line) + + # Append lines to the buffer and persist to file (keeps ordering) + with self._lock: + self._buffers[channel].extend(lines) + self._append_to_file(lines) + + def extend(self, lines: Iterable[str], channel: str = "default") -> None: + with self._lock: + for ln in lines: + if ln: + self._buffers[channel].append(str(ln)) + + def get_text(self, channel: Optional[str] = None) -> str: + with self._lock: + # All channels + if channel is None: + if not self._buffers: + return "" + # Just concatenate all logs in insertion order of channels + parts: list[str] = [] + for ch, lines in self._buffers.items(): + if not lines: + continue + # Optional header per channel (helps when viewing “All”) + parts.append(f"[{ch}]") + parts.extend(lines) + parts.append("") # blank line between channels + return "\n".join(parts).rstrip() + # Single channel + if channel not in self._buffers: + return "" + return "\n".join(self._buffers[channel]) + + def clear(self, channel: Optional[str] = None) -> None: + + # Check if clearing is allowed + if not self._configuration.get("log.clear"): + return + + # Clear all channels if channel is None + with self._lock: + if channel is None: + self._buffers.clear() + else: + self._buffers.pop(channel, None) + + def has_data(self, channel: str = "default") -> bool: + with self._lock: + return bool(self._buffers.get(channel)) + + def has_any_data(self) -> bool: + with self._lock: + return any(bool(buf) for buf in self._buffers.values()) + + # ---------- UI helper ---------- + + def show(self, parent=None, channel: Optional[str] = None, filter_text: str | None = None): + # If called from a clicked(bool) signal, parent may be a bool; ignore non-widget parents + if not isinstance(parent, QWidget): + parent = None + + if parent is not None and isinstance(parent, QWidget): + self._parent = parent + elif self._parent is None: + # Try to parent to the currently active window (e.g. the configuration dialog) + aw = QApplication.activeWindow() + if isinstance(aw, QWidget): + self._parent = aw + + # Remember last requested channel (can be None = all) + self._channel = channel + + if channel is None: + # All channels + if not self.has_any_data(): + MsgBox.show( + title="No log available", + message="There is no log yet. Perform some actions first.", + icon="info", + buttons="OK", + default="OK", + icon_lookup_fn=self._helper.get_sys_path, + ) + return + + # Snapshot buffers for the dialog + with self._lock: + channels_text = { + ch: "\n".join(lines) for ch, lines in self._buffers.items() + } + text = self.get_text(None) # all channels, formatted + else: + # Single channel + if not self.has_data(channel): + MsgBox.show( + title="No log available", + message="There is no log yet for this channel. Perform some actions first.", + icon="info", + buttons="OK", + default="OK", + icon_lookup_fn=self._helper.get_sys_path, + ) + return + + with self._lock: + channels_text = { + ch: "\n".join(lines) for ch, lines in self._buffers.items() + } + text = self.get_text(channel) + + dlg = LogDialog( + self._parent, + text=text, + filter_text=filter_text, + channels_text=channels_text, + initial_channel=channel, + default_save_dir=getattr(self, "_log_dir", None), + ) + # Run the log window as a modal dialog so it appears on top and is interactive + dlg.exec_() + return dlg + +class LogDialog(QDialog): + + def __init__( + self, + parent=None, + text: str = "", + filter_text: str | None = None, + channels_text: Optional[dict[str, str]] = None, + initial_channel: Optional[str] = None, + default_save_dir: str | None = None, + ): + super().__init__(parent) + self.setWindowTitle("Log") + self.setObjectName("logWindow") + self.setMinimumSize(720, 420) + + # Store per-channel logs (may be empty dict) + self._channels_text: dict[str, str] = channels_text or {} + self._current_channel: Optional[str] = initial_channel + self._default_save_dir = default_save_dir + + self._full_text = text or "" + + self.text = QTextEdit(self) + self.text.setReadOnly(True) + self.text.setPlainText(self._full_text) + + # Channel selector + self.channel_box = QComboBox(self) + self.channel_box.addItem("All channels", userData=None) + for ch in sorted(self._channels_text.keys()): + self.channel_box.addItem(ch, userData=ch) + + # Set initial selection + if initial_channel is None: + self.channel_box.setCurrentIndex(0) + else: + idx = self.channel_box.findData(initial_channel) + if idx >= 0: + self.channel_box.setCurrentIndex(idx) + + self.channel_box.currentIndexChanged.connect(self._on_channel_change) + + self.find_box = QLineEdit(self) + self.find_box.setPlaceholderText("Filter...") + self.find_box.textChanged.connect(self.apply_filter) + + self.copy_btn = QPushButton("Copy all") + self.copy_btn.clicked.connect( + lambda: self._copy_all() + ) + self.save_btn = QPushButton("Save as...") + self.save_btn.clicked.connect(self.save_as) + + top = QHBoxLayout() + top.addWidget(self.channel_box) # ⬅️ add channel selector to the toolbar row + top.addWidget(self.find_box) + top.addWidget(self.copy_btn) + top.addWidget(self.save_btn) + + root = QVBoxLayout(self) + root.addLayout(top) + root.addWidget(self.text) + + # If opened with an initial filter, apply it right away + if filter_text: + self.find_box.setText(filter_text) + else: + self.apply_filter() + + # ------ basic operations ------ + + def set_text(self, text: str): + self._full_text = text or "" + self.apply_filter() + + def _copy_all(self): + QApplication.clipboard().setText(self.text.toPlainText()) + + def save_as(self): + default_name = "log.log" + if self._default_save_dir: + default_name = os.path.join(self._default_save_dir, default_name) + + path, _ = QFileDialog.getSaveFileName( + self, "Save log", default_name, + "Log Files (*.log);;Text Files (*.txt);;All Files (*)" + ) + if path: + with open(path, "w", encoding="utf-8") as f: + f.write(self.text.toPlainText()) + + # ------ filtering + highlighting ------ + + def apply_filter(self): + + needle = self.find_box.text().strip() + if not needle: + self._set_view_text(self._full_text) + return + + filtered_lines = [ + ln for ln in self._full_text.splitlines() + if needle.lower() in ln.lower() + ] + self._set_view_text("\n".join(filtered_lines)) + self._highlight_all(needle) + + def _set_view_text(self, s: str): + self.text.blockSignals(True) + self.text.setPlainText(s) + self.text.blockSignals(False) + + def _highlight_all(self, needle: str): + + if not needle: + return + + doc = self.text.document() + cursor = self.text.textCursor() + cursor.beginEditBlock() + + # clear previous formats + clear = QTextCharFormat() + rng = self.text.textCursor() + rng.movePosition(rng.Start) + rng.movePosition(rng.End, rng.KeepAnchor) + rng.setCharFormat(clear) + + fmt = QTextCharFormat() + fmt.setBackground(QColor("yellow")) + fmt.setForeground(QColor("black")) + + rx = QRegExp(needle) + rx.setCaseSensitivity(Qt.CaseInsensitive) + + pos = 0 + plain = doc.toPlainText() + while True: + pos = rx.indexIn(plain, pos) + if pos < 0: + break + match_cursor = self.text.textCursor() + match_cursor.setPosition(pos) + match_cursor.setPosition(pos + rx.matchedLength(), match_cursor.KeepAnchor) + match_cursor.mergeCharFormat(fmt) + pos += max(1, rx.matchedLength()) + + cursor.endEditBlock() + + # ----- event handlers ------ + + def _on_channel_change(self, idx: int): + ch = self.channel_box.itemData(idx) # None = All channels + self._current_channel = ch + + if ch is None: + # All channels: rebuild from the per-channel dict if available, + # otherwise fall back to whatever initial text we had. + if self._channels_text: + parts: list[str] = [] + for name in sorted(self._channels_text.keys()): + txt = (self._channels_text.get(name) or "").strip() + if not txt: + continue + parts.append(f"[{name}]") + parts.append(txt) + parts.append("") + self._full_text = "\n".join(parts).rstrip() + else: + self._full_text = self._full_text or "" + else: + self._full_text = self._channels_text.get(ch, "") + + self.apply_filter() diff --git a/dist/macos/Replicator.app/Contents/Resources/core/network/diagnostic.py b/dist/macos/Replicator.app/Contents/Resources/core/network/diagnostic.py new file mode 100644 index 00000000..16645c81 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/network/diagnostic.py @@ -0,0 +1,330 @@ +#!/usr/bin/env python3 +# src/core/network/diagnostic.py + +from __future__ import annotations + +from typing import Any, Callable, Optional, Iterable, TYPE_CHECKING + +from PyQt5.QtCore import QThread, pyqtSignal, Qt, QObject +from PyQt5.QtWidgets import ( + QDialog, QVBoxLayout, QHBoxLayout, + QLabel, QPushButton, QTextEdit, QWidget, + QApplication +) +from PyQt5.QtGui import QPixmap, QIcon + +try: + from core.helper import Helper + from core.log import Log + from core.ui import SpinningIconLabel +except ImportError: + from helper import Helper + from log import Log + from ui import SpinningIconLabel + +from .tools import Tools + +if TYPE_CHECKING: + # For type hints only, avoids circular import at runtime + try: + from core.application import Application + except ImportError: + from application import Application + +class DiagnosticStep: + def __init__( + self, + name: str, + label: str, + icon: Optional[str], + func: Callable[[Callable[[str], None]], bool] + ): + self.name = name + self.label = label + self.icon = icon + self.func = func + +class DiagnosticThread(QThread): + log = pyqtSignal(str) + step_state = pyqtSignal(str, str) # name, state: idle|running|ok|fail + finished = pyqtSignal(dict) # {step_name: bool} + + def __init__(self, steps: Iterable[DiagnosticStep], parent: Optional[QWidget] = None): + app = QApplication.instance() + if app is not None and hasattr(app, "logger"): + self._logger = app.logger + else: + self._logger = Log() + self._logger.append(f"[DiagnosticThread] Initializing with {len(list(steps))} steps", channel="diagnostic", level="debug") + super().__init__(parent) + self._steps = list(steps) + + def run(self): + self._logger.append(f"[DiagnosticThread] run() started with {len(self._steps)} steps", channel="diagnostic", level="debug") + results = {} + + step_names = [step.name for step in self._steps] + self._logger.append(f"[DiagnosticThread] Steps to run: {step_names}", channel="diagnostic", level="debug") + + def printer(msg: str) -> None: + self.log.emit(msg) + + for step in self._steps: + self._logger.append(f"[DiagnosticThread] Starting step {step.name}", channel="diagnostic", level="debug") + self.step_state.emit(step.name, "running") + try: + res = step.func(printer) + ok = bool(res) + self._logger.append(f"[DiagnosticThread] Step {step.name} returned {ok}", channel="diagnostic", level="debug") + except Exception as e: + printer(f"[{step.label}] error: {e!r}") + self._logger.append(f"[DiagnosticThread] Step {step.name} raised exception: {e!r}", channel="diagnostic", level="error") + ok = False + + results[step.name] = ok + self.step_state.emit(step.name, "ok" if ok else "fail") + + self.finished.emit(results) + self._logger.append(f"[DiagnosticThread] run() completed with results: {results}", channel="diagnostic", level="debug") + +class Diagnostic(QObject): + def __init__(self, host: str, ports: Any, parent: Optional[QWidget] = None): + super().__init__(parent) + + # Retrieve the application instance + self._app: Application = QApplication.instance() + + # Ensure Client is created after Application + if self._app is None: + raise RuntimeError("Client must be created after QApplication/Application.") + + self._logger = self._app.logger or Log() + self._helper = Helper() + self._tools = Tools() + self.host = (host or "").strip() + self.ports = ports + self._parent: Optional[QWidget] = None + self._logger.append(f"[Diagnostic] Initialized with host={self.host!r}, ports={self.ports!r}", channel="diagnostic", level="debug") + + self._steps: list[DiagnosticStep] = [] + self._finished_listeners: list[Callable[[bool], None]] = [] + + def add( + self, + name: str, + label: str, + icon: Optional[str], + func: Callable[[Callable[[str], None]], bool] + ) -> None: + self._steps.append(DiagnosticStep(name, label, icon, func)) + self._logger.append(f"[Diagnostic] Added step: name={name}, label={label}, icon_provided={icon is not None}", channel="diagnostic", level="debug") + + def on_finish(self, fn: Callable[[bool], None]) -> None: + """ + Register a listener to be called when the diagnostic run finishes. + + The listener will receive a single bool argument indicating overall success. + """ + if callable(fn): + self._finished_listeners.append(fn) + self._logger.append(f"[Diagnostic] Added finished listener: {fn!r}", channel="diagnostic", level="debug") + + def show( + self, + parent: Optional[QWidget] = None, + finished: Optional[Callable[[bool], None]] = None, + ) -> QDialog: + self._logger.append(f"[Diagnostic] show() called with parent type: {type(parent)}", channel="diagnostic", level="debug") + if parent is not None and isinstance(parent, QWidget): + self._parent = parent + + dlg = DiagnosticDialog(self._steps, parent=self._parent) + self._logger.append(f"[Diagnostic] DiagnosticDialog created with {len(self._steps)} steps", channel="diagnostic", level="debug") + + for fn in self._finished_listeners: + dlg.finished.connect(fn) + + if finished is not None: + dlg.finished.connect(finished) + + self._logger.append("[Diagnostic] Diagnostics dialog about to be executed modally", channel="diagnostic", level="debug") + dlg.exec_() + self._logger.append("[Diagnostic] Diagnostics dialog returned from exec_", channel="diagnostic", level="debug") + dlg.raise_() + dlg.activateWindow() + return dlg + +class DiagnosticDialog(QDialog): + finished = pyqtSignal(bool) + + def __init__(self, steps: Iterable[DiagnosticStep], parent: Optional[QWidget] = None): + app = QApplication.instance() + if app is not None and hasattr(app, "logger"): + self._logger = app.logger + else: + self._logger = Log() + + super().__init__(parent) + + self._helper = Helper() + self._steps = list(steps) + self._logger.append(f"[DiagnosticDialog] Initialized with steps: {[step.name for step in self._steps]} (count={len(self._steps)})", channel="diagnostic", level="debug") + + self.setWindowTitle("Diagnostic") + self.setObjectName("DiagnosticDialog") + self.setWindowFlags( + Qt.Dialog + | Qt.WindowTitleHint + | Qt.CustomizeWindowHint + | Qt.WindowCloseButtonHint + ) + self.setMinimumSize(700, 420) + + icons_path = self._helper.get_path("core/icons") + circle_path = self._helper.join(icons_path, "circle.svg") + spinner_path = self._helper.join(icons_path, "spinner.svg") + error_path = self._helper.join(icons_path, "error.svg") + success_path = self._helper.join(icons_path, "success.svg") + + self._status_icons = { + "idle": QIcon(circle_path).pixmap(32, 32), + "running": QIcon(spinner_path).pixmap(32, 32), + "fail": QIcon(error_path).pixmap(32, 32), + "ok": QIcon(success_path).pixmap(32, 32), + "success": QIcon(success_path).pixmap(32, 32), + "error": QIcon(error_path).pixmap(32, 32), + } + + self._step_icon_labels: dict[str, QLabel] = {} + + top_layout = QHBoxLayout() + top_layout.setSpacing(24) + top_layout.setContentsMargins(16, 16, 16, 8) + + for step in self._steps: + icon_label = SpinningIconLabel(spinner_path, size=32) + icon_label.setStyleSheet("padding: 0px; margin: 0px; border: none;") + icon_label.setFixedSize(32, 32) + icon_label.setAlignment(Qt.AlignCenter) + icon_label.setScaledContents(True) + + # initial state = idle (static) + icon_label.setPixmap(self._status_icons["idle"]) + icon_label.stop() # make sure timer isn't running + + text_label = QLabel(step.label) + text_label.setAlignment(Qt.AlignCenter) + + step_layout = QVBoxLayout() + step_layout.setSpacing(4) + step_layout.addWidget(icon_label, alignment=Qt.AlignCenter) + step_layout.addWidget(text_label, alignment=Qt.AlignCenter) + step_layout.addStretch(1) + + container = QWidget() + container.setLayout(step_layout) + top_layout.addWidget(container, 1) + + self._step_icon_labels[step.name] = icon_label + + self.log = QTextEdit() + self.log.setReadOnly(True) + + btns = QHBoxLayout() + btns.setContentsMargins(16, 8, 16, 16) + self.run_btn = QPushButton("Run Diagnostics") + self.run_btn.clicked.connect(self.start_diagnostic) + self.close_btn = QPushButton("Close") + self.close_btn.clicked.connect(self.close) + btns.addStretch(1) + btns.addWidget(self.run_btn) + if self._logger is not None: + self.log_btn = QPushButton("Open Log") + self.log_btn.clicked.connect(self._logger.show) + btns.addWidget(self.log_btn) + btns.addWidget(self.close_btn) + + root = QVBoxLayout(self) + root.addLayout(top_layout) + root.addWidget(self.log) + root.addLayout(btns) + + self._thr: Optional[DiagnosticThread] = None + + def start_diagnostic(self): + self._logger.append(f"[DiagnosticDialog] Starting diagnostics with {len(self._steps)} steps...", channel="diagnostic", level="debug") + self.log.clear() + + for label in self._step_icon_labels.values(): + if isinstance(label, SpinningIconLabel): + label.stop() + label.setPixmap(self._status_icons["idle"]) + + self.run_btn.setEnabled(False) + + self._thr = DiagnosticThread(self._steps, parent=self) + self._thr.log.connect(self._on_log) + self._thr.step_state.connect(self._on_step_state) + self._thr.finished.connect(self._on_finished) + self._thr.finished.connect(lambda _: self.run_btn.setEnabled(True)) + self._thr.start() + self._logger.append("[DiagnosticDialog] DiagnosticThread created and started", channel="diagnostic", level="debug") + + def _on_log(self, s: str) -> None: + self._logger.append(s, channel="diagnostic", level="debug") + self.log.append(s) + + def _on_step_state(self, name: str, state: str) -> None: + self._logger.append( + f"[DiagnosticDialog] Step {name} state changed to {state}", + channel="diagnostic", + level="debug", + ) + + label = self._step_icon_labels.get(name) + if not label: + return + + # We only created SpinningIconLabel instances, but be defensive: + if isinstance(label, SpinningIconLabel): + if state == "idle": + # QLabel behavior (static idle icon) + label.stop() + label.setPixmap(self._status_icons["idle"]) + + elif state == "running": + # SpinningIconLabel behavior (spinner icon + animation) + label.setPixmap(self._status_icons["running"]) + label.start() + + elif state == "ok": + # QLabel behavior (static success icon) + label.stop() + label.setPixmap(self._status_icons["ok"]) + + elif state == "fail": + # QLabel behavior (static error icon) + label.stop() + label.setPixmap(self._status_icons["fail"]) + + else: + # Unknown state -> default back to idle, no animation + self._logger.append( + f"[DiagnosticDialog] Unknown state '{state}' for step '{name}', defaulting to idle", + channel="diagnostic", + level="warning", + ) + label.stop() + label.setPixmap(self._status_icons["idle"]) + + return + + # Fallback for plain QLabel (just in case) + pix = self._status_icons.get(state) + if pix is not None: + label.setPixmap(pix) + + def _on_finished(self, results: dict) -> None: + success = all(bool(v) for v in results.values()) if results else False + self._logger.append(f"[DiagnosticDialog] Diagnostics finished with results: {results}, success={success}", channel="diagnostic", level="debug") + self.finished.emit(success) diff --git a/dist/macos/Replicator.app/Contents/Resources/core/network/tools.py b/dist/macos/Replicator.app/Contents/Resources/core/network/tools.py new file mode 100644 index 00000000..25bb9819 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/network/tools.py @@ -0,0 +1,478 @@ +#!/usr/bin/env python3 +# src/core/network/tools.py + +import shutil +import socket +import re +import subprocess +from typing import Optional, List +from PyQt5.QtWidgets import QApplication + +try: + from core.helper import Helper +except ImportError: + from helper import Helper + +class Tools: + + def __init__( + self, + helper: Optional[Helper] = None + ): + + # Initialize QObject + super().__init__() + + # --- auto-wire from QApplication if not provided --- + if helper is None: + app = QApplication.instance() + if app is None: + raise RuntimeError("Client must be created after QApplication/Application.") + # narrow the type for linters / IDEs + # no runtime import to avoid circular imports + helper = helper or app.helper # type: ignore[attr-defined] + + # Helper + self._helper: Helper = helper + + # OS type + self._os: str = self._helper.get_os() + + def ping(self, host): + args = [] + if self._os == "windows": + args = ["ping", "-n", "1", "-w", "1000"] + elif self._os == "linux": + args = [shutil.which("ping") or "ping", "-c", "1", "-W", "1"] + else: # macOS + args = ["/sbin/ping", "-c", "1", "-t", "1"] + return self._helper.run(args + [host])[0] == 0 + + def traceroute(self,host): + args = [] + if self._os == "windows": + args = ["tracert", "-d", "-h", "30", "-w", "1000", host] + elif self._os == "macos": + args = ["/usr/sbin/traceroute", "-n", "-m", "30", "-w", "1", host] + else: # linux + args = [shutil.which("traceroute") or "traceroute", "-n", "-m", "30", "-w", "1", host] + rc, out = self._helper.run(args) + if rc != 0: + return None + hops = [] + for line in out.splitlines(): + line = line.strip() + if re.match(r"^\d+\s+", line): + parts = line.split() + if len(parts) >= 2: + hop_ip = parts[1] + hops.append(hop_ip) + return hops + + def nslookup(self, host): + """ + Perform a DNS lookup for `host`. + + Returns: + - list[str]: All resolved IPv4 addresses (unique, in order of appearance), + excluding the DNS server IP (e.g. 127.0.0.53#53 after "Server:"). + - False: If the lookup failed or no valid addresses were found. + """ + # Build command + if self._os == "windows": + args = ["nslookup", host] + else: + args = [shutil.which("nslookup") or "nslookup", host] + + rc, out = self._helper.run(args) + if rc != 0: + return False + + ips: List[str] = [] + prev_line = "" + + # Typical Linux/systemd-resolved output looks like: + # Server: 127.0.0.53 + # Address: 127.0.0.53#53 + # + # We want to *skip* that "server" address and only keep the + # addresses from the answer section. + for line in out.splitlines(): + stripped = line.strip() + + m = re.search(r"Address:\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", stripped) + if m: + ip = m.group(1) + + # Skip the resolver/server IP line that immediately follows a "Server:" line + if prev_line.strip().lower().startswith("server:"): + prev_line = stripped + continue + + if ip not in ips: + ips.append(ip) + + prev_line = stripped + + return ips if ips else False + + def gateway(self): + # Windows: parse ipconfig output + if self._os == "windows": + rc, out = self._helper.run(["ipconfig"]) + if rc != 0: + return None + + # Typical line: "Default Gateway . . . . . . . . . : 192.168.1.1" + m = re.search(r"Default Gateway[ .:]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", out) + if m: + return m.group(1) + return None + + # Linux: use "ip route" + if self._os == "linux": + rc, out = self._helper.run(["ip", "route"]) + if rc != 0: + return None + + for line in out.splitlines(): + line = line.strip() + # e.g. "default via 192.168.1.1 dev eth0 ..." + if line.startswith("default "): + m = re.search(r"default\s+via\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", line) + if m: + return m.group(1) + return None + + # macOS: use "route -n get default" + # self._os assumed "macos" for your helper + rc, out = self._helper.run(["route", "-n", "get", "default"]) + if rc != 0: + return None + + # Typical line: "gateway: 192.168.1.1" + m = re.search(r"gateway:\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", out) + if m: + return m.group(1) + return None + + def host(self): + try: + return socket.gethostname() + except Exception: + return None + + def ip(self): + ips = [] + + # --------------------------- + # Windows + # --------------------------- + if self._os == "windows": + rc, out = self._helper.run(["ipconfig"]) + if rc == 0: + # "IPv4 Address. . . . . . . . . . . : 192.168.1.24" + for line in out.splitlines(): + m = re.search(r"IPv4 Address[.\s:]*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", line) + if m: + ip = m.group(1) + if not ip.startswith("127.") and not self.apipa(ip): + ips.append(ip) + return ips + + # --------------------------- + # Linux + # --------------------------- + if self._os == "linux": + rc, out = self._helper.run([shutil.which("ip") or "ip", "addr"]) + if rc == 0: + # Lines like: "inet 192.168.1.24/24 brd ... " + for line in out.splitlines(): + line = line.strip() + if line.startswith("inet "): + m = re.search(r"inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", line) + if m: + ip = m.group(1) + if not ip.startswith("127.") and not self.apipa(ip): + ips.append(ip) + return ips + + # Fallback to ifconfig if ip fails + rc, out = self._helper.run([shutil.which("ifconfig") or "ifconfig", "-a"]) + if rc == 0: + for line in out.splitlines(): + line = line.strip() + # "inet 192.168.1.24 netmask 0xffffff00 ..." + if line.startswith("inet "): + m = re.search(r"inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", line) + if m: + ip = m.group(1) + if not ip.startswith("127.") and not self.apipa(ip): + ips.append(ip) + return ips + + # --------------------------- + # macOS + # --------------------------- + if self._os == "macos": + # macOS standard is ifconfig; there is usually no ip(8) + rc, out = self._helper.run([shutil.which("ifconfig") or "ifconfig"]) + if rc == 0: + for line in out.splitlines(): + line = line.strip() + # Lines with IPv4 usually look like: + # "inet 192.168.1.24 netmask 0xffffff00 broadcast 192.168.1.255" + if line.startswith("inet "): + m = re.search(r"inet\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)", line) + if m: + ip = m.group(1) + if not ip.startswith("127.") and not self.apipa(ip): + ips.append(ip) + return ips + + # --------------------------- + # Fallback: use gethostbyname_ex + # --------------------------- + try: + hostname = socket.gethostname() + host_info = socket.gethostbyname_ex(hostname) + for ip in host_info[2]: + if not ip.startswith("127.") and not self.apipa(ip): + ips.append(ip) + except Exception: + pass + + return ips + + def mac(self): + macs = set() + + def _norm(m: str) -> str: + # Normalize to aa:bb:cc:dd:ee:ff + m = m.strip().lower().replace('-', ':') + parts = m.split(':') + if len(parts) != 6: + return m + return ':'.join(p.zfill(2) for p in parts) + + # --------------------------- + # Windows: use getmac + # --------------------------- + if self._os == "windows": + rc, out = self._helper.run(["getmac", "/v", "/fo", "csv"]) + if rc == 0: + # Lines contain something like: + # "Connection Name","Network Adapter","Physical Address","Transport Name" + for line in out.splitlines(): + # Look for MAC patterns + for m in re.findall(r'([0-9A-Fa-f]{2}([-:])[0-9A-Fa-f]{2}(?:\2[0-9A-Fa-f]{2}){4})', line): + macs.add(_norm(m[0])) + return sorted(macs) + + # Fallback: ipconfig /all + rc, out = self._helper.run(["ipconfig", "/all"]) + if rc == 0: + for line in out.splitlines(): + # "Physical Address. . . . . . . . . : 00-11-22-33-44-55" + mm = re.search(r'Physical Address[.\s:]*([0-9A-Fa-f\-:]{17})', line) + if mm: + macs.add(_norm(mm.group(1))) + return sorted(macs) + + return [] + + # --------------------------- + # Linux / macOS: ip link + # --------------------------- + rc, out = self._helper.run([shutil.which("ip") or "ip", "link"]) + if rc == 0: + # Lines with "link/ether 00:11:22:33:44:55" + for line in out.splitlines(): + mm = re.search(r'link/ether\s+([0-9A-Fa-f:]{17})', line) + if mm: + macs.add(_norm(mm.group(1))) + if macs: + return sorted(macs) + + # Fallback: ifconfig + rc, out = self._helper.run([shutil.which("ifconfig") or "ifconfig", "-a"]) + if rc == 0: + for line in out.splitlines(): + # Look for MAC in common formats + for m in re.findall(r'([0-9A-Fa-f]{2}([-:])[0-9A-Fa-f]{2}(?:\2[0-9A-Fa-f]{2}){4})', line): + macs.add(_norm(m[0])) + + return sorted(macs) + + def wan(self): + # IPv4 regex + ipv4_re = re.compile(r'\b([0-9]{1,3}(?:\.[0-9]{1,3}){3})\b') + + # --------------------------- + # Non-Windows: use dig + # --------------------------- + if self._os in ("linux", "macos"): + dig_path = shutil.which("dig") or "dig" + rc, out = self._helper.run( + [dig_path, "+short", "myip.opendns.com", "@resolver1.opendns.com"] + ) + if rc == 0: + for line in out.splitlines(): + m = ipv4_re.search(line) + if m: + return m.group(1) + # If dig is missing or fails, fall through to nslookup below. + + # --------------------------- + # Windows or fallback: nslookup + # --------------------------- + rc, out = self._helper.run([ + shutil.which("nslookup") or "nslookup", + "myip.opendns.com", + "resolver1.opendns.com", + ]) + if rc == 0: + # Typical output has several "Address:" lines; the last IPv4 is usually the WAN IP. + candidates = [] + for line in out.splitlines(): + m = ipv4_re.search(line) + if m: + ip = m.group(1) + # Skip the resolver's own IP (208.67.x.x) if you want only your WAN IP + if not ip.startswith("208.67."): + candidates.append(ip) + if candidates: + return candidates[-1] + + return None + + def apipa(self, ip): + if not isinstance(ip, str): + return False + + parts = ip.split(".") + if len(parts) != 4: + return False + + try: + octets = [int(p) for p in parts] + except ValueError: + return False + + # 169.254.x.x + return (octets[0] == 169 and octets[1] == 254) + + def nmap(self, host, ports): + # Normalize `ports` into a list of ints + port_list = [] + + if isinstance(ports, int): + port_list = [ports] + + elif isinstance(ports, (list, tuple)): + for p in ports: + try: + port_list.append(int(p)) + except Exception: + pass + + elif isinstance(ports, str) and "-" in ports: + # range like "20-30" + try: + start, end = ports.split("-", 1) + start = int(start) + end = int(end) + port_list = list(range(start, end + 1)) + except Exception: + return {} + + else: + # last fallback + try: + port_list = [int(ports)] + except Exception: + return {} + + # No valid ports + if not port_list: + return {} + + results = {} + + # ------------------------------------------------------- + # Try using nmap (fast, reliable, bulk scan) + # ------------------------------------------------------- + nmap_bin = shutil.which("nmap") + if nmap_bin: + # Build port string: "22,80,443" + port_str = ",".join(str(p) for p in port_list) + + args = [ + nmap_bin, + "-p", port_str, + "-T4", + "-Pn", + host + ] + + rc, out = self._helper.run(args) + if rc == 0: + # Parse output for each port + for port in port_list: + pattern = rf"^{port}/\w+\s+open\b" + is_open = False + for line in out.splitlines(): + if re.search(pattern, line.strip(), re.IGNORECASE): + is_open = True + break + results[str(port)] = is_open + + return results + + # ------------------------------------------------------- + # Fallback: try TCP connect for each port + # ------------------------------------------------------- + import socket + for port in port_list: + try: + with socket.create_connection((host, port), timeout=1.0): + results[str(port)] = True + except Exception: + results[str(port)] = False + + return results + + def scan_ap(self) -> List[str]: + ssids: List[str] = [] + + # --- Prefer nmcli if available --- + if shutil.which("nmcli"): + try: + out = subprocess.check_output( + ["nmcli", "-t", "-f", "SSID", "dev", "wifi"], + stderr=subprocess.DEVNULL, + text=True, + ) + for line in out.splitlines(): + s = line.strip() + if s and s not in ssids: + ssids.append(s) + except Exception as e: + print(f"[Tools] nmcli wifi scan failed: {e}") + + # --- Fallback to iwlist if no SSIDs yet --- + if not ssids and shutil.which("iwlist"): + try: + out = subprocess.check_output( + ["iwlist", "scan"], + stderr=subprocess.DEVNULL, + text=True, + ) + for m in re.finditer(r'ESSID:"([^"]*)"', out): + s = m.group(1).strip() + if s and s not in ssids: + ssids.append(s) + except Exception as e: + print(f"[Tools] iwlist wifi scan failed: {e}") + + return ssids diff --git a/dist/macos/Replicator.app/Contents/Resources/core/service.py b/dist/macos/Replicator.app/Contents/Resources/core/service.py new file mode 100644 index 00000000..ab1677a9 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/service.py @@ -0,0 +1,1674 @@ +#!/usr/bin/env python3 +# src/core/service.py + +from __future__ import annotations + +import os +import sys +import time +import signal +import shutil +import subprocess +import platform +import ctypes +import json +from pathlib import Path +from dataclasses import dataclass +from typing import Any, Callable, Optional +from PyQt5.QtCore import QTimer +# PyQt5 widgets +from PyQt5.QtWidgets import ( + QApplication, + QDialog, + QTabWidget, + QGroupBox, + QVBoxLayout, + QHBoxLayout, + QFormLayout, + QLabel, + QPushButton, + QPlainTextEdit, + QMessageBox, + QWidget, +) + +# Optional UI helpers (icons/buttons) +try: + from .ui import Form # type: ignore +except Exception: # pragma: no cover + Form = None # type: ignore + + +@dataclass +class _Task: + description: str + callable: Callable[..., Any] + interval: float = 60.0 + last_run: float = 0.0 + + +class Service: + """Service module for corePY. + + This class is **not** an application runner like CommandLine / Application. + It is a module that: + - Adds service-management commands to the CLI (start/stop/restart/install/uninstall) + - Allows apps to register tasks to be executed by the service loop + + Usage pattern (from an app/handler): + + def cli(self, cli): + cli.add("run", "Run jobs", self.run) + cli.service.add("run", "Run jobs", self.run, interval=60) + + Then: + python main.py --start + + runs all registered service tasks in a loop. + """ + + def __init__(self, logger=None, configuration=None): + self._tasks: dict[str, _Task] = {} + self._stop_requested = False + self._loop_sleep = 1.0 + self._pidfile_path: Optional[str] = None + + # Optional integrations (passed by CommandLine) + self._logger = logger + self._configuration = configuration + + # Service configuration defaults + if self._configuration is not None: + # How often the main loop wakes up to check due tasks (seconds) + self._configuration.add("service.loopSleep", 1, "number", label="Service loop sleep (s)", min=1, max=60) + # Default interval used when registering tasks (seconds) + self._configuration.add("service.defaultInterval", 3600, "number", label="Service default task interval (s)", min=1, max=86400) + # Reverse-DNS prefix used to name/register the service (e.g. com.laswitchtech) + # The final label becomes: . (lowercased and sanitized) + self._configuration.add("service.domain", "com.corepy", "text", label="Service domain (reverse DNS)") + # Persist any new defaults + self._configuration.save() + + # Initial visibility update + self._refresh_action_visibility() + + # Keep visibility in sync when configuration is saved/changed + try: + self._configuration.configChanged.connect(lambda _cfg: self._refresh_action_visibility()) + except Exception: + pass + def _service_domain(self) -> str: + """Return reverse-DNS domain used for service labels. + + Prefer configuration key `service.domain` when available; fall back to + an environment override COREPY_SERVICE_DOMAIN; then to 'com.corepy'. + """ + # 1) Configuration + try: + if self._configuration is not None: + v = (self._configuration.get("service.domain", "") or "").strip() + if v: + return v + except Exception: + pass + + # 2) Environment override + v = (os.environ.get("COREPY_SERVICE_DOMAIN") or "").strip() + if v: + return v + + return "com.corepy" + def _refresh_action_visibility(self) -> None: + """Show/hide configuration action buttons based on install/running state.""" + if self._configuration is None: + return + + installed = self._is_installed() + running = self._is_service_active() if installed else self._is_running() + + # Start/Stop are mutually exclusive when installed; when not installed, start runs in-process. + self._configuration.visibility("service.actions.start", not running) + self._configuration.visibility("service.actions.stop", running) + + # Restart only makes sense when running + self._configuration.visibility("service.actions.restart", running) + + # Install/Uninstall are mutually exclusive + self._configuration.visibility("service.actions.install", not installed) + self._configuration.visibility("service.actions.uninstall", installed) + + # ------------------------------------------------------------------ + # CLI integration + # ------------------------------------------------------------------ + + def cli(self, cli=None) -> None: + """Register service management commands into CommandLine.""" + if cli is None: + return + + cli.add("service.status", "Show service status.", self.status) + cli.add("service.start", "Start the service loop.", self.start) + cli.add("service.stop", "Stop the running service.", self.stop) + cli.add("service.restart", "Restart the running service.", self.restart) + cli.add("service.install", "Install as a python service.", self.install) + cli.add("service.uninstall", "Uninstall the python service.", self.uninstall) + + # ------------------------------------------------------------------ + # Task registry + # ------------------------------------------------------------------ + + def add( + self, + command: str, + description: str = "", + callable: Optional[Callable[..., Any]] = None, + *, + interval: Optional[float] = None, + ) -> None: + """Register a command to run as part of the service loop. + + Notes: + - The command name is informational here (used for logs / debugging). + - The callable is invoked with **no arguments** by the service loop. + - Use closures/lambdas if you need to bind context. + """ + if callable is None: + raise ValueError("Service.add() requires a callable") + + # Keep the name consistent with CLI commands (no leading -- expected here) + normalized = command[2:] if command.startswith("--") else command + + # Resolve effective interval from configuration (if present) + # - interval is None: use configured service.defaultInterval (default 3600) + # - interval == 0: run every tick + # - interval > 0: use that value (and allow override via per-task config) + if interval is None: + effective_interval = 0.0 + else: + effective_interval = float(interval) + + if self._configuration is not None: + key = f"service.intervals.{normalized}" + + # Schema default for this task's interval + if interval is None: + schema_default = int(self._configuration.get("service.defaultInterval", 3600) or 3600) + else: + schema_default = int(effective_interval) + + self._configuration.add( + key, + schema_default, + "spin", + label=f"Service interval: {normalized} (s)", + min=0, + max=86400, + ) + + try: + configured = self._configuration.get(key, schema_default) + effective_interval = float(configured) if configured is not None else float(schema_default) + except Exception: + effective_interval = float(schema_default) + + self._configuration.save() + else: + # No configuration system; if interval is None, fall back to 3600 + if interval is None: + effective_interval = 3600.0 + + self._tasks[normalized] = _Task( + description=description, + callable=callable, + interval=effective_interval, + last_run=0.0, + ) + + def remove(self, command: str) -> None: + normalized = command[2:] if command.startswith("--") else command + if normalized in self._tasks: + del self._tasks[normalized] + + def clear(self) -> None: + self._tasks.clear() + + def set_loop_sleep(self, seconds: float) -> None: + """How often to wake up to check due tasks.""" + self._loop_sleep = max(0.1, float(seconds)) + + def _log(self, message: str, level: str = "info") -> None: + """Log to core Log module if available, else print.""" + try: + if self._logger is not None and hasattr(self._logger, "append"): + self._logger.append(message, channel="service", level=level) + return + except Exception: + pass + + # Fallback to console + if level == "error": + print(message, file=sys.stderr) + else: + print(message) + + # ------------------------------------------------------------------ + # Service control + # ------------------------------------------------------------------ + + def start(self) -> None: + """Enter the service loop in the current process.""" + self._stop_requested = False + + # If installed, either: + # - We are a *manager* request (user invoked --start): delegate to OS manager, OR + # - We are the *service process* (OS invoked --start): run the loop in-process. + if self._is_installed() and not self._running_under_service_manager(): + self._service_manager_start() + self._refresh_action_visibility() + return + + # Apply configured loop sleep if available + if self._configuration is not None: + try: + self._loop_sleep = float(self._configuration.get("service.loopSleep", 1) or 1) + except Exception: + self._loop_sleep = 1.0 + + self._install_signal_handlers() + + pidfile = self._pidfile() + if self._is_running(): + self._log(f"Service already running (pidfile: {pidfile}).", level="info") + return + + os.makedirs(os.path.dirname(pidfile), exist_ok=True) + with open(pidfile, "w", encoding="utf-8") as f: + f.write(str(os.getpid())) + + self._log(f"Service started (PID {os.getpid()}).", level="info") + + try: + self._service_loop() + finally: + self._cleanup_pidfile() + self._log("Service stopped.", level="info") + + def stop(self) -> None: + """Stop a running service by signaling the PID from the pidfile.""" + # If installed, delegate to platform service manager. + if self._is_installed(): + self._service_manager_stop() + self._refresh_action_visibility() + return + + pid = self._read_pidfile() + if not pid: + self._log("Service is not running (no pidfile).", level="info") + return + + if not self._pid_exists(pid): + self._log("Service pidfile found but process is not running. Cleaning up.", level="warning") + self._cleanup_pidfile() + return + + try: + os.kill(pid, signal.SIGTERM) + self._log(f"Stop signal sent to PID {pid}.", level="info") + except PermissionError: + self._log(f"Permission denied sending SIGTERM to PID {pid}.", level="error") + except ProcessLookupError: + self._log(f"Process {pid} not found. Cleaning up pidfile.", level="error") + self._cleanup_pidfile() + + def restart(self) -> None: + # If installed, delegate to platform service manager. + if self._is_installed(): + self._service_manager_restart() + self._refresh_action_visibility() + return + + # Otherwise run in-process restart + self.stop() + time.sleep(0.5) + self.start() + + def status(self) -> None: + """Show current service status.""" + pidfile = self._pidfile() + pid = self._read_pidfile() + + installed = self._is_installed() + running = self._is_service_active() if installed else bool(pid and self._pid_exists(pid)) + + # Build a readable status + lines = [] + lines.append(f"Service: {self._app_name()}") + lines.append(f"PID file: {pidfile}") + lines.append(f"Installed: {'yes' if installed else 'no'}") + lines.append(f"Running: {'yes' if running else 'no'}") + if pid: + lines.append(f"PID: {pid}") + lines.append(f"Tasks registered: {len(self._tasks)}") + + # Show intervals (effective) + if self._configuration is not None and self._tasks: + lines.append("Task intervals (s):") + for name in sorted(self._tasks.keys()): + key = f"service.intervals.{name}" + interval = self._configuration.get(key, self._tasks[name].interval) + lines.append(f" - {name}: {interval}") + + msg = "\n".join(lines) + print(msg) + self._log(msg, level="info") + + + # ------------------------------------------------------------------ + # UI helper + # ------------------------------------------------------------------ + + def open_manager_dialog(self, parent=None) -> None: + """Open a small GUI dialog to manage the service (install/start/stop + logs). + + This is intentionally optional: apps can call it when running with a GUI. + """ + try: + dlg = ServiceManagerDialog(self, parent=parent) + dlg.exec_() + except Exception as e: + # If called from a non-GUI context, fail gracefully. + self._log(f"Failed to open service manager dialog: {e}", level="error") + + def request_stop(self) -> None: + """Request the current service loop to stop (used by signal handlers).""" + self._stop_requested = True + + # ------------------------------------------------------------------ + # Scheduler loop + # ------------------------------------------------------------------ + + def _service_loop(self) -> None: + if not self._tasks: + self._log("Warning: no tasks registered for service mode.", level="warning") + + while not self._stop_requested: + now = time.time() + + for name, task in list(self._tasks.items()): + # interval == 0 means "run every tick" + due = (task.interval <= 0) or (now - task.last_run >= task.interval) + if not due: + continue + + try: + task.callable() + task.last_run = now + except Exception as e: + # Keep the service alive; print error. + self._log(f"Task {name} failed: {e}", level="error") + + time.sleep(self._loop_sleep) + + # ------------------------------------------------------------------ + # systemd integration (Linux only) + # ------------------------------------------------------------------ + + def install(self) -> None: + + if sys.platform.startswith("win"): + self._install_windows_service() + elif sys.platform == "darwin": + self._install_macos_launchd() + else: + self._install_systemd() + + self._refresh_action_visibility() + + def uninstall(self) -> None: + + if sys.platform.startswith("win"): + self._uninstall_windows_service() + elif sys.platform == "darwin": + self._uninstall_macos_launchd() + else: + self._uninstall_systemd() + + self._refresh_action_visibility() + + def _install_systemd(self) -> None: + """Install a systemd unit that runs ` --start`.""" + if shutil.which("systemctl") is None: + raise RuntimeError("systemctl not found; systemd does not appear available") + + service_name = f"{self._app_name()}.service" + unit_path = os.path.join("/etc/systemd/system", service_name) + + program_start, argv_start, workdir = self._service_command("start") + program_stop, argv_stop, _ = self._service_command("stop") + + unit = self._systemd_unit( + service_name=service_name, + python_exe=program_start, + entrypoint=" ".join(argv_start), + working_dir=workdir, + pidfile=self._pidfile(), + execstop_program=program_stop, + execstop_args=" ".join(argv_stop), + ) + + with open(unit_path, "w", encoding="utf-8") as f: + f.write(unit) + + subprocess.run(["systemctl", "daemon-reload"], check=False) + subprocess.run(["systemctl", "enable", "--now", service_name], check=False) + + print(f"Installed and started: {unit_path}") + + def _uninstall_systemd(self) -> None: + if shutil.which("systemctl") is None: + raise RuntimeError("systemctl not found; systemd does not appear available") + + service_name = f"{self._app_name()}.service" + unit_path = os.path.join("/etc/systemd/system", service_name) + + subprocess.run(["systemctl", "disable", "--now", service_name], check=False) + if os.path.exists(unit_path): + os.remove(unit_path) + subprocess.run(["systemctl", "daemon-reload"], check=False) + + print(f"Uninstalled: {unit_path}") + + def _systemd_unit( + self, + *, + service_name: str, + python_exe: str, + entrypoint: str, + working_dir: str, + pidfile: str, + execstop_program: str, + execstop_args: str, + ) -> str: + app_name = self._app_name() + return ( + "[Unit]\n" + f"Description={app_name}\n" + "After=network.target\n\n" + "[Service]\n" + "Type=simple\n" + "Environment=COREPY_RUN_AS_SERVICE=1\n" + f"Environment=COREPY_SERVICE_LABEL={self._service_label()}\n" + f"WorkingDirectory={working_dir}\n" + f"ExecStart={python_exe} {entrypoint}\n" + f"ExecStop={execstop_program} {execstop_args}\n" + "Restart=on-failure\n" + "RestartSec=2\n" + f"PIDFile={pidfile}\n" + "\n" + "[Install]\n" + "WantedBy=multi-user.target\n" + ) + def _running_under_service_manager(self) -> bool: + """Return True if this process should run the service loop. + + When installed, `start()` is used both to *request* the service manager to + start the job and as the entrypoint that the service manager executes. + + We differentiate the two cases using an explicit env flag set by the + service definitions (launchd/systemd/Windows), plus a couple of platform + hints as fallback. + """ + # Explicit flag (preferred) + flag = (os.environ.get("COREPY_RUN_AS_SERVICE") or "").strip().lower() + if flag in ("1", "true", "yes", "on"): + return True + + # Fallback hints + if sys.platform == "darwin": + # launchd commonly sets this for jobs + xpc = (os.environ.get("XPC_SERVICE_NAME") or "").strip() + if xpc and xpc == self._service_label(): + return True + + if not sys.platform.startswith("win"): + # systemd sets INVOCATION_ID for services + if os.environ.get("INVOCATION_ID"): + return True + + return False + + # ------------------------------------------------------------------ + # Internals + # ------------------------------------------------------------------ + + def _app_name(self) -> str: + # Try to read from Qt application if present, else fallback. + try: + inst = QApplication.instance() + if inst and inst.applicationName(): + return inst.applicationName() + except Exception: + pass + return "corepy" + + def _pidfile(self) -> str: + if self._pidfile_path: + return self._pidfile_path + self._pidfile_path = self._default_pidfile_path() + return self._pidfile_path + + def _default_pidfile_path(self) -> str: + name = self._app_name() or "corepy" + candidate = os.path.join("/run", f"{name}.pid") + try: + os.makedirs(os.path.dirname(candidate), exist_ok=True) + if os.access(os.path.dirname(candidate), os.W_OK): + return candidate + except Exception: + pass + return os.path.join("/tmp", f"{name}.pid") + + def _read_pidfile(self) -> Optional[int]: + try: + with open(self._pidfile(), "r", encoding="utf-8") as f: + raw = f.read().strip() + return int(raw) if raw else None + except Exception: + return None + + def _cleanup_pidfile(self) -> None: + try: + path = self._pidfile() + if os.path.exists(path): + os.remove(path) + except Exception: + pass + + def _pid_exists(self, pid: int) -> bool: + if pid <= 0: + return False + try: + os.kill(pid, 0) + return True + except Exception: + return False + + def _is_running(self) -> bool: + pid = self._read_pidfile() + return bool(pid and self._pid_exists(pid)) + + def _install_signal_handlers(self) -> None: + def _handler(_sig, _frame): + self.request_stop() + + try: + signal.signal(signal.SIGTERM, _handler) + signal.signal(signal.SIGINT, _handler) + except Exception: + pass + + + # ------------------------------------------------------------------ + # Windows elevation helpers + # ------------------------------------------------------------------ + + def _windows_is_admin(self) -> bool: + """Return True if the current process has admin rights on Windows.""" + if not sys.platform.startswith("win"): + return False + try: + return bool(ctypes.windll.shell32.IsUserAnAdmin()) + except Exception: + return False + + def _windows_relaunch_elevated(self, argv: list[str]) -> bool: + """Relaunch the current executable with UAC elevation. + + Returns True if the elevation prompt was successfully triggered. + """ + if not sys.platform.startswith("win"): + return False + + # Avoid infinite loops if something goes wrong. + if (os.environ.get("COREPY_ELEVATED_RELAUNCH") or "").strip() == "1": + return False + + try: + # Build argument string for ShellExecuteW. + # Use subprocess.list2cmdline to quote correctly for Windows. + args = list(argv[1:]) + ["--elevated-relaunch"] + params = subprocess.list2cmdline(args) + + # Pass a marker to the elevated process. + # We cannot reliably set environment variables via ShellExecute, + # so we append an internal flag and also set an env var for same-process codepaths. + os.environ["COREPY_ELEVATED_RELAUNCH"] = "1" + + # 1 = SW_SHOWNORMAL + rc = ctypes.windll.shell32.ShellExecuteW(None, "runas", argv[0], params, None, 1) + return int(rc) > 32 + except Exception: + return False + + # ------------------------------------------------------------------ + # Cross-platform service manager helpers + # ------------------------------------------------------------------ + + def _run_subprocess(self, args: list[str], **kwargs) -> subprocess.CompletedProcess: + if sys.platform.startswith("win"): + try: + kwargs.setdefault("creationflags", subprocess.CREATE_NO_WINDOW) + except Exception: + pass + return subprocess.run(args, **kwargs) + + def _service_label(self) -> str: + """Stable label used for OS service registration. + + - macOS launchd prefers reverse-DNS labels. + - Windows 'sc' service names and systemd unit names also benefit from stability. + + Result: . (lowercased and sanitized) + """ + domain = (self._service_domain() or "com.corepy").strip().strip(".") + app = (self._app_name() or "corepy").strip() + + base = f"{domain}.{app}" if domain else app + base = base.lower() + + # Keep only characters typically safe across platforms; replace others with '-' + safe = "".join(c if c.isalnum() or c in ("-", "_", ".") else "-" for c in base) + # Avoid accidental leading/trailing dots + safe = safe.strip(".") + return safe or "com.corepy.corepy" + + def _entry_command(self) -> tuple[str, str, str]: + """Return (python_exe, entrypoint, working_dir) for service registration. + + Notes: + - When `sys.argv[0]` is a relative path and the current working directory + is already inside `src/`, it's easy to end up with paths like `src/src/main.py`. + - launchd will happily try to execute that path, but the process will fail. + + This helper resolves the path and applies a small normalization pass. + """ + python_exe = sys.executable + + # Resolve argv[0] robustly (handles relative paths) + try: + p = Path(sys.argv[0]).expanduser() + entry_path = (p if p.is_absolute() else (Path.cwd() / p)).resolve() + except Exception: + entry_path = Path(os.path.abspath(sys.argv[0])) + + def _dedupe_consecutive(parts: list[str]) -> list[str]: + out: list[str] = [] + for seg in parts: + if out and out[-1] == seg: + continue + out.append(seg) + return out + + # If we ended up with duplicated segments like .../src/src/..., collapse them. + parts = list(entry_path.parts) + deduped = Path(*_dedupe_consecutive(parts)) + + # Prefer the deduped version if it exists. + if deduped.exists(): + entry_path = deduped + else: + # Common case: /.../src/src/main.py -> /.../src/main.py + # If the path contains two consecutive 'src' segments, drop one. + if "src" in parts: + try: + new_parts: list[str] = [] + i = 0 + while i < len(parts): + if i + 1 < len(parts) and parts[i] == parts[i + 1]: + # Drop the duplicate segment + new_parts.append(parts[i]) + i += 2 + continue + new_parts.append(parts[i]) + i += 1 + candidate = Path(*new_parts) + if candidate.exists(): + entry_path = candidate + except Exception: + pass + + entry = str(entry_path) + workdir = str(entry_path.parent) + return python_exe, entry, workdir + + def _is_installed(self) -> bool: + """Best-effort check whether this app is installed as a service.""" + try: + if sys.platform.startswith("win"): + name = self._service_label() + # sc query returns non-zero if missing + r = self._run_subprocess(["sc", "query", name], capture_output=True, text=True) + return r.returncode == 0 + if sys.platform == "darwin": + return self._macos_plist_path().exists() + # linux + if shutil.which("systemctl") is None: + return False + service_name = f"{self._service_label()}.service" + r = subprocess.run(["systemctl", "is-enabled", service_name], capture_output=True, text=True) + return r.returncode == 0 + except Exception: + return False + + def _is_service_active(self) -> bool: + """Check if the installed service is running (best-effort).""" + try: + if sys.platform.startswith("win"): + name = self._service_label() + r = self._run_subprocess(["sc", "query", name], capture_output=True, text=True) + if r.returncode != 0: + return False + out = (r.stdout or "") + (r.stderr or "") + return "RUNNING" in out.upper() + if sys.platform == "darwin": + label = self._service_label() + r = subprocess.run(["launchctl", "print", f"gui/{os.getuid()}/{label}"], capture_output=True, text=True) + if r.returncode != 0: + return False + out = (r.stdout or "") + (r.stderr or "") + o = out.lower() + # Typical indicators in `launchctl print` output + if "job state = running" in o: + return True + if "state = running" in o: + return True + # If explicitly exited, consider not running + if "job state = exited" in o: + return False + # Fallback: loaded but ambiguous => treat as active + return True + # linux + if shutil.which("systemctl") is None: + return False + service_name = f"{self._service_label()}.service" + r = subprocess.run(["systemctl", "is-active", service_name], capture_output=True, text=True) + return r.returncode == 0 + except Exception: + return False + + def _service_manager_start(self) -> None: + label = self._service_label() + try: + if sys.platform.startswith("win"): + # Prefer NSSM if bundled + if self._windows_has_nssm(): + self._windows_nssm_run(["start", label]) + else: + self._run_subprocess(["sc", "start", label], check=False) + self._log(f"Requested start for Windows service: {label}") + return + if sys.platform == "darwin": + plist = self._macos_plist_path() + domain = f"gui/{os.getuid()}" + target = f"{domain}/{label}" + + # If it's already loaded, bootstrap may fail with error 5. + already_loaded = False + try: + r = subprocess.run(["launchctl", "print", target], capture_output=True, text=True) + already_loaded = (r.returncode == 0) + except Exception: + already_loaded = False + + if plist.exists() and not already_loaded: + subprocess.run(["launchctl", "bootstrap", domain, str(plist)], check=False) + + # Enable + kickstart regardless (these are safe even if already loaded) + subprocess.run(["launchctl", "enable", target], check=False) + subprocess.run(["launchctl", "kickstart", "-k", target], check=False) + + self._log(f"Requested start for launchd agent: {label}") + return + # linux + service_name = f"{label}.service" + subprocess.run(["systemctl", "start", service_name], check=False) + self._log(f"Requested start for systemd service: {service_name}") + except Exception as e: + self._log(f"Failed to start service via manager: {e}", level="error") + + def _service_manager_stop(self) -> None: + label = self._service_label() + try: + if sys.platform.startswith("win"): + # Prefer NSSM if bundled + if self._windows_has_nssm(): + self._windows_nssm_run(["stop", label]) + else: + self._run_subprocess(["sc", "stop", label], check=False) + self._log(f"Requested stop for Windows service: {label}") + return + if sys.platform == "darwin": + subprocess.run(["launchctl", "bootout", f"gui/{os.getuid()}/{label}"], check=False) + self._log(f"Requested stop for launchd agent: {label}") + return + service_name = f"{label}.service" + subprocess.run(["systemctl", "stop", service_name], check=False) + self._log(f"Requested stop for systemd service: {service_name}") + except Exception as e: + self._log(f"Failed to stop service via manager: {e}", level="error") + + def _service_manager_restart(self) -> None: + label = self._service_label() + try: + if sys.platform.startswith("win"): + if self._windows_has_nssm(): + self._windows_nssm_run(["restart", label]) + else: + self._run_subprocess(["sc", "stop", label], check=False) + time.sleep(0.5) + self._run_subprocess(["sc", "start", label], check=False) + self._log(f"Requested restart for Windows service: {label}") + return + if sys.platform == "darwin": + subprocess.run(["launchctl", "kickstart", "-k", f"gui/{os.getuid()}/{label}"], check=False) + self._log(f"Requested restart for launchd agent: {label}") + return + service_name = f"{label}.service" + subprocess.run(["systemctl", "restart", service_name], check=False) + self._log(f"Requested restart for systemd service: {service_name}") + except Exception as e: + self._log(f"Failed to restart service via manager: {e}", level="error") + + # ------------------------------------------------------------------ + # Windows service install/uninstall (sc.exe) + # ------------------------------------------------------------------ + + def _install_windows_service(self) -> None: + """Install Windows service. + + Prefer NSSM when available (bundled in corePY). + + Why: + - `sc create` + a long `cmd.exe /c ...` binPath is fragile. + - NSSM hosts a normal console program and reports service state properly. + """ + name = self._service_label() + + # Installing a Windows service requires elevation. + if not self._windows_is_admin(): + self._log("Admin privileges required to install the service. Requesting elevation...", level="info") + if self._windows_relaunch_elevated(sys.argv): + return + raise RuntimeError("Admin privileges required to install the service.") + + # Use NSSM if present. + if not self._windows_has_nssm(): + raise RuntimeError( + "NSSM was not found. Expected one of: " + "src/bin/nssm/windows/x86/nssm.exe or src/bin/nssm/windows/x86_64/nssm.exe (or the same under core/src/bin)." + ) + + # Resolve the command the service should run. + program, argv, workdir = self._service_command("start") + + # Install directory: stable place for logs and (optionally) copied binaries. + install_dir = self._windows_install_dir() + install_dir.mkdir(parents=True, exist_ok=True) + + logs_dir = install_dir.parent / "log" + logs_dir.mkdir(parents=True, exist_ok=True) + + stdout_log = logs_dir / f"{name}.out.log" + stderr_log = logs_dir / f"{name}.err.log" + + # In frozen mode, it's safer to point NSSM at a stable path. + # If we're already running from Program Files/ProgramData, we can use it directly. + # Otherwise (common during dev / unpackaged runs), we still allow it, but you may + # want to set COREPY_SERVICE_EXECUTABLE to an installed *-cli.exe. + app_program = program + app_dir = workdir + + # Install (create) service + self._windows_nssm_run(["install", name, app_program] + argv) + + # Configure working directory + self._windows_nssm_run(["set", name, "AppDirectory", app_dir]) + + # Environment variables so `start()` knows this is the service process + env_extra = "COREPY_RUN_AS_SERVICE=1\r\n" + f"COREPY_SERVICE_LABEL={name}" + "\r\n" + self._windows_nssm_run(["set", name, "AppEnvironmentExtra", env_extra]) + + # Logging + self._windows_nssm_run(["set", name, "AppStdout", str(stdout_log)]) + self._windows_nssm_run(["set", name, "AppStderr", str(stderr_log)]) + self._windows_nssm_run(["set", name, "AppRotateFiles", "1"]) + self._windows_nssm_run(["set", name, "AppRotateOnline", "1"]) + self._windows_nssm_run(["set", name, "AppRotateSeconds", "86400"]) + self._windows_nssm_run(["set", name, "AppRotateBytes", str(10 * 1024 * 1024)]) + + # Startup + self._windows_nssm_run(["set", name, "Start", "SERVICE_AUTO_START"]) + + # Restart policy + self._windows_nssm_run(["set", name, "AppExit", "Default", "Restart"]) + + self._log(f"Installed Windows service (NSSM): {name}") + + def _uninstall_windows_service(self) -> None: + name = self._service_label() + + # Uninstalling a Windows service requires elevation. + if not self._windows_is_admin(): + self._log("Admin privileges required to uninstall the service. Requesting elevation...", level="info") + if self._windows_relaunch_elevated(sys.argv): + return + raise RuntimeError("Admin privileges required to uninstall the service.") + + # Prefer NSSM removal if available + if self._windows_has_nssm(): + # Stop (best-effort) + self._windows_nssm_run(["stop", name], check=False) + # remove confirm + self._windows_nssm_run(["remove", name, "confirm"], check=False) + self._log(f"Uninstalled Windows service (NSSM): {name}") + return + + # Fallback to sc + subprocess.run(["sc", "stop", name], check=False) + r = subprocess.run(["sc", "delete", name], capture_output=True, text=True) + if r.returncode != 0: + raise RuntimeError(f"sc delete failed: {(r.stdout or '') + (r.stderr or '')}") + self._log(f"Uninstalled Windows service: {name}") + + # ------------------------------------------------------------------ + # macOS launchd install/uninstall (per-user LaunchAgent) + # ------------------------------------------------------------------ + + def _macos_plist_path(self) -> Path: + # Per-user agent (no root required) + return Path.home() / "Library" / "LaunchAgents" / f"{self._service_label()}.plist" + + def _install_macos_launchd(self) -> None: + label = self._service_label() + program, argv, workdir = self._service_command("start") + plist_path = self._macos_plist_path() + plist_path.parent.mkdir(parents=True, exist_ok=True) + # Ensure logs directory exists + logs_dir = Path.home() / "Library" / "Logs" / self._app_name() + logs_dir.mkdir(parents=True, exist_ok=True) + + # Simple LaunchAgent; keep it alive, run at load. + plist = ( + "\n" + "\n" + "\n" + "\n" + f" Label{label}\n" + " ProgramArguments\n" + " \n" + f" {program}\n" + + "".join(f" {a}\n" for a in argv) + + " \n" + f" WorkingDirectory{workdir}\n" + " EnvironmentVariables\n" + " \n" + " COREPY_RUN_AS_SERVICE1\n" + f" COREPY_SERVICE_LABEL{label}\n" + " \n" + " RunAtLoad\n" + " KeepAlive\n" + f" StandardOutPath{Path.home() / 'Library' / 'Logs' / self._app_name() / 'service.out.log'}\n" + f" StandardErrorPath{Path.home() / 'Library' / 'Logs' / self._app_name() / 'service.err.log'}\n" + "\n" + "\n" + ) + + plist_path.write_text(plist, encoding="utf-8") + + # Load into the current user's launchd + subprocess.run(["launchctl", "bootstrap", f"gui/{os.getuid()}", str(plist_path)], check=False) + subprocess.run(["launchctl", "enable", f"gui/{os.getuid()}/{label}"], check=False) + subprocess.run(["launchctl", "kickstart", "-k", f"gui/{os.getuid()}/{label}"], check=False) + + self._log(f"Installed launchd LaunchAgent: {plist_path}") + + def _uninstall_macos_launchd(self) -> None: + label = self._service_label() + plist_path = self._macos_plist_path() + + subprocess.run(["launchctl", "bootout", f"gui/{os.getuid()}/{label}"], check=False) + if plist_path.exists(): + try: + plist_path.unlink() + except Exception: + pass + + self._log(f"Uninstalled launchd LaunchAgent: {label}") + + def _service_command(self, action: str) -> tuple[str, list[str], str]: + """Return (program, argv, working_dir) for service manager registration. + + Supports both source runs (python + entry script) and frozen bundles (.exe/.app). + + Environment overrides: + - COREPY_SERVICE_EXECUTABLE: absolute/relative path to the executable to register + (useful to force a sibling *-cli.exe on Windows). + """ + action = (action or "").strip().lstrip("-") + if action not in ("start", "stop"): + raise ValueError(f"Invalid service action: {action}") + + # Frozen bundle: run the executable directly. + if getattr(sys, "frozen", False): + exe_path = Path(sys.executable).expanduser() + + # Optional override (preferred for Windows to target a console *-cli.exe) + override = (os.environ.get("COREPY_SERVICE_EXECUTABLE") or "").strip().strip('"') + if override: + ov = Path(override).expanduser() + if not ov.is_absolute(): + ov = (Path.cwd() / ov).resolve() + if ov.exists(): + exe_path = ov + + # Best-effort Windows: if running GUI exe, prefer sibling "-cli.exe". + if sys.platform.startswith("win"): + try: + s = str(exe_path) + if s.lower().endswith(".exe") and not s.lower().endswith("-cli.exe"): + cand = Path(s[:-4] + "-cli.exe") + if cand.exists(): + exe_path = cand + except Exception: + pass + + program = str(exe_path) + workdir = str(exe_path.parent) + argv = [f"--{action}"] + return program, argv, workdir + + # Source run: python + entrypoint + python_exe, entry, workdir = self._entry_command() + program = python_exe + argv = [entry, f"--{action}"] + return program, argv, workdir + + def _windows_is_64bit(self) -> bool: + try: + return platform.machine().endswith("64") or ("PROGRAMFILES(X86)" in os.environ) + except Exception: + return True + + def _windows_install_dir(self) -> Path: + """Stable per-machine install dir for service-related assets/logs.""" + base = Path(os.environ.get("PROGRAMDATA", r"C:\\ProgramData")) + return base / (self._app_name() or "corepy") / "bin" + + def _windows_bin_dir(self) -> Path: + """Best-effort directory where vendored tools live on Windows. + + Priority: + 1) Stable install dir under ProgramData (created by this module) + 2) If frozen, beside the executable (typical for unpacked builds) + 3) Source-tree locations (dev) + + Returns a directory that *may* not exist; callers should validate. + """ + # 1) Preferred stable location + try: + d = self._windows_install_dir() + if d: + return d + except Exception: + pass + + # 2) Frozen bundle: beside the executable + if getattr(sys, "frozen", False): + try: + return Path(sys.executable).resolve().parent + except Exception: + pass + + # 3) Fallback: current working directory + return Path.cwd() + + def _windows_copy_tool_to_install_dir(self, tool_path: Path) -> Path: + """Copy a bundled tool (like nssm.exe) into the stable install dir. + + This avoids services pointing into PyInstaller's temporary _MEI folder. + """ + install_dir = self._windows_install_dir() + install_dir.mkdir(parents=True, exist_ok=True) + + dest = install_dir / tool_path.name + try: + # Only copy if missing or different size/mtime; keep it simple. + if not dest.exists(): + shutil.copy2(str(tool_path), str(dest)) + else: + try: + if tool_path.stat().st_size != dest.stat().st_size: + shutil.copy2(str(tool_path), str(dest)) + except Exception: + # If we can't stat, just overwrite. + shutil.copy2(str(tool_path), str(dest)) + except Exception: + # Last resort: attempt overwrite + try: + shutil.copy2(str(tool_path), str(dest)) + except Exception: + pass + + return dest + + def _windows_nssm_candidates(self) -> list[Path]: + """Return candidate NSSM locations (supports both corePY and vendored corePY inside apps).""" + # Running inside corePY source tree + here = Path(__file__).resolve() + core_dir = here.parent # .../src/core + + rels = [ + # Common repo layouts + Path("src") / "bin" / "nssm" / "windows" / "x86" / "nssm.exe", + Path("src") / "bin" / "nssm" / "windows" / "x86_64" / "nssm.exe", + Path("bin") / "nssm" / "windows" / "x86" / "nssm.exe", + Path("bin") / "nssm" / "windows" / "x86_64" / "nssm.exe", + + # Vendored corePY inside another repo (e.g. Replicator: src/core/src/bin/...) + Path("src") / "core" / "src" / "bin" / "nssm" / "windows" / "x86" / "nssm.exe", + Path("src") / "core" / "src" / "bin" / "nssm" / "windows" / "x86_64" / "nssm.exe", + + # Flat copies in a bin dir (after we copy tools into ProgramData) + Path("nssm.exe"), + Path("bin") / "nssm.exe", + Path("tools") / "nssm.exe", + ] + + roots = [ + Path.cwd(), + core_dir.parent, # .../src + core_dir.parent.parent, # project root + here.parent.parent, # .../src (safe-ish) + ] + + # Preferred stable install dir (ProgramData) for services + try: + roots.insert(0, self._windows_install_dir()) + except Exception: + pass + + # If frozen, also look beside the executable + if getattr(sys, "frozen", False): + try: + roots.append(Path(sys.executable).resolve().parent) + except Exception: + pass + + out: list[Path] = [] + for root in roots: + for rel in rels: + p = (root / rel).resolve() + out.append(p) + return out + + def _windows_find_nssm(self) -> Optional[Path]: + if not sys.platform.startswith("win"): + return None + + # Allow explicit override + override = (os.environ.get("COREPY_NSSM") or "").strip().strip('"') + if override: + p = Path(override).expanduser() + if not p.is_absolute(): + p = (Path.cwd() / p).resolve() + if p.exists(): + return p + + want_64 = self._windows_is_64bit() + # Prefer matching arch first + preferred = ["x86_64"] if want_64 else ["x86"] + preferred += ["x86"] if want_64 else ["x86_64"] + + candidates = self._windows_nssm_candidates() + candidate: Optional[Path] = None + # Prefer matching arch + for arch in preferred: + for p in candidates: + if f"\\{arch}\\" in str(p).lower() and p.exists(): + candidate = p + break + if candidate is not None: + break + # Any existing + if candidate is None: + for p in candidates: + if p.exists(): + candidate = p + break + if candidate is not None: + # If it's in a temp unpack dir, copy to stable dir. + try: + s = str(candidate) + if "_mei" in s.lower() or "\\appdata\\local\\temp\\" in s.lower(): + stable = self._windows_copy_tool_to_install_dir(candidate) + if stable.exists(): + return stable + except Exception: + pass + return candidate + + # If we found NSSM inside a PyInstaller temp folder (_MEI...), copy it to stable ProgramData + # and return the stable path so services never reference a temporary location. + try: + found = None + for arch in preferred: + for p in candidates: + if f"\\{arch}\\" in str(p).lower() and p.exists(): + found = p + break + if found: + break + if found is None: + for p in candidates: + if p.exists(): + found = p + break + + if found is not None: + s = str(found) + if "_mei" in s.lower() or "\\appdata\\local\\temp\\" in s.lower(): + stable = self._windows_copy_tool_to_install_dir(found) + if stable.exists(): + return stable + except Exception: + pass + + return None + + def _windows_has_nssm(self) -> bool: + return bool(self._windows_find_nssm()) + + + def _windows_nssm_run(self, args: list[str], *, check: bool = True) -> subprocess.CompletedProcess: + """Run NSSM with the given args. + + Uses the bundled NSSM, and captures output for better error messages. + """ + nssm = self._windows_find_nssm() + # Prefer a stable copy under ProgramData if available + try: + stable = self._windows_install_dir() / "nssm.exe" + if stable.exists(): + nssm = stable + except Exception: + pass + + if not nssm: + raise RuntimeError("NSSM not found (COREPY_NSSM override not set and no bundled binary found).") + + cmd = [str(nssm)] + list(args) + r = subprocess.run(cmd, capture_output=True, text=True) + if check and r.returncode != 0: + raise RuntimeError(f"nssm failed: {cmd}\n{(r.stdout or '') + (r.stderr or '')}") + return r + + +# ------------------------------------------------------------------ +# Service Manager Dialog UI (PyQt5) +# ------------------------------------------------------------------ + +class _TailReader: + """Tiny file tailer used by the ServiceManagerDialog. + + Keeps an in-memory cursor per file and reads new bytes on each poll. + """ + + def __init__(self) -> None: + self._pos: dict[str, int] = {} + + def read_new_text(self, path: str, *, max_bytes: int = 256 * 1024) -> str: + if not path: + return "" + try: + if not os.path.exists(path): + return "" + + last = self._pos.get(path, 0) + size = os.path.getsize(path) + + # If file was truncated/rotated, restart. + if size < last: + last = 0 + + # Avoid reading gigantic chunks at once. + start = max(0, size - max_bytes) if last == 0 and size > max_bytes else last + + with open(path, "rb") as f: + f.seek(start) + data = f.read() + + self._pos[path] = start + len(data) + + # Best-effort decode + try: + return data.decode("utf-8", errors="replace") + except Exception: + return data.decode(errors="replace") + except Exception: + return "" + + +class ServiceManagerDialog(QDialog): + """Cross-platform service manager UI. + + Focus: + - Install / Uninstall + - Start / Stop + - Status (installed/running) + - Live-ish log view (stdout/stderr files when available) + + Note: On Linux, services often log to journald; this dialog will show file logs + when present, otherwise it shows a hint. + """ + + def __init__(self, service: Service, parent=None) -> None: + super().__init__(parent) + self._svc = service + self._tail = _TailReader() + self._poll_ms = 1000 + + self.setWindowTitle("Service Manager") + self.setModal(True) + self.resize(980, 560) + + # ----------------------------- + # Logs (right column, under controls) + # ----------------------------- + self._tabs = QTabWidget() + + self._txt_out = QPlainTextEdit() + self._txt_out.setReadOnly(True) + self._txt_err = QPlainTextEdit() + self._txt_err.setReadOnly(True) + + self._tabs.addTab(self._txt_out, "Stdout") + self._tabs.addTab(self._txt_err, "Stderr") + + logs_box = QGroupBox() + logs_layout = QVBoxLayout(logs_box) + logs_layout.addWidget(self._tabs) + + # ----------------------------- + # Controls (right column) + # ----------------------------- + controls = QGroupBox() + self._controls_layout = QHBoxLayout(controls) + self._controls_layout.setSpacing(10) + self._controls_layout.setContentsMargins(10, 10, 10, 10) + + # Use Form.button when available (for icons); fallback to QPushButton. + def _mk_btn(label: str, fn: Callable[[], None], icon: str = ""): + if Form is not None and hasattr(Form, "button"): + return Form.button(label="", icon=icon, action=fn) + b = QPushButton(label) + b.clicked.connect(fn) + return b + + self._btn_install = _mk_btn("Install", self._on_install, icon="download") + self._btn_uninstall = _mk_btn("Uninstall", self._on_uninstall, icon="trash") + self._btn_start = _mk_btn("Start", self._on_start, icon="play") + self._btn_stop = _mk_btn("Stop", self._on_stop, icon="stop") + self._btn_refresh = _mk_btn("Refresh", self.refresh, icon="arrow-clockwise") + + self._controls_layout.addWidget(self._btn_install) + self._controls_layout.addWidget(self._btn_uninstall) + self._controls_layout.addWidget(self._btn_start) + self._controls_layout.addWidget(self._btn_stop) + self._controls_layout.addWidget(self._btn_refresh) + self._controls_layout.addStretch(1) + + # ----------------------------- + # Status (left column) + # ----------------------------- + self._lbl_name = QLabel("") + self._lbl_label = QLabel("") + self._lbl_installed = QLabel("") + self._lbl_running = QLabel("") + self._lbl_pid = QLabel("") + self._lbl_mgr = QLabel("") + self._lbl_nssm = QLabel("") + self._lbl_stdout = QLabel("") + self._lbl_stderr = QLabel("") + + status_box = QGroupBox() + status_form = QFormLayout(status_box) + status_form.addRow("Application:", self._lbl_name) + status_form.addRow("Service label:", self._lbl_label) + status_form.addRow("Manager:", self._lbl_mgr) + status_form.addRow("Installed:", self._lbl_installed) + status_form.addRow("Running:", self._lbl_running) + status_form.addRow("PID:", self._lbl_pid) + status_form.addRow("NSSM:", self._lbl_nssm) + + # ----------------------------- + # Root layout: 2 columns + # Left (1/4): Status + # Right (3/4): Controls + Logs + # ----------------------------- + root = QHBoxLayout(self) + root.setContentsMargins(8, 8, 8, 8) + root.setSpacing(10) + + # Left column (Status) + root.addWidget(status_box, 1) + + # Right column (Controls + Logs) + right = QWidget(self) + right_layout = QVBoxLayout(right) + right_layout.setContentsMargins(0, 0, 0, 0) + right_layout.setSpacing(10) + right_layout.addWidget(controls, 0) + right_layout.addWidget(logs_box, 1) + + root.addWidget(right, 3) + + # Avoid UI flashing on Windows by only updating widgets when values actually change. + self._last_snapshot: dict[str, object] = {} + self._refresh_tick = 0 + # Poll timer (status + logs) + self._timer = QTimer(self) + self._timer.setInterval(self._poll_ms) + self._timer.timeout.connect(self._on_timer) + + # Initial refresh + self.refresh() + self._timer.start() + + # ----------------------------- + # Helpers + # ----------------------------- + + def _manager_name(self) -> str: + if sys.platform.startswith("win"): + return "Windows Service Control Manager (NSSM)" if self._svc._windows_has_nssm() else "Windows Service Control Manager" + if sys.platform == "darwin": + return "launchd" + return "systemd" if shutil.which("systemctl") else "(unknown)" + + def _windows_log_paths(self) -> tuple[str, str]: + label = self._svc._service_label() + try: + logs_dir = self._svc._windows_install_dir().parent / "log" + return str(logs_dir / f"{label}.out.log"), str(logs_dir / f"{label}.err.log") + except Exception: + return "", "" + + def _macos_log_paths(self) -> tuple[str, str]: + try: + logs_dir = Path.home() / "Library" / "Logs" / self._svc._app_name() + return str(logs_dir / "service.out.log"), str(logs_dir / "service.err.log") + except Exception: + return "", "" + + def _log_paths(self) -> tuple[str, str]: + if sys.platform.startswith("win"): + return self._windows_log_paths() + if sys.platform == "darwin": + return self._macos_log_paths() + # Linux: systemd typically logs to journal; still try common file paths + return "", "" + + def _set_bool_label(self, lbl: QLabel, value: bool) -> None: + lbl.setText("yes" if value else "no") + + def refresh(self) -> None: + try: + name = self._svc._app_name() + label = self._svc._service_label() + installed = self._svc._is_installed() + running = self._svc._is_service_active() if installed else self._svc._is_running() + pid = self._svc._read_pidfile() if not installed else None + + # NSSM path (Windows only) + if sys.platform.startswith("win"): + try: + nssm_path = self._svc._windows_find_nssm() + nssm_text = str(nssm_path) if nssm_path else "(not found)" + except Exception: + nssm_text = "(unknown)" + else: + nssm_text = "-" + + out_path, err_path = self._log_paths() + stdout_text = out_path if out_path else "(no file log configured)" + stderr_text = err_path if err_path else "(no file log configured)" + + # Snapshot current state to avoid redundant UI updates (prevents flashing on Windows) + snap: dict[str, object] = { + "name": name, + "label": label, + "manager": self._manager_name(), + "installed": installed, + "running": running, + "pid": str(pid) if pid else "-", + "nssm": nssm_text, + "stdout": stdout_text, + "stderr": stderr_text, + "btn_install": (not installed), + "btn_uninstall": installed, + "btn_start": (installed and not running), + "btn_stop": (installed and running), + } + + if snap != self._last_snapshot: + self._lbl_name.setText(str(snap["name"])) + self._lbl_label.setText(str(snap["label"])) + self._lbl_mgr.setText(str(snap["manager"])) + self._set_bool_label(self._lbl_installed, bool(snap["installed"])) + self._set_bool_label(self._lbl_running, bool(snap["running"])) + self._lbl_pid.setText(str(snap["pid"])) + self._lbl_nssm.setText(str(snap["nssm"])) + self._lbl_stdout.setText(str(snap["stdout"])) + self._lbl_stderr.setText(str(snap["stderr"])) + + # Button visibility: only show actions that make sense. + self._btn_install.setVisible(bool(snap["btn_install"])) + self._btn_uninstall.setVisible(bool(snap["btn_uninstall"])) + self._btn_start.setVisible(bool(snap["btn_start"])) + self._btn_stop.setVisible(bool(snap["btn_stop"])) + + self._last_snapshot = snap + + # Show a helpful note in logs pane when file logs aren't available. + if not out_path and not err_path: + note = ( + "Logs are not available as files on this platform/configuration.\n" + "- Windows: logs are written to ProgramData via NSSM settings.\n" + "- macOS: logs are written to ~/Library/Logs//.\n" + "- Linux: consider using journald (journalctl -u ).\n" + ) + # Only set the note once to avoid flicker + if self._txt_out.toPlainText().strip() == "": + self._txt_out.setPlainText(note) + if self._txt_err.toPlainText().strip() == "": + self._txt_err.setPlainText(note) + + except Exception as e: + QMessageBox.warning(self, "Service", f"Failed to refresh status: {e}") + + # ----------------------------- + # Actions + # ----------------------------- + + def _on_install(self) -> None: + try: + self._svc.install() + except Exception as e: + QMessageBox.critical(self, "Service", f"Install failed:\n\n{e}") + finally: + self.refresh() + + def _on_uninstall(self) -> None: + try: + self._svc.uninstall() + except Exception as e: + QMessageBox.critical(self, "Service", f"Uninstall failed:\n\n{e}") + finally: + self.refresh() + + def _on_start(self) -> None: + try: + self._svc._service_manager_start() + except Exception as e: + QMessageBox.critical(self, "Service", f"Start failed:\n\n{e}") + finally: + self.refresh() + + def _on_stop(self) -> None: + try: + self._svc._service_manager_stop() + except Exception as e: + QMessageBox.critical(self, "Service", f"Stop failed:\n\n{e}") + finally: + self.refresh() + + # ----------------------------- + # Log polling + # ----------------------------- + + def _on_timer(self) -> None: + # Only tail logs on a timer. Avoid polling status (may spawn sc/systemctl windows). + self._poll_logs() + + # ----------------------------- + # Log polling + # ----------------------------- + + def _append_text(self, widget: QPlainTextEdit, text: str) -> None: + if not text: + return + try: + widget.moveCursor(widget.textCursor().End) + widget.insertPlainText(text) + widget.moveCursor(widget.textCursor().End) + except Exception: + # Safe fallback + try: + widget.setPlainText(widget.toPlainText() + text) + except Exception: + pass + + def _poll_logs(self) -> None: + out_path, err_path = self._log_paths() + if out_path: + self._append_text(self._txt_out, self._tail.read_new_text(out_path)) + if err_path: + self._append_text(self._txt_err, self._tail.read_new_text(err_path)) + + def closeEvent(self, event) -> None: # type: ignore[override] + try: + if self._timer.isActive(): + self._timer.stop() + except Exception: + pass + super().closeEvent(event) diff --git a/dist/macos/Replicator.app/Contents/Resources/core/src/bin/nssm/windows/x86/nssm.exe b/dist/macos/Replicator.app/Contents/Resources/core/src/bin/nssm/windows/x86/nssm.exe new file mode 100644 index 00000000..8faee45b Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/core/src/bin/nssm/windows/x86/nssm.exe differ diff --git a/dist/macos/Replicator.app/Contents/Resources/core/src/bin/nssm/windows/x86_64/nssm.exe b/dist/macos/Replicator.app/Contents/Resources/core/src/bin/nssm/windows/x86_64/nssm.exe new file mode 100644 index 00000000..6ccfe3cf Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/core/src/bin/nssm/windows/x86_64/nssm.exe differ diff --git a/dist/macos/Replicator.app/Contents/Resources/core/styles/style.css b/dist/macos/Replicator.app/Contents/Resources/core/styles/style.css new file mode 100644 index 00000000..8a40cedd --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/styles/style.css @@ -0,0 +1,320 @@ +QDialog, QMessageBox, QProgressDialog, QTabWidget, QTabWidget::pane, QGroupBox, QGroupBox::title { + background-color: #212121; + color: #FFFFFF; + font-family: Arial, sans-serif; + font-size: 14px; +} + +QGroupBox { + border: 1px solid #76797C; + border-radius: 5px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 10px; + padding: 0 6px; +} + +QTabWidget::pane { + background-color: #414141; + border: 1px solid #76797C; + border-radius: 5px; + position: absolute; + top: -1px; + padding: 10px; +} + +QLabel, QLineEdit, QTimeEdit, QCheckBox, QTextEdit, QComboBox, QSpinBox, QPushButton, QTabBar::tab, QPlainTextEdit { + font-size: 14px; + border: 1px solid #76797C; + border-radius: 5px; + padding: 10px; + margin: 5px 0px; +} + +QLineEdit, QTimeEdit, QTextEdit, QComboBox, QSpinBox, QPlainTextEdit { + background-color: #212121; + color: #FFFFFF; + width: 300px; +} + +QTimeEdit { + width: 75px; +} + +QLineEdit:focus, QTimeEdit:focus, QTextEdit:focus, QComboBox:focus, QSpinBox:focus, QPlainTextEdit:focus { + border: 1px solid #0d6efd; +} + +QSpinBox { + padding-right: 39px; +} +QSpinBox::up-button, +QSpinBox::down-button { + border: none; + border-left: 1px solid #76797C; + background-color: #414344; + width: 39px; +} +QSpinBox::up-button { + border-top-right-radius: 5px; + border-bottom-right-radius: 0px; +} +QSpinBox::down-button { + border-top-right-radius: 0px; + border-bottom-right-radius: 5px; +} +QSpinBox::up-button:hover, +QSpinBox::down-button:hover { + background-color: #5f6263; +} +QSpinBox::up-button:pressed, +QSpinBox::down-button:pressed, +QSpinBox::up-button:focus, +QSpinBox::down-button:focus { + background-color: #0d6efd; +} +QSpinBox::up-arrow, +QSpinBox::down-arrow { + width: 20px; + height: 20px; +} + +QComboBox::drop-down { + border: none; + border-left: 1px solid #76797C; + border-radius: 5px; + border-top-left-radius: 0px; + border-bottom-left-radius: 0px; + margin: 0px; + background-color: #414344; + color: #FFFFFF; + width: 39px; + height: 39px; +} +QComboBox::down-arrow:pressed, +QComboBox::drop-down:hover { + background-color: #5f6263; +} +QComboBox::down-arrow:pressed, +QComboBox::down-arrow:focus, +QComboBox::drop-down:pressed, +QComboBox::drop-down:focus { + background-color: #0d6efd; +} +QComboBox::down-arrow { + width: 20px; + height: 20px; +} +QListView, +QAbstractItemView { + border: 1px solid #76797C; + border-radius: 5px; + background-color: #212121; + color: #FFFFFF; + outline: 0; + selection-background-color: #0d6efd; + selection-color: #FFFFFF; +} +QListView::item, +QAbstractItemView::item { + min-height: 28px; + padding: 6px 10px; + border: none; +} +QListView::item:selected, +QAbstractItemView::item:selected { + background-color: #0d6efd; + color: #FFFFFF; +} +QListView::item:hover, +QAbstractItemView::item:hover { + background-color: #5f6263; + border: none; +} + +/* Added styling for QTableView and QTableWidget to match dark theme */ +QTableView, QTableWidget { + border: 1px solid #76797C; + border-radius: 5px; + background-color: #212121; + color: #FFFFFF; + gridline-color: #414344; + selection-background-color: #0d6efd; + selection-color: #FFFFFF; + outline: 0; + padding: 0px; + margin: 5px 0px; +} + +QHeaderView::section { + background-color: #414344; + color: #FFFFFF; + border: 1px solid #414344; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + padding: 8px 10px; +} + +QTableCornerButton::section { + background-color: #414344; + color: #FFFFFF; + border: 1px solid #414344; + padding: 8px 10px; +} + +QTableView::item, QTableWidget::item { + padding: 6px 10px; + border: none; +} + +QTableView::item:hover, QTableWidget::item:hover { + background-color: #5f6263; +} + +QTableView::item:selected, QTableWidget::item:selected { + background-color: #0d6efd; + color: #FFFFFF; +} + +QTableView:focus, QTableWidget:focus { + outline: 0; +} + +QComboBox QFrame, +QFrame#qt_qcombobox_popup { + background-color: #212121; + border: 1px solid #76797C; + border-radius: 5px; + padding: 0px; +} +QFrame#qt_qcombobox_popup QListView, +QFrame#qt_qcombobox_popup QAbstractItemView { + background-color: #212121; + border: none; +} + +QLabel, QCheckBox { + color: #FFFFFF; + border: none; +} + +QCheckBox { + spacing: 8px; +} + +QCheckBox::indicator { + width: 18px; + height: 18px; + border: 1px solid #76797C; + border-radius: 5px; + background: #212121; + margin-right: 6px; +} +QCheckBox::indicator:hover { + border-color: #5f6263; +} +QCheckBox::indicator:pressed { + background: #5f6263; + border-color: #5f6263; +} +QCheckBox::indicator:checked { + background: #0d6efd; + border-color: #0d6efd; +} +QCheckBox:disabled { + color: #8c8c8c; +} +QCheckBox::indicator:disabled { + background: #2b2b2b; + border-color: #555555; +} +QCheckBox:focus { + outline: none; +} +QCheckBox::indicator:focus { + border-color: #0d6efd; +} + +QPushButton, +QTabBar::tab { + background-color: #414344; + color: #FFFFFF; + + selection-background-color: #414344; + selection-color: #FFFFFF; +} +QPushButton:focus, +QTabBar::tab:focus { + border-color: #0d6efd; + background-color: #414344; +} +QPushButton:hover, +QTabBar::tab:hover { + background-color: #5f6263; + border-color: #5f6263; +} +QPushButton:pressed, +QTabBar::tab:pressed, +QTabBar::tab:selected { + background-color: #0d6efd; + border-color: #0d6efd; +} +QPushButton:default, +QPushButton:default:focus, +QTabBar::tab:default, +QTabBar::tab:default:focus { + background-color: #414344; + border-color: #0d6efd; +} + +QTabWidget::tab-bar, QTabBar { + alignment: center; +} +QTabBar::tab { + border-radius: 0px; +} +QTabBar::tab:first { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; +} +QTabBar::tab:last { + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; +} +QPushButton:hover, QTabBar::tab:hover { + background-color: #5f6263; + border-color: #5f6263; +} +QPushButton:pressed, QTabBar::tab:pressed, QTabBar::tab:selected { + background-color: #0d6efd; + border-color: #0d6efd; +} + +#MsgBox { + min-width: 400px; + background-color: #212121; + color: #FFFFFF; + padding: 10px; + font-size: 14px; +} + +#Client { + min-width: 400px; + background-color: #212121; + color: #FFFFFF; + padding: 10px; + font-size: 14px; +} + +#DiagnosticDialog QLabel#statusDot { + padding: 0; + margin: 0; + min-width: 16px; + min-height: 16px; + max-width: 16px; + max-height: 16px; + border-radius: 8px; +} diff --git a/dist/macos/Replicator.app/Contents/Resources/core/ui.py b/dist/macos/Replicator.app/Contents/Resources/core/ui.py new file mode 100644 index 00000000..20ddb653 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/ui.py @@ -0,0 +1,775 @@ +#!/usr/bin/env python3 +# src/core/ui.py + +from __future__ import annotations + +import os +import base64 + +from typing import Iterable, Optional, Callable, List + +from PyQt5.QtWidgets import ( + QDialog, QVBoxLayout, QLabel, QHBoxLayout, QPushButton, + QLineEdit, QSpinBox, QComboBox, QCheckBox, QColorDialog, + QSizePolicy, QStyle, QStyleOptionButton, QWidget, QFileDialog, + QListView, QFrame, QApplication, QListWidget +) +from PyQt5.QtGui import ( + QIcon, QPixmap, QPainter, QColor, QPen, QTransform +) +from PyQt5.QtCore import QRect, Qt, QTimer +from PyQt5.QtSvg import QSvgWidget, QSvgRenderer + +# Allow this module to be used both as part of the 'app' package and as a standalone script +try: + from .helper import Helper + from .network.tools import Tools +except ImportError: # likely running as a top-level script + from helper import Helper + from network.tools import Tools + +class MsgBox(QDialog): + + ICONS = { + "info": "core/icons/info.svg", + "error": "core/icons/error.svg", + "warning": "core/icons/warning.svg", + "question":"core/icons/question.svg", + } + + def __init__( + self, + parent=None, + title: str = "", + message: str = "", + icon: Optional[str] = None, + buttons: Iterable[str] = ("OK",), + default: Optional[str] = None, + icon_size: int = 64, + icon_lookup_fn: Optional[Callable[[str], Optional[str]]] = None, + ): + super().__init__(parent) + self.setWindowTitle(title) + self.setObjectName("MsgBox") + self.setModal(True) + + self._selected: Optional[str] = None + self._icon_lookup = icon_lookup_fn + self._helper = None + + if isinstance(buttons, str): + buttons = (buttons,) + else: + buttons = tuple(buttons) + + layout = QVBoxLayout(self) + + # --- Top area: icon + message --- + top = QHBoxLayout() + layout.addLayout(top) + + if icon: + icon_path = self._resolve_icon_path(icon) + if icon_path: + svg = QSvgWidget(icon_path) + svg.setFixedSize(icon_size, icon_size) + svg.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + top.addWidget(svg, alignment=Qt.AlignVCenter) + + # message text + msg_label = QLabel(message) + msg_label.setWordWrap(True) + msg_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) + top.addWidget(msg_label) + + # --- Buttons --- + btn_row = QHBoxLayout() + btn_row.addStretch(1) + self._buttons: dict[str, QPushButton] = {} + + for text in buttons: + btn = QPushButton(text) + self._buttons[text] = btn + btn.clicked.connect(lambda _, t=text: self._on_click(t)) + btn_row.addWidget(btn) + + layout.addLayout(btn_row) + + # default selection + if default and default in self._buttons: + self._buttons[default].setDefault(True) + self._buttons[default].setFocus() + + # ------------------------------------------------------------------ + # Internals + # ------------------------------------------------------------------ + + def _ensure_helper(self): + """ + Lazily import and instantiate helper. + """ + if self._helper is not None: + return self._helper + + try: + self._helper = Helper() + except Exception as e: + print(f"[MsgBox] Failed to initialize helpers: {e}") + self._helper = None + + return self._helper + + def _resolve_icon_path(self, icon: str) -> Optional[str]: + """ + Resolve an icon name or path using ICONS + optional lookup function. + """ + # Named icon → relative path from ICONS + candidate = self.ICONS.get(icon, icon) + + if self._icon_lookup: + resolved = self._icon_lookup(candidate) + if resolved: + return resolved + else: + if self._ensure_helper() is not None: + resolved = self._helper.get_path(candidate) + if resolved and self._helper.file_exists(resolved): + return resolved + + return candidate + + def _on_click(self, text: str): + self._selected = text + self.accept() + + # ------------------------------------------------- + # Convenience static helper + # ------------------------------------------------- + + @staticmethod + def show( + parent=None, + title: str = "", + message: str = "", + icon: Optional[str] = None, + buttons: Iterable[str] = ("OK",), + default: Optional[str] = None, + icon_lookup_fn: Optional[Callable[[str], Optional[str]]] = None, + ) -> str: + """ + Show the dialog modally and return the label of the chosen button. + """ + dlg = MsgBox( + parent=parent, + title=title, + message=message, + icon=icon, + buttons=buttons, + default=default, + icon_lookup_fn=icon_lookup_fn, + ) + dlg.exec_() + return dlg._selected or default or "" + +class SpinningIconLabel(QLabel): + + def __init__(self, svg_path: str, size: int = 32, interval_ms: int = 50, parent=None): + super().__init__(parent) + self._size = size + self._svg_path = svg_path + self._angle = 0 + + self._base_pixmap = QIcon(svg_path).pixmap(size, size) + + self.setFixedSize(size, size) + self.setAlignment(Qt.AlignCenter) + self.setScaledContents(True) + self.setStyleSheet("padding: 0; margin: 0; border: none;") + + # Timer + self._timer = QTimer(self) + self._timer.timeout.connect(self._tick) + self._timer.start(interval_ms) + + def _tick(self): + """Rotate icon by a fixed number of degrees.""" + self._angle = (self._angle + 10) % 360 + + rotated = self._rotate_pixmap(self._base_pixmap, self._angle) + self.setPixmap(rotated) + + def _rotate_pixmap(self, pixmap: QPixmap, angle: float) -> QPixmap: + """Return a rotated copy of the pixmap.""" + transform = QTransform() + transform.rotate(angle) + rotated = pixmap.transformed(transform, Qt.SmoothTransformation) + + # Scale back to exact size + return rotated.scaled(self._size, self._size, Qt.KeepAspectRatio, Qt.SmoothTransformation) + + def stop(self): + self._timer.stop() + + def start(self): + self._timer.start() + +class ColorButton(QPushButton): + def __init__(self, initial: str = "#265162", parent=None): + super().__init__(parent) + self._color = QColor(initial) + self.clicked.connect(self._pick) + + def _pick(self): + chosen = QColorDialog.getColor(self._color, self, "Choose Color") + if chosen.isValid(): + self._color = chosen + self.update() # repaint + + def color(self) -> QColor: + return self._color + + def hex(self) -> str: + return self._color.name() + + def setHex(self, value: str): + if not value: + return + c = QColor(value) + if c.isValid(): + self._color = c + self.update() # repaint + + def _styleOption(self): + option = QStyleOptionButton() + option.initFrom(self) + option.text = self.text() + option.icon = self.icon() + return option + + def paintEvent(self, event): + super().paintEvent(event) + + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing, True) + + # Get content rect WITHIN QPushButton's styled padding + content = self.style().subElementRect( + QStyle.SE_PushButtonContents, + self._styleOption(), + self + ) + + pen = QPen(QColor(118, 121, 124)) + painter.setPen(pen) + painter.setBrush(self._color) + + painter.drawRoundedRect(content, 4, 4) + painter.end() + +class PictureButton(QPushButton): + def __init__(self, initial: Optional[str] = None, parent=None, max_size: int = 72): + super().__init__(parent) + self._b64: str = "" + self._max_size = max_size + + # Visual setup + self.setFixedSize(max_size + 16, max_size + 24) + self.setStyleSheet("padding: 4px;") + self.setText("Select Logo") + + # Initialize from existing config value + if initial: + self._init_from_value(initial) + + self.clicked.connect(self._pick) + + # ----- public API for Configuration ----- + + def value(self) -> str: + """ + Return the stored base64 string (or "" if none). + """ + return self._b64 + + def setValue(self, raw: str): + # Reset visuals first + self._b64 = "" + self.setIcon(QIcon()) + self.setText("Select Logo") + + if raw: + self._init_from_value(raw) + + # ----- internals ----- + + def _init_from_value(self, raw: str): + raw = raw.strip() + if not raw: + return + + # 1) Try as base64 + data: Optional[bytes] = None + try: + data = base64.b64decode(raw, validate=True) + except Exception: + data = None + + # 2) If not valid base64, treat as path + if data is None: + if os.path.isfile(raw): + try: + with open(raw, "rb") as f: + data = f.read() + except Exception as e: + print(f"[PictureButton] Failed to read logo file '{raw}': {e}") + return + else: + # Unknown format; give up silently + return + + # At this point we have `data` + pm = QPixmap() + if not pm.loadFromData(data, "PNG"): + return + + self._b64 = base64.b64encode(data).decode("ascii") + self._set_pixmap(pm) + + def _pick(self): + path, _ = QFileDialog.getOpenFileName( + self, + "Select Logo", + "", + "PNG Files (*.png)" + ) + if not path: + return + + try: + with open(path, "rb") as f: + data = f.read() + + pm = QPixmap() + if not pm.loadFromData(data, "PNG"): + print(f"[PictureButton] Not a valid PNG: {path}") + return + + self._b64 = base64.b64encode(data).decode("ascii") + self._set_pixmap(pm) + except Exception as e: + print(f"[PictureButton] Failed to load logo '{path}': {e}") + + def _set_pixmap(self, pm: QPixmap): + scaled = pm.scaled( + self._max_size, + self._max_size, + Qt.KeepAspectRatio, + Qt.SmoothTransformation, + ) + self.setIcon(QIcon(scaled)) + self.setIconSize(scaled.size()) + self.setText("") + self.update() + +class FileInput(QWidget): + def __init__( + self, + initial: str = "", + caption: str = "Select File", + directory: str = "", + filter: str = "All Files (*)", + as_base64: bool = False, + on_changed: Optional[Callable[[str], None]] = None, + parent=None, + ): + super().__init__(parent) + self._caption = caption + self._directory = directory + self._filter = filter + self._as_base64 = as_base64 + self._on_changed = on_changed + self._stored_value: str = initial or "" + + layout = QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(4) + + self._edit = QLineEdit(self) + + if not self._as_base64: + if initial: + self._edit.setText(initial) + else: + display = "" + if initial: + if "::" in initial: + fname, _ = initial.split("::", 1) + display = fname + else: + display = "(embedded)" + self._edit.setText(display) + + self._btn = QPushButton("...", self) + self._btn.clicked.connect(self._browse) + + layout.addWidget(self._edit) + layout.addWidget(self._btn) + + def _browse(self): + # Start from configured directory, or from current value's folder + start_dir = self._directory or os.path.dirname(self._edit.text() or "") or "" + path, _ = QFileDialog.getOpenFileName( + self, + self._caption, + start_dir, + self._filter, + ) + if path: + self._edit.setText(path) + if self._on_changed: + self._on_changed(path) + + def value(self) -> str: + """ + Return either the raw path (default) or a 'filename::base64' value + when as_base64=True. + """ + path_or_name = self._edit.text().strip() + + if not self._as_base64: + # Normal mode – return the path from the line edit + return path_or_name + + # Base64 mode + # If the text points to an actual file, re-read and encode it + if path_or_name and os.path.isfile(path_or_name): + try: + with open(path_or_name, "rb") as f: + data = f.read() + b64 = base64.b64encode(data).decode("ascii") + fname = os.path.basename(path_or_name) + self._stored_value = f"{fname}::{b64}" + except Exception as e: + print(f"[FileInput] Failed to read '{path_or_name}' for base64: {e}") + + # If it's not a real file path, just return the last stored value + return self._stored_value or "" + + def setValue(self, value: str): + """ + Update both the stored value and the visible text. + value is expected to be either: + - a path (normal mode), or + - 'filename::base64' / raw base64 (as_base64=True). + """ + if not self._as_base64: + self._edit.setText(value or "") + if self._on_changed: + self._on_changed(value) + return + + self._stored_value = value or "" + + display = "" + if value: + if "::" in value: + fname, _ = value.split("::", 1) + display = fname + else: + display = "(embedded)" + + self._edit.setText(display) + + # Only call on_changed if we really want config-file reactions etc. + if self._on_changed: + self._on_changed(value) + +class WiFiButton(QPushButton): + + def __init__(self, parent=None, label: str = "Connect"): + super().__init__(label, parent) + self._ssid: str = "" + self._tools = None # lazy-loaded network.Tools instance + self.clicked.connect(self._on_click) + + # ------------------------------------------------------------------ + # Public API + # ------------------------------------------------------------------ + + def value(self) -> str: + """ + Return the currently selected SSID (or "" if none). + """ + return self._ssid + + def setValue(self, ssid: str): + """ + Set the currently selected SSID and update the button label. + """ + self._ssid = ssid or "" + self.setText(self._ssid or "Connect") + + # ------------------------------------------------------------------ + # Internals + # ------------------------------------------------------------------ + + def _ensure_tools(self): + """ + Lazily import and instantiate network.tools.Tools. + """ + if self._tools is not None: + return self._tools + + try: + self._tools = Tools() + except Exception as e: + print(f"[WiFiButton] Failed to initialize network Tools: {e}") + self._tools = None + + return self._tools + + def _on_click(self): + tools = self._ensure_tools() + if tools is None: + MsgBox.show( + parent=self, + title="Wi-Fi", + message="Network tools are not available.", + icon="error", + ) + return + + # --- 1) Show a small dialog that immediately displays the scanning message --- + dlg = QDialog(self) + dlg.setModal(True) + dlg.setWindowTitle("Wi-Fi Networks") + + layout = QVBoxLayout(dlg) + scanning_label = QLabel("Scanning Access Points...") + layout.addWidget(scanning_label) + + dlg.show() + QApplication.processEvents() + + # Perform the scan (synchronously) + try: + networks = tools.scan_ap() + except Exception as e: + print(f"[WiFiButton] Failed to scan Wi-Fi networks: {e}") + networks = [] + + # Clear the "Scanning..." UI + while layout.count(): + item = layout.takeAt(0) + w = item.widget() + if w is not None: + w.deleteLater() + + # --- 2) If no networks found, show a simple message + Close button --- + if not networks: + info = QLabel("No Wi-Fi networks found.") + layout.addWidget(info) + + btn_row = QHBoxLayout() + btn_row.addStretch(1) + close_btn = QPushButton("Close", dlg) + close_btn.clicked.connect(dlg.reject) + btn_row.addWidget(close_btn) + layout.addLayout(btn_row) + + dlg.exec_() + dlg.deleteLater() + return + + # --- 3) Show list of access points + Connect / Cancel buttons --- + list_widget = QListWidget(dlg) + list_widget.addItems(networks) + layout.addWidget(list_widget) + + btn_row = QHBoxLayout() + btn_row.addStretch(1) + cancel_btn = QPushButton("Cancel", dlg) + ok_btn = QPushButton("Connect", dlg) + + def on_ok(): + # Require a selection to accept + if list_widget.currentItem() is not None: + dlg.accept() + + cancel_btn.clicked.connect(dlg.reject) + ok_btn.clicked.connect(on_ok) + + btn_row.addWidget(cancel_btn) + btn_row.addWidget(ok_btn) + layout.addLayout(btn_row) + + def on_item_double_clicked(_item): + dlg.accept() + + list_widget.itemDoubleClicked.connect(on_item_double_clicked) + + result = dlg.exec_() + selected_ssid = "" + if result == QDialog.Accepted and list_widget.currentItem() is not None: + selected_ssid = list_widget.currentItem().text().strip() + + dlg.deleteLater() + self.setValue(selected_ssid) + +class StepIndicator(QWidget): + def __init__(self, text: str, parent=None): + super().__init__(parent) + self._state = 'idle' + self.dot = QLabel() + self.dot.setObjectName("statusDot") + self.dot.setFixedSize(16, 16) + self.label = QLabel(text) + + lay = QVBoxLayout(self) + lay.setContentsMargins(4, 4, 4, 4) + lay.setSpacing(6) + dot_wrap = QWidget() + dot_wrap.setFixedHeight(20) + dot_lay = QHBoxLayout(dot_wrap) + dot_lay.setContentsMargins(0,0,0,0) + dot_lay.addStretch(1) + dot_lay.addWidget(self.dot, 0, Qt.AlignCenter) + dot_lay.addStretch(1) + + lay.addWidget(dot_wrap) + self.label.setAlignment(Qt.AlignCenter) + lay.addWidget(self.label) + self._apply_style() + + def set_state(self, state: str): + self._state = state + self._apply_style() + + def _apply_style(self): + colors = { + 'idle': '#A0A4A8', # grey + 'running': '#F5C542', # amber + 'ok': '#2FB344', # green + 'fail': '#E03131', # red + } + c = colors.get(self._state, '#A0A4A8') + self.dot.setStyleSheet(f"background:{c}; border-radius:7px; border:1px solid rgba(0,0,0,.25);") + +class Form: + + @staticmethod + def text(text: str = "", placeholder: str = "") -> QLineEdit: + w = QLineEdit() + if text: + w.setText(text) + if placeholder: + w.setPlaceholderText(placeholder) + return w + + @staticmethod + def password(text: str = "", placeholder: str = "") -> QLineEdit: + w = QLineEdit() + w.setEchoMode(QLineEdit.Password) + if text: + w.setText(text) + if placeholder: + w.setPlaceholderText(placeholder) + return w + + @staticmethod + def checkbox(checked: bool = False) -> QCheckBox: + w = QCheckBox() + w.setChecked(checked) + return w + + @staticmethod + def spin(value: int = 0, minimum: int = 0, maximum: int = 65535) -> QSpinBox: + w = QSpinBox() + w.setRange(minimum, maximum) + w.setValue(value) + return w + + @staticmethod + def number(value: int = 0, minimum: int = 0, maximum: int = 65535) -> QSpinBox: + w = QSpinBox() + w.setRange(minimum, maximum) + w.setValue(value) + return w + + @staticmethod + def integer(value: int = 0, minimum: int = 0, maximum: int = 65535) -> QSpinBox: + w = QSpinBox() + w.setRange(minimum, maximum) + w.setValue(value) + return w + + @staticmethod + def select(items: Iterable[str], current: Optional[str] = None) -> QComboBox: + cb = QComboBox() + popup = QListView() + popup.setFrameShape(QFrame.NoFrame) + popup.setFrameShadow(QFrame.Plain) + cb.setView(popup) + vals: List[str] = list(items) + cb.addItems(vals) + if current is not None: + idx = cb.findText(str(current)) + if idx >= 0: + cb.setCurrentIndex(idx) + return cb + + @staticmethod + def color(initial: str = "#265162") -> ColorButton: + return ColorButton(initial) + + @staticmethod + def button(label: str, action: Callable | None, icon: str = "") -> QPushButton: + helper = Helper() + btn = QPushButton(label) + if icon: + icon_path = helper.get_path(f"core/icons/{icon}.svg") + if icon_path: + if helper.file_exists(icon_path): + renderer = QSvgRenderer(icon_path) + pixmap = QPixmap(18, 18) + pixmap.fill(Qt.transparent) + painter = QPainter(pixmap) + renderer.render(painter) + painter.end() + icon = QIcon(pixmap) + btn.setIcon(icon) + btn.setIconSize(pixmap.size()) + if label: + btn.setText("\u2002" + label) + if action: + btn.clicked.connect(action) + return btn + + @staticmethod + def picture(initial: Optional[str] = None) -> PictureButton: + return PictureButton(initial=initial) + + @staticmethod + def file( + initial: str = "", + caption: str = "Select File", + directory: str = "", + filter: str = "All Files (*)", + as_base64: bool = False, + on_changed: Optional[Callable[[str], None]] = None, + ) -> FileInput: + return FileInput( + initial=initial, + caption=caption, + directory=directory, + filter=filter, + as_base64=as_base64, + on_changed=on_changed, + ) + + @staticmethod + def wifi(current: str = "") -> WiFiButton: + btn = WiFiButton() + if current: + btn.setValue(current) + return btn diff --git a/dist/macos/Replicator.app/Contents/Resources/core/update.sh b/dist/macos/Replicator.app/Contents/Resources/core/update.sh new file mode 100755 index 00000000..86308c99 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/core/update.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +BRANCH=$(git config -f .gitmodules submodule.src/core.branch) +cd src/core && git checkout $BRANCH && git pull && cd ../.. +git add src/core +git commit -m "General: Update submodule corePY" || echo "No changes to commit" +git push diff --git a/dist/macos/Replicator.app/Contents/Resources/icon.icns b/dist/macos/Replicator.app/Contents/Resources/icon.icns new file mode 100644 index 00000000..e1a2c0f7 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/icon.icns differ diff --git a/dist/macos/Replicator.app/Contents/Resources/icons/icon.icns b/dist/macos/Replicator.app/Contents/Resources/icons/icon.icns new file mode 100644 index 00000000..e1a2c0f7 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/icons/icon.icns differ diff --git a/dist/macos/Replicator.app/Contents/Resources/icons/icon.png b/dist/macos/Replicator.app/Contents/Resources/icons/icon.png new file mode 100644 index 00000000..e683fe20 Binary files /dev/null and b/dist/macos/Replicator.app/Contents/Resources/icons/icon.png differ diff --git a/dist/macos/Replicator.app/Contents/Resources/icons/icon.svg b/dist/macos/Replicator.app/Contents/Resources/icons/icon.svg new file mode 100644 index 00000000..d29f6262 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/icons/icon.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dist/macos/Replicator.app/Contents/Resources/libcrypto.3.dylib b/dist/macos/Replicator.app/Contents/Resources/libcrypto.3.dylib new file mode 120000 index 00000000..cc14f152 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/libcrypto.3.dylib @@ -0,0 +1 @@ +../Frameworks/libcrypto.3.dylib \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/liblzma.5.dylib b/dist/macos/Replicator.app/Contents/Resources/liblzma.5.dylib new file mode 120000 index 00000000..fbed50fa --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/liblzma.5.dylib @@ -0,0 +1 @@ +../Frameworks/liblzma.5.dylib \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/libmpdec.4.dylib b/dist/macos/Replicator.app/Contents/Resources/libmpdec.4.dylib new file mode 120000 index 00000000..21d144b1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/libmpdec.4.dylib @@ -0,0 +1 @@ +../Frameworks/libmpdec.4.dylib \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/libsqlite3.dylib b/dist/macos/Replicator.app/Contents/Resources/libsqlite3.dylib new file mode 120000 index 00000000..d1e11ce8 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/libsqlite3.dylib @@ -0,0 +1 @@ +../Frameworks/libsqlite3.dylib \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/libssl.3.dylib b/dist/macos/Replicator.app/Contents/Resources/libssl.3.dylib new file mode 120000 index 00000000..4651492c --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/libssl.3.dylib @@ -0,0 +1 @@ +../Frameworks/libssl.3.dylib \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/python3.11 b/dist/macos/Replicator.app/Contents/Resources/python3.11 new file mode 120000 index 00000000..68fdb5d2 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/python3.11 @@ -0,0 +1 @@ +../Frameworks/python3.11 \ No newline at end of file diff --git a/dist/macos/Replicator.app/Contents/Resources/replicator/__init__.py b/dist/macos/Replicator.app/Contents/Resources/replicator/__init__.py new file mode 100644 index 00000000..7c3a9253 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/replicator/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# src/core/__init__.py + +from .replicator import Replicator +from .ui import JobDialog, ScheduleDialog +from .job import Schedule, Endpoint, Job, JobRunResult, JobStore +from .migration import Migration +from .mount import RemoteMountError, MountedEndpoint, mount_endpoint_if_remote + +__version__ = "1.0.0" + +__all__ = [ + "Replicator", + "JobDialog", + "ScheduleDialog", + "Schedule", + "Endpoint", + "Job", + "JobRunResult", + "JobStore", + "Migration", + "RemoteMountError", + "MountedEndpoint", + "mount_endpoint_if_remote", +] diff --git a/dist/macos/Replicator.app/Contents/Resources/replicator/job.py b/dist/macos/Replicator.app/Contents/Resources/replicator/job.py new file mode 100644 index 00000000..56f102e6 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/replicator/job.py @@ -0,0 +1,766 @@ +#!/usr/bin/env python3 +# src/replicator/job.py + +from __future__ import annotations +import json +from dataclasses import dataclass, field +from datetime import datetime, timedelta, timezone, time +from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Tuple, Union +from urllib.parse import urlparse +from .mount import RemoteMountError, MountedEndpoint, mount_endpoint_if_remote + +try: + # corePY SQLite wrapper (preferred) + from core.database.sqlite import SQLite # type: ignore +except Exception: # pragma: no cover + SQLite = None # type: ignore + +JsonDict = Dict[str, Any] + +# --------------------------------------------------------------------------- +# Data models +# --------------------------------------------------------------------------- + +@dataclass(frozen=True) +class Endpoint: + type: str = "local" + location: str = "" + auth: JsonDict = field(default_factory=dict) + + def validate(self, role: str) -> List[str]: + errs: List[str] = [] + if not self.type: + errs.append(f"{role} endpoint type is required.") + if not self.location: + errs.append(f"{role} endpoint location is required.") + t = (self.type or "").lower() + # SMB port validation removed + return errs + + def to_db_fields(self, role: str) -> JsonDict: + t = (self.type or "local").lower() + auth = dict(self.auth or {}) + + guest: int = 1 + username: Optional[str] = None + password: Optional[str] = None + options: JsonDict = {} + + if t == "local": + pass + elif t == "smb": + guest = 1 if bool(auth.get("guest", True)) else 0 + username = auth.get("username") or None + password = auth.get("password") or None + # Optional SMB domain + options["domain"] = auth.get("domain") + # Optional rclone args (applies to all remote types) + if isinstance(auth.get("rcloneArgs"), list): + options["rcloneArgs"] = auth.get("rcloneArgs") + + known_keys = {"guest", "username", "password", "domain"} + for k, v in auth.items(): + if k not in known_keys: + options[k] = v + + return { + "role": role, + "type": t, + "location": self.location, + "port": None, + "guest": guest, + "username": username, + "password": password, + "options": json.dumps(options) if options else None, + } + + @staticmethod + def from_db_row(row: Mapping[str, Any]) -> "Endpoint": + t = (row.get("type") or "local").lower() + auth: JsonDict = {} + + if t == "local": + auth = {} + elif t == "smb": + auth = { + "guest": bool(row.get("guest", 1)), + "username": row.get("username") or "", + "password": row.get("password") or "", + } + # domain is stored in options JSON when present + + opt = row.get("options") + if opt: + try: + extra = json.loads(opt) + if isinstance(extra, dict): + auth.update(extra) + except Exception: + pass + + return Endpoint(type=t, location=row.get("location") or "", auth=auth) + +@dataclass +class Schedule: + enabled: bool = False + intervalSeconds: int = 3600 + windows: Dict[str, Any] = field(default_factory=dict) + + def to_dict(self) -> Dict[str, Any]: + return { + "enabled": bool(self.enabled), + "intervalSeconds": int(self.intervalSeconds or 0), + "windows": self.windows if isinstance(self.windows, dict) else {}, + } + + @staticmethod + def from_dict(d: Optional[Dict[str, Any]]) -> "Schedule": + d = d or {} + enabled = bool(d.get("enabled", False)) + # intervalSeconds can be on the schedule itself, or in per-day window objects + try: + interval_s = int(d.get("intervalSeconds") or 0) + except Exception: + interval_s = 0 + windows = d.get("windows") if isinstance(d.get("windows"), dict) else {} + if interval_s <= 0: + # best-effort: derive from first window on any day + try: + for _k, _v in windows.items(): + if isinstance(_v, list) and _v and isinstance(_v[0], dict): + v = _v[0].get("intervalSeconds") + if v is not None: + interval_s = int(v or 0) + break + except Exception: + pass + if interval_s <= 0: + interval_s = 3600 + return Schedule(enabled=enabled, intervalSeconds=interval_s, windows=windows) + + def validate(self) -> List[str]: + errs: List[str] = [] + if self.enabled: + try: + iv = int(self.intervalSeconds or 0) + except Exception: + iv = 0 + if iv <= 0: + errs.append("Schedule intervalSeconds must be > 0 when schedule is enabled.") + # windows is optional; if provided, validate structure best-effort + if self.windows and not isinstance(self.windows, dict): + errs.append("Schedule windows must be an object/dict.") + return errs + + def _parse_hhmm(val: Any) -> Optional[Tuple[int, int]]: + try: + parts = str(val).strip().split(":") + if len(parts) != 2: + return None + hh = int(parts[0]); mm = int(parts[1]) + if hh < 0 or hh > 23 or mm < 0 or mm > 59: + return None + return (hh, mm) + except Exception: + return None + + try: + for _day, arr in (self.windows or {}).items(): + if not isinstance(arr, list): + errs.append("Schedule windows entries must be lists.") + continue + for w in arr: + if not isinstance(w, dict): + errs.append("Schedule window must be an object.") + continue + if _parse_hhmm(w.get("start")) is None: + errs.append("Schedule window start must be HH:MM.") + if _parse_hhmm(w.get("end")) is None: + errs.append("Schedule window end must be HH:MM.") + if "intervalSeconds" in w: + try: + if int(w.get("intervalSeconds") or 0) <= 0: + errs.append("Schedule window intervalSeconds must be > 0 when provided.") + except Exception: + errs.append("Schedule window intervalSeconds must be an integer.") + except Exception: + # best-effort validation only + pass + + return errs + + def _window_allows_now_local(self, now_local: datetime) -> bool: + # If windows is missing/not-a-dict, treat as unrestricted (legacy). + if self.windows is None or not isinstance(self.windows, dict): + return True + # If windows is an empty dict, treat as "no service window configured" => not allowed. + if not self.windows: + return False + + wd = now_local.weekday() # 0..6 (Mon..Sun) + day_windows = self.windows.get(str(wd)) or self.windows.get(wd) + if not isinstance(day_windows, list) or not day_windows: + return False + + tnow = now_local.time().replace(tzinfo=None) + + def _parse_hhmm(val: Any) -> Optional[Tuple[int, int]]: + try: + parts = str(val).strip().split(":") + if len(parts) != 2: + return None + hh = int(parts[0]); mm = int(parts[1]) + if hh < 0 or hh > 23 or mm < 0 or mm > 59: + return None + return (hh, mm) + except Exception: + return None + + for w in day_windows: + if not isinstance(w, dict): + continue + ps = _parse_hhmm(w.get("start")) + pe = _parse_hhmm(w.get("end")) + if ps is None or pe is None: + continue + sh, sm = ps; eh, em = pe + ts = datetime(2000, 1, 1, sh, sm).time() + te = datetime(2000, 1, 1, eh, em).time() + + if ts <= te: + if ts <= tnow <= te: + return True + else: + # overnight window (e.g. 22:00-06:00) + if tnow >= ts or tnow <= te: + return True + + return False + + def interval_seconds_for_now(self, now: Optional[datetime] = None) -> int: + now_local = (now or datetime.now(timezone.utc)).astimezone() + # Priority: + # 1) per-day window intervalSeconds (first window entry) + # 2) schedule.intervalSeconds + try: + wd = now_local.weekday() + day = None + if isinstance(self.windows, dict): + day = self.windows.get(str(wd)) or self.windows.get(wd) + if isinstance(day, list) and day and isinstance(day[0], dict): + v = day[0].get("intervalSeconds") + if v is not None: + iv = int(v or 0) + if iv > 0: + return iv + except Exception: + pass + + try: + iv = int(self.intervalSeconds or 0) + return iv if iv > 0 else 3600 + except Exception: + return 3600 + + def should_run_now(self, now: Optional[datetime] = None) -> bool: + if not self.enabled: + return False + now_local = (now or datetime.now(timezone.utc)).astimezone() + return self._window_allows_now_local(now_local) + + def next_run_at(self, now: Optional[datetime] = None) -> Optional[datetime]: + # This domain object doesn't store lastScheduledRunAt; caller should decide cadence. + # We return "now + interval" if windows allow now; otherwise the next allowed window start. + if not self.enabled: + return None + + now_utc = now or datetime.now(timezone.utc) + now_local = now_utc.astimezone() + + if self._window_allows_now_local(now_local): + return now_utc + timedelta(seconds=int(self.interval_seconds_for_now(now_utc))) + + # Find next allowed window start within the next 7 days (best-effort). + if not self.windows or not isinstance(self.windows, dict): + return now_utc + timedelta(seconds=int(self.interval_seconds_for_now(now_utc))) + + def _parse_hhmm(val: Any) -> Optional[Tuple[int, int]]: + try: + parts = str(val).strip().split(":") + if len(parts) != 2: + return None + hh = int(parts[0]); mm = int(parts[1]) + if hh < 0 or hh > 23 or mm < 0 or mm > 59: + return None + return (hh, mm) + except Exception: + return None + + base_local = now_local.replace(second=0, microsecond=0) + for add_days in range(0, 8): + day_local = base_local + timedelta(days=add_days) + wd = day_local.weekday() + day_windows = self.windows.get(str(wd)) or self.windows.get(wd) + if not isinstance(day_windows, list) or not day_windows: + continue + # use the first window as the start candidate (UI currently writes a single window per day) + w0 = day_windows[0] if isinstance(day_windows[0], dict) else None + if not w0: + continue + ps = _parse_hhmm(w0.get("start")) + if ps is None: + continue + sh, sm = ps + candidate_local = day_local.replace(hour=sh, minute=sm) + candidate_utc = candidate_local.astimezone(timezone.utc) + if candidate_utc > now_utc: + return candidate_utc + + return None + +@dataclass +class JobRunResult: + ok: bool + started_at: str + ended_at: str + result: str + message: Optional[str] = None + stats: JsonDict = field(default_factory=dict) + +@dataclass +class Job: + id: Optional[int] = None + name: str = "" + enabled: bool = True + mode: str = "mirror" + direction: str = "unidirectional" + preserveMetadata: bool = True + conflictPolicy: str = "newest" + pairId: Optional[str] = None + + sourceEndpoint: Endpoint = field(default_factory=Endpoint) + targetEndpoint: Endpoint = field(default_factory=Endpoint) + + schedule: Schedule = field(default_factory=Schedule) + + lastRun: Optional[str] = None + lastResult: Optional[str] = None + lastError: Optional[str] = None + + def validate(self) -> List[str]: + errs: List[str] = [] + if not self.name.strip(): + errs.append("Job name is required.") + if not self.mode: + errs.append("Job mode is required.") + if not self.direction: + errs.append("Job direction is required.") + + errs.extend(self.sourceEndpoint.validate("source")) + errs.extend(self.targetEndpoint.validate("target")) + errs.extend(self.schedule.validate()) + + d = (self.direction or "").lower() + if d not in ("unidirectional", "bidirectional"): + errs.append("Job direction must be 'unidirectional' or 'bidirectional'.") + + cp = (self.conflictPolicy or "newest").lower() + if cp not in ("newest", "keepa", "a", "keepb", "b"): + errs.append("conflictPolicy must be one of: newest, keepA/a, keepB/b.") + + return errs + + def should_run_now(self, now: Optional[datetime] = None) -> bool: + if not self.enabled: + return False + return self.schedule.should_run_now(now) + + def next_run_at(self, now: Optional[datetime] = None) -> Optional[datetime]: + if not self.enabled: + return None + return self.schedule.next_run_at(now) + + def run( + self, + *, + now: Optional[datetime] = None, + copy_func: Optional[Callable[..., bool]] = None, + bidirectional_func: Optional[Callable[..., Tuple[bool, JsonDict]]] = None, + logger: Optional[Callable[[str, str], None]] = None, + ) -> JobRunResult: + now_dt = now or datetime.now(timezone.utc) + started_at = now_dt.isoformat() + + def _log(msg: str, level: str = "info") -> None: + if logger: + try: + logger(msg, level) + except Exception: + pass + + errs = self.validate() + if errs: + msg = "; ".join(errs) + ended = datetime.now(timezone.utc).isoformat() + self.lastRun = ended + self.lastResult = "fail" + self.lastError = msg + return JobRunResult( + ok=False, + started_at=started_at, + ended_at=ended, + result="fail", + message=msg, + stats={}, + ) + + if not self.enabled: + ended = datetime.now(timezone.utc).isoformat() + return JobRunResult( + ok=True, + started_at=started_at, + ended_at=ended, + result="ok", + message="Job disabled; skipped.", + stats={}, + ) + + preserve = bool(self.preserveMetadata) + allow_del = (str(self.mode or "").lower() == "mirror") + + # Resolve endpoints (mount SMB endpoints to local paths for the duration of the run) + mounted: List[MountedEndpoint] = [] + ok: bool = False + stats: JsonDict = {} + + # Define upfront so logging/error handling can't reference undefined vars. + src = "" + dst = "" + + try: + # Mount endpoints inside the try so a failure mounting target still cleans up source. + src_m = mount_endpoint_if_remote(self.sourceEndpoint, self.id, "source", logger=logger) + mounted.append(src_m) + dst_m = mount_endpoint_if_remote(self.targetEndpoint, self.id, "target", logger=logger) + mounted.append(dst_m) + + src = src_m.local_path + dst = dst_m.local_path + + if (self.direction or "").lower() == "bidirectional": + if not bidirectional_func: + raise NotImplementedError("Bidirectional engine not provided.") + + # IMPORTANT: + # The bidirectional engine historically enforced local endpoints only by checking + # endpoint types. Since remote endpoints are mounted to local paths for the duration + # of the run, we provide a local-view of this job to the engine. + job_local_view = Job( + id=self.id, + name=self.name, + enabled=self.enabled, + mode=self.mode, + direction=self.direction, + preserveMetadata=self.preserveMetadata, + conflictPolicy=self.conflictPolicy, + pairId=self.pairId, + sourceEndpoint=Endpoint(type="local", location=src, auth={}), + targetEndpoint=Endpoint(type="local", location=dst, auth={}), + schedule=self.schedule, + lastRun=self.lastRun, + lastResult=self.lastResult, + lastError=self.lastError, + ) + + _log(f"[Job] Running bidirectional job '{self.name}': {src} <-> {dst}", "info") + ok, stats = bidirectional_func(job_local_view, None) + else: + if not copy_func: + raise NotImplementedError("Copy function not provided.") + _log(f"[Job] Running unidirectional job '{self.name}': {src} -> {dst}", "info") + ok = bool(copy_func(src, dst, preserve_metadata=preserve, allow_deletion=allow_del)) + except NotImplementedError as e: + ok = False + self.lastError = str(e) + _log(f"[Job] Not supported: {e}", "error") + except Exception as e: + ok = False + self.lastError = str(e) + _log(f"[Job] Execution failed: {e}", "error") + finally: + # Always unmount remote endpoints + for m in reversed(mounted): + try: + m.cleanup() + except Exception: + pass + + ended_at = datetime.now(timezone.utc).isoformat() + self.lastRun = ended_at + self.lastResult = "ok" if ok else "fail" + if ok: + self.lastError = None + else: + self.lastError = self.lastError or "Failed" + + return JobRunResult( + ok=ok, + started_at=started_at, + ended_at=ended_at, + result="ok" if ok else "fail", + message=None if ok else self.lastError, + stats=stats or {}, + ) + + def to_row_dicts(self) -> Dict[str, Any]: + job_row = { + "id": self.id, + "name": self.name, + "enabled": 1 if self.enabled else 0, + "mode": self.mode or "mirror", + "direction": self.direction or "unidirectional", + # "allowDeletion" entry removed; will be derived at write time + "preserveMetadata": 1 if self.preserveMetadata else 0, + "pairId": self.pairId, + "conflictPolicy": self.conflictPolicy or "newest", + "lastRun": self.lastRun, + "lastResult": self.lastResult, + "lastError": self.lastError, + } + + endpoint_rows = [ + self.sourceEndpoint.to_db_fields("source"), + self.targetEndpoint.to_db_fields("target"), + ] + + sched_row = { + "enabled": 1 if self.schedule and self.schedule.enabled else 0, + "intervalSeconds": int(self.schedule.intervalSeconds if self.schedule else 3600), + "windows": json.dumps(self.schedule.windows if self.schedule and isinstance(self.schedule.windows, dict) else {}), + } + + return { + "job_row": job_row, + "endpoint_rows": endpoint_rows, + "schedule_row": sched_row, + } + + @staticmethod + def from_db_rows( + job_row: Mapping[str, Any], + endpoint_rows: Iterable[Mapping[str, Any]], + schedule_row: Optional[Mapping[str, Any]] = None, + ) -> "Job": + j = Job( + id=int(job_row.get("id")) if job_row.get("id") is not None else None, + name=str(job_row.get("name") or ""), + enabled=bool(job_row.get("enabled", 1)), + mode=str(job_row.get("mode") or "mirror"), + direction=str(job_row.get("direction") or "unidirectional"), + preserveMetadata=bool(job_row.get("preserveMetadata", 1)), + conflictPolicy=str(job_row.get("conflictPolicy") or "newest"), + pairId=job_row.get("pairId"), + lastRun=job_row.get("lastRun"), + lastResult=job_row.get("lastResult"), + lastError=job_row.get("lastError"), + ) + + src = None + tgt = None + for r in endpoint_rows: + role = (r.get("role") or "").lower() + ep = Endpoint.from_db_row(r) + if role == "source": + src = ep + elif role == "target": + tgt = ep + + j.sourceEndpoint = src or Endpoint() + j.targetEndpoint = tgt or Endpoint() + + if schedule_row: + # Read intervalSeconds and windows as new model, fallback as needed + try: + interval_s = int(schedule_row.get("intervalSeconds") or 0) + except Exception: + interval_s = 0 + # Remove legacy everyMinutes fallback + if interval_s <= 0: + interval_s = 3600 + windows = {} + try: + raw = schedule_row.get("windows") + if raw: + windows = json.loads(raw) if isinstance(raw, str) else (raw if isinstance(raw, dict) else {}) + except Exception: + windows = {} + j.schedule = Schedule( + enabled=bool(schedule_row.get("enabled", 1)), + intervalSeconds=int(interval_s), + windows=windows, + ) + else: + j.schedule = Schedule() + + return j + + + +# --------------------------------------------------------------------------- +# JobStore (DB persistence) +# --------------------------------------------------------------------------- + +class JobStore: + """SQLite persistence for Job domain objects (UI-agnostic).""" + + def __init__(self, db: Any): + self._db = db + if SQLite is None or not isinstance(self._db, SQLite): + raise TypeError("JobStore requires core.database.sqlite.SQLite") + + def _is_core_sqlite(self) -> bool: + return True + + def _select(self, table: str, where: Optional[str] = None, params: Any = None, *, order_by: Optional[str] = None) -> List[Dict[str, Any]]: + return self._db.select(table, where=where, params=params, order_by=order_by) # type: ignore[union-attr] + + def _one(self, table: str, where: str, params: Any) -> Optional[Dict[str, Any]]: + return self._db.one(f'SELECT * FROM "{table}" WHERE {where} LIMIT 1;', params) # type: ignore[union-attr] + + def _insert(self, table: str, data: Dict[str, Any]) -> int: + return int(self._db.insert(table, data)) # type: ignore[union-attr] + + def _update(self, table: str, data: Dict[str, Any], where: str, params: Any) -> None: + if not isinstance(params, dict): + raise ValueError("JobStore._update requires dict params") + self._db.update(table, data, where, params) # type: ignore[union-attr] + + def _upsert(self, table: str, data: Dict[str, Any], conflict_columns: List[str], update_columns: Optional[List[str]] = None) -> None: + self._db.upsert(table, data, conflict_columns, update_columns) # type: ignore[union-attr] + + def _delete(self, table: str, where: str, params: Any) -> None: + self._db.delete(table, where, params) # type: ignore[union-attr] + + def _transaction(self): + return self._db.transaction() # type: ignore[union-attr] + + # ------------------------------- + # Reads + # ------------------------------- + + def fetch_all(self) -> List[Job]: + job_rows = self._select("jobs", order_by="id ASC") + jobs: List[Job] = [] + for jr in job_rows: + jid = int(jr.get("id") or 0) + ep_rows = self.fetch_endpoints_rows(jid) + sched_row = self.fetch_schedule_row(jid) + jobs.append(Job.from_db_rows(jr, ep_rows, sched_row)) + return jobs + + def fetch_by_id(self, job_id: int) -> Optional[Job]: + jr = self._one("jobs", "id = ?", (int(job_id),)) + if not jr: + return None + ep_rows = self.fetch_endpoints_rows(int(job_id)) + sched_row = self.fetch_schedule_row(int(job_id)) + return Job.from_db_rows(jr, ep_rows, sched_row) + + def fetch_endpoints_rows(self, job_id: int) -> List[Dict[str, Any]]: + return self._select("endpoints", "jobId = ?", (int(job_id),)) + + def fetch_schedule_row(self, job_id: int) -> Optional[Dict[str, Any]]: + return self._one("schedule", "jobId = ?", (int(job_id),)) + + # ------------------------------- + # Writes + # ------------------------------- + + def upsert(self, job: Job) -> int: + row_dicts = job.to_row_dicts() + job_row: Dict[str, Any] = row_dicts["job_row"] + endpoint_rows: List[Dict[str, Any]] = row_dicts["endpoint_rows"] + schedule_row: Dict[str, Any] = row_dicts["schedule_row"] + + with self._transaction(): + # --- jobs --- + data = { + "name": job_row.get("name"), + "enabled": int(job_row.get("enabled") or 0), + "mode": job_row.get("mode") or "mirror", + "direction": job_row.get("direction") or "unidirectional", + # mode is the source of truth for deletion behavior + "allowDeletion": 1 if (str(job_row.get("mode") or "mirror").lower() == "mirror") else 0, + "preserveMetadata": int(job_row.get("preserveMetadata") or 0), + "pairId": job_row.get("pairId"), + "conflictPolicy": job_row.get("conflictPolicy") or "newest", + "lastRun": job_row.get("lastRun"), + "lastResult": job_row.get("lastResult"), + "lastError": job_row.get("lastError"), + } + + if job.id: + self._update("jobs", data, "id = :id", {"id": int(job.id)}) + job_id = int(job.id) + else: + job_id = self._insert("jobs", data) + job.id = job_id + + # --- endpoints (unique: jobId+role) --- + for ep in endpoint_rows: + role = ep.get("role") + if role not in ("source", "target"): + continue + ep_data = { + "jobId": job_id, + "role": role, + "type": ep.get("type"), + "location": ep.get("location"), + "port": ep.get("port"), + "guest": ep.get("guest"), + "username": ep.get("username"), + "password": ep.get("password"), + "options": ep.get("options"), + } + self._upsert( + "endpoints", + ep_data, + ["jobId", "role"], + update_columns=["type", "location", "port", "guest", "username", "password", "options"], + ) + + # --- schedule (unique: jobId) --- + s_data = { + "jobId": job_id, + "enabled": int(schedule_row.get("enabled") or 0), + "intervalSeconds": int(schedule_row.get("intervalSeconds") or 0), + "windows": schedule_row.get("windows"), + } + self._upsert( + "schedule", + s_data, + ["jobId"], + update_columns=["enabled", "intervalSeconds", "windows"], + ) + + return int(job.id or 0) + + def delete(self, job_id: int) -> None: + jid = int(job_id) + with self._transaction(): + # Delete dependent rows first to avoid orphan data (and to work even without FK cascades) + try: + self._delete("endpoints", "jobId = ?", (jid,)) + except Exception: + pass + try: + self._delete("schedule", "jobId = ?", (jid,)) + except Exception: + pass + # These tables may exist depending on enabled features; delete best-effort. + for tbl in ("runs", "conflicts", "file_state"): + try: + self._delete(tbl, "jobId = ?", (jid,)) + except Exception: + pass + self._delete("jobs", "id = ?", (jid,)) diff --git a/dist/macos/Replicator.app/Contents/Resources/replicator/migration.py b/dist/macos/Replicator.app/Contents/Resources/replicator/migration.py new file mode 100644 index 00000000..e4cddada --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/replicator/migration.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 +# src/replicator/migration.py + +from __future__ import annotations + +from typing import List, Optional, Sequence, Tuple + +try: + from core.database.sqlite import SQLite + from core.log import Log +except ImportError: + from database.sqlite import SQLite + from log import Log + + +class Migration: + """Database schema creation + migrations for Replicator. + + This class intentionally *does not* re-implement a DB wrapper. + It relies on corePY's `SQLite` for connections/transactions and only + owns Replicator's schema + migration history + small meta KV helpers. + """ + + def __init__(self, db: SQLite, logger: Optional[Log] = None): + self._db = db + self._logger = logger + + # ------------------------------------------------------------------ + # Public API + # ------------------------------------------------------------------ + + def ensure(self) -> None: + """Ensure base tables exist and apply all pending migrations.""" + self._ensure_schema_migrations_table() + self._apply_migrations(self._migrations()) + + def get_meta(self, key: str, default: Optional[str] = None) -> Optional[str]: + """Read a value from the `meta` table. Returns default if missing.""" + try: + row = self._db.one("SELECT value FROM meta WHERE key = ?", (key,)) + if not row: + return default + val = row.get("value") + return default if val is None else str(val) + except Exception: + return default + + def set_meta(self, key: str, value: Optional[str]) -> None: + """Upsert a value into the `meta` table.""" + try: + with self._db.transaction(): + exists = self._db.scalar("SELECT 1 FROM meta WHERE key = ? LIMIT 1", (key,)) + if exists: + self._db.execute( + "UPDATE meta SET value = ?, modified = CURRENT_TIMESTAMP WHERE key = ?", + (value, key), + ) + else: + self._db.execute( + "INSERT INTO meta (key, value) VALUES (?, ?)", + (key, value), + ) + except Exception: + # best effort + pass + + # ------------------------------------------------------------------ + # Internals + # ------------------------------------------------------------------ + + def _log(self, msg: str, *, level: str = "info", channel: str = "migration") -> None: + if self._logger is not None and hasattr(self._logger, "append"): + self._logger.append(msg, level=level, channel=channel) # type: ignore[call-arg] + else: + print(msg) + + def _ensure_schema_migrations_table(self) -> None: + self._db.execute( + """ + CREATE TABLE IF NOT EXISTS schema_migrations ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + name TEXT NOT NULL UNIQUE + ); + """ + ) + + def _is_applied(self, name: str) -> bool: + r = self._db.scalar( + "SELECT 1 FROM schema_migrations WHERE name = ? LIMIT 1;", + (name,), + ) + return bool(r) + + def _apply_migrations(self, migrations: Sequence[Tuple[str, Sequence[str]]]) -> None: + for name, stmts in migrations: + if self._is_applied(name): + continue + + try: + with self._db.transaction(): + for stmt in stmts: + self._db.execute(stmt) + self._db.execute("INSERT INTO schema_migrations (name) VALUES (?)", (name,)) + + self._log(f"[Migration] applied {name}", level="debug") + except Exception as e: + raise RuntimeError(f"Failed to apply migration {name}: {e}") + + def _migrations(self) -> List[Tuple[str, List[str]]]: + return [ + ( + "0001_init", + [ + # jobs + """ + CREATE TABLE IF NOT EXISTS jobs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + name TEXT NOT NULL, + enabled INTEGER NOT NULL DEFAULT 1, + mode TEXT NOT NULL DEFAULT 'mirror', + direction TEXT NOT NULL DEFAULT 'unidirectional', + allowDeletion INTEGER NOT NULL DEFAULT 0, + preserveMetadata INTEGER NOT NULL DEFAULT 1, + pairId TEXT NULL, + conflictPolicy TEXT NOT NULL DEFAULT 'newest', + lastRun TEXT NULL, + lastResult TEXT NULL, + lastError TEXT NULL + ); + """, + "CREATE INDEX IF NOT EXISTS idx_jobs_enabled ON jobs(enabled);", + + # endpoints + """ + CREATE TABLE IF NOT EXISTS endpoints ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL, + role TEXT NOT NULL, + type TEXT NOT NULL, + location TEXT NOT NULL, + port INTEGER NULL, + guest INTEGER NOT NULL DEFAULT 1, + username TEXT NULL, + password TEXT NULL, + options TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """, + "CREATE UNIQUE INDEX IF NOT EXISTS uq_endpoints_job_role ON endpoints(jobId, role);", + + # schedule + """ + CREATE TABLE IF NOT EXISTS schedule ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL UNIQUE, + -- Schedule is controlled via per-day windows and intervalSeconds. + enabled INTEGER NOT NULL DEFAULT 1, + intervalSeconds INTEGER NOT NULL DEFAULT 3600, + nextRunAt TEXT NULL, + lastScheduledRunAt TEXT NULL, + windows TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """, + + # runs + """ + CREATE TABLE IF NOT EXISTS runs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL, + startedAt TEXT NOT NULL, + endedAt TEXT NULL, + result TEXT NOT NULL, + message TEXT NULL, + stats TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """, + "CREATE INDEX IF NOT EXISTS idx_runs_job_started ON runs(jobId, startedAt);", + + # file_state + """ + CREATE TABLE IF NOT EXISTS file_state ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL, + side TEXT NOT NULL, + relPath TEXT NOT NULL, + size INTEGER NOT NULL DEFAULT 0, + mtime INTEGER NOT NULL DEFAULT 0, + hash TEXT NULL, + isDir INTEGER NOT NULL DEFAULT 0, + deleted INTEGER NOT NULL DEFAULT 0, + deletedAt TEXT NULL, + meta TEXT NULL, + lastSeenAt TEXT NULL, + lastSeenRunId INTEGER NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """, + "CREATE UNIQUE INDEX IF NOT EXISTS uq_file_state ON file_state(jobId, side, relPath);", + + # conflicts + """ + CREATE TABLE IF NOT EXISTS conflicts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL, + runId INTEGER NULL, + relPath TEXT NOT NULL, + a_size INTEGER NULL, + a_mtime INTEGER NULL, + a_hash TEXT NULL, + b_size INTEGER NULL, + b_mtime INTEGER NULL, + b_hash TEXT NULL, + status TEXT NOT NULL DEFAULT 'open', + resolution TEXT NULL, + note TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE, + FOREIGN KEY(runId) REFERENCES runs(id) ON DELETE SET NULL + ); + """, + "CREATE INDEX IF NOT EXISTS idx_conflicts_job_status ON conflicts(jobId, status);", + + # meta (simple KV store) + """ + CREATE TABLE IF NOT EXISTS meta ( + key TEXT PRIMARY KEY, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + value TEXT NULL + ); + """, + ], + ), + ( + "0002_schedule_enabled_default_off", + [ + # SQLite cannot ALTER COLUMN defaults directly; rebuild the schedule table so + # new rows default to enabled=0 while preserving existing data. + "PRAGMA foreign_keys=OFF;", + """ + CREATE TABLE IF NOT EXISTS schedule_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL UNIQUE, + -- Schedule is controlled via per-day windows and intervalSeconds. + enabled INTEGER NOT NULL DEFAULT 0, + intervalSeconds INTEGER NOT NULL DEFAULT 3600, + nextRunAt TEXT NULL, + lastScheduledRunAt TEXT NULL, + windows TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """.strip(), + """ + INSERT INTO schedule_new (id, created, modified, jobId, enabled, intervalSeconds, nextRunAt, lastScheduledRunAt, windows) + SELECT id, created, modified, jobId, enabled, intervalSeconds, nextRunAt, lastScheduledRunAt, windows + FROM schedule; + """.strip(), + "DROP TABLE schedule;", + "ALTER TABLE schedule_new RENAME TO schedule;", + "PRAGMA foreign_keys=ON;", + ], + ), + ] diff --git a/dist/macos/Replicator.app/Contents/Resources/replicator/mount.py b/dist/macos/Replicator.app/Contents/Resources/replicator/mount.py new file mode 100644 index 00000000..30f3276a --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/replicator/mount.py @@ -0,0 +1,317 @@ + +#!/usr/bin/env python3 +# src/replicator/mount.py + +"""Remote mount helpers for Replicator. + +Purpose +------- +Centralize SMB mounting logic so it can be reused by both: + - UI runner (replicator.py) which often works with legacy dict endpoints + - Domain runner (job.py) which uses Endpoint dataclass objects + +Supported +--------- +- SMB (CIFS / Windows shares) + +This module is intentionally thin and delegates to corePY's Share helper: + from core.filesystem.share import Share, ShareAuth + +Notes +----- +- Remote "location" strings are accepted in common forms: + * \\host\\Share\\dir + * //host/Share/dir + * host/Share/dir +- On macOS, `mount_smbfs` expects URL-style paths; the remote part is + percent-encoded (spaces, etc.) while keeping '/' separators intact. +- Secrets are never logged; obvious fields are redacted. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Callable, Dict, Optional, Tuple + +import os +import re +import tempfile +from urllib.parse import quote + +# corePY Share helper (import once at module import time) +try: + from core.filesystem.share import Share, ShareAuth # type: ignore +except Exception as _e: # pragma: no cover + Share = None # type: ignore + ShareAuth = None # type: ignore + _COREPY_SHARE_IMPORT_ERROR = _e +else: + _COREPY_SHARE_IMPORT_ERROR = None + +# --------------------------------------------------------------------------- +# Exceptions +# --------------------------------------------------------------------------- + +class RemoteMountError(RuntimeError): + """Raised when a remote endpoint cannot be mounted or parsed.""" + +# --------------------------------------------------------------------------- +# Logging helpers +# --------------------------------------------------------------------------- + +def redact_secrets(s: str) -> str: + """Best-effort secret redaction for log lines.""" + if not s: + return s + # key=value patterns + s = re.sub(r"(pass=)([^,\s]+)", r"\1***", s, flags=re.IGNORECASE) + s = re.sub(r"(password=)([^,\s]+)", r"\1***", s, flags=re.IGNORECASE) + # CLI flags + s = re.sub(r"(--password\s+)(\S+)", r"\1***", s, flags=re.IGNORECASE) + s = re.sub(r"(--pass\s+)(\S+)", r"\1***", s, flags=re.IGNORECASE) + return s + +class ShareLoggerAdapter: + """Adapter to feed Share's logging into Replicator/corePY style append().""" + + def __init__(self, append_fn: Callable[[str, str], None] | Callable[..., None]): + self._append = append_fn + + def debug(self, msg: str) -> None: + self._append(redact_secrets(msg), level="debug") # type: ignore[misc] + + def info(self, msg: str) -> None: + self._append(redact_secrets(msg), level="info") # type: ignore[misc] + + def warning(self, msg: str) -> None: + self._append(redact_secrets(msg), level="warning") # type: ignore[misc] + + def error(self, msg: str) -> None: + self._append(redact_secrets(msg), level="error") # type: ignore[misc] + +# --------------------------------------------------------------------------- +# Models +# --------------------------------------------------------------------------- + +@dataclass +class MountedEndpoint: + """Represents a mounted (or local) endpoint.""" + + local_path: str + mount_point: Optional[str] = None + share: Any = None # Share instance (only present when mounted) + + def cleanup(self, *, elevate: bool = False) -> None: + """Unmount the share if mounted; best-effort. + + Notes + ----- + Some platforms/targets may require elevation to unmount. We keep the + default as `False` to match current behavior; callers can opt-in. + """ + if self.share is not None and self.mount_point: + try: + self.share.umount(self.mount_point, elevate=bool(elevate)) + except Exception: + pass + +# --------------------------------------------------------------------------- +# Parsing +# --------------------------------------------------------------------------- + +def parse_smb_location(location: str) -> Tuple[str, str]: + """Parse SMB location into (host, remote). + + Accepts forms: + - \\host\\Share + - \\host\\Share\\dir\\sub + - //host/Share/dir + - host/Share/dir + + Returns: + host, remote where remote is "Share" or "Share/dir/sub". + """ + s = (location or "").strip() + if not s: + raise RemoteMountError("SMB location is empty") + + # Normalize to backslashes then split. + s = s.replace("/", "\\") + while s.startswith("\\"): + s = s[1:] + + parts = [p for p in s.split("\\") if p] + if len(parts) < 2: + raise RemoteMountError( + f"Invalid SMB location '{location}'. Expected //host/Share[/path] or \\\\host\\Share[/path]." + ) + + host = parts[0] + remote = "/".join(parts[1:]) + return host, remote + +# --------------------------------------------------------------------------- +# Mounting +# --------------------------------------------------------------------------- + +def _get_mount_point(job_id: Optional[int], role: str, *, unique: bool = False) -> str: + """Compute the local mount point for a job/role.""" + base = Path(tempfile.gettempdir()) / "replicator" / "mounts" / (str(job_id or "new")) / role + if unique: + # Avoid collisions if caller mounts multiple times quickly. + base = base / str(os.getpid()) + base.mkdir(parents=True, exist_ok=True) + return str(base) + +def mount_endpoint_if_remote( + endpoint: Any, + job_id: Optional[int], + role: str, + *, + share: Any = None, + log_append: Optional[Callable[..., None]] = None, + logger: Any = None, + timeout: int = 60, +) -> MountedEndpoint: + """Mount an endpoint if it is remote; otherwise return the local path. + + Parameters + ---------- + endpoint: + Can be either: + - dict-like: {type, location, auth?} or legacy endpoint row fields + - an object with attributes: .type, .location, .auth + job_id: + Job id (used for mount dir structure). + role: + "source" or "target" (used for mount dir structure). + share: + Optional Share instance to reuse. + log_append: + Function compatible with core Log.append(msg, level=..., channel=...). + If provided, used for safe debug messages. + logger: + Backward-compatible alias used by some callers (e.g. job.py). + Can be either: + - an object exposing `.append(msg, level=...)` (core Log-like) + - a callable compatible with `log_append` + If provided and `log_append` is None, it will be used. + """ + + # Share support is optional at import time; raise a meaningful error at runtime. + if Share is None or ShareAuth is None: + raise RemoteMountError( + "Share support not available (corePY missing or failed to import). " + f"Import error: {_COREPY_SHARE_IMPORT_ERROR}" + ) + + # Backward-compatible: allow callers to pass `logger=` instead of `log_append=`. + if log_append is None and logger is not None: + if callable(logger): + log_append = logger # type: ignore[assignment] + else: + append_fn = getattr(logger, "append", None) + if callable(append_fn): + def _append(msg: str, *, level: str = "info") -> None: + # core Log.append may accept (msg, level=..., channel=...) or (msg, level) + try: + append_fn(msg, level=level) # type: ignore[misc] + except TypeError: + append_fn(msg, level) # type: ignore[misc] + + log_append = _append + + def _get(d: Any, k: str, default: Any = None) -> Any: + if isinstance(d, dict): + return d.get(k, default) + return getattr(d, k, default) + + t = str(_get(endpoint, "type", "local") or "local").lower() + loc = str(_get(endpoint, "location", "") or "").strip() + + if t == "local": + return MountedEndpoint(local_path=loc) + + if t != "smb": + raise RemoteMountError(f"Unsupported endpoint type: {t}") + + mount_point = _get_mount_point(job_id, role, unique=False) + + # Build auth dict from endpoint.auth + legacy flat fields + auth: Dict[str, Any] = {} + raw_auth = _get(endpoint, "auth", None) + if isinstance(raw_auth, dict): + auth.update(raw_auth) + + # Backward compatible: top-level fields (as stored in endpoints table) + for k in ("port", "guest", "username", "password", "options", "domain", "workgroup", "read_only", "ro"): + v = _get(endpoint, k, None) + if v is not None and k not in auth: + auth[k] = v + + # Parse host/remote + host, remote = parse_smb_location(loc) + + # Percent-encode remote path (keep '/' separators) + remote_enc = quote(remote, safe="/") + + # Port + port = 445 + try: + if auth.get("port") is not None: + port = int(auth.get("port") or 445) + except Exception: + port = 445 + + # Options + opts: Dict[str, Any] = {} + if isinstance(auth.get("options"), dict): + opts.update(auth.get("options") or {}) + + # ShareAuth (best effort) + share_auth = ShareAuth( + username=auth.get("username"), + password=auth.get("password"), + domain=auth.get("domain") or auth.get("workgroup"), + ) + + # Share instance (reuse if provided). If we create one here, wire it with our adapter. + if share is None: + share_logger = ShareLoggerAdapter(log_append) if log_append is not None else None + share = Share(logger=share_logger) + + # Emit safe debug line + if log_append is not None: + safe_auth = dict(auth) + for k in ("password", "pass"): + if k in safe_auth and safe_auth[k]: + safe_auth[k] = "***" + msg = ( + f"[Replicator][Mount] protocol={t} host={host} remote={remote_enc} " + f"mount_point={mount_point} auth={safe_auth}" + ) + try: + log_append(msg, level="debug") # type: ignore[misc] + except TypeError: + # Some callables accept only positional args. + log_append(msg) # type: ignore[misc] + + # Mount + try: + share.mount( + t, + host, + remote_enc, + mount_point, + auth=share_auth, + port=port, + options=opts, + read_only=bool(auth.get("read_only") or auth.get("ro") or False), + elevate=False, + timeout=int(timeout or 60), + ) + except Exception as e: + raise RemoteMountError(f"Failed to mount SMB endpoint '{loc}': {e}") + + return MountedEndpoint(local_path=mount_point, mount_point=mount_point, share=share) diff --git a/dist/macos/Replicator.app/Contents/Resources/replicator/replicator.py b/dist/macos/Replicator.app/Contents/Resources/replicator/replicator.py new file mode 100644 index 00000000..208ea9a7 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/replicator/replicator.py @@ -0,0 +1,1424 @@ +#!/usr/bin/env python3 +# src/replicator/replicator.py + +from __future__ import annotations +import os +import json +import shutil +import time +from typing import Optional, Any, Dict, List +from datetime import datetime, timezone, timedelta +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QPixmap +from PyQt5.QtWidgets import ( + QApplication, + QMainWindow, + QWidget, + QVBoxLayout, + QHBoxLayout, + QLabel, + QTableWidget, + QTableWidgetItem, + QHeaderView, + QDialog, +) +from .ui import JobDialog, ScheduleDialog +from .migration import Migration +from .job import Job, Endpoint, Schedule, JobStore +from .mount import RemoteMountError, MountedEndpoint, mount_endpoint_if_remote + +try: + from core.helper import Helper + from core.configuration import Configuration + from core.log import Log + from core.ui import MsgBox, Form + from core.filesystem.filesystem import FileSystem + from core.filesystem.share import Share, ShareAuth + from core.database.sqlite import SQLite +except ImportError: + from helper import Helper + from configuration import Configuration + from log import Log + from ui import MsgBox, Form + from filesystem.filesystem import FileSystem + from filesystem.share import Share, ShareAuth + from database.sqlite import SQLite + +# --------------------------------------------------------------------------- +# Remote endpoints (Share mount) +# --------------------------------------------------------------------------- + +class _ShareLogger: + """Adapter that forwards Share logs into Replicator's logger.""" + + def __init__(self, append_fn): + self._append = append_fn + + def debug(self, msg: str) -> None: + self._append(f"[Share] {msg}", level="debug") + + def info(self, msg: str) -> None: + self._append(f"[Share] {msg}", level="info") + + def warning(self, msg: str) -> None: + self._append(f"[Share] {msg}", level="warning") + + def error(self, msg: str) -> None: + self._append(f"[Share] {msg}", level="error") + +class Replicator(QMainWindow): + + # ------------------------------------------------------------------ + # Initialization + # ------------------------------------------------------------------ + + def __init__( + self, + helper: Optional[Helper] = None, + configuration: Optional[Configuration] = None, + logger: Optional[Log] = None, + ): + super().__init__() + + self._app = QApplication.instance() + if self._app is None: + raise RuntimeError("Replicator must be created after QApplication/Application.") + + helper = helper or getattr(self._app, "helper", None) + configuration = configuration or getattr(self._app, "configuration", None) + logger = logger or getattr(self._app, "logger", None) + + if helper is None or configuration is None: + raise RuntimeError("Replicator requires corePY Helper + Configuration.") + + self._helper: Helper = helper + self._configuration: Configuration = configuration + self._logger: Optional[Log] = logger + + self._fs = FileSystem(helper=self._helper, logger=self._logger) + + # Shared Share instance (for SMB mounts) so we don't recreate it on every job run. + self._share_logger = _ShareLogger(self._log) + self._share = Share(logger=self._share_logger) + + # --- Database path setup --- + # Use Helper.get_data_path to locate data/replicator.db + data_dir = self._helper.get_data_path("data", scope="system") + if data_dir is None: + raise RuntimeError("Could not locate data/ directory via Helper.get_data_path().") + os.makedirs(data_dir, exist_ok=True) + db_path = os.path.join(data_dir, "replicator.db") + + # --- Database (corePY SQLite wrapper) + migrations --- + self._db = SQLite(db_path=db_path) + self._migration = Migration(self._db, logger=self._logger) + self._migration.ensure() + + self._store = JobStore(self._db) + + self._log(f"[Replicator] Database: {db_path}", level="debug") + self._log("[Replicator] Database migrations applied.", level="info") + + # Domain jobs (Job objects) + self._jobs: List[Job] = [] + self._table: Optional[QTableWidget] = None + + # After DB is ready, log a snapshot of DB layout/counts (non-verbose) + self._db_debug_snapshot(verbose=False) + + # ------------------------------------------------------------------ + # Scheduler (service mode) + # ------------------------------------------------------------------ + + def _parse_iso_dt(self, s: Any) -> Optional[datetime]: + if not s: + return None + try: + dt = datetime.fromisoformat(str(s)) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=timezone.utc) + return dt + except Exception: + return None + + def _should_run_scheduled(self, job: Job, *, now_utc: datetime) -> bool: + """Decide if a job should run in SERVICE/SCHEDULED mode. + + Manual 'Run now' intentionally bypasses this. + """ + if not job.id: + return False + + sched = self._db.one( + "SELECT enabled, nextRunAt, lastScheduledRunAt FROM schedule WHERE jobId=?", + (int(job.id),), + ) + if not sched: + # No schedule row => do not auto-run (manual run still works) + return False + + # Schedule must be explicitly enabled in DB + if not bool(sched.get("enabled", 0)): + return False + + # Schedule windows/interval are defined on the Job domain object + if not job.schedule.should_run_now(now_utc): + return False + + # Respect nextRunAt if present + next_dt = self._parse_iso_dt(sched.get("nextRunAt")) + if next_dt and now_utc < next_dt: + return False + + # Respect lastScheduledRunAt + interval + last_dt = self._parse_iso_dt(sched.get("lastScheduledRunAt")) + if last_dt is None: + return True + + interval_s = int(job.schedule.interval_seconds_for_now(now_utc) or 0) + if interval_s <= 0: + interval_s = self._default_interval_seconds() + + elapsed = (now_utc - last_dt).total_seconds() + return elapsed >= float(interval_s) + # Bidirectional sync helpers (local-only for now) + # ------------------------------------------------------------------ + + def _endpoint_local_root(self, ep: Dict[str, Any]) -> str: + """Return the local root path for an endpoint or raise. + This is a simple extractor for the already-mounted path.""" + if not isinstance(ep, dict): + raise ValueError("Endpoint is missing") + loc = (ep.get("location") or "").strip() + if not loc: + raise ValueError("Endpoint location is required") + return loc + + def _scan_local_tree(self, root: str) -> Dict[str, Dict[str, Any]]: + """Return a map relPath -> {isDir,size,mtime} for a local filesystem root.""" + root = os.path.abspath(root) + out: Dict[str, Dict[str, Any]] = {} + if not os.path.exists(root): + return out + + # Walk directories; include dirs as entries so deletions can be propagated. + for dirpath, dirnames, filenames in os.walk(root): + # Normalize and skip hidden special entries if needed (keep simple for now) + rel_dir = os.path.relpath(dirpath, root) + if rel_dir == ".": + rel_dir = "" + + # Record directory itself (except root) + if rel_dir: + try: + st = os.stat(dirpath) + out[rel_dir] = { + "isDir": True, + "size": 0, + "mtime": int(st.st_mtime), + } + except Exception: + # If stat fails, still record directory + out[rel_dir] = {"isDir": True, "size": 0, "mtime": 0} + + for fn in filenames: + full = os.path.join(dirpath, fn) + rel = os.path.relpath(full, root) + try: + st = os.stat(full) + out[rel] = { + "isDir": False, + "size": int(st.st_size), + "mtime": int(st.st_mtime), + } + except Exception: + out[rel] = {"isDir": False, "size": 0, "mtime": 0} + + return out + + def _load_prev_file_state(self, job_id: int, side: str) -> Dict[str, Dict[str, Any]]: + rows = self._db.query( + "SELECT relPath, size, mtime, isDir, deleted, deletedAt, lastSeenAt, lastSeenRunId FROM file_state WHERE jobId=? AND side=?", + (job_id, side), + ) + prev: Dict[str, Dict[str, Any]] = {} + for r in rows or []: + prev[str(r.get("relPath"))] = { + "size": int(r.get("size") or 0), + "mtime": int(r.get("mtime") or 0), + "isDir": bool(r.get("isDir")), + "deleted": bool(r.get("deleted")), + "deletedAt": r.get("deletedAt"), + "lastSeenAt": r.get("lastSeenAt"), + "lastSeenRunId": r.get("lastSeenRunId"), + } + return prev + + def _persist_file_state(self, job_id: int, side: str, cur: Dict[str, Dict[str, Any]], run_id: Optional[int]) -> None: + # Use wrapper transaction; no raw connection needed. + now_iso = datetime.now(timezone.utc).isoformat() + with self._db.transaction(): + # Upsert all current entries + for rel, meta in cur.items(): + is_dir = 1 if meta.get("isDir") else 0 + size = int(meta.get("size", 0) or 0) + mtime = int(meta.get("mtime", 0) or 0) + + exists = self._db.scalar( + "SELECT id FROM file_state WHERE jobId=? AND side=? AND relPath=?", + (job_id, side, rel), + ) + if exists: + self._db.execute( + "UPDATE file_state SET size=?, mtime=?, isDir=?, deleted=0, deletedAt=NULL, lastSeenAt=?, lastSeenRunId=? WHERE jobId=? AND side=? AND relPath=?", + (size, mtime, is_dir, now_iso, run_id, job_id, side, rel), + ) + else: + self._db.execute( + "INSERT INTO file_state (jobId, side, relPath, size, mtime, isDir, deleted, deletedAt, lastSeenAt, lastSeenRunId) VALUES (?,?,?,?,?,?,0,NULL,?,?)", + (job_id, side, rel, size, mtime, is_dir, now_iso, run_id), + ) + + # Mark missing as deleted (single UPDATE) + rels = list(cur.keys()) + if rels: + placeholders = ",".join(["?"] * len(rels)) + self._db.execute( + f"UPDATE file_state SET deleted=1, deletedAt=COALESCE(deletedAt, ?) WHERE jobId=? AND side=? AND deleted=0 AND relPath NOT IN ({placeholders})", + (now_iso, job_id, side, *rels), + ) + else: + # cur is empty: mark all as deleted for this job/side + self._db.execute( + "UPDATE file_state SET deleted=1, deletedAt=COALESCE(deletedAt, ?) WHERE jobId=? AND side=? AND deleted=0", + (now_iso, job_id, side), + ) + + def _ensure_parent_dir(self, path: str) -> None: + parent = os.path.dirname(path) + if parent and not os.path.exists(parent): + os.makedirs(parent, exist_ok=True) + + def _copy_local_path(self, src_root: str, dst_root: str, rel: str, is_dir: bool, preserve_metadata: bool) -> None: + src_full = os.path.join(src_root, rel) + dst_full = os.path.join(dst_root, rel) + + if is_dir: + os.makedirs(dst_full, exist_ok=True) + return + + self._ensure_parent_dir(dst_full) + if preserve_metadata: + shutil.copy2(src_full, dst_full) + else: + shutil.copy(src_full, dst_full) + + def _delete_local_path(self, root: str, rel: str, is_dir: bool) -> None: + full = os.path.join(root, rel) + if not os.path.exists(full): + return + if is_dir: + # Only remove if empty; never rmtree blindly in sync engine. + try: + os.rmdir(full) + except OSError: + pass + else: + try: + os.remove(full) + except Exception: + pass + + def _record_conflict( + self, + job_id: int, + run_id: Optional[int], + rel: str, + a: Dict[str, Any], + b: Dict[str, Any], + note: str = "", + ) -> None: + try: + # Avoid inserting duplicate open conflicts for the same path/note. + existing = self._db.one( + "SELECT id FROM conflicts WHERE jobId=? AND relPath=? AND status='open' AND COALESCE(note,'')=COALESCE(?, '') ORDER BY id DESC LIMIT 1", + (job_id, rel, note or ""), + ) + if existing: + return + self._db.execute( + """ + INSERT INTO conflicts (jobId, runId, relPath, a_size, a_mtime, a_hash, b_size, b_mtime, b_hash, status, note) + VALUES (?,?,?,?,?,?,?,?,?,'open',?) + """, + ( + job_id, + run_id, + rel, + int(a.get("size", 0) or 0), + int(a.get("mtime", 0) or 0), + a.get("hash"), + int(b.get("size", 0) or 0), + int(b.get("mtime", 0) or 0), + b.get("hash"), + note or None, + ), + ) + except Exception as e: + self._log(f"[Replicator][DB] Failed to record conflict for '{rel}': {e}", level="warning") + + def _run_job_bidirectional(self, job: Dict[str, Any], run_id: Optional[int]) -> tuple[bool, Dict[str, Any]]: + """Bidirectional sync using `file_state` as the persistent baseline. + + Currently implemented for local<->local only. + """ + job_id = int(job.get("id") or 0) + if job_id <= 0: + raise ValueError("Job must have an id to run bidirectional sync") + + src_ep = job.get("sourceEndpoint") + dst_ep = job.get("targetEndpoint") + a_root = self._endpoint_local_root(src_ep) + b_root = self._endpoint_local_root(dst_ep) + + # Deletion behavior is derived from mode; mirror allows deletions. + allow_deletion = str(job.get("mode") or "mirror").lower() == "mirror" + preserve_metadata = bool(job.get("preserveMetadata", True)) + conflict_policy = (job.get("conflictPolicy") or "newest").lower() + + # Load previous baseline before scanning/persisting. + prev_a = self._load_prev_file_state(job_id, "A") + prev_b = self._load_prev_file_state(job_id, "B") + + # Scan current trees + cur_a = self._scan_local_tree(a_root) + cur_b = self._scan_local_tree(b_root) + + def _meta_changed(cur: Dict[str, Any], prev: Dict[str, Any]) -> bool: + return ( + bool(cur.get("isDir")) != bool(prev.get("isDir")) + or int(cur.get("size", 0) or 0) != int(prev.get("size", 0) or 0) + or int(cur.get("mtime", 0) or 0) != int(prev.get("mtime", 0) or 0) + ) + + def _changed_set(cur: Dict[str, Dict[str, Any]], prev: Dict[str, Dict[str, Any]]) -> set[str]: + out = set() + for rel, meta in cur.items(): + p = prev.get(rel) + if p is None or p.get("deleted", False): + out.add(rel) + else: + if _meta_changed(meta, p): + out.add(rel) + return out + + def _deleted_set(cur: Dict[str, Dict[str, Any]], prev: Dict[str, Dict[str, Any]]) -> set[str]: + # deleted since last baseline means it existed (not deleted) and now missing + out = set() + for rel, p in prev.items(): + if p.get("deleted", False): + continue + if rel not in cur: + out.add(rel) + return out + + changed_a = _changed_set(cur_a, prev_a) + changed_b = _changed_set(cur_b, prev_b) + deleted_a = _deleted_set(cur_a, prev_a) + deleted_b = _deleted_set(cur_b, prev_b) + + self._log( + f"[Replicator][BiDi] Snapshot A={len(cur_a)} entries, B={len(cur_b)} entries; changedA={len(changed_a)} changedB={len(changed_b)} deletedA={len(deleted_a)} deletedB={len(deleted_b)}", + level="debug", + ) + + # Build unified rel set + all_paths = set(cur_a.keys()) | set(cur_b.keys()) | set(prev_a.keys()) | set(prev_b.keys()) + + actions_copy_a_to_b: list[tuple[str, bool]] = [] + actions_copy_b_to_a: list[tuple[str, bool]] = [] + actions_del_a: list[tuple[str, bool]] = [] + actions_del_b: list[tuple[str, bool]] = [] + + # Helper for newest + def _winner_newest(a: Dict[str, Any], b: Dict[str, Any]) -> str: + am = int(a.get("mtime", 0) or 0) + bm = int(b.get("mtime", 0) or 0) + if am == bm: + # tie-breaker: larger size wins + return "A" if int(a.get("size", 0) or 0) >= int(b.get("size", 0) or 0) else "B" + return "A" if am > bm else "B" + + for rel in sorted(all_paths): + a_cur = cur_a.get(rel) + b_cur = cur_b.get(rel) + + a_exists = a_cur is not None + b_exists = b_cur is not None + + a_changed = rel in changed_a + b_changed = rel in changed_b + + a_deleted = rel in deleted_a + b_deleted = rel in deleted_b + + # If exists only on one side. + # When deletions are enabled and the missing side deleted it since the last baseline, + # deletion should win unless the existing side also changed (conflict). + if a_exists and not b_exists: + if b_deleted and allow_deletion: + if a_changed: + # conflict: B deleted while A changed + self._record_conflict(job_id, run_id, rel, a_cur, {"deleted": True}, note="B deleted, A changed") + winner = "A" if conflict_policy == "newest" else "A" + if winner == "A": + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + else: + actions_del_a.append((rel, bool(a_cur.get("isDir")))) + else: + # propagate deletion (keep B deleted, delete A) + actions_del_a.append((rel, bool(a_cur.get("isDir")))) + elif b_deleted and not allow_deletion: + # If B was deleted and deletions are not allowed, do NOT copy A->B (do nothing) + pass + else: + # no deletion involved: treat as create on A, copy to B + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + continue + + if b_exists and not a_exists: + if a_deleted and allow_deletion: + if b_changed: + # conflict: A deleted while B changed + self._record_conflict(job_id, run_id, rel, {"deleted": True}, b_cur, note="A deleted, B changed") + winner = "B" if conflict_policy == "newest" else "B" + if winner == "B": + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + else: + actions_del_b.append((rel, bool(b_cur.get("isDir")))) + else: + # propagate deletion (keep A deleted, delete B) + actions_del_b.append((rel, bool(b_cur.get("isDir")))) + elif a_deleted and not allow_deletion: + # If A was deleted and deletions are not allowed, do NOT copy B->A (do nothing) + pass + else: + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + continue + + # Missing on both sides: maybe deletion propagation; nothing to do. + if not a_exists and not b_exists: + continue + + # Exists on both: check if identical + if a_exists and b_exists: + same = ( + bool(a_cur.get("isDir")) == bool(b_cur.get("isDir")) + and int(a_cur.get("size", 0) or 0) == int(b_cur.get("size", 0) or 0) + and int(a_cur.get("mtime", 0) or 0) == int(b_cur.get("mtime", 0) or 0) + ) + + if same: + # Maybe propagate deletions if one side deleted previously (should not happen if same exists) + continue + + # Not same: detect changes since baseline + if a_changed and b_changed: + # true conflict + self._record_conflict(job_id, run_id, rel, a_cur, b_cur, note="Changed on both sides") + if conflict_policy == "newest": + winner = _winner_newest(a_cur, b_cur) + elif conflict_policy in ("keepa", "a"): + winner = "A" + elif conflict_policy in ("keepb", "b"): + winner = "B" + else: + winner = _winner_newest(a_cur, b_cur) + + if winner == "A": + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + else: + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + elif a_changed and not b_changed: + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + elif b_changed and not a_changed: + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + else: + # differs but we can't prove which changed vs baseline (e.g., first run with baseline empty) + # Choose newest as default. + winner = _winner_newest(a_cur, b_cur) + if winner == "A": + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + else: + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + + # Deletions propagation (safe rules) + if allow_deletion: + # If A deleted and B did not change since baseline, delete on B + for rel in sorted(deleted_a): + if rel in changed_b: + # conflict: deleted on A but changed on B + self._record_conflict(job_id, run_id, rel, {"deleted": True}, cur_b.get(rel, {}), note="A deleted, B changed") + continue + pb = prev_b.get(rel) + if pb and not pb.get("deleted", False) and rel in cur_b: + actions_del_b.append((rel, bool(cur_b[rel].get("isDir")))) + + # If B deleted and A did not change since baseline, delete on A + for rel in sorted(deleted_b): + if rel in changed_a: + self._record_conflict(job_id, run_id, rel, cur_a.get(rel, {}), {"deleted": True}, note="B deleted, A changed") + continue + pa = prev_a.get(rel) + if pa and not pa.get("deleted", False) and rel in cur_a: + actions_del_a.append((rel, bool(cur_a[rel].get("isDir")))) + + # Execute actions + try: + # Copy directories first to ensure parents exist + for rel, is_dir in actions_copy_a_to_b: + self._copy_local_path(a_root, b_root, rel, is_dir, preserve_metadata) + for rel, is_dir in actions_copy_b_to_a: + self._copy_local_path(b_root, a_root, rel, is_dir, preserve_metadata) + + # Then copy files (copy method handles both, but ordering helps for deep paths) + # (Already handled in _copy_local_path) + + # Deletions last + for rel, is_dir in actions_del_a: + self._delete_local_path(a_root, rel, is_dir) + for rel, is_dir in actions_del_b: + self._delete_local_path(b_root, rel, is_dir) + + except Exception as e: + self._log(f"[Replicator][BiDi] Execution failed: {e}", level="error") + return False, {} + + # After actions, scan again and persist final file state as baseline + final_a = self._scan_local_tree(a_root) + final_b = self._scan_local_tree(b_root) + self._persist_file_state(job_id, "A", final_a, run_id) + self._persist_file_state(job_id, "B", final_b, run_id) + + stats = { + "copyAtoB": len(actions_copy_a_to_b), + "copyBtoA": len(actions_copy_b_to_a), + "delA": len(actions_del_a), + "delB": len(actions_del_b), + "changedA": len(changed_a), + "changedB": len(changed_b), + "deletedA": len(deleted_a), + "deletedB": len(deleted_b), + } + self._log(f"[Replicator][BiDi] Actions: {stats}", level="debug") + + # Update run stats if possible + if run_id: + try: + self._db.execute( + "UPDATE runs SET stats=? WHERE id=?", + (json.dumps(stats), run_id), + ) + except Exception: + pass + + return True, stats + + # ------------------------------------------------------------------ + # CLI integration + # ------------------------------------------------------------------ + + def cli(self, cli: QApplication = None) -> None: + """ + Called by corePY CommandLine when running in CLI mode. + """ + if cli is None: + return + cli.add("run", "Run all replication jobs.", self.run) + cli.service.add("run", "Run all replication jobs", self.run_scheduled, interval=1) + + # ------------------------------------------------------------------ + # UI + # ------------------------------------------------------------------ + + def show(self): + self.init() + super().show() + + def init(self): + self.setWindowTitle(getattr(self._app, "name", "Replicator")) + self.setObjectName("Replicator") + # Ensure minimum window width for table visibility + self.setMinimumWidth(800) + + central = QWidget(self) + self.setCentralWidget(central) + central.setStyleSheet("background-color: #212121;") + root = QVBoxLayout(central) + root.setContentsMargins(16, 16, 16, 16) + root.setSpacing(12) + + # Logo (top, centered) + logo = QLabel() + logo.setAlignment(Qt.AlignCenter) + + # Use app icon/logo if you have one; otherwise harmless + # Adjust path to wherever you store icons in Replicator + candidate = self._helper.get_path("icons/icon.png") or self._helper.get_path("core/icons/info.svg") + name = getattr(self._app, "name", None) or self._app.applicationName() + if candidate and self._helper.file_exists(candidate) and candidate.lower().endswith(".png"): + pm = QPixmap(candidate) + if not pm.isNull(): + logo.setPixmap(pm.scaled(256, 256, Qt.KeepAspectRatio, Qt.SmoothTransformation)) + else: + logo.setText(name) + logo.setStyleSheet("font-size: 32px; font-weight: 200; opacity: 0.8; padding: 0px; margin: 0px;") + + root.addWidget(logo) + + # Application name (under logo) + app_name = QLabel() + app_name.setText(str(name) if name else "") + app_name.setAlignment(Qt.AlignCenter) + app_name.setStyleSheet("font-size: 32px; font-weight: 200; opacity: 0.8; padding: 0px; margin: 0px;") + root.addWidget(app_name) + + # --- Actions row (top, after logo) --- + actions_row = QHBoxLayout() + # No stretch at start; left-aligned by default + self._add_btn = Form.button(label="", icon="plus-circle", action=self._add_job) + self._add_btn.setToolTip("Add job") + self._edit_btn = Form.button(label="", icon="pencil-square", action=self._edit_job) + self._edit_btn.setToolTip("Edit job") + self._edit_btn.setVisible(False) + self._dup_btn = Form.button(label="", icon="files", action=self._duplicate_job) + self._dup_btn.setToolTip("Duplicate job") + self._dup_btn.setVisible(False) + self._del_btn = Form.button(label="", icon="trash", action=self._delete_job) + self._del_btn.setToolTip("Delete job") + self._del_btn.setVisible(False) + self._schedule_btn = Form.button(label="", icon="calendar-event", action=self._edit_schedule) + self._schedule_btn.setToolTip("Schedule") + self._schedule_btn.setVisible(False) + actions_row.addWidget(self._add_btn) + actions_row.addWidget(self._edit_btn) + actions_row.addWidget(self._dup_btn) + actions_row.addWidget(self._del_btn) + actions_row.addWidget(self._schedule_btn) + actions_row.addStretch(1) + root.addLayout(actions_row) + + # Table + self._table = QTableWidget(0, 6, self) + self._table.setHorizontalHeaderLabels([ + "Name", "Enabled", "Source", "Target", "Last run", "Result" + ]) + self._table.setSelectionBehavior(QTableWidget.SelectRows) + self._table.setEditTriggers(QTableWidget.NoEditTriggers) + + # Hide row numbers + self._table.verticalHeader().setVisible(False) + + # Connect selection change to update visibility of action buttons + self._table.selectionModel().selectionChanged.connect(self._on_selection_changed) + + # Ensure columns never shrink below their content (use scrollbar for overflow) + header = self._table.horizontalHeader() + # Performance: ResizeToContents on every column can get painfully slow. + header.setSectionResizeMode(0, QHeaderView.Stretch) # Name + for i in range(1, self._table.columnCount()): + header.setSectionResizeMode(i, QHeaderView.ResizeToContents) + + # Keep horizontal scrollbar available for overflow + header.setStretchLastSection(False) + + root.addWidget(self._table) + + # --- Bottom row: Service Manager, Configurator and Run now (right aligned) --- + bottom_row = QHBoxLayout() + bottom_row.addStretch(1) + + service_btn = Form.button(label="", icon="hdd-network", action=self._open_service_manager) + service_btn.setToolTip("Service Manager") + + config_btn = Form.button(label="", icon="gear-fill", action=self._configuration.show) + config_btn.setToolTip("Configurator") + + run_btn = Form.button(label="", icon="play-fill", action=lambda: self._run_with_ui_feedback()) + run_btn.setToolTip("Run now") + + bottom_row.addWidget(service_btn) + bottom_row.addWidget(config_btn) + bottom_row.addWidget(run_btn) + root.addLayout(bottom_row) + + self._reload_jobs() + self._on_selection_changed() + + def _on_selection_changed(self, *_args): + has = self._selected_index() >= 0 + if hasattr(self, "_edit_btn"): + self._edit_btn.setVisible(has) + if hasattr(self, "_dup_btn"): + self._dup_btn.setVisible(has) + if hasattr(self, "_del_btn"): + self._del_btn.setVisible(has) + if hasattr(self, "_schedule_btn"): + self._schedule_btn.setVisible(has) + + def _selected_index(self) -> int: + if not self._table: + return -1 + rows = self._table.selectionModel().selectedRows() + if not rows: + return -1 + return rows[0].row() + + def _reload_jobs(self): + self._jobs = self._store.fetch_all() + self._refresh_table() + + def _save_jobs(self): + return + + def _refresh_table(self): + if not self._table: + return + self._table.setRowCount(0) + + for job in self._jobs: + r = self._table.rowCount() + self._table.insertRow(r) + + def _it(v: Any) -> QTableWidgetItem: + item = QTableWidgetItem(str(v) if v is not None else "") + item.setFlags(item.flags() ^ Qt.ItemIsEditable) + return item + + self._table.setItem(r, 0, _it(job.name)) + self._table.setItem(r, 1, _it("On" if job.enabled else "Off")) + + src_str = f"{job.sourceEndpoint.type}:{job.sourceEndpoint.location}" + tgt_str = f"{job.targetEndpoint.type}:{job.targetEndpoint.location}" + self._table.setItem(r, 2, _it(src_str)) + self._table.setItem(r, 3, _it(tgt_str)) + + last_run = job.lastRun + self._table.setItem(r, 4, _it(last_run if last_run else "Never")) + + self._table.setItem(r, 5, _it(job.lastResult or "")) + + def _default_interval_seconds(self) -> int: + """Return the configured default interval in seconds (service.defaultInterval), fallback to 3600.""" + try: + v = self._configuration.get("service.defaultInterval", 3600) + iv = int(v) + return iv if iv > 0 else 3600 + except Exception: + return 3600 + + def _default_schedule_dict(self) -> Dict[str, Any]: + interval = self._default_interval_seconds() + windows: Dict[str, Any] = {} + for wd in range(7): + windows[str(wd)] = [{"start": "00:00", "end": "23:59", "intervalSeconds": interval}] + return { + "enabled": False, + "intervalSeconds": interval, + "windows": windows, + } + + def _schedule_interval_seconds_for_now(self, sched: Dict[str, Any]) -> int: + # Kept for backward compatibility with existing log formatting. + # Prefer the Job/Schedule domain helpers where possible. + try: + j = self._job_from_legacy_dict({"schedule": sched, "name": "_tmp", "enabled": True, "sourceEndpoint": {"type": "local", "location": "/"}, "targetEndpoint": {"type": "local", "location": "/"}}) + return int(j.schedule.interval_seconds_for_now(datetime.now(timezone.utc)) or 0) or self._default_interval_seconds() + except Exception: + return self._default_interval_seconds() + + def _job_from_legacy_dict(self, d: Dict[str, Any], *, existing_id: Optional[int] = None) -> Job: + src = d.get("sourceEndpoint") or {"type": "local", "location": d.get("source", ""), "auth": {}} + tgt = d.get("targetEndpoint") or {"type": "local", "location": d.get("target", ""), "auth": {}} + + # Schedule defaults: + # - enabled + # - every day, all day + # - interval 3600 seconds (1h) + sched = d.get("schedule") + if not isinstance(sched, dict): + sched = self._default_schedule_dict() + + default_interval = self._default_interval_seconds() + + # Normalize intervalSeconds (no everyMinutes support) + try: + iv = int(sched.get("intervalSeconds") or 0) + except Exception: + iv = 0 + if iv <= 0: + iv = default_interval + sched["intervalSeconds"] = iv + + # Ensure windows exist; if missing, make it "every day, all day" with per-day interval + windows = sched.get("windows") + if not isinstance(windows, dict) or not windows: + windows = {} + for wd in range(7): + windows[str(wd)] = [{"start": "00:00", "end": "23:59", "intervalSeconds": iv}] + sched["windows"] = windows + else: + # Ensure each enabled day window includes intervalSeconds (per-day) for the upcoming scheduler logic + for k, v in list(windows.items()): + if isinstance(v, list) and v and isinstance(v[0], dict): + if "intervalSeconds" not in v[0]: + v[0]["intervalSeconds"] = iv + + j = Job( + id=existing_id, + name=str(d.get("name") or ""), + enabled=bool(d.get("enabled", True)), + mode=str(d.get("mode") or "mirror"), + direction=str(d.get("direction") or "unidirectional"), + # Deletion behavior is derived from mode; mirror allows deletions. + allowDeletion=(str(d.get("mode") or "mirror").lower() == "mirror"), + preserveMetadata=bool(d.get("preserveMetadata", True)), + conflictPolicy=str(d.get("conflictPolicy") or "newest"), + pairId=d.get("pairId"), + lastRun=d.get("lastRun"), + lastResult=d.get("lastResult"), + lastError=d.get("lastError"), + ) + + j.sourceEndpoint = Endpoint( + type=str(src.get("type") or "local"), + location=str(src.get("location") or ""), + auth=dict(src.get("auth") or {}), + ) + j.targetEndpoint = Endpoint( + type=str(tgt.get("type") or "local"), + location=str(tgt.get("location") or ""), + auth=dict(tgt.get("auth") or {}), + ) + + windows = sched.get("windows") if isinstance(sched.get("windows"), dict) else {} + + j.schedule = Schedule( + enabled=bool(sched.get("enabled", False)), + intervalSeconds=int(iv), + windows=windows, + ) + + return j + + def _add_job(self): + # Pass configured service.defaultInterval into the dialog so Schedule defaults match user config + dlg = JobDialog(self, default_interval_seconds=self._default_interval_seconds()) + if dlg.exec_() == QDialog.Accepted: + new_job_dict = dlg.value() + if "schedule" not in new_job_dict or not isinstance(new_job_dict.get("schedule"), dict): + new_job_dict["schedule"] = self._default_schedule_dict() + job_obj = self._job_from_legacy_dict(new_job_dict) + job_id = self._store.upsert(job_obj) + job_obj.id = job_id + self._reload_jobs() + + def _edit_job(self): + idx = self._selected_index() + if idx < 0: + MsgBox.show(self, "Jobs", "Select a job to edit.", icon="info") + return + + current = self._jobs[idx] + # Pass configured service.defaultInterval into the dialog so Schedule defaults remain consistent + dlg = JobDialog(self, current.to_legacy_dict(), default_interval_seconds=self._default_interval_seconds()) + if dlg.exec_() == QDialog.Accepted: + updated_dict = dlg.value() + job_obj = self._job_from_legacy_dict(updated_dict, existing_id=current.id) + self._store.upsert(job_obj) + self._reload_jobs() + + def _duplicate_job(self): + idx = self._selected_index() + if idx < 0: + MsgBox.show(self, "Jobs", "Select a job to duplicate.", icon="info") + return + + orig = self._jobs[idx] + d = orig.to_legacy_dict() + d.pop("id", None) + d["name"] = f"{orig.name} (copy)" if orig.name else "Copy" + + job_obj = self._job_from_legacy_dict(d) + self._store.upsert(job_obj) + self._reload_jobs() + + if self._table: + # Select the newest row (best-effort) + self._table.selectRow(self._table.rowCount() - 1) + + def _delete_job(self): + idx = self._selected_index() + if idx < 0: + MsgBox.show(self, "Jobs", "Select a job to delete.", icon="info") + return + + job = self._jobs[idx] + choice = MsgBox.show( + self, + title="Delete", + message=f"Delete job '{job.name}'?", + icon="question", + buttons=("Cancel", "Delete"), + default="Cancel", + ) + if choice == "Delete": + if job.id: + jid = int(job.id) + try: + with self._db.transaction(): + # Explicitly delete dependent rows to avoid orphans. + self._db.execute("DELETE FROM endpoints WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM schedule WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM runs WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM conflicts WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM file_state WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM jobs WHERE id = ?", (jid,)) + except Exception as e: + self._log(f"[Replicator][DB] Failed to delete job {jid} cascade: {e}", level="warning") + # Fallback to store deletion if cascade failed. + try: + self._store.delete(jid) + except Exception: + pass + self._reload_jobs() + + def _edit_schedule(self): + idx = self._selected_index() + if idx < 0: + MsgBox.show(self, "Jobs", "Select a job to edit schedule.", icon="info") + return + + current = self._jobs[idx] + # Pass configured service.defaultInterval into the schedule editor so defaults match user config + dlg = ScheduleDialog(self, job=current.to_legacy_dict(), default_interval_seconds=self._default_interval_seconds()) + if dlg.exec_() == QDialog.Accepted: + d = current.to_legacy_dict() + d["schedule"] = dlg.value() + job_obj = self._job_from_legacy_dict(d, existing_id=current.id) + self._store.upsert(job_obj) + self._reload_jobs() + + def _run_with_ui_feedback(self): + ok = self.run() + MsgBox.show( + self, + title="Replicator", + message="Replication completed successfully." if ok else "Replication finished with errors.", + icon="info" if ok else "warning", + ) + + # ------------------------------------------------------------------ + # Execution + # ------------------------------------------------------------------ + + def run_scheduled(self) -> bool: + """ + Scheduled/service execution entrypoint. + Respects per-job schedule (enabled/windows/interval). + Returns True if all eligible jobs succeeded. + """ + self._reload_jobs() + + verbose_db = False + try: + verbose_db = bool(self._configuration.get("log.verbose", False)) + except Exception: + verbose_db = False + self._db_debug_snapshot(verbose=verbose_db) + + if not self._jobs: + self._log("[Replicator] No jobs configured.", level="warning") + return False + + now_utc = datetime.now(timezone.utc) + + any_ran = False + all_ok = True + + for job in self._jobs: + if not bool(job.enabled): + continue + + if not self._should_run_scheduled(job, now_utc=now_utc): + continue + + any_ran = True + ok = self._run_job(job) + all_ok = all_ok and ok + + # Update schedule bookkeeping for this job + try: + interval_s = int(job.schedule.interval_seconds_for_now(datetime.now(timezone.utc)) or 0) or self._default_interval_seconds() + next_run = (datetime.now(timezone.utc) + timedelta(seconds=int(interval_s))).isoformat() + self._db.update( + "schedule", + { + "lastScheduledRunAt": datetime.now(timezone.utc).isoformat(), + "nextRunAt": next_run, + }, + "jobId = :jobId", + {"jobId": int(job.id)}, + ) + except Exception: + pass + + if not any_ran: + self._log("[Replicator] No jobs due per schedule.", level="debug") + + return all_ok + + def run(self) -> bool: + """ + Run all configured jobs (from DB). + Returns True if all jobs succeeded. + """ + self._reload_jobs() + # After reloading jobs, log a DB snapshot for debugging. + # Only log verbose DB details when log.verbose is enabled. + verbose_db = False + try: + verbose_db = bool(self._configuration.get("log.verbose", False)) + except Exception: + verbose_db = False + + self._db_debug_snapshot(verbose=verbose_db) + jobs: List[Job] = self._jobs + if not jobs: + self._log("[Replicator] No jobs configured.", level="warning") + return False + + all_ok = True + for job in jobs: + if not bool(job.enabled): + self._log(f"[Replicator] Skipping disabled job '{job.name or 'Unnamed'}'.", level="info") + continue + ok = self._run_job(job) + all_ok = all_ok and ok + + # Run DB maintenance at most once per day. + try: + last = self._migration.get_meta("maintenance.lastRunAt") + should = True + if last: + try: + last_dt = datetime.fromisoformat(str(last)) + if last_dt.tzinfo is None: + last_dt = last_dt.replace(tzinfo=timezone.utc) + should = (datetime.now(timezone.utc) - last_dt).total_seconds() >= 86400 + except Exception: + should = True + if should: + self._db_maintenance() + except Exception: + pass + + return all_ok + + def _run_job(self, job: Job) -> bool: + name = job.name or "Unnamed" + if not bool(job.enabled): + self._log(f"[Replicator] Job '{name}' is disabled; skipping.", level="info") + return True + job_id = job.id + src = job.sourceEndpoint.location + src_type = job.sourceEndpoint.type + dst = job.targetEndpoint.location + dst_type = job.targetEndpoint.type + mode = job.mode + # Deletion behavior is derived from mode; mirror allows deletions. + allow_deletion = str(mode or "mirror").lower() == "mirror" + preserve_metadata = bool(job.preserveMetadata) + direction = job.direction + + if not src or not dst: + self._log(f"[Replicator] Job '{name}' invalid: missing source or target path (src='{src}', dst='{dst}').", level="error") + return False + + sched_str = "" + try: + if job_id: + sched = self._db.one( + "SELECT enabled FROM schedule WHERE jobId=?", + (int(job_id),), + ) + if sched and bool(sched.get("enabled", 0)): + interval_s = int(job.schedule.interval_seconds_for_now(datetime.now(timezone.utc)) or 0) or self._default_interval_seconds() + sched_str = f", schedule=Interval {interval_s}s" + except Exception: + pass + logline = f"[Replicator] Running job '{name}': {src} -> {dst} (mode={mode}, direction={direction}, delete={allow_deletion}, meta={preserve_metadata}{sched_str}" + logline += f", srcType={src_type}, dstType={dst_type})" + self._log(logline) + + # Insert a run record at start + started_at = datetime.now(timezone.utc).isoformat() + run_id = None + bidi_stats = None + try: + run_id = None + if job_id: + try: + run_id = int(self._db.insert("runs", {"jobId": int(job_id), "startedAt": started_at, "result": "running"})) + except Exception as e: + self._log(f"[Replicator] Failed to insert run record: {e}", level="warning") + except Exception as e: + self._log(f"[Replicator] Failed to insert run record: {e}", level="warning") + + record_noop_runs = bool(self._configuration.get("db.recordNoopRuns", False)) + + ok = False + try: + # Always build a legacy dict so we can reuse the endpoint records + auth. + job_dict = job.to_legacy_dict() + src_ep = job_dict.get("sourceEndpoint") or {"type": "local", "location": src, "auth": {}} + dst_ep = job_dict.get("targetEndpoint") or {"type": "local", "location": dst, "auth": {}} + + # Mount remote endpoints (SMB only) via Share so BOTH uni + bidi operate on + # local filesystem paths, and we get connectivity debug logs. + mounted: list[MountedEndpoint] = [] + + try: + src_m = mount_endpoint_if_remote(src_ep, job_id, "source", share=self._share, log_append=self._log) + mounted.append(src_m) + dst_m = mount_endpoint_if_remote(dst_ep, job_id, "target", share=self._share, log_append=self._log) + mounted.append(dst_m) + + # Use the mounted/local view for execution + local_src = src_m.local_path + local_dst = dst_m.local_path + + if str(direction).lower() == "bidirectional": + # Local view for the bidirectional sync engine + job_dict["sourceEndpoint"] = {"type": "local", "location": local_src, "auth": {}} + job_dict["targetEndpoint"] = {"type": "local", "location": local_dst, "auth": {}} + ok, bidi_stats = self._run_job_bidirectional(job_dict, run_id) + else: + # Unidirectional copy (mirror) also uses mounted/local paths + ok = self._fs.copy( + local_src, + local_dst, + preserve_metadata=preserve_metadata, + allow_deletion=allow_deletion, + ) + finally: + for m in reversed(mounted): + try: + m.cleanup() + except Exception: + pass + except NotImplementedError as e: + self._log(f"[Replicator] Job '{name}' not supported: {e}", level="error") + ok = False + except RemoteMountError as e: + self._log(f"[Replicator] Job '{name}' failed to mount remote endpoint: {e}", level="error") + ok = False + except Exception as e: + self._log(f"[Replicator] Job '{name}' failed: {e}", level="error") + ok = False + + # If this was a bidirectional run with no actions/changes, optionally drop the run row. + if run_id and bidi_stats is not None and not record_noop_runs: + try: + noop = ( + int(bidi_stats.get("copyAtoB", 0) or 0) == 0 + and int(bidi_stats.get("copyBtoA", 0) or 0) == 0 + and int(bidi_stats.get("delA", 0) or 0) == 0 + and int(bidi_stats.get("delB", 0) or 0) == 0 + and int(bidi_stats.get("changedA", 0) or 0) == 0 + and int(bidi_stats.get("changedB", 0) or 0) == 0 + and int(bidi_stats.get("deletedA", 0) or 0) == 0 + and int(bidi_stats.get("deletedB", 0) or 0) == 0 + ) + if noop: + self._db.execute("DELETE FROM runs WHERE id = ?", (run_id,)) + run_id = None + except Exception: + pass + + # Persist lastRun and lastResult, refresh UI, save to DB + now_str = datetime.now(timezone.utc).isoformat() + job.lastRun = now_str + job.lastResult = "ok" if ok else "fail" + job.lastError = None if ok else (job.lastError or "Failed") + self._store.upsert(job) + if run_id: + try: + self._db.update( + "runs", + {"endedAt": now_str, "result": ("ok" if ok else "fail"), "message": (None if ok else (job.lastError or "Failed"))}, + "id = :id", + {"id": int(run_id)}, + ) + except Exception as e: + self._log(f"[Replicator] Failed to update run record: {e}", level="warning") + if self._table: + self._reload_jobs() + + self._log(f"[Replicator] Job '{job.name}' result: {'OK' if ok else 'FAIL'} (lastResult={job.lastResult})", level="info" if ok else "warning") + return ok + + def _log(self, msg: str, level: str = "info", channel: str = "replicator") -> None: + if self._logger is not None and hasattr(self._logger, "append"): + self._logger.append(msg, level=level, channel=channel) # type: ignore[call-arg] + else: + print(msg) + + def _db_debug_snapshot(self, verbose: bool = False) -> None: + """ + Log a compact snapshot of the current DB layout + row counts. + If verbose=True, also logs the most recent rows for key tables. + """ + try: + # List tables + tables = [r["name"] for r in self._db.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name")] + + self._log(f"[Replicator][DB] Tables: {', '.join(tables) if tables else '(none)'}", level="debug") + + # Layout + counts + for t in tables: + try: + cols = self._db.query(f"PRAGMA table_info({t})") + col_names = [c.get("name") for c in cols] + count = int(self._db.scalar(f"SELECT COUNT(*) FROM {t}") or 0) + self._log(f"[Replicator][DB] {t}: columns={len(col_names)} rows={count}", level="debug") + if verbose: + self._log(f"[Replicator][DB] {t}: {', '.join(col_names)}", level="debug") + except Exception as e: + self._log(f"[Replicator][DB] Failed introspecting {t}: {e}", level="warning") + + if not verbose: + return + + for t, order_col in (("jobs", "id"), ("runs", "id"), ("schedule", "id"), ("conflicts", "id")): + if t in tables: + try: + rows = self._db.query(f"SELECT * FROM {t} ORDER BY {order_col} DESC LIMIT 3") + self._log(f"[Replicator][DB] {t}: latest {len(rows)} row(s)", level="debug") + for r in rows: + dr = dict(r) + for k in ("password", "pass"): + if k in dr and dr[k]: + dr[k] = "***" + self._log(f"[Replicator][DB] {t}: {dr}", level="debug") + except Exception as e: + self._log(f"[Replicator][DB] Failed reading latest rows from {t}: {e}", level="warning") + + except Exception as e: + self._log(f"[Replicator][DB] Snapshot failed: {e}", level="warning") + + def _db_maintenance(self) -> None: + """Prune old history and run lightweight SQLite maintenance. + + Safe defaults: + - Keep last N runs per job (db.retention.runs.keepLast) + - Also prune runs older than X days (db.retention.runs.keepDays) + - Keep open conflicts; prune resolved conflicts older than X days + - Optionally VACUUM (off by default) + + This is designed to be called periodically (e.g. daily) by the service loop. + """ + try: + keep_last = int(self._configuration.get("db.retention.runs.keepLast", 500)) + keep_days = int(self._configuration.get("db.retention.runs.keepDays", 30)) + prune_conflict_days = int(self._configuration.get("db.retention.conflicts.keepDays", 90)) + prune_deleted_state_days = int(self._configuration.get("db.retention.fileState.deletedKeepDays", 30)) + do_vacuum = bool(self._configuration.get("db.maintenance.vacuum", False)) + except Exception: + keep_last, keep_days = 500, 30 + prune_conflict_days, prune_deleted_state_days = 90, 30 + do_vacuum = False + + now = datetime.now(timezone.utc) + now_iso = now.isoformat() + + # Runs: keep last N per job + prune anything older than keep_days + try: + job_ids = [int(r.get("id")) for r in (self._db.query("SELECT id FROM jobs") or [])] + with self._db.transaction(): + for jid in job_ids: + if keep_last > 0: + self._db.execute( + """ + DELETE FROM runs + WHERE jobId = ? + AND id NOT IN ( + SELECT id FROM runs WHERE jobId = ? ORDER BY id DESC LIMIT ? + ) + """, + (jid, jid, keep_last), + ) + + if keep_days > 0: + self._db.execute( + "DELETE FROM runs WHERE julianday(created) < julianday('now', ?) ", + (f'-{keep_days} days',), + ) + except Exception as e: + self._log(f"[Replicator][DB] Maintenance: runs prune failed: {e}", level="warning") + + # Conflicts: keep all open; prune non-open older than prune_conflict_days + try: + if prune_conflict_days > 0: + with self._db.transaction(): + self._db.execute( + "DELETE FROM conflicts WHERE status <> 'open' AND julianday(created) < julianday('now', ?) ", + (f'-{prune_conflict_days} days',), + ) + except Exception as e: + self._log(f"[Replicator][DB] Maintenance: conflicts prune failed: {e}", level="warning") + + # file_state: prune deleted entries that have been deleted for a long time + try: + if prune_deleted_state_days > 0: + with self._db.transaction(): + self._db.execute( + "DELETE FROM file_state WHERE deleted = 1 AND deletedAt IS NOT NULL AND julianday(deletedAt) < julianday('now', ?) ", + (f'-{prune_deleted_state_days} days',), + ) + except Exception as e: + self._log(f"[Replicator][DB] Maintenance: file_state prune failed: {e}", level="warning") + + # SQLite maintenance: optimize; optionally vacuum + try: + self._db.execute("PRAGMA optimize;") + if do_vacuum: + self._db.execute("VACUUM;") + self._migration.set_meta("maintenance.lastRunAt", now_iso) + self._log("[Replicator][DB] Maintenance completed.", level="debug") + except Exception as e: + self._log(f"[Replicator][DB] Maintenance failed: {e}", level="warning") + + def _open_service_manager(self) -> None: + """Open the corePY Service Manager dialog (if available).""" + try: + svc = getattr(self._app, "service", None) + if svc is None: + raise RuntimeError("Service is not available on the application instance.") + + # Preferred helper added in corePY Service + if hasattr(svc, "open_manager_dialog"): + svc.open_manager_dialog(parent=self) + return + + # Fallback: if the dialog class exists, try to instantiate it + dlg_cls = getattr(svc, "ServiceManagerDialog", None) + if dlg_cls is not None: + dlg = dlg_cls(parent=self, service=svc) + dlg.exec_() + return + + raise RuntimeError("Service manager UI is not available in this build.") + + except Exception as e: + MsgBox.show(self, "Service", f"Unable to open Service Manager: {e}", icon="warning") diff --git a/dist/macos/Replicator.app/Contents/Resources/replicator/ui.py b/dist/macos/Replicator.app/Contents/Resources/replicator/ui.py new file mode 100644 index 00000000..e0c96b10 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/Resources/replicator/ui.py @@ -0,0 +1,816 @@ +#!/usr/bin/env python3 +# src/replicator/ui.py + +from __future__ import annotations + +from typing import Optional, Any, Dict, List, Tuple + +from PyQt5.QtCore import Qt, QTime, pyqtSignal +from PyQt5.QtWidgets import ( + QWidget, + QVBoxLayout, + QHBoxLayout, + QLabel, + QPushButton, + QDialog, + QFormLayout, + QLineEdit, + QCheckBox, + QComboBox, + QSpinBox, + QTextEdit, + QFrame, + QSizePolicy, + QLayout, + QTimeEdit, + QFileDialog, +) + +try: + from core.ui import MsgBox +except ImportError: + from ui import MsgBox + +# ------------------------------------------------------------------ +# Helpers +# ------------------------------------------------------------------ +class BrowseLineEdit(QLineEdit): + """QLineEdit that emits a signal when clicked (used to open browse dialogs).""" + clicked = pyqtSignal() + + def mousePressEvent(self, event): + try: + self.clicked.emit() + except Exception: + pass + super().mousePressEvent(event) + +# ------------------------------------------------------------------ +# Job Dialog +# ------------------------------------------------------------------ +class JobDialog(QDialog): + def __init__(self, parent=None, job: Optional[Dict[str, Any]] = None, *, default_interval_seconds: Optional[int] = None): + super().__init__(parent) + self.setWindowTitle("Replication Job") + self.setModal(True) + self.setFixedHeight(400) + self.setMinimumHeight(400) + self.setMinimumWidth(1200) + + job = job or {} + self._original_job = job + + # Default interval for new schedules (seconds). Provided by the app (e.g. Configuration service.defaultInterval). + try: + di = int(default_interval_seconds) if default_interval_seconds is not None else 3600 + except Exception: + di = 3600 + if di <= 0: + di = 3600 + self._default_interval_seconds = di + + layout = QVBoxLayout(self) + layout.setAlignment(Qt.AlignTop) + layout.setSizeConstraint(QLayout.SetMinimumSize) + + # ------------------------------ + # Name row + # ------------------------------ + name_row = QHBoxLayout() + name_row.addWidget(QLabel("Name")) + self.name = QLineEdit(job.get("name", "")) + name_row.addWidget(self.name, 1) + layout.addLayout(name_row) + + # Helper to get endpoint dict from job or fallback + def _get_endpoint(key_endpoint: str, key_str: str, default_type: str = "local") -> Dict[str, Any]: + ep = job.get(key_endpoint) + if isinstance(ep, dict): + return dict(ep) + return {"type": default_type, "location": job.get(key_str, ""), "auth": {}} + + self._source_ep = _get_endpoint("sourceEndpoint", "source", "local") + self._target_ep = _get_endpoint("targetEndpoint", "target", "local") + + # ------------------------------ + # Two-column Source / Destination + # ------------------------------ + cols = QHBoxLayout() + cols.setSpacing(20) + cols.setAlignment(Qt.AlignTop) + + src_frame = QFrame() + src_frame.setObjectName("EndpointFrame") + src_frame.setFrameShape(QFrame.NoFrame) + src_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + src_frame.setMinimumHeight(0) + src_frame.setStyleSheet( + "#EndpointFrame { border: 1px solid rgba(255,255,255,0.12); border-radius: 8px; padding: 10px; }" + ) + src_col = QVBoxLayout(src_frame) + src_col.setContentsMargins(10, 10, 10, 10) + src_col.setSpacing(8) + src_col.setAlignment(Qt.AlignTop) + + dst_frame = QFrame() + dst_frame.setObjectName("EndpointFrame") + dst_frame.setFrameShape(QFrame.NoFrame) + dst_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + dst_frame.setMinimumHeight(0) + dst_frame.setStyleSheet( + "#EndpointFrame { border: 1px solid rgba(255,255,255,0.12); border-radius: 8px; padding: 10px; }" + ) + dst_col = QVBoxLayout(dst_frame) + dst_col.setContentsMargins(10, 10, 10, 10) + dst_col.setSpacing(8) + dst_col.setAlignment(Qt.AlignTop) + + src_title = QLabel("Source") + src_title.setStyleSheet("font-weight: 600;") + dst_title = QLabel("Destination") + dst_title.setStyleSheet("font-weight: 600;") + + src_col.addWidget(src_title) + dst_col.addWidget(dst_title) + + ( + self._source_type_combo, + self._source_location_edit, + self._source_port_spin, + self._source_endpoint_row, + self._source_auth_widget, + self._source_auth_widgets, + ) = self._build_endpoint(existing=self._source_ep) + + ( + self._target_type_combo, + self._target_location_edit, + self._target_port_spin, + self._target_endpoint_row, + self._target_auth_widget, + self._target_auth_widgets, + ) = self._build_endpoint(existing=self._target_ep) + + src_col.addWidget(self._source_endpoint_row) + src_col.addWidget(self._source_auth_widget) + + dst_col.addWidget(self._target_endpoint_row) + dst_col.addWidget(self._target_auth_widget) + + cols.addWidget(src_frame, 1) + cols.addWidget(dst_frame, 1) + layout.addLayout(cols) + + # ------------------------------ + # Mode + Direction on same line + # ------------------------------ + self.mode = QComboBox() + # Mode is now a first-class control. + # mirror => allowDeletion=True + # incremental => allowDeletion=False + self.mode.addItems(["mirror", "incremental"]) + + # Backward compatibility: + # - Older jobs may only have allowDeletion without a mode. + # - Some jobs may still have mode="mirror". + mode_val = str(job.get("mode") or "").strip().lower() + if mode_val not in ("mirror", "incremental"): + # Infer from allowDeletion when mode is missing/legacy. + mode_val = "mirror" if bool(job.get("allowDeletion", False)) else "incremental" + + idx = self.mode.findText(mode_val) + if idx >= 0: + self.mode.setCurrentIndex(idx) + + self.direction = QComboBox() + self.direction.addItems(["unidirectional", "bidirectional"]) + direction_val = job.get("direction", "unidirectional") + idx = self.direction.findText(direction_val) + if idx >= 0: + self.direction.setCurrentIndex(idx) + + mode_dir_row = QHBoxLayout() + + mode_wrap = QWidget() + mode_wrap.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + mode_lay = QHBoxLayout(mode_wrap) + mode_lay.setContentsMargins(0, 0, 0, 0) + mode_lay.setSpacing(8) + mode_lay.addWidget(QLabel("Mode")) + mode_lay.addWidget(self.mode, 1) + + dir_wrap = QWidget() + dir_wrap.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + dir_lay = QHBoxLayout(dir_wrap) + dir_lay.setContentsMargins(0, 0, 0, 0) + dir_lay.setSpacing(8) + dir_lay.addWidget(QLabel("Direction")) + dir_lay.addWidget(self.direction, 1) + + mode_dir_row.addWidget(mode_wrap, 1) + mode_dir_row.addWidget(dir_wrap, 1) + layout.addLayout(mode_dir_row) + + # ------------------------------ + # Other options + # ------------------------------ + opts_row = QHBoxLayout() + + # Deletion behavior is controlled by mode now. + # Keep the UI simple: show metadata + enabled toggles here. + self.preserve_metadata = QCheckBox("Preserve metadata") + self.preserve_metadata.setChecked(bool(job.get("preserveMetadata", True))) + self.enabled = QCheckBox("Enabled") + self.enabled.setChecked(bool(job.get("enabled", True))) + + opts_row.addWidget(self.preserve_metadata) + opts_row.addSpacing(16) + opts_row.addWidget(self.enabled) + opts_row.addStretch(1) + + # Schedule button (UI stays here) + self._schedule_btn = QPushButton("Schedule…") + self._schedule_btn.clicked.connect(self._open_schedule) + opts_row.addWidget(self._schedule_btn) + + layout.addLayout(opts_row) + + # ------------------------------ + # Buttons + # ------------------------------ + btn_row = QHBoxLayout() + btn_row.addStretch(1) + cancel_btn = QPushButton("Cancel") + ok_btn = QPushButton("Save") + cancel_btn.clicked.connect(self.reject) + ok_btn.clicked.connect(self._on_ok) + btn_row.addWidget(cancel_btn) + btn_row.addWidget(ok_btn) + layout.addLayout(btn_row) + + # Wire type changes + self._source_type_combo.currentIndexChanged.connect(lambda _i: self._on_type_changed( + self._source_type_combo, + self._source_location_edit, + self._source_port_spin, + self._source_auth_widget, + self._source_auth_widgets, + )) + self._target_type_combo.currentIndexChanged.connect(lambda _i: self._on_type_changed( + self._target_type_combo, + self._target_location_edit, + self._target_port_spin, + self._target_auth_widget, + self._target_auth_widgets, + )) + + # Trigger initial state + self._on_type_changed( + self._source_type_combo, + self._source_location_edit, + self._source_port_spin, + self._source_auth_widget, + self._source_auth_widgets, + initial=True, + ) + self._on_type_changed( + self._target_type_combo, + self._target_location_edit, + self._target_port_spin, + self._target_auth_widget, + self._target_auth_widgets, + initial=True, + ) + + def _open_schedule(self) -> None: + job = self._original_job if isinstance(self._original_job, dict) else {} + dlg = ScheduleDialog(self, job=job, default_interval_seconds=self._default_interval_seconds) + if dlg.exec_() == QDialog.Accepted: + # store schedule back into original job dict so value() preserves it + if not isinstance(self._original_job, dict): + self._original_job = {} + self._original_job["schedule"] = dlg.value() + + # ------------------------------------------------------------------ + # Endpoint UI + # ------------------------------------------------------------------ + + def _build_endpoint(self, existing: Dict[str, Any]): + type_combo = QComboBox() + type_combo.addItems(["local", "smb"]) + idx = type_combo.findText(existing.get("type", "local")) + if idx >= 0: + type_combo.setCurrentIndex(idx) + if idx < 0: + type_combo.setCurrentIndex(0) + type_combo.setFixedWidth(110) + type_combo.setProperty("existing_type", existing.get("type", "local")) + type_combo.setProperty("existing_auth", existing.get("auth", {}) or {}) + + location_edit = BrowseLineEdit(existing.get("location", "")) + + port_spin = QSpinBox() + port_spin.setRange(1, 65535) + port_spin.setFixedWidth(110) + # Ports are not used for local/SMB endpoints. + port_spin.setValue(1) + port_spin.setVisible(False) + + endpoint_fields = QWidget() + fields_lay = QHBoxLayout(endpoint_fields) + fields_lay.setContentsMargins(0, 0, 0, 0) + fields_lay.setSpacing(8) + fields_lay.addWidget(type_combo) + fields_lay.addWidget(location_edit, 1) + fields_lay.addWidget(port_spin) + + def _browse_location(): + try: + typ = (type_combo.currentText() or "").lower() + if typ != "local": + return + start_dir = location_edit.text().strip() or "" + # If the user typed a file path, prefer its directory. + if start_dir and not start_dir.endswith("/") and not start_dir.endswith("\\"): + try: + import os + if os.path.isfile(start_dir): + start_dir = os.path.dirname(start_dir) + except Exception: + pass + selected = QFileDialog.getExistingDirectory(self, "Select folder", start_dir) + if selected: + location_edit.setText(selected) + except Exception: + return + + # Click-to-browse for local paths (no extra button needed). + location_edit.clicked.connect(_browse_location) + + endpoint_row = QWidget() + endpoint_row.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + endpoint_form = QFormLayout(endpoint_row) + endpoint_form.setContentsMargins(0, 0, 0, 0) + endpoint_form.setSpacing(6) + endpoint_form.addRow(endpoint_fields) + + auth_widget = QFrame() + auth_widget.setFrameShape(QFrame.NoFrame) + auth_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + auth_widget.setMinimumHeight(0) + + auth_lay = QVBoxLayout(auth_widget) + auth_lay.setContentsMargins(0, 0, 0, 0) + auth_lay.setSpacing(6) + auth_lay.setAlignment(Qt.AlignTop) + + auth_title = QLabel("Authentication") + auth_title.setStyleSheet("font-weight: 600;") + + widgets: Dict[str, Any] = {} + + # SMB auth + smb_wrap = QWidget() + smb_wrap.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + smb_form = QFormLayout(smb_wrap) + smb_form.setContentsMargins(0, 0, 0, 0) + smb_guest = QCheckBox("Login as Guest") + smb_user_lbl = QLabel("Username (user or user@domain)") + smb_username = QLineEdit() + smb_pass_lbl = QLabel("Password") + smb_password = QLineEdit() + smb_password.setEchoMode(QLineEdit.Password) + + smb_auth = existing.get("auth", {}) if existing.get("type") == "smb" else {} + smb_guest.setChecked(bool(smb_auth.get("guest", True))) + smb_username.setText(smb_auth.get("username", "")) + smb_password.setText(smb_auth.get("password", "")) + + smb_form.addRow(smb_guest) + smb_form.addRow(smb_user_lbl, smb_username) + smb_form.addRow(smb_pass_lbl, smb_password) + + def _smb_guest_update(): + guest = smb_guest.isChecked() + smb_user_lbl.setVisible(not guest) + smb_username.setVisible(not guest) + smb_pass_lbl.setVisible(not guest) + smb_password.setVisible(not guest) + + smb_guest.stateChanged.connect(_smb_guest_update) + _smb_guest_update() + + auth_lay.addWidget(auth_title) + auth_lay.addWidget(smb_wrap) + + widgets["smb"] = { + "wrap": smb_wrap, + "guest": smb_guest, + "user_lbl": smb_user_lbl, + "username": smb_username, + "pass_lbl": smb_pass_lbl, + "password": smb_password, + } + + return type_combo, location_edit, port_spin, endpoint_row, auth_widget, widgets + + def _on_type_changed( + self, + type_combo: QComboBox, + location_edit: QLineEdit, + port_spin: QSpinBox, + auth_widget: QWidget, + widgets: Dict[str, Any], + initial: bool = False, + ): + typ = type_combo.currentText() + + placeholder = { + "local": "Local path (e.g. /data or C:\\Data)", + "smb": "SMB path (e.g. \\\\SERVER\\Share\\Folder)", + }.get(typ, "") + location_edit.setPlaceholderText(placeholder) + # For local endpoints, clicking the location field opens a folder chooser. + # For non-local endpoints, keep normal typing behavior. + if (typ or "").lower() == "local": + location_edit.setCursorPosition(len(location_edit.text())) + # Ports are not used for local/SMB endpoints. + port_spin.setVisible(False) + + if typ == "local": + auth_widget.setVisible(False) + auth_widget.setMaximumHeight(0) + else: + auth_widget.setVisible(True) + auth_widget.setMaximumHeight(16777215) + + # Hide all auth sections + for key in ("smb",): + if key in widgets and "wrap" in widgets[key]: + widgets[key]["wrap"].setVisible(False) + + # Show only the relevant auth section + if typ == "smb": + widgets["smb"]["wrap"].setVisible(True) + + auth_widget.adjustSize() + if auth_widget.parentWidget() is not None: + auth_widget.parentWidget().adjustSize() + self.adjustSize() + + # ------------------------------------------------------------------ + # Validation + # ------------------------------------------------------------------ + + def _on_ok(self): + if not self.name.text().strip(): + MsgBox.show(self, "Job", "Name is required.", icon="warning") + return + + src_type = self._source_type_combo.currentText() + tgt_type = self._target_type_combo.currentText() + + src_loc = self._source_location_edit.text().strip() + tgt_loc = self._target_location_edit.text().strip() + + if not src_loc: + MsgBox.show(self, "Job", "Source location is required.", icon="warning") + return + if not tgt_loc: + MsgBox.show(self, "Job", "Target location is required.", icon="warning") + return + + if src_type == "smb": + w = self._source_auth_widgets["smb"] + if not w["guest"].isChecked(): + # Either Guest is enabled OR both username+password are provided. + # If either field is missing, force Guest and block save. + if not w["username"].text().strip() or not w["password"].text().strip(): + w["guest"].setChecked(True) + MsgBox.show( + self, + "Job", + "For the Source SMB endpoint, either enable Guest or provide BOTH a username and a password.", + icon="warning", + ) + return + + if tgt_type == "smb": + w = self._target_auth_widgets["smb"] + if not w["guest"].isChecked(): + # Either Guest is enabled OR both username+password are provided. + # If either field is missing, force Guest and block save. + if not w["username"].text().strip() or not w["password"].text().strip(): + w["guest"].setChecked(True) + MsgBox.show( + self, + "Job", + "For the Destination SMB endpoint, either enable Guest or provide BOTH a username and a password.", + icon="warning", + ) + return + + self.accept() + + # ------------------------------------------------------------------ + # Value extraction + # ------------------------------------------------------------------ + + def value(self) -> Dict[str, Any]: + def _extract(type_combo: QComboBox, location_edit: QLineEdit, port_spin: QSpinBox, widgets: Dict[str, Any]) -> Dict[str, Any]: + typ = type_combo.currentText() + location = location_edit.text().strip() + auth: Dict[str, Any] = {} + + if typ == "local": + auth = {} + elif typ == "smb": + w = widgets["smb"] + guest = bool(w["guest"].isChecked()) + # If Guest is enabled, credentials are irrelevant; clear them on save. + auth = { + "guest": guest, + "username": "" if guest else w["username"].text().strip(), + "password": "" if guest else w["password"].text(), + } + else: + # Unsupported/legacy types fall back to local + typ = "local" + auth = {} + + return {"type": typ, "location": location, "auth": auth} + + source_ep = _extract(self._source_type_combo, self._source_location_edit, self._source_port_spin, self._source_auth_widgets) + target_ep = _extract(self._target_type_combo, self._target_location_edit, self._target_port_spin, self._target_auth_widgets) + + val: Dict[str, Any] = { + "name": self.name.text().strip(), + "sourceEndpoint": source_ep, + "targetEndpoint": target_ep, + "source": source_ep["location"], # backward compatibility + "target": target_ep["location"], # backward compatibility + # Backward compatible field: allowDeletion derives from mode. + "allowDeletion": bool((self.mode.currentText() or "").lower() == "mirror"), + "preserveMetadata": bool(self.preserve_metadata.isChecked()), + "mode": self.mode.currentText(), + "direction": self.direction.currentText(), + "enabled": bool(self.enabled.isChecked()), + } + + # Preserve schedule (and update if ScheduleDialog was used) + if self._original_job and isinstance(self._original_job, dict): + sched = self._original_job.get("schedule") + if sched is not None: + val["schedule"] = sched + + return val + # Remove any remaining references to self.allow_deletion in this class. + +# ------------------------------------------------------------------ +# Schedule Dialog +# ------------------------------------------------------------------ +class ScheduleDialog(QDialog): + """Schedule editor UI. + + Persists as: + schedule = { + "enabled": bool, + "intervalSeconds": int, # computed fallback (minimum per-day interval if enabled, else default) + "windows": { + "0":[{"start":"22:00","end":"06:00","intervalSeconds":3600}], + ... + } + } + """ + + _DAYS: List[Tuple[int, str]] = [ + (0, "Monday"), + (1, "Tuesday"), + (2, "Wednesday"), + (3, "Thursday"), + (4, "Friday"), + (5, "Saturday"), + (6, "Sunday"), + ] + + def __init__(self, parent=None, job: Optional[Dict[str, Any]] = None, *, default_interval_seconds: Optional[int] = None): + super().__init__(parent) + self.setWindowTitle("Schedule") + self.setModal(True) + + # Default interval for new schedules (seconds). Provided by the app (e.g. Configuration service.defaultInterval). + try: + di = int(default_interval_seconds) if default_interval_seconds is not None else 3600 + except Exception: + di = 3600 + if di <= 0: + di = 3600 + self._default_interval_seconds = di + + job = job or {} + schedule = job.get("schedule") if isinstance(job.get("schedule"), dict) else {} + + # IMPORTANT semantics: + # - schedule.enabled == False => job can be run manually but will NOT be executed by the service. + # - schedule.enabled == True => job may run in the service, but ONLY within selected day windows. + # - enabled with no days selected means "run never" (no service runs). + + if not schedule: + # New schedule default: enabled, every day, all day, default interval + schedule = {"enabled": True, "intervalSeconds": int(self._default_interval_seconds), "windows": {}} + for wd in range(7): + schedule["windows"][str(wd)] = [ + {"start": "00:00", "end": "23:59", "intervalSeconds": int(self._default_interval_seconds)} + ] + else: + # Existing schedule: preserve intent. + # If windows is missing/empty, DO NOT auto-populate days (that would change meaning). + if not isinstance(schedule.get("windows"), dict): + schedule["windows"] = {} + + # Ensure each existing day window has intervalSeconds + try: + for _k, _v in list(schedule["windows"].items()): + if isinstance(_v, list) and _v and isinstance(_v[0], dict) and "intervalSeconds" not in _v[0]: + _v[0]["intervalSeconds"] = int(schedule.get("intervalSeconds") or self._default_interval_seconds) + except Exception: + pass + + self._windows: Dict[str, Any] = schedule.get("windows", {}) if isinstance(schedule.get("windows", {}), dict) else {} + + layout = QVBoxLayout(self) + layout.setAlignment(Qt.AlignTop) + layout.setSizeConstraint(QLayout.SetMinimumSize) + + form = QFormLayout() + layout.addLayout(form) + + self.enabled = QCheckBox() + self.enabled.setChecked(bool(schedule.get("enabled", False))) + + form.addRow("Enabled", self.enabled) + + hint = QLabel("Tip: Enable the schedule to allow service runs. If enabled and no days are selected, the job will not run in the service.") + hint.setWordWrap(True) + hint.setStyleSheet("opacity: 0.75;") + layout.addWidget(hint) + + # Windows editor + win_frame = QFrame() + win_frame.setFrameShape(QFrame.NoFrame) + win_lay = QVBoxLayout(win_frame) + win_lay.setContentsMargins(0, 0, 0, 0) + win_lay.setSpacing(6) + + title = QLabel("Allowed run windows") + title.setStyleSheet("font-weight: 600;") + win_lay.addWidget(title) + + self._day_controls: Dict[int, Dict[str, Any]] = {} + + for wd, label in self._DAYS: + row = QHBoxLayout() + row.setSpacing(10) + + day_enabled = QCheckBox(label) + start = QTimeEdit() + end = QTimeEdit() + start.setDisplayFormat("HH:mm") + end.setDisplayFormat("HH:mm") + start.setTime(QTime(0, 0)) + end.setTime(QTime(23, 59)) + + interval = QSpinBox() + interval.setRange(1, 604800) # 1s .. 7 days + interval.setFixedWidth(130) + interval.setValue(int(schedule.get("intervalSeconds", self._default_interval_seconds) or self._default_interval_seconds)) + + # Load from existing windows if present + key = str(wd) + day_windows = self._windows.get(key) + if isinstance(day_windows, list) and len(day_windows) > 0 and isinstance(day_windows[0], dict): + w0 = day_windows[0] + s = str(w0.get("start", "00:00")) + e = str(w0.get("end", "23:59")) + day_enabled.setChecked(True) + start.setTime(self._parse_qtime(s, QTime(0, 0))) + end.setTime(self._parse_qtime(e, QTime(23, 59))) + try: + interval.setValue(int(w0.get("intervalSeconds", schedule.get("intervalSeconds", self._default_interval_seconds)) or self._default_interval_seconds)) + except Exception: + interval.setValue(int(schedule.get("intervalSeconds", self._default_interval_seconds) or self._default_interval_seconds)) + else: + day_enabled.setChecked(False) + try: + interval.setValue(int(schedule.get("intervalSeconds", self._default_interval_seconds) or self._default_interval_seconds)) + except Exception: + interval.setValue(int(self._default_interval_seconds)) + + # Disable edits when not enabled + def _apply_enabled_state(_=None, *, _day_enabled=day_enabled, _start=start, _end=end, _interval=interval): + en = _day_enabled.isChecked() + _start.setEnabled(en) + _end.setEnabled(en) + _interval.setEnabled(en) + + day_enabled.stateChanged.connect(_apply_enabled_state) + _apply_enabled_state() + + row.addWidget(day_enabled, 1) + row.addWidget(QLabel("Start")) + row.addWidget(start) + row.addWidget(QLabel("End")) + row.addWidget(end) + row.addWidget(QLabel("Interval (s)")) + row.addWidget(interval) + + win_lay.addLayout(row) + + self._day_controls[wd] = {"enabled": day_enabled, "start": start, "end": end, "interval": interval} + + layout.addWidget(win_frame) + + btn_row = QHBoxLayout() + btn_row.addStretch(1) + cancel_btn = QPushButton("Cancel") + ok_btn = QPushButton("Save") + cancel_btn.clicked.connect(self.reject) + ok_btn.clicked.connect(self._on_ok) + btn_row.addWidget(cancel_btn) + btn_row.addWidget(ok_btn) + layout.addLayout(btn_row) + + self._sync_enabled_state() + + self.enabled.stateChanged.connect(lambda _i: self._sync_enabled_state()) + + def _sync_enabled_state(self): + en = self.enabled.isChecked() + for wd, ctrls in self._day_controls.items(): + ctrls["enabled"].setEnabled(en) + # if schedule disabled, visually disable time edits too + if not en: + ctrls["start"].setEnabled(False) + ctrls["end"].setEnabled(False) + ctrls["interval"].setEnabled(False) + else: + # restore per-day checkbox logic + day_en = ctrls["enabled"].isChecked() + ctrls["start"].setEnabled(day_en) + ctrls["end"].setEnabled(day_en) + ctrls["interval"].setEnabled(day_en) + + def _parse_qtime(self, s: str, default: QTime) -> QTime: + try: + parts = s.strip().split(":") + if len(parts) != 2: + return default + hh = int(parts[0]) + mm = int(parts[1]) + if hh < 0 or hh > 23 or mm < 0 or mm > 59: + return default + return QTime(hh, mm) + except Exception: + return default + + def _on_ok(self): + if self.enabled.isChecked(): + any_day = any(bool(ctrls["enabled"].isChecked()) for _wd, ctrls in self._day_controls.items()) + if not any_day: + MsgBox.show(self, "Schedule", "Select at least one day when the schedule is enabled (otherwise the job will never run in the service).", icon="warning") + return + for _wd, ctrls in self._day_controls.items(): + if not ctrls["enabled"].isChecked(): + continue + if int(ctrls["interval"].value() or 0) < 1: + MsgBox.show(self, "Schedule", "Per-day interval must be at least 1 second for enabled days.", icon="warning") + return + + # Basic validation: ensure enabled days have valid times (QTimeEdit ensures format) + # Allow overnight windows naturally (start > end) — that's intended. + self.accept() + + def value(self) -> Dict[str, Any]: + windows: Dict[str, Any] = {} + enabled_intervals = [] + if self.enabled.isChecked(): + for wd, ctrls in self._day_controls.items(): + if not ctrls["enabled"].isChecked(): + continue + s = ctrls["start"].time().toString("HH:mm") + e = ctrls["end"].time().toString("HH:mm") + itv = int(ctrls["interval"].value()) + windows[str(wd)] = [{"start": s, "end": e, "intervalSeconds": itv}] + enabled_intervals.append(itv) + + # Compute fallback intervalSeconds: min per-day interval if enabled, else default + if self.enabled.isChecked() and enabled_intervals: + computed_interval_seconds = min(enabled_intervals) + else: + computed_interval_seconds = int(self._default_interval_seconds) + + return { + "enabled": bool(self.enabled.isChecked()), + "intervalSeconds": int(computed_interval_seconds), + "windows": windows, + } diff --git a/dist/macos/Replicator.app/Contents/_CodeSignature/CodeResources b/dist/macos/Replicator.app/Contents/_CodeSignature/CodeResources new file mode 100644 index 00000000..7ae972c1 --- /dev/null +++ b/dist/macos/Replicator.app/Contents/_CodeSignature/CodeResources @@ -0,0 +1,26051 @@ + + + + + files + + Resources/PyQt5/Qt5/translations/qt_ar.qm + + 1a6wmuVXzu+3WJcuxKxiTN3J5qc= + + Resources/PyQt5/Qt5/translations/qt_bg.qm + + hZmrm3Mb/IT27segEp85b7j+xOo= + + Resources/PyQt5/Qt5/translations/qt_ca.qm + + 6+9u2EYCGM6N9zVlmoy81pNgCsY= + + Resources/PyQt5/Qt5/translations/qt_cs.qm + + tOlfgngSHiVJ+LtrXa8UlvFzin0= + + Resources/PyQt5/Qt5/translations/qt_da.qm + + /yRA27/gSthsbyhUJqr9SaiVsSg= + + Resources/PyQt5/Qt5/translations/qt_de.qm + + 3q8bU8P+5ssohAQY0AYK+k1Z0/w= + + Resources/PyQt5/Qt5/translations/qt_en.qm + + SIT9mvaJBke3rxrvpX84zKSa2Jk= + + Resources/PyQt5/Qt5/translations/qt_es.qm + + 3mUOlqnBMNNfikmCAnc+9/yHXSc= + + Resources/PyQt5/Qt5/translations/qt_fa.qm + + 7bb1N88KN4Clc7iC/eXiDPuXnpw= + + Resources/PyQt5/Qt5/translations/qt_fi.qm + + vyO0wTa4Y7EOdwAZot9i/JiIWd8= + + Resources/PyQt5/Qt5/translations/qt_fr.qm + + YjEt/zxM04uuhFbJgWAdDYlgD2M= + + Resources/PyQt5/Qt5/translations/qt_gd.qm + + JRI2FUgpR3chduBV5KdAQ7L7yqA= + + Resources/PyQt5/Qt5/translations/qt_gl.qm + + 615yBTVc/GvLTfJ+IkB5hCyXspY= + + Resources/PyQt5/Qt5/translations/qt_he.qm + + g2jzIDnMB3ahuVyd7V/myeoNk/0= + + Resources/PyQt5/Qt5/translations/qt_help_ar.qm + + V1G+loF7tq58nanx+6f0LzHPzF0= + + Resources/PyQt5/Qt5/translations/qt_help_bg.qm + + cla+OQuIoFPAJSSIxEO+Qvby2So= + + Resources/PyQt5/Qt5/translations/qt_help_ca.qm + + gJ3QwiHjNugS/5rCwRTO1zRsmcI= + + Resources/PyQt5/Qt5/translations/qt_help_cs.qm + + fwYc8MaZ0SWlUx40gMIZZEUvReo= + + Resources/PyQt5/Qt5/translations/qt_help_da.qm + + x38KFIJiqRZ58ZaJ5HkLdU1F1dU= + + Resources/PyQt5/Qt5/translations/qt_help_de.qm + + cIhut+9WayltCBS9TCRArBdmmdY= + + Resources/PyQt5/Qt5/translations/qt_help_en.qm + + SIT9mvaJBke3rxrvpX84zKSa2Jk= + + Resources/PyQt5/Qt5/translations/qt_help_es.qm + + qRiuFaDfGHx3ib6FmagOJ58DmWQ= + + Resources/PyQt5/Qt5/translations/qt_help_fr.qm + + RyktBoFy+8ncDZvi9HnokKN84Tg= + + Resources/PyQt5/Qt5/translations/qt_help_gl.qm + + WJzgmfLB2SWBtc8OF75Jor8AFNQ= + + Resources/PyQt5/Qt5/translations/qt_help_hr.qm + + 9KxH3kxpESyJlULlvLBWxN6qS1g= + + Resources/PyQt5/Qt5/translations/qt_help_hu.qm + + 1vB59A+7gTsCk8HSIQuucIQJL+w= + + Resources/PyQt5/Qt5/translations/qt_help_it.qm + + ZZNaZ8c/Gfz2Aj+5UDClrK+dohw= + + Resources/PyQt5/Qt5/translations/qt_help_ja.qm + + m3N+0F+A/l082PWIzOwWuxHdNWA= + + Resources/PyQt5/Qt5/translations/qt_help_ko.qm + + rqIuSg0hOWczgCx6tzjd0Dc3t9Y= + + Resources/PyQt5/Qt5/translations/qt_help_nl.qm + + XBilR68q3A4KAhAnMG4X5XekBDY= + + Resources/PyQt5/Qt5/translations/qt_help_nn.qm + + NQMMNLoLNSxhsFkszNhWkRXX7rw= + + Resources/PyQt5/Qt5/translations/qt_help_pl.qm + + igm9OJmFQ7dOJnNHjt1U+0u90Gg= + + Resources/PyQt5/Qt5/translations/qt_help_pt_BR.qm + + G1yOhdQK6XUsQosgN/Z+XsDbrL0= + + Resources/PyQt5/Qt5/translations/qt_help_ru.qm + + Ogw2mHKxEqFXKqF+64FLFosiXZg= + + Resources/PyQt5/Qt5/translations/qt_help_sk.qm + + 4+X0WCzF+v5t9DZE0RSEhhAjwIQ= + + Resources/PyQt5/Qt5/translations/qt_help_sl.qm + + yU6DJZXsdlNwVTRo+HwC2359E4o= + + Resources/PyQt5/Qt5/translations/qt_help_tr.qm + + WC7gedvUIADDeOBwHSZAV1BSTbo= + + Resources/PyQt5/Qt5/translations/qt_help_uk.qm + + XfOyE9mFo7vbR2s3t3gNfX3xfkE= + + Resources/PyQt5/Qt5/translations/qt_help_zh_CN.qm + + TtQ/AmgRy0aMnHkOQJjK2FQ1/t0= + + Resources/PyQt5/Qt5/translations/qt_help_zh_TW.qm + + ZMyrJ0P8wW5D8Le2g7ws2XbKbtg= + + Resources/PyQt5/Qt5/translations/qt_hr.qm + + d3T7h/yC2sXRmpD6QEv5Gwcu5/s= + + Resources/PyQt5/Qt5/translations/qt_hu.qm + + TFaDax+xDZkDspnLy5JZR9UVtMg= + + Resources/PyQt5/Qt5/translations/qt_it.qm + + P7p3PVjm02mcIKtBruaAHnHi3a4= + + Resources/PyQt5/Qt5/translations/qt_ja.qm + + KzR2WINQxThOD5pR/y42WeibSEY= + + Resources/PyQt5/Qt5/translations/qt_ko.qm + + VycQkhiyIuO2VKjMmTPpcOt8IRg= + + Resources/PyQt5/Qt5/translations/qt_lt.qm + + 4idmpJYS95FWxVDYPGwjA0XdpDM= + + Resources/PyQt5/Qt5/translations/qt_lv.qm + + Rugmg86ijYd8c6XOAvlluxEw/GI= + + Resources/PyQt5/Qt5/translations/qt_nl.qm + + 5o41fN93Ke0kKniRUrVv5YDXBmQ= + + Resources/PyQt5/Qt5/translations/qt_nn.qm + + VueyLTXZ3/UAHuBFRqhYxtv+4DQ= + + Resources/PyQt5/Qt5/translations/qt_pl.qm + + YQJv5gL9G4tEKg00HGvXWe7HVIg= + + Resources/PyQt5/Qt5/translations/qt_pt_BR.qm + + XZQ/HWLmXTKdACn9bBHpqy4xlzU= + + Resources/PyQt5/Qt5/translations/qt_pt_PT.qm + + zBErnJUTvPdJfzQXFotMip92QKk= + + Resources/PyQt5/Qt5/translations/qt_ru.qm + + Bl6YcTnF+4Cab5zfOEW815cH/bs= + + Resources/PyQt5/Qt5/translations/qt_sk.qm + + Cmfx7YykpRgvUEgG+NR9SZeJ8tI= + + Resources/PyQt5/Qt5/translations/qt_sl.qm + + nzyFwRWig+UjDR7q2EyMtzpx+gM= + + Resources/PyQt5/Qt5/translations/qt_sv.qm + + rlk0jgwuT4b5nabPXas7fpJQS3w= + + Resources/PyQt5/Qt5/translations/qt_tr.qm + + bkA8kJazBRlz4raB3+u8jdAkgw0= + + Resources/PyQt5/Qt5/translations/qt_uk.qm + + 8N8s/5E+WIt8rf2rv2n09jKy+Wo= + + Resources/PyQt5/Qt5/translations/qt_zh_CN.qm + + YyHpkogeDVql25FNKMxCxmcCjL0= + + Resources/PyQt5/Qt5/translations/qt_zh_TW.qm + + MI4rj3S4Y6Ya0LaPShjtBpZevqo= + + Resources/PyQt5/Qt5/translations/qtbase_ar.qm + + If0TGyO90bunu7hvPtXIOHb0Vjg= + + Resources/PyQt5/Qt5/translations/qtbase_bg.qm + + ZUQJzfP1UVVZV9Pbz41qDY8DpsU= + + Resources/PyQt5/Qt5/translations/qtbase_ca.qm + + ik1Qjx+tOPfYKIR28Xq8fBHwdec= + + Resources/PyQt5/Qt5/translations/qtbase_cs.qm + + Og53dTnFG7Ze52uOHY3OQ4bLyIY= + + Resources/PyQt5/Qt5/translations/qtbase_da.qm + + cLGbKmkU2n1in1d/iYdVNxPNXT8= + + Resources/PyQt5/Qt5/translations/qtbase_de.qm + + skmqHL+MJjbOV+tJMtU0kuTONqw= + + Resources/PyQt5/Qt5/translations/qtbase_en.qm + + SIT9mvaJBke3rxrvpX84zKSa2Jk= + + Resources/PyQt5/Qt5/translations/qtbase_es.qm + + gJ5YDNvy/9oQx3+L6brAgZeMECs= + + Resources/PyQt5/Qt5/translations/qtbase_fa.qm + + sK2+lQeQkkJCgG9nFxLFe1hLWPs= + + Resources/PyQt5/Qt5/translations/qtbase_fi.qm + + e1MTzaEmu3hjABSZ+2b7G1bCVfw= + + Resources/PyQt5/Qt5/translations/qtbase_fr.qm + + 7POzFW/+FFaezfgFzzvhLyloEmE= + + Resources/PyQt5/Qt5/translations/qtbase_gd.qm + + JPf/gJ4vEcV5zTiP6lpMVS/41NA= + + Resources/PyQt5/Qt5/translations/qtbase_he.qm + + 2znGuqRDqpuyCAQ+9/t+NAPBLZA= + + Resources/PyQt5/Qt5/translations/qtbase_hr.qm + + yVpBY4hSHvW9s+5dEenc1M4i670= + + Resources/PyQt5/Qt5/translations/qtbase_hu.qm + + u/NcBBd88pC0P30lM75EoV2SnQI= + + Resources/PyQt5/Qt5/translations/qtbase_it.qm + + mK16iJ2yBZ0webAzX5vxjegfA14= + + Resources/PyQt5/Qt5/translations/qtbase_ja.qm + + f0QDmauiMSD0D29Pyulm1iGhzGc= + + Resources/PyQt5/Qt5/translations/qtbase_ko.qm + + 8Q6IJ2Lc0uYAQb3WzFdZj8PfQ0M= + + Resources/PyQt5/Qt5/translations/qtbase_lv.qm + + lTjE2LualcDZ3FfHcIqZ3VOjLR8= + + Resources/PyQt5/Qt5/translations/qtbase_nl.qm + + XM6JLNftkkOwtXkj7pLHmtYmFTs= + + Resources/PyQt5/Qt5/translations/qtbase_nn.qm + + afxH/zozrcI0FfT4cnIFOZjWFJo= + + Resources/PyQt5/Qt5/translations/qtbase_pl.qm + + drlyJaEd0fd8rG7xRIEvkb2HNL0= + + Resources/PyQt5/Qt5/translations/qtbase_pt_BR.qm + + /RNzQXx+k9Y8l7O+eVbNfdgM6+k= + + Resources/PyQt5/Qt5/translations/qtbase_ru.qm + + QF9FNhpTfHkjwkDVGw/xxGYhwgM= + + Resources/PyQt5/Qt5/translations/qtbase_sk.qm + + AhG0kRtbdMwaRsD8qH079WMqpEo= + + Resources/PyQt5/Qt5/translations/qtbase_tr.qm + + Th5ro3ckKCJ8sDN0cAa0iH5dmtE= + + Resources/PyQt5/Qt5/translations/qtbase_uk.qm + + Y6FDJ9DPCUHW1rWL+n6LEDN/VXs= + + Resources/PyQt5/Qt5/translations/qtbase_zh_CN.qm + + NWH5X2RrIXLS6HCXO22B6YPtAKY= + + Resources/PyQt5/Qt5/translations/qtbase_zh_TW.qm + + YveJ6PoME8X9T+JQV2v0WwfIV4E= + + Resources/base_library.zip + + r+U0M7cyxfWAVEcfuVigk9EPV6o= + + Resources/bin/nssm/windows/x86/nssm.exe + + 4ZCMqrb5OEBK+Fp98PgPh3pNnuY= + + Resources/bin/nssm/windows/x86_64/nssm.exe + + R8ESwjx73yrySiC9US+R/2r3a8Y= + + Resources/core/.editorconfig + + DxfYYhYdYzC6/1Zfy84vpFXuPBU= + + Resources/core/.git + + ekJ8cBXsqunlZDE+6BzdIdl6aqA= + + Resources/core/.github/FUNDING.yml + + hxaQ/pPyo9rNEBbbUV9u8qQ+Fi8= + + Resources/core/.github/ISSUE_TEMPLATE/bug_report.md + + ZIRaVQsCKmW01emYVsJWQvMoEGA= + + Resources/core/.github/ISSUE_TEMPLATE/feature_request.md + + z1mvYgsfLJ3sqt01M32pmL+BXjU= + + Resources/core/.github/no-response.yml + + CkNspNn2JgYU6NTvNDsw5Eb0UGg= + + Resources/core/.github/workflows/release.yml + + KnRpAO3Ghl1vtyJ9bza5AHiPJ6w= + + Resources/core/.gitignore + + 2IwuMoV34WFggKrk/O5s3eBJabU= + + Resources/core/LICENSE + + MaPUYLs8fZiEUYfHFqMNuBxEthU= + + Resources/core/README.md + + UFIJhGIW6ujsqzNAsnblih0nViU= + + Resources/core/SECURITY.md + + VxzcDNEhmbLySdv04QzfsvF4kGI= + + Resources/core/VERSION + + ICwgfLjh5FknNDqp5863tzEoVfM= + + Resources/core/__init__.py + + uDfQJ3gsXr0khboXA4LcUN38OuQ= + + Resources/core/__pycache__/__init__.cpython-311.pyc + + SJUDeUmXPYs9LO5GYHuXGRjzLQI= + + Resources/core/__pycache__/__init__.cpython-312.pyc + + q4nbOsaZqOeXPnzz/U2FuewMi3E= + + Resources/core/__pycache__/__init__.cpython-314.pyc + + nQ4E9RijlW1J4lluAGlSAuW0sgo= + + Resources/core/__pycache__/application.cpython-311.pyc + + VKGYpga9T19n7NwuikhJKKLoIHA= + + Resources/core/__pycache__/application.cpython-312.pyc + + WJNnVhIHq9qXvVWjdjIBjjXYmWI= + + Resources/core/__pycache__/application.cpython-314.pyc + + vo1rpU38lxUYP9mFz1+nEmFW07k= + + Resources/core/__pycache__/cli.cpython-311.pyc + + 8lTNBZhC4pnGDKnxTZcc6UkVC4Q= + + Resources/core/__pycache__/cli.cpython-312.pyc + + N9alwMWQqdEC/ZVaVWLzs22yEag= + + Resources/core/__pycache__/configuration.cpython-311.pyc + + K6SabsH7w7fxj63RoyM0WAfrA1k= + + Resources/core/__pycache__/configuration.cpython-312.pyc + + vNYka2mQhLo21v1sUjUzY9xlZdo= + + Resources/core/__pycache__/helper.cpython-311.pyc + + kuNxNPuLEiGqdoUxNaZ5Fcfvpb4= + + Resources/core/__pycache__/helper.cpython-312.pyc + + WJfD706rPG7mYNmvBPFnYaepNWk= + + Resources/core/__pycache__/log.cpython-311.pyc + + eAofXzXoAu/tdWVlQG5flABVgJU= + + Resources/core/__pycache__/log.cpython-312.pyc + + SLp7dJlVZYyyCuhmHJbUwPPNRTk= + + Resources/core/__pycache__/service.cpython-311.pyc + + HHnf6SmUew153jm5wgr5Sj6bKw4= + + Resources/core/__pycache__/service.cpython-312.pyc + + tXS07Lh9/jJnU2jL8cvnLqkezIs= + + Resources/core/__pycache__/ui.cpython-311.pyc + + UCXy2m3sCmKASnB+tGgv5niZ1yQ= + + Resources/core/__pycache__/ui.cpython-312.pyc + + SCZOkPSvShBlRhStGhLlYcxpJ7E= + + Resources/core/application.py + + 1PdL7ghNbE3+41tK0QQNwt5NO6o= + + Resources/core/build.sh + + ACFtW7ca5miLZlF2W3Cp1QYPJ6A= + + Resources/core/bundle.sh + + iCHgxqGQIn4JqXef2DOYnDRoFsM= + + Resources/core/cli.py + + 7hYlxa2dkt86P37pTLHXU8G6+7k= + + Resources/core/configuration.py + + UG2HYg8SsdcMgFtEZTY/5rU/Fzw= + + Resources/core/database/__init__.py + + 4Nt+5Rf4xGnt4SGGLr5W8YLzYXg= + + Resources/core/database/__pycache__/__init__.cpython-311.pyc + + vQQzd5Q06gky0hLwvyc2lK4h8to= + + Resources/core/database/__pycache__/__init__.cpython-312.pyc + + GRlWNQ6tbchSIKa7985dyylw+dU= + + Resources/core/database/__pycache__/sqlite.cpython-311.pyc + + 9XjZCvdMmXCNp9QL3+Il9zxR69g= + + Resources/core/database/__pycache__/sqlite.cpython-312.pyc + + mASuSzrNeGkgl0HRhZ8vM0W+STI= + + Resources/core/database/sqlite.py + + NELDiL9+bNDDu2SXhDChL3yPziI= + + Resources/core/filesystem/__init__.py + + Fr/sO+PQ9b3LP2wjg8Kon5HHLmA= + + Resources/core/filesystem/__pycache__/__init__.cpython-311.pyc + + dA0dyN8I7t5FvtLGIWXlCRKQsDc= + + Resources/core/filesystem/__pycache__/__init__.cpython-312.pyc + + XMUq78147JY5JyneySjKNwtkac4= + + Resources/core/filesystem/__pycache__/filesystem.cpython-311.pyc + + oF3JDCPI9DSWOdjigMM+eqPDDrM= + + Resources/core/filesystem/__pycache__/filesystem.cpython-312.pyc + + PFCjLfRYguq87Nqxep+EFb9AZMk= + + Resources/core/filesystem/__pycache__/share.cpython-311.pyc + + zlnDuOVqgVDKWgSh8pkcYO0e3EU= + + Resources/core/filesystem/filesystem.py + + XwiaKaqKulVxRC4PxYxhxcCbxrE= + + Resources/core/filesystem/share.py + + eqx4b4CfBdOuLKuQrVOsEStEdfU= + + Resources/core/helper.py + + p1D4iZS3LtjbaNp0Gbl3TtQHkBI= + + Resources/core/icons/0-circle-fill.svg + + 6hIp9W0BuObMZTr9f2Pl1jTTYuw= + + Resources/core/icons/0-circle.svg + + k7NpvnKq47UH6sA5STl4Wvi8HJg= + + Resources/core/icons/0-square-fill.svg + + Fnen0wcBZ02vl8wi/5te/aO4kas= + + Resources/core/icons/0-square.svg + + mYQ/fAy+JINSyphw7SyrNzbcpvo= + + Resources/core/icons/1-circle-fill.svg + + a5mvyZ3vg+WIsJhSgnGsmerTpoE= + + Resources/core/icons/1-circle.svg + + tFX7XA+V84Oy9ncMt179q2lB74w= + + Resources/core/icons/1-square-fill.svg + + +ZwigAzd7hNj3aV1kNndlYC+/i8= + + Resources/core/icons/1-square.svg + + D0ucP/0NMCEX3YxaJWJR4hydjOc= + + Resources/core/icons/123.svg + + kVH/EagA1E/eZ04RCEhCB3651To= + + Resources/core/icons/2-circle-fill.svg + + +qd4/AjNzro/2QAaaRTWN7f62cI= + + Resources/core/icons/2-circle.svg + + CB2Rs1KpCGxRHaSqHYYZLXg8ItI= + + Resources/core/icons/2-square-fill.svg + + Xt6M8GZuUoqhiCxUsHpJ2lpBX9Y= + + Resources/core/icons/2-square.svg + + vvEKfEGyt40dxtbN1qiy/C9Un4Y= + + Resources/core/icons/3-circle-fill.svg + + rzvZEaKzzzVTSHgDtp5RDJSqtq0= + + Resources/core/icons/3-circle.svg + + 9PNNXXU+8fuDL8oZlDqwUdWXFis= + + Resources/core/icons/3-square-fill.svg + + qpBBOJ03euc5zbA+v4DP+Pid2II= + + Resources/core/icons/3-square.svg + + kzyXuV0F0Cq90Rw8LR6vcK0Qi30= + + Resources/core/icons/4-circle-fill.svg + + ujYcJMF89r+iLu1NbtuUTRwe4d8= + + Resources/core/icons/4-circle.svg + + /sdxHvSpxcR9le3xZUKtGb4Ppcg= + + Resources/core/icons/4-square-fill.svg + + JWgyKWz/6UciHRbDcvlRuPCThy8= + + Resources/core/icons/4-square.svg + + PaeagIcQLLvkY9e+ExWYuCwLN+8= + + Resources/core/icons/5-circle-fill.svg + + QnJOy3INUSiK+ecFPrNxtV29150= + + Resources/core/icons/5-circle.svg + + YNg/OMSCpbit5/xl09r7nmlp7is= + + Resources/core/icons/5-square-fill.svg + + Aq/vpCDWqKUgnmZ+gXzFV61ipOE= + + Resources/core/icons/5-square.svg + + UAoe5XZ3AFDQX+SaGHdkaRkNQcA= + + Resources/core/icons/6-circle-fill.svg + + DqGwuuObm6/+bZTvIGkjpHgAQtM= + + Resources/core/icons/6-circle.svg + + NExewBK/a721meJGC+nO6Gf0r7Y= + + Resources/core/icons/6-square-fill.svg + + XT1k00PH++p8LAd1l4Qisw7/NUU= + + Resources/core/icons/6-square.svg + + bEOtvRAXmRFZyuX+ZJUV3kafXwY= + + Resources/core/icons/7-circle-fill.svg + + k5s/vITCzsbI96BAgodpYQI9w5c= + + Resources/core/icons/7-circle.svg + + ptYMC8gEAappm24QUDS4v0V6Hws= + + Resources/core/icons/7-square-fill.svg + + taSFJyIXvWk6dYqH2XFVrOhJ8QA= + + Resources/core/icons/7-square.svg + + DJ+xibmNp3sZM03wKcKaMamVQhE= + + Resources/core/icons/8-circle-fill.svg + + CIrLVaNAgrwSXlQ2gG1ehY5Ig1U= + + Resources/core/icons/8-circle.svg + + 60913AagqEZ9iIesgzEw6pXDVCA= + + Resources/core/icons/8-square-fill.svg + + GV5SWKLdSH80H/bGe0vUHjPyq5E= + + Resources/core/icons/8-square.svg + + rT73aLsdOqZXpY6DuLXVi1uVHM0= + + Resources/core/icons/9-circle-fill.svg + + BA+dF6L5IDXkH+nWZQo88VqagiQ= + + Resources/core/icons/9-circle.svg + + pkgIk5HYKjcyWzYdealuI6B4q2o= + + Resources/core/icons/9-square-fill.svg + + ad2VGh4WI3M1jLWsy1Ra8b7RXpM= + + Resources/core/icons/9-square.svg + + 9o5YFQ8jzbuLqbfsWzUIeWYKQqI= + + Resources/core/icons/activity.svg + + Uu38Ooiaysodz6TjdMEUYK9xh6g= + + Resources/core/icons/airplane-engines-fill.svg + + 9HnO1CAAuumrTtwW3qIohZghbxo= + + Resources/core/icons/airplane-engines.svg + + 95HD5faKwHaYPzHyjpwcDoPOxl4= + + Resources/core/icons/airplane-fill.svg + + IYWRa7ukLa9/qE4636me39w7NDE= + + Resources/core/icons/airplane.svg + + gWDlhoXhkxqvjrkbTOPny7TNFQ8= + + Resources/core/icons/alarm-fill.svg + + 5KVK+aE3PRv0Gui081YYNYcg5xo= + + Resources/core/icons/alarm.svg + + PUOR3UTNnY07L/qGlSidWnJdRas= + + Resources/core/icons/alexa.svg + + 5nrMCVs7Zu230Q0CW/ciE3M38uU= + + Resources/core/icons/align-bottom.svg + + Bz3y+cfNSnZalEKui1QA5m09moE= + + Resources/core/icons/align-center.svg + + gHk4sedsBoO9mLcJsrKC1tGxSFE= + + Resources/core/icons/align-end.svg + + ChD5V9gnhCs5VCg6zS2CpReWo6Q= + + Resources/core/icons/align-middle.svg + + CjpAAsODHhG1/ZV7RT5PgjHXnZY= + + Resources/core/icons/align-start.svg + + DKfYOhcSjTZkpWOxl00DMKg9DQk= + + Resources/core/icons/align-top.svg + + 8Eak4uLd5w/jkAmFnVZnrrWcMAw= + + Resources/core/icons/alipay.svg + + kkCY32gAg41zSfvyeSmUwxJcIJE= + + Resources/core/icons/alphabet-uppercase.svg + + +eXVLINqMo9emD4NpC1nyIOMkzE= + + Resources/core/icons/alphabet.svg + + QYkIam045TF1is+K6q9y6w3gdDI= + + Resources/core/icons/alt.svg + + gHnt5tVMNZdMAIZnTMvWzLB9s/U= + + Resources/core/icons/amazon.svg + + /UoFyRwzRDjz2FsozWXKXvfu7Yo= + + Resources/core/icons/amd.svg + + xs3cBlyzaZYuQPNSXA6GO943CzU= + + Resources/core/icons/android.svg + + 0fYFX7ZVpsh86gaPYEk8qqhPZPE= + + Resources/core/icons/android2.svg + + LSqDIkLmQLzbQVknA+yfFQNESpk= + + Resources/core/icons/anthropic.svg + + W2/rPUjyt3f3hg+Y4+nQik2OPz0= + + Resources/core/icons/app-indicator.svg + + 56RBkiwT8+o9aPEfgFUwkMROV8A= + + Resources/core/icons/app.svg + + vt6IO9x/0M8QQGsk3BN94INW8ZY= + + Resources/core/icons/apple-music.svg + + ZkNBJIyhn2FgRJMb4Vciir71VtQ= + + Resources/core/icons/apple.svg + + cHHgjkaO5CQQA0zZq4xCyurAVpI= + + Resources/core/icons/archive-fill.svg + + 5LFl6t2fcKqt49Aio1zIOfpU+oc= + + Resources/core/icons/archive.svg + + BuUo0ewDEkf3560zyrecbr4rIrc= + + Resources/core/icons/arrow-90deg-down.svg + + jcu9cha3SWVlaPTGAMdbLCxSpEg= + + Resources/core/icons/arrow-90deg-left.svg + + FFzTP3tcQWHbC/8DdGOxVsi949A= + + Resources/core/icons/arrow-90deg-right.svg + + Dizp+58gdrpEE1vksxL01lxY+k8= + + Resources/core/icons/arrow-90deg-up.svg + + F2c7PAx5wOOogJEVHp+c87X8rbc= + + Resources/core/icons/arrow-bar-down.svg + + X3n5cJTk+16MexoKZzluriURRLM= + + Resources/core/icons/arrow-bar-left.svg + + d7MssJ19I6E6Pq88uGL2ckqaPbc= + + Resources/core/icons/arrow-bar-right.svg + + 1qUaCgvEobw5pctJitXY0VgFLNE= + + Resources/core/icons/arrow-bar-up.svg + + ftrBbDCcM/cCO1n1jayFNEdzPqI= + + Resources/core/icons/arrow-clockwise.svg + + qfoFhPigxqFY2sxdHHP1M90lflY= + + Resources/core/icons/arrow-counterclockwise.svg + + GYpgwQFDRUIWJJcA8xFWwYoFQOA= + + Resources/core/icons/arrow-down-circle-fill.svg + + OzJ1JMpbrEDTTe4kWMyIbY6Hgbc= + + Resources/core/icons/arrow-down-circle.svg + + Wno4m2feqL9Y/yRxPGX3ABIGyg0= + + Resources/core/icons/arrow-down-left-circle-fill.svg + + E42Pl4MaUdARwqoPyAWnn1z1nCc= + + Resources/core/icons/arrow-down-left-circle.svg + + mRSGyboYOOPr1WaGRnfE95eTa/g= + + Resources/core/icons/arrow-down-left-square-fill.svg + + vZOYYBXTnoyQL9CpaKgXq0SdF9A= + + Resources/core/icons/arrow-down-left-square.svg + + bzB6QttN1lIzIiywzs+T8pjg/Go= + + Resources/core/icons/arrow-down-left.svg + + WTZ67XkQAytOZQ4TetZNwXrg7mQ= + + Resources/core/icons/arrow-down-right-circle-fill.svg + + rGzDepLVwA7+IU6qn3woV4BN5KM= + + Resources/core/icons/arrow-down-right-circle.svg + + W6sVAM0iTTu3jm7vF+RXkc3mGGU= + + Resources/core/icons/arrow-down-right-square-fill.svg + + iHlL5nfoneF9S7/hVbdYX82xEUM= + + Resources/core/icons/arrow-down-right-square.svg + + R5COSCdxPxHlIkm0/AfVlrTRYw0= + + Resources/core/icons/arrow-down-right.svg + + SdfH1e0dKmZFmBGTDsUmYOZ+V6Q= + + Resources/core/icons/arrow-down-short.svg + + XIp2obdm6OS7rS2qxpmq8F25q78= + + Resources/core/icons/arrow-down-square-fill.svg + + d+OOKmIFVatZ87aCbaTnhBzSAAs= + + Resources/core/icons/arrow-down-square.svg + + /KDTeBOtDAEPYZ4Hq/98A4t6V5w= + + Resources/core/icons/arrow-down-up.svg + + XFA2Q8yMzqHdQWWe+4xPjXJNMjI= + + Resources/core/icons/arrow-down.svg + + UZLflwLfaHtqODgSUCI1x8K/vo4= + + Resources/core/icons/arrow-left-circle-fill.svg + + B0QodXy6eor1pVxboyCVTJE9dOI= + + Resources/core/icons/arrow-left-circle.svg + + gv5YI0e7cSS3pHss7biLYWn0Wk4= + + Resources/core/icons/arrow-left-right.svg + + +qvBdw/ZjzQ6FqDcItRnPkI2q5E= + + Resources/core/icons/arrow-left-short.svg + + 5wXOvCxhunJeIv6upRNbwPgRK24= + + Resources/core/icons/arrow-left-square-fill.svg + + YMT5GA0tNur7kHZfaH+AW2sKWDQ= + + Resources/core/icons/arrow-left-square.svg + + ru+XjCLXYukJPwB0iClvBbC97E0= + + Resources/core/icons/arrow-left.svg + + rqhQacSOsI3Q1e73e912tDhaOeI= + + Resources/core/icons/arrow-repeat.svg + + aNnlfcfDTiTw80mpRWeaHeJCdP8= + + Resources/core/icons/arrow-return-left.svg + + WuzgLIRL9+yxu2idpqBsGrfpvTg= + + Resources/core/icons/arrow-return-right.svg + + rBkudLQHL+zoSdHPYbLGWPR7zro= + + Resources/core/icons/arrow-right-circle-fill.svg + + cLNq3R0l28AzKWQz718msGyXf6g= + + Resources/core/icons/arrow-right-circle.svg + + vZU03vA4cRtET0+AE4R3AKJNEpw= + + Resources/core/icons/arrow-right-short.svg + + 39gFKPLRHVOsoXZ5hMhluk7BvIo= + + Resources/core/icons/arrow-right-square-fill.svg + + bkGNXWCdFsdTs+HyU2Zc4XVoPek= + + Resources/core/icons/arrow-right-square.svg + + ULLoHpKnoYIPMkQerP2yFMOya9I= + + Resources/core/icons/arrow-right.svg + + VDtx6wSkdDKRYRGa5aTAqlUyU4k= + + Resources/core/icons/arrow-through-heart-fill.svg + + m8AE89za3Bh/EOwci/UcZ91nUys= + + Resources/core/icons/arrow-through-heart.svg + + rTWh9LeIWuaVuxuDmaSTSDyLtDg= + + Resources/core/icons/arrow-up-circle-fill.svg + + L6G1UPcv/h+fuWV9pjP2V95DLlY= + + Resources/core/icons/arrow-up-circle.svg + + f7DvZ1RvbXaBt8rPEn8gZLxJcCY= + + Resources/core/icons/arrow-up-left-circle-fill.svg + + OkbhpglQO2R6nhnN6JhNgmal2To= + + Resources/core/icons/arrow-up-left-circle.svg + + AAN5fCSgwJYJd+XAqxa9vxjqYOY= + + Resources/core/icons/arrow-up-left-square-fill.svg + + WH3Do8JPA78UJev9cBVKaJ5zW/w= + + Resources/core/icons/arrow-up-left-square.svg + + BE0kfk2TpWO9/n1mykeAR3Pwsx4= + + Resources/core/icons/arrow-up-left.svg + + coxlUsHhH86+VU7v8Hv5nreVeGs= + + Resources/core/icons/arrow-up-right-circle-fill.svg + + 8Sp0sebCTeq3ejEV3STZ/jpn6wE= + + Resources/core/icons/arrow-up-right-circle.svg + + E83b7YtGkSvp4brnRhrXyaBAiM8= + + Resources/core/icons/arrow-up-right-square-fill.svg + + KJ7HQGM62XRTWP8g+nT62A01OYA= + + Resources/core/icons/arrow-up-right-square.svg + + eksEnfl1yUnSQj/Yq5SfeQE9GIc= + + Resources/core/icons/arrow-up-right.svg + + nafulhQ1tk328C3ss58fyv/1XcQ= + + Resources/core/icons/arrow-up-short.svg + + sDXYQoJ3HT2RckjaoI9guZx7auI= + + Resources/core/icons/arrow-up-square-fill.svg + + yqTfmLapRpmoYZPD7NgCtP2yt0k= + + Resources/core/icons/arrow-up-square.svg + + y+wAgzvR04sqm1EFymcxvZACEOM= + + Resources/core/icons/arrow-up.svg + + W7fSoW+t05F42Z45rJaxsSs38sA= + + Resources/core/icons/arrows-angle-contract.svg + + aNsivpRrVNE9buVo768koa7hyNc= + + Resources/core/icons/arrows-angle-expand.svg + + i3LQ3YQ/U+OsT+xLXtreVhV+n4A= + + Resources/core/icons/arrows-collapse-vertical.svg + + +tKFjoInyMH9d7/vyGEfiZfg4qE= + + Resources/core/icons/arrows-collapse.svg + + gPdnLskcR2L857F2JC99q+PB6ys= + + Resources/core/icons/arrows-expand-vertical.svg + + Lxrd06KZORG3lf2BY84SMYP4DSY= + + Resources/core/icons/arrows-expand.svg + + 8UIQsOS2okdYRJQcDNsr8TJBFdU= + + Resources/core/icons/arrows-fullscreen.svg + + 8dfI+0PJw7L3Dnn2xWqqnQIARC4= + + Resources/core/icons/arrows-move.svg + + XMTc7pMDT+skcw8oQ5yoPmUu2lY= + + Resources/core/icons/arrows-vertical.svg + + b/GBE9VtkUWIfzysjSPTszYD92g= + + Resources/core/icons/arrows.svg + + P5OUKn3cQWxlZVrl/8FChbcmV1o= + + Resources/core/icons/aspect-ratio-fill.svg + + q5cYx7KX/ldK8KXZGyW3Id+PjIA= + + Resources/core/icons/aspect-ratio.svg + + 9ajlPFTKKrDFVryEbgADajONdIk= + + Resources/core/icons/asterisk.svg + + IV4K6rl4X6Pde49mpw+gzpL9nhI= + + Resources/core/icons/at.svg + + T6GPRoVIzzu44fcE05Vvzy82oQQ= + + Resources/core/icons/award-fill.svg + + e9ocvYCi1nF373CmR0DcBVcP73Y= + + Resources/core/icons/award.svg + + 4acRHmHok87Vt79ChSsAKVEZDhE= + + Resources/core/icons/back.svg + + W+9/OqXIJQqQxlgNXECrapX+854= + + Resources/core/icons/backpack-fill.svg + + lroMtETgMXSU3fqhz2a/tN7UA8o= + + Resources/core/icons/backpack.svg + + g4qMhkyYDwKBxr2lt9YM9ZFcEb8= + + Resources/core/icons/backpack2-fill.svg + + wu18DZZg3wNBgP8gfF9H0YGE5ls= + + Resources/core/icons/backpack2.svg + + oVPThHPhGzqeQfsZIMS+F6RfgI8= + + Resources/core/icons/backpack3-fill.svg + + x72TlvtuBZ03rCdQ1ta/PjnuyC4= + + Resources/core/icons/backpack3.svg + + 1BH8pKxn/DQ+8b56fCcIFE5F/R0= + + Resources/core/icons/backpack4-fill.svg + + sIQS28HKgIOYVNn1ZKAf4iblofA= + + Resources/core/icons/backpack4.svg + + iLKe3INfrxq4BwWdw+6tZceN67c= + + Resources/core/icons/backspace-fill.svg + + l3k4ir07pu6BDjzd7rg+c020u/I= + + Resources/core/icons/backspace-reverse-fill.svg + + NvsEpVRmMbU/iIJdPpK7E7Ct/3Q= + + Resources/core/icons/backspace-reverse.svg + + qbjiymbq7XF14UcLyUjABdoFqew= + + Resources/core/icons/backspace.svg + + c0J5dAzSsLBAhC7Flj7BP/nuUes= + + Resources/core/icons/badge-3d-fill.svg + + zeNOhrjZVLOFNog1dFoKR4j0PXk= + + Resources/core/icons/badge-3d.svg + + pavh7K8paPLTbBfWct1Tyxg24FA= + + Resources/core/icons/badge-4k-fill.svg + + U11zNS/gsPGUcncwxblusyS4jX0= + + Resources/core/icons/badge-4k.svg + + iTX3kY58okGd5drsYFFW40Z7TZI= + + Resources/core/icons/badge-8k-fill.svg + + JRWbgHYfXbg2FeaVRNUcJzcNnns= + + Resources/core/icons/badge-8k.svg + + 6xYIiXwtrtCFjI8A9Ausq+hVXqY= + + Resources/core/icons/badge-ad-fill.svg + + FyF+oojkgSuqnLizF3WuqB8PwPA= + + Resources/core/icons/badge-ad.svg + + KUDq9RZVdBDA+DKIbS3MEZWuujk= + + Resources/core/icons/badge-ar-fill.svg + + RRP8R5B3d+ueoonX2bjqZ4JKJDc= + + Resources/core/icons/badge-ar.svg + + a8LMevppviHQshWKJWZdXLPWqLk= + + Resources/core/icons/badge-cc-fill.svg + + eyDilTCym7eVKCyhp+7H0YJMJsI= + + Resources/core/icons/badge-cc.svg + + Iia1AyoICxcISJy/OvjsYVSxjTE= + + Resources/core/icons/badge-hd-fill.svg + + qRikTbM+sy5W0IOLXJEv+1Dl6mM= + + Resources/core/icons/badge-hd.svg + + 3x2Us/P2khaBP9yVqguc0PP4nBI= + + Resources/core/icons/badge-sd-fill.svg + + goOrtZl7V54eZ8wW4Agw+HJbPPA= + + Resources/core/icons/badge-sd.svg + + e0SAxulyhdjrg7fs3sI3lCRFpEM= + + Resources/core/icons/badge-tm-fill.svg + + 07S5BDq2V/arxyq0k+d8+8ywH/o= + + Resources/core/icons/badge-tm.svg + + B6NwcZgRJaOrCFu4ZGJVYOnkg/0= + + Resources/core/icons/badge-vo-fill.svg + + W9I2odMDL4zLuwlaI9phQuEHBuE= + + Resources/core/icons/badge-vo.svg + + 0Qrns8Z84fnL6EVFfd/pYmWZKE0= + + Resources/core/icons/badge-vr-fill.svg + + cUJhrrfgc8fuNBJWuieV7o4zNaE= + + Resources/core/icons/badge-vr.svg + + 0/avkrVo+Cd37EMkb84+xm0OoQM= + + Resources/core/icons/badge-wc-fill.svg + + y3oLRLBJdYsq/TqBkcRkvv/8Cwo= + + Resources/core/icons/badge-wc.svg + + 7M6F2jXCMfVZvNbipc3DHCcLXlg= + + Resources/core/icons/bag-check-fill.svg + + 4ox1O8JFPSmwjU2HXnWbGgaMe4A= + + Resources/core/icons/bag-check.svg + + Bl9aqVhcCKU/iZ9zJZZP5qIMryE= + + Resources/core/icons/bag-dash-fill.svg + + aJUVTTmPRlo9YWWzAJIBW9i20xQ= + + Resources/core/icons/bag-dash.svg + + MjDsXvFd7kx5jJGBxVndkRnX7ZQ= + + Resources/core/icons/bag-fill.svg + + Lp24d8+WqXWVLLv03EsNXX1dUdE= + + Resources/core/icons/bag-heart-fill.svg + + 0gJEkHxHLvDR6x5x6Z14SohNIuw= + + Resources/core/icons/bag-heart.svg + + 3Z/iDx8X/hmKjDz7fBrB3JWUa+A= + + Resources/core/icons/bag-plus-fill.svg + + 0cy91IuAXk5dwTb7XN8PyOHJ8MA= + + Resources/core/icons/bag-plus.svg + + diezBP3TLoqoXNuxY0uRfpf3ypg= + + Resources/core/icons/bag-x-fill.svg + + AoG3CsZtAcy7zoz+D7RDwU5zSfs= + + Resources/core/icons/bag-x.svg + + 0/0m8e2gZJL1wywKxv3xGFF4sQk= + + Resources/core/icons/bag.svg + + FOWRIuSZrOx/qEvkycODoOwD1Es= + + Resources/core/icons/balloon-fill.svg + + juO5/mcjVeDZsdiR0fIb6YftGHU= + + Resources/core/icons/balloon-heart-fill.svg + + T4te8ks6Mbb/u2jy04ODgAYKl5k= + + Resources/core/icons/balloon-heart.svg + + YMr6EAlWjliGM3IRpLbRDEQ/6/w= + + Resources/core/icons/balloon.svg + + 5fZEdwzeDv1Wj0w+e6rsCMcMJFs= + + Resources/core/icons/ban-fill.svg + + NstSm6H54Qhyjw489u79qiw6gEY= + + Resources/core/icons/ban.svg + + 8GUR7EZxG/kdQi5NJkrpgH4EIqU= + + Resources/core/icons/bandaid-fill.svg + + m3SfGOL1MISj3dBf7L7rcrVFwgA= + + Resources/core/icons/bandaid.svg + + Alh0RF07oG27KC9goWo+gr1AmyI= + + Resources/core/icons/bank.svg + + y18EuySzuUkozK9be33l7HpY1NA= + + Resources/core/icons/bank2.svg + + r964M1wme8juTYVoidKwjqqkfHc= + + Resources/core/icons/bar-chart-fill.svg + + Svv1WQ6Q9gGg4Pq/+Jz0bNTQJX0= + + Resources/core/icons/bar-chart-line-fill.svg + + O1eQpQwb68hJn0AKfAsV/whQ8vk= + + Resources/core/icons/bar-chart-line.svg + + UomNJ2B57Pp9FHPNx7XXUg5FeXE= + + Resources/core/icons/bar-chart-steps.svg + + GuKvMGLTp4Fa8wRbVR9hGgTo24o= + + Resources/core/icons/bar-chart.svg + + FL7kj9g1ENwMny4/0Gb8aJr/XMY= + + Resources/core/icons/basket-fill.svg + + gi4e4pKDQseB/w2vU8QULNYwtOg= + + Resources/core/icons/basket.svg + + rxhJVcBUhZn3GWNPTTF+jgaWlZs= + + Resources/core/icons/basket2-fill.svg + + 0hPkiq5c1VAoG5woftJLwYGplEc= + + Resources/core/icons/basket2.svg + + 3WalySaGoSrpGbwms1Mme96yvUo= + + Resources/core/icons/basket3-fill.svg + + 7qmdLg22s52I62EbTrngM4wbIgo= + + Resources/core/icons/basket3.svg + + M5cEh/AOaqd4t/0H9cxRu8of+ks= + + Resources/core/icons/battery-charging.svg + + SGzOEUc0aH01kM8+/0HOI+2zRCQ= + + Resources/core/icons/battery-full.svg + + ibYp5P7UZ4CYcRBm1r85O9kjA/4= + + Resources/core/icons/battery-half.svg + + fn9VOUTfgg5Ps/u1VwvvcSThNqQ= + + Resources/core/icons/battery-low.svg + + gDo8rMN6Uau2TZ/euko0H+OMG2k= + + Resources/core/icons/battery.svg + + tisCWhk3aMBMI9slkm5GWinIdPc= + + Resources/core/icons/beaker-fill.svg + + kJ0qPXhv4xZH5yBn0keErs9ZvFo= + + Resources/core/icons/beaker.svg + + ++L4UjalUGan6ScN1N+qyPc1TMg= + + Resources/core/icons/behance.svg + + zJt5DsA/ZZ0M5P6ASLQN6QvYNHo= + + Resources/core/icons/bell-fill.svg + + IiMSYOtsrbNPirf6wZJkFVhy5VY= + + Resources/core/icons/bell-slash-fill.svg + + Fu46nX2vJuQOZlxLYctoup+wGk8= + + Resources/core/icons/bell-slash.svg + + 4S5K+ArgTnRrMaKF7Aws8bGzlko= + + Resources/core/icons/bell.svg + + ZR3Y+StVSuS1i9vgVeDypxl/CGg= + + Resources/core/icons/bezier.svg + + HdPQEPlwr6xtIivY6g9QJxaZaTc= + + Resources/core/icons/bezier2.svg + + h2fepRChT3XwMj8sgHoGtq/P7Nw= + + Resources/core/icons/bicycle.svg + + CBtQqz8SOVzTGquSxotEKnzWz0M= + + Resources/core/icons/bing.svg + + 4OzR6UIfYQrrhmyIXxJMwNXF22Q= + + Resources/core/icons/binoculars-fill.svg + + 05s38CsVOZkvN2r3jEsTpdqmQC0= + + Resources/core/icons/binoculars.svg + + y3AcOP4KBA7FRj/dTaSUQI+C3PI= + + Resources/core/icons/blockquote-left.svg + + RrrgI68ZiqH6c2VRAPOaLO+lryY= + + Resources/core/icons/blockquote-right.svg + + SXkuP0PAPNfntZu7RIxdbg3Kks8= + + Resources/core/icons/bluesky.svg + + WaCcXx5Vv0NXRwdGvFCFw9lyxzE= + + Resources/core/icons/bluetooth.svg + + v2Zz5JTK7UC1aku4LTrrk1wBPkQ= + + Resources/core/icons/body-text.svg + + hJK26SYDy40cDB4lL8fg3xy/+oc= + + Resources/core/icons/book-fill.svg + + eBaDtUXdXzV0EqntKyyd8dRz0d4= + + Resources/core/icons/book-half.svg + + RKX1Ie5k/zVwMC1y/DV9QnbOd9Q= + + Resources/core/icons/book.svg + + q84YGk3QiJbzcDYIMlBaeLCptCc= + + Resources/core/icons/bookmark-check-fill.svg + + Lzulx2XPOlRkVNtdAO1Fwa/33ow= + + Resources/core/icons/bookmark-check.svg + + Hre9RvPx5B1ib9p8M6e9MJm3Ivo= + + Resources/core/icons/bookmark-dash-fill.svg + + tfAW+beOEmbc3xOkmQ77xA56U5c= + + Resources/core/icons/bookmark-dash.svg + + 3EfJs3pcroLXI1SRekEwFCwn2/s= + + Resources/core/icons/bookmark-fill.svg + + lSc/Z8eCNOb/807WBHjUsrRlEjo= + + Resources/core/icons/bookmark-heart-fill.svg + + c+vqfjiwhCoMl2Ut04rsefHd7sU= + + Resources/core/icons/bookmark-heart.svg + + Kn9H7exXSG8qSPwR48StJtRabOc= + + Resources/core/icons/bookmark-plus-fill.svg + + 7NMkr8jOCtAmrHJ7P1Ya9JHa3jM= + + Resources/core/icons/bookmark-plus.svg + + mtgUvhmaHdRhiLJn7W1qwX/tEyA= + + Resources/core/icons/bookmark-star-fill.svg + + KlwJUkFVCQPfMO+UK31nRLjM2rU= + + Resources/core/icons/bookmark-star.svg + + dax74lNGRueVTxe2N+l3VdxZ1wM= + + Resources/core/icons/bookmark-x-fill.svg + + g0IID4jPF3xpoRSAW9LlPMPj/MY= + + Resources/core/icons/bookmark-x.svg + + 0i11P+xbqL0IgcPNZzE1ZWO6WmI= + + Resources/core/icons/bookmark.svg + + qrVK97GfmkP943zFxc5pbsPKOxg= + + Resources/core/icons/bookmarks-fill.svg + + 1zozMqmps1LEqhDZSFsd91b4iJ8= + + Resources/core/icons/bookmarks.svg + + fiCAELD9EfYzJ7Ei+s0jRqXekAg= + + Resources/core/icons/bookshelf.svg + + y65UJPEL9v5Z2WuOuFKE0/W3fvM= + + Resources/core/icons/boombox-fill.svg + + pmL6+EGthm+me18mPsXZBI+fJhw= + + Resources/core/icons/boombox.svg + + DXPDmOH0lBt/dBjCC0/zVtMZVOE= + + Resources/core/icons/bootstrap-fill.svg + + 3lsrERV6FV4pu6qns5jTJjQvhzQ= + + Resources/core/icons/bootstrap-icons.css + + ptHboTbR5gcHjbMAMHDqs0tR7FA= + + Resources/core/icons/bootstrap-icons.json + + dRchq4AL7fq6aRvn9+2eAti3wVM= + + Resources/core/icons/bootstrap-icons.min.css + + rp/p6DPa9owjeUXpre5bfzVHjRk= + + Resources/core/icons/bootstrap-icons.scss + + dB2E5pHnxHA/MshiQsxjpA9Hk8w= + + Resources/core/icons/bootstrap-icons.svg + + Tl+nM23FD6yJWaYY9GoPb5hPXYk= + + Resources/core/icons/bootstrap-reboot.svg + + T5uBknt5YknmexG3oRwEKAb6XvA= + + Resources/core/icons/bootstrap.svg + + Bxx8nl0lqwruiTpDUbjy6kPahLo= + + Resources/core/icons/border-all.svg + + jJa+CBcPE4AtSfTtGnGyDsIRRFk= + + Resources/core/icons/border-bottom.svg + + KB2hNrgrkDOmDV8maUUUbYwp/jU= + + Resources/core/icons/border-center.svg + + kopUFrvF3Ybl74tdsvFXVr9HX7E= + + Resources/core/icons/border-inner.svg + + AFo7wlMtTgkMPF5AEF7NitQDO5g= + + Resources/core/icons/border-left.svg + + +NJss7si751uRJZLJ5gc9wOmMZ8= + + Resources/core/icons/border-middle.svg + + cQ5esce9RNwEZDE6eNEy8e3mU0U= + + Resources/core/icons/border-outer.svg + + Jadms6MtqvAVSpA+nf/4bNdZgWE= + + Resources/core/icons/border-right.svg + + Qsr8Uw5qJWl3OrVAK7QyylkRwSg= + + Resources/core/icons/border-style.svg + + X65dG5i44LMSoTpB3MvDBPHbj20= + + Resources/core/icons/border-top.svg + + ebGpGv3pP9wulG4QkulQnnJDFEI= + + Resources/core/icons/border-width.svg + + vFo3j0jY4lqKzzpPmOnNEZsCo0M= + + Resources/core/icons/border.svg + + IEA8Yd9khRu46izShuzRvMyR05g= + + Resources/core/icons/bounding-box-circles.svg + + NfQ72IGoyibhLcpr6cI2lTA1nsc= + + Resources/core/icons/bounding-box.svg + + C5zs02hUIoMNJWIWH5kKCSK/I1k= + + Resources/core/icons/box-arrow-down-left.svg + + 8KHTCKY89RUoa5SBpjfFuR817Bw= + + Resources/core/icons/box-arrow-down-right.svg + + f4DChasNpWLGhvFEITmFWrTcwQ8= + + Resources/core/icons/box-arrow-down.svg + + HfOkfolaTT6WaKnhxL1wvXxszQw= + + Resources/core/icons/box-arrow-in-down-left.svg + + dClFJWwfN1D55kh4js2WtPsn7V4= + + Resources/core/icons/box-arrow-in-down-right.svg + + 0YVMCkpCTPmRn5i9YydOdm8TaI8= + + Resources/core/icons/box-arrow-in-down.svg + + +IhCN+liB5iz+UWbYG83/EhvQK0= + + Resources/core/icons/box-arrow-in-left.svg + + xWdKUJcvPsmcDyLdwqRJtdE1c74= + + Resources/core/icons/box-arrow-in-right.svg + + 4G8fN3Rr7kxe6aZWQ99GWevOk3s= + + Resources/core/icons/box-arrow-in-up-left.svg + + muKz2ux213i0SRRpS7ESQlvFQBA= + + Resources/core/icons/box-arrow-in-up-right.svg + + KjoUCSWoe5SkQ8myiXf/oUMebIs= + + Resources/core/icons/box-arrow-in-up.svg + + AUU36xwXAihr3KPrU2Sj2xC7R/Y= + + Resources/core/icons/box-arrow-left.svg + + Z5R68s1PAVgPlGjGIxhyIAJcX28= + + Resources/core/icons/box-arrow-right.svg + + 2JdU5/tXw1Lg9jfDXNzbDeN+ZkM= + + Resources/core/icons/box-arrow-up-left.svg + + kZTu341qhrf3VaOpJxY7YMdsg+M= + + Resources/core/icons/box-arrow-up-right.svg + + kVmVKWntDlYbQUmmOpZC8e8SqAQ= + + Resources/core/icons/box-arrow-up.svg + + ezc+giyvFCfRe0fZPJowKr+Ge70= + + Resources/core/icons/box-fill.svg + + YFdzFjvP7JQis4m+NGNlzpkjXlc= + + Resources/core/icons/box-seam-fill.svg + + 9yGwnBDcmRKI7QYi4lrPwaF2DMY= + + Resources/core/icons/box-seam.svg + + uH+xOHUeEiXEaJNvoWLil4kHhYQ= + + Resources/core/icons/box.svg + + d+IvBwN9l9V/LenNMfdmcnDkBVY= + + Resources/core/icons/box2-fill.svg + + objwKsUoT7XUnUrj+tvovwqNj2U= + + Resources/core/icons/box2-heart-fill.svg + + 4hXph5uYCdYIdE0l+79hxiEBdDw= + + Resources/core/icons/box2-heart.svg + + ZsvQeBgcgONcTo/rtHtzzQ8kdcc= + + Resources/core/icons/box2.svg + + NnLfFY+jxnKS/dDnVF2i3FWHPGY= + + Resources/core/icons/boxes.svg + + 1PYGWzUTYJPZ/pYayaSIefm2gqg= + + Resources/core/icons/braces-asterisk.svg + + xYW0Lfldn/+cMR9NrgOVJKsYMQ4= + + Resources/core/icons/braces.svg + + ix1zTPbDGD6vmKCG0PAblN7+BB0= + + Resources/core/icons/bricks.svg + + xddh/q0Xj9+hYgmrjTKsOSw/zVM= + + Resources/core/icons/briefcase-fill.svg + + KuZJpXQj4JqeZCbxYM+SXE7qzR0= + + Resources/core/icons/briefcase.svg + + Zukg8LQr62Vf/NDjWRamv5fNQsw= + + Resources/core/icons/brightness-alt-high-fill.svg + + kGccgfLa0WwJElXU1B7u4xirNU8= + + Resources/core/icons/brightness-alt-high.svg + + Emk4wEpLBkRHG6HcuC7BJAIib5A= + + Resources/core/icons/brightness-alt-low-fill.svg + + 4CKDyfx161eIq02SwzfETpwbCks= + + Resources/core/icons/brightness-alt-low.svg + + 7k5bh/KoEt2g2f3qEwoMedvXzvc= + + Resources/core/icons/brightness-high-fill.svg + + clIsIcbH71Yi8/184zmpHNI/Lk4= + + Resources/core/icons/brightness-high.svg + + EbMf5njoEsg+Qooe6t7pwoJ0zDE= + + Resources/core/icons/brightness-low-fill.svg + + 1S23XHpfNLoqZyhjZef/M5/2W90= + + Resources/core/icons/brightness-low.svg + + KIEkwgfSZeRv2n5FBY3jFKXS2Ik= + + Resources/core/icons/brilliance.svg + + yNr/S5X70rXwBbUwTBAWs2jBbTo= + + Resources/core/icons/broadcast-pin.svg + + +gahNMbRw4PUmzZscOYvUOOn55Q= + + Resources/core/icons/broadcast.svg + + BFejGxbG7/a2jh3NiGT0PivCdG8= + + Resources/core/icons/browser-chrome.svg + + P1ndctyKdwhSXDZUyx8dCMW0i5k= + + Resources/core/icons/browser-edge.svg + + XDJLit8Y/5QpREBG9tgxeBRGTsE= + + Resources/core/icons/browser-firefox.svg + + K6cgG6f9rJbtjzCBJqYbKFIXaKs= + + Resources/core/icons/browser-safari.svg + + u9LginBdCJjL+vmtLCKWCBkr4jg= + + Resources/core/icons/brush-fill.svg + + hW3Xjub3AspoO6tsAnOk8QdeSRU= + + Resources/core/icons/brush.svg + + uClZSer+2++soFlnfnmj64ffvC4= + + Resources/core/icons/bucket-fill.svg + + AtiU8PCVAHzsfD0kKp3H3KVnX7Y= + + Resources/core/icons/bucket.svg + + r64+ONb5Ryk8YPztSPw56vwM9LA= + + Resources/core/icons/bug-fill.svg + + JZFikN6sYNYyo0duWfp+TPeJSLg= + + Resources/core/icons/bug.svg + + 2EQ48J5rC61xPYwDS1bV+df58vA= + + Resources/core/icons/building-add.svg + + c2o9I5eo/mQG3n3SrJlze8D0pEk= + + Resources/core/icons/building-check.svg + + cklVfgA3GUUDVSkBZDDMuE9SYNE= + + Resources/core/icons/building-dash.svg + + REg2+muh2n4k7XrgU/+j0es08/E= + + Resources/core/icons/building-down.svg + + 7K97mHhFLZ84IYdINHOxtkXHyDA= + + Resources/core/icons/building-exclamation.svg + + ItwjMmh+RyiG7KSOrzq/IPT3Q3Y= + + Resources/core/icons/building-fill-add.svg + + cW0dwmhKDf+CyLTkWSc7PxdHgUs= + + Resources/core/icons/building-fill-check.svg + + MU4k9HpRvnDCn67q0apTmy24hcE= + + Resources/core/icons/building-fill-dash.svg + + /Id/kz9R5M8i6biqkkGnXGKyjQw= + + Resources/core/icons/building-fill-down.svg + + 8jo2+C2S/qXd/9ejpVPDgbJMLAA= + + Resources/core/icons/building-fill-exclamation.svg + + 5KwogTmH1JSuAcqu053s0UnLS6w= + + Resources/core/icons/building-fill-gear.svg + + 0xlRsaSdJ+DnNVSAtdwQLk2BWxo= + + Resources/core/icons/building-fill-lock.svg + + HlihsKAYAXLYQoB/fUlGpegbgO8= + + Resources/core/icons/building-fill-slash.svg + + K8T2m9FKtbovUfB83A8spFWe7Zg= + + Resources/core/icons/building-fill-up.svg + + AJRnHl5+0daM1O/OoFYScf2j0+w= + + Resources/core/icons/building-fill-x.svg + + H+pcv6lrz/O4wsWLf1aW1VY5EDM= + + Resources/core/icons/building-fill.svg + + zY637UQHgCzGjNjLor8J0eLoe4k= + + Resources/core/icons/building-gear.svg + + 6qMobaX/LWxPB1DBEmhs6fu427M= + + Resources/core/icons/building-lock.svg + + /xT6myqCM29sLVQObpEgrKG8Gw4= + + Resources/core/icons/building-slash.svg + + ywdMY6N939NOZaRLvPCWv7BAtzs= + + Resources/core/icons/building-up.svg + + Ncq9cRO4CEok+I4FR3gOAWB2vHY= + + Resources/core/icons/building-x.svg + + JQwTXB3otsT61RoWhvf93Uvyr24= + + Resources/core/icons/building.svg + + bH02u+zIIvD60glT0P5B0cA+ku8= + + Resources/core/icons/buildings-fill.svg + + vg2awp3IrFQy/ihjeuL62hYPpQ4= + + Resources/core/icons/buildings.svg + + stJ/q2U4BEcZ6wSu/MXegWgCjaA= + + Resources/core/icons/bullseye.svg + + RC1EfOcXzBIw81pfv27r5Cy5rvw= + + Resources/core/icons/bus-front-fill.svg + + FqMc3R8owzy7I/blPi0lh7CeQFw= + + Resources/core/icons/bus-front.svg + + m0riUafNKx6cm+vr24MfHoO6HJk= + + Resources/core/icons/c-circle-fill.svg + + xwiH6xnOGtZR2jO0G0Q8WdV0Bn4= + + Resources/core/icons/c-circle.svg + + fMP6WOjAgXi6srcn28VUPEeTFYw= + + Resources/core/icons/c-square-fill.svg + + MDzweBrV1+jfdzg1ZwuJNZoZZlo= + + Resources/core/icons/c-square.svg + + bgm5SH/hMrF6amCzE3/o0UO9PeU= + + Resources/core/icons/cake-fill.svg + + SdEtN8Hrjchgdrx+r8+NQ7znnXQ= + + Resources/core/icons/cake.svg + + e4cGHNvCZgossL33WAAZB0gmrjw= + + Resources/core/icons/cake2-fill.svg + + JuNadrBwwaDOYt7d2EPsQ5M8w/Y= + + Resources/core/icons/cake2.svg + + tlZCcYKbfvl1pLyf4feeDKD1TyI= + + Resources/core/icons/calculator-fill.svg + + DVxFnTpBJbg6Yvs5Osh0U6oKPnQ= + + Resources/core/icons/calculator.svg + + bIO2FGJnHCssXSGMahT1q4m/ySg= + + Resources/core/icons/calendar-check-fill.svg + + +jjFc+FOsqkfzilFfIt4+V3wj3I= + + Resources/core/icons/calendar-check.svg + + p12joWKufxKJb4II2dIq/gIlRWs= + + Resources/core/icons/calendar-date-fill.svg + + 4HIkOpQt3eIMUkYKdKJ+5YS9+28= + + Resources/core/icons/calendar-date.svg + + JH7YZVF32M2QCuImSsMt47hrB2U= + + Resources/core/icons/calendar-day-fill.svg + + +aHBhR9E4gGFK8mAqxbz/JOkIOU= + + Resources/core/icons/calendar-day.svg + + dFLw1FztsUrmPec1HvgDkaOZ9nU= + + Resources/core/icons/calendar-event-fill.svg + + wjcH1LFSH/Tayq0HM1Y+As7sztU= + + Resources/core/icons/calendar-event.svg + + QcyVwivXQXvOhhyKyqPrJqpHAm4= + + Resources/core/icons/calendar-fill.svg + + cZzld5/a7SnHyGuKek/bhG+/jYE= + + Resources/core/icons/calendar-heart-fill.svg + + eQEX4Ew7Z+d9Ti2t9kI+/2fXnAk= + + Resources/core/icons/calendar-heart.svg + + OEp5w4ZQ/QmAAZnKzUU3Qc08Xq8= + + Resources/core/icons/calendar-minus-fill.svg + + 5BGidqwkAIOy3LxrCGuBNrKx4Ho= + + Resources/core/icons/calendar-minus.svg + + WSQDXPOD/TEzwoHDwk0mrNWeZrk= + + Resources/core/icons/calendar-month-fill.svg + + EKT7fa5dU911zi3Qte7UG8ySuNk= + + Resources/core/icons/calendar-month.svg + + CpWGT3Bh5T2hpToTO/iE+YJOKQ0= + + Resources/core/icons/calendar-plus-fill.svg + + /9+zdfd0CuOSVqplOqR/4j571q4= + + Resources/core/icons/calendar-plus.svg + + dbumD1tkj6N79F7oulZqvQFEL6M= + + Resources/core/icons/calendar-range-fill.svg + + 3FYY8Hn/lfYID0RAPq0XdJDXj3A= + + Resources/core/icons/calendar-range.svg + + rPS6wjTqFxksUSp/sWcnUsZB/m8= + + Resources/core/icons/calendar-week-fill.svg + + W7pDvVFbwZipq47cjxL447OPAC8= + + Resources/core/icons/calendar-week.svg + + 67xSJRdqnBR7EwjvH8KhTym0yJc= + + Resources/core/icons/calendar-x-fill.svg + + JFHJsXg4rOqpNWpAIXhgQkABHYg= + + Resources/core/icons/calendar-x.svg + + snFBHP58NQPAE7L0H5PxqpTtgZ8= + + Resources/core/icons/calendar.svg + + 0bZV3Tn/b0oCQsloJtNBb03WAbs= + + Resources/core/icons/calendar2-check-fill.svg + + 2Br77bjn/MIW45KK7n0FcPPFkSo= + + Resources/core/icons/calendar2-check.svg + + Le9Tp9E8LWtYtVPjxmcf6faeQ9o= + + Resources/core/icons/calendar2-date-fill.svg + + iXh0cpYajPVXcm6LAPiGCyMa9KE= + + Resources/core/icons/calendar2-date.svg + + mitQvRQspZ3DnkZHxX/TzTvdx3k= + + Resources/core/icons/calendar2-day-fill.svg + + 2WxGOWJLFyfd0s78rfwei2do2Gk= + + Resources/core/icons/calendar2-day.svg + + Uzr7gsF+jX41vWNX6tJ8zGJJPG8= + + Resources/core/icons/calendar2-event-fill.svg + + AOHAHySEcJg3BZTuUkZgWR3v4xE= + + Resources/core/icons/calendar2-event.svg + + 9Pa3+m5Q4UVUikCn1ZiiJbFDZ20= + + Resources/core/icons/calendar2-fill.svg + + /5Iz/U4SCY8CASzhSIJVfGLHw3E= + + Resources/core/icons/calendar2-heart-fill.svg + + 59WfGsUCoUiNm4umL+cgQJBDulY= + + Resources/core/icons/calendar2-heart.svg + + zlhtmN3fK0HPm4QEf1HYlbFLP1g= + + Resources/core/icons/calendar2-minus-fill.svg + + 2USv/GC+YngUkY3ZEl52OYv9Exc= + + Resources/core/icons/calendar2-minus.svg + + w3YAmDnF5sv2FA4WoRxdl1YhpAw= + + Resources/core/icons/calendar2-month-fill.svg + + RrlszhaGEMdSQSn4uHNaQfImg9o= + + Resources/core/icons/calendar2-month.svg + + Sz3NJrT8fYzSiqTRuVKe2GIxRI0= + + Resources/core/icons/calendar2-plus-fill.svg + + F9t3qz6R2oHBGwIPl/nJaBPZP3A= + + Resources/core/icons/calendar2-plus.svg + + Fh/+efOBGJMD/v4VL4S9y2LQWoA= + + Resources/core/icons/calendar2-range-fill.svg + + IAgsFUaau8D8fTe3IXcDT4jP6w4= + + Resources/core/icons/calendar2-range.svg + + ATcqnkHlKtCeJhMdJ0jYAXRuA0o= + + Resources/core/icons/calendar2-week-fill.svg + + zaE95m7UuU9nM4u0+oyz5HPSosM= + + Resources/core/icons/calendar2-week.svg + + 2GWRyAz0anI+KrVLRwT1mjTJkwM= + + Resources/core/icons/calendar2-x-fill.svg + + /G8084TOS4HawA/Q8C+3f50Vh50= + + Resources/core/icons/calendar2-x.svg + + BGiUZinrBznc7wH9H4d3HXsdz5k= + + Resources/core/icons/calendar2.svg + + b3Wzw3uaE4+HkpXdu+eI709nvsg= + + Resources/core/icons/calendar3-event-fill.svg + + vEhvx7+4dxamDXdC63O36fGRPaQ= + + Resources/core/icons/calendar3-event.svg + + hbT9PcwdRFOKH0KSgy6IkmbK6sc= + + Resources/core/icons/calendar3-fill.svg + + BdqUvs+LFUXCses/iCI/QBEmfNE= + + Resources/core/icons/calendar3-range-fill.svg + + 0Gyi5TexGZ1WSq0yFB10TJwrFqA= + + Resources/core/icons/calendar3-range.svg + + 8VBNc5s2s9UGAnFJE/c1w4N3Uuk= + + Resources/core/icons/calendar3-week-fill.svg + + y2bbEzMjbFOQgBlBXC3h5vHifMw= + + Resources/core/icons/calendar3-week.svg + + Z/vradBwJBVJVgSPGNs9bfSetOE= + + Resources/core/icons/calendar3.svg + + ZvljPDVe6t3quUem99We24HhMa4= + + Resources/core/icons/calendar4-event.svg + + kqC673EcrFV+7dFbPaFitW836oc= + + Resources/core/icons/calendar4-range.svg + + J7P5YST+g9V8D1wVGLbQvLrMlRc= + + Resources/core/icons/calendar4-week.svg + + ZeoPUhrbJvfba2U4Gc7t1YWnSUE= + + Resources/core/icons/calendar4.svg + + yvYBuT8FlRjL0ZODcyqL7qnCB64= + + Resources/core/icons/camera-fill.svg + + xDESahTLHpqpEdxPMXac30Ei5ow= + + Resources/core/icons/camera-reels-fill.svg + + E/Lb39axwTF2NJCVjqLi6D86ehs= + + Resources/core/icons/camera-reels.svg + + Oe73swodtbP0v76y5uftMztlQys= + + Resources/core/icons/camera-video-fill.svg + + rCk9gOAVlbJr4cxeUwZRL9Nb4oU= + + Resources/core/icons/camera-video-off-fill.svg + + JgSw4LHetT2bomw4N+ERySyEbkk= + + Resources/core/icons/camera-video-off.svg + + 3YdBDiQDK0HNITgTpr5TvFbhSCY= + + Resources/core/icons/camera-video.svg + + 5gS0iiuedZx5D2M355hPRa5x08c= + + Resources/core/icons/camera.svg + + FQRGddbMGUtuA3g7YZqpaAowTbU= + + Resources/core/icons/camera2.svg + + R7doHNPdFIkty1bSRtqnT6VMc8A= + + Resources/core/icons/capslock-fill.svg + + 3IvHVmtKdqxENgMFF/wcfVosB8A= + + Resources/core/icons/capslock.svg + + QXmcnwdh+EKCPulYsTXYcX59Nmo= + + Resources/core/icons/capsule-pill.svg + + k4doywFpOHMRV/5TBxyspU08GUk= + + Resources/core/icons/capsule.svg + + i7uFmqo2dwkdVORAYOxgEdgDRtU= + + Resources/core/icons/car-front-fill.svg + + fHc4m598/lRt1BbHv6FBGJV8y+g= + + Resources/core/icons/car-front.svg + + pp7GpU8XADtWSlBH4e/UWVPtIXU= + + Resources/core/icons/card-checklist.svg + + mbuy3a+N0vdpExNcVk7P0JQV+uc= + + Resources/core/icons/card-heading.svg + + RHflLVgCRnKL5k2v6yVNomYAxQk= + + Resources/core/icons/card-image.svg + + GepqqvDVCKI7RLluL/zOe8Y4WbM= + + Resources/core/icons/card-list.svg + + Q8QRuxVHp3j5X15KGPyaFSiBOHs= + + Resources/core/icons/card-text.svg + + 8x7m+DDFqzpk+JXxqTkRF2UXngA= + + Resources/core/icons/caret-down-fill.svg + + 1E5FAnF/MxQefMTNyEc1cQ8MF4s= + + Resources/core/icons/caret-down-square-fill.svg + + 8leL+37VlNTT9sH2pg41zq7acnc= + + Resources/core/icons/caret-down-square.svg + + BzhW5z7bpHswhuPynaJTkcUzA98= + + Resources/core/icons/caret-down.svg + + 8kLeK3QUCrWX7OoT8dwf3ldsm9E= + + Resources/core/icons/caret-left-fill.svg + + LWuUYwxzAMP52/lVOWbYVdRcsQg= + + Resources/core/icons/caret-left-square-fill.svg + + rRVfRVsBliCRCJPAZsQrm9sY6GQ= + + Resources/core/icons/caret-left-square.svg + + 7Ov6LIOpR9oBOzNFCgjV7IXi7es= + + Resources/core/icons/caret-left.svg + + AyJ0fpORJAxcEGXDFCdDBxb5BcY= + + Resources/core/icons/caret-right-fill.svg + + ix5DHYOQtq6P4rEMBKpS/MxuI5E= + + Resources/core/icons/caret-right-square-fill.svg + + VoH/vsTa+z3IQPGKIC0NH++Ge/k= + + Resources/core/icons/caret-right-square.svg + + d8bE8nLrl4iMSkmaPsyxxXYwaVY= + + Resources/core/icons/caret-right.svg + + YKIiHFCBCv7D4FHIc8wiJmDglUs= + + Resources/core/icons/caret-up-fill.svg + + f7fkNz4uDwnLlIv0nvHHm/u8LJg= + + Resources/core/icons/caret-up-square-fill.svg + + o+959QtHBCh2d47v3Upxygo2VwM= + + Resources/core/icons/caret-up-square.svg + + wygXgU7aa4wtHX/Xy9/l97IyCKE= + + Resources/core/icons/caret-up.svg + + CtSPqc1C/in1kPkit6slByfT0zc= + + Resources/core/icons/cart-check-fill.svg + + WC6rd0CLE3joQOa9lOud0Cn4Rto= + + Resources/core/icons/cart-check.svg + + kpQHtW+zVWabrsOG9Wd4piOwk0w= + + Resources/core/icons/cart-dash-fill.svg + + 6px8XzHs7mran1LdNnPeLQrzUnI= + + Resources/core/icons/cart-dash.svg + + i/4PYK9AhqjNYyggKCuMEa9eUcw= + + Resources/core/icons/cart-fill.svg + + 60dtv0OXonYCRuR4x36Hmm/Zlx0= + + Resources/core/icons/cart-plus-fill.svg + + VmeJdTvzGI93zITUxpliT6VE9OI= + + Resources/core/icons/cart-plus.svg + + bCGYksYjteg9scrodRBOXXqOPuk= + + Resources/core/icons/cart-x-fill.svg + + YdpQhPHlevC8eKyWDg/xQvJwW7E= + + Resources/core/icons/cart-x.svg + + XZ7BrjKXTGBGEmuQ9/UxMhE0EaU= + + Resources/core/icons/cart.svg + + QMXb5229/TyOIZqGH3IHZoNJ4ts= + + Resources/core/icons/cart2.svg + + cbimonMvEt+sizLOTHmYZc9E8dg= + + Resources/core/icons/cart3.svg + + BDeWElMEpl+G+n7qHZHyzHAWcMY= + + Resources/core/icons/cart4.svg + + xItxWYAc24S4BuqxBWiwnJH69K8= + + Resources/core/icons/cash-coin.svg + + 3/ZoAnV4o3Tw8CjzAPk2oP4g5g4= + + Resources/core/icons/cash-stack.svg + + oZggYWoayKc+YP3DPoaa4CLnUrw= + + Resources/core/icons/cash.svg + + Ph6QdW+WBCOGWzYyxYZQEYS7vZU= + + Resources/core/icons/cassette-fill.svg + + F4qM2YcrLWHLYnwbFF87O3KjKvc= + + Resources/core/icons/cassette.svg + + NqwJRccLNfIndzWAS0MiRLNBwh4= + + Resources/core/icons/cast.svg + + 7AP5/IVbHO44nNZzePzGghHysiw= + + Resources/core/icons/cc-circle-fill.svg + + Vm6Qv/hIQwRVuhFP/0Ygg4cOabs= + + Resources/core/icons/cc-circle.svg + + qPdLlG8+7620USOSrlYdHFA2m9I= + + Resources/core/icons/cc-square-fill.svg + + fiQB/lMuk+roe/Pirmei9/Ezvm4= + + Resources/core/icons/cc-square.svg + + di+6h62gQ7sDgC+RrS47FQkQVNM= + + Resources/core/icons/chat-dots-fill.svg + + ZazrPqRYroHjPtanbSYOhLiQc2U= + + Resources/core/icons/chat-dots.svg + + LzYvBS5N3VstJ/Dg9Q6nAxvQ1sM= + + Resources/core/icons/chat-fill.svg + + wR8TW7GkqnvoOa1FP2qaNrQl82g= + + Resources/core/icons/chat-heart-fill.svg + + KuF3cqJgtyLHKi/TDKz0WB+HAPs= + + Resources/core/icons/chat-heart.svg + + eV9zB+45adjvc27F9k2DOQHxeKk= + + Resources/core/icons/chat-left-dots-fill.svg + + rXF8fhNe5gZ+U3aFHVtud1uQDwo= + + Resources/core/icons/chat-left-dots.svg + + UjloQ220aQaPlJYKYJPW5yevrxM= + + Resources/core/icons/chat-left-fill.svg + + lNHbGbO0QHI7NspaoysFOU7xQro= + + Resources/core/icons/chat-left-heart-fill.svg + + Z4UC7eVRDWqULp62Do4Zb3rcZQ4= + + Resources/core/icons/chat-left-heart.svg + + CbokhP0F0b+6YeavFtNRrglPsnY= + + Resources/core/icons/chat-left-quote-fill.svg + + RyqB/9eN40+3ZkGABg3AyacHll0= + + Resources/core/icons/chat-left-quote.svg + + vXfL3FvlL2+wHl6qrl35UofOQb4= + + Resources/core/icons/chat-left-text-fill.svg + + d7+c2a56RvQN7INFMilK6YWW9xQ= + + Resources/core/icons/chat-left-text.svg + + lIR/3z0vtUASRgQpPIuafzCrHfM= + + Resources/core/icons/chat-left.svg + + gKY7ZG5LqavSLJ/FJKgP1bhvCnI= + + Resources/core/icons/chat-quote-fill.svg + + 6A+F8UAUsb9ibCRVSBNUc7gtOMw= + + Resources/core/icons/chat-quote.svg + + uZ8QPMXSmb49K2ftHazAPyVPtRc= + + Resources/core/icons/chat-right-dots-fill.svg + + ZTq7t85jN7Y2rdV2jnvfClWa9LQ= + + Resources/core/icons/chat-right-dots.svg + + JHb/cG3lZzFhxElA8FM6j7II4KQ= + + Resources/core/icons/chat-right-fill.svg + + 91HiE1qN2kFFuos3evuRh2l6V/g= + + Resources/core/icons/chat-right-heart-fill.svg + + jD+EUf//qBLG9htD98LdOP2CixI= + + Resources/core/icons/chat-right-heart.svg + + PFHIn8QRhw0Sn81NZ5OQrnmAiAA= + + Resources/core/icons/chat-right-quote-fill.svg + + DUgw1lPD/hATJ0TVh+XR3L+yy5E= + + Resources/core/icons/chat-right-quote.svg + + 9ylj8I3c/iqxD0G07O7MGxeuWpQ= + + Resources/core/icons/chat-right-text-fill.svg + + LM/wwyRYaxzL8HODMMdmuVMrjpc= + + Resources/core/icons/chat-right-text.svg + + rd69wfG+3xxnL1fePMBwLBZC6t0= + + Resources/core/icons/chat-right.svg + + a9PWPzR3LhqqyqxNNHXtzPS1bak= + + Resources/core/icons/chat-square-dots-fill.svg + + nBYuU6HMj5sghdkN73cNsHKLd5Y= + + Resources/core/icons/chat-square-dots.svg + + RUFZMbj+dRceZv/abB6Xn5reZhY= + + Resources/core/icons/chat-square-fill.svg + + dv7ApUmHD0+6BfBMQz51ho6AyIg= + + Resources/core/icons/chat-square-heart-fill.svg + + GbLfklLfxxow3C68AuO3Vmmhwtg= + + Resources/core/icons/chat-square-heart.svg + + c3egEUA/tok3zQhv+ydWkC/iWEE= + + Resources/core/icons/chat-square-quote-fill.svg + + T8Z8BQma1aJhSsTXkm0rVcqdvvs= + + Resources/core/icons/chat-square-quote.svg + + 1JMHuBBFi8gBivXQk1SxjOGDo0k= + + Resources/core/icons/chat-square-text-fill.svg + + MoT5ORCPFJ7iZGQeMJQJ84zKFVE= + + Resources/core/icons/chat-square-text.svg + + WMZ5KRMyYIuekfUTT/f8xKYyTLU= + + Resources/core/icons/chat-square.svg + + dlTIIYCX7/hVBWfWEF5xAY1yd0I= + + Resources/core/icons/chat-text-fill.svg + + 6lmz3z4QDqRrtxfO4MNit8xD9GY= + + Resources/core/icons/chat-text.svg + + /rTgIilI2bc+vYHrYsPmXFdeOB0= + + Resources/core/icons/chat.svg + + T7ltF9FORBcPpHQ188y03eTw1og= + + Resources/core/icons/check-all.svg + + Wq/FE76cJLESo+csEWzeq2R7XL4= + + Resources/core/icons/check-circle-fill.svg + + Tcd4TC3ZVlC3OQ7gr5xXQC0pJCQ= + + Resources/core/icons/check-circle.svg + + DQsie8aUD+NYodI1dqlJbaTh3oQ= + + Resources/core/icons/check-lg.svg + + XgBRgekEw16lGD2XQOU2kbx3Fow= + + Resources/core/icons/check-square-fill.svg + + +dB0+7SB4i/dzCI/tfS5IUReRIs= + + Resources/core/icons/check-square.svg + + vxTNy9CukDiFOesXZLsb9pSPlMw= + + Resources/core/icons/check.svg + + rHIq7QF+he86SEaMwj2Z6rvNL9Y= + + Resources/core/icons/check2-all.svg + + nsBAzt+l8slqfzNcbae8+fGNKM4= + + Resources/core/icons/check2-circle.svg + + e6saOhf6fJpalgKdhElrHVRT2ek= + + Resources/core/icons/check2-square.svg + + 0xS2bLmc1Gxw9XUXGnhj9vvepYo= + + Resources/core/icons/check2.svg + + ajHgpB4V9bloBbivSedt1Urmiu4= + + Resources/core/icons/chevron-bar-contract.svg + + gpMv1sVN8WurkURH1y+3rMaAf7c= + + Resources/core/icons/chevron-bar-down.svg + + CtNfo/n/UIYNWAJ7k6h/h/7hE20= + + Resources/core/icons/chevron-bar-expand.svg + + eLjlonJpx6A0HdG/mNUQBTxUY78= + + Resources/core/icons/chevron-bar-left.svg + + pqxWsPitpX6aArFZLhLseqBd+a8= + + Resources/core/icons/chevron-bar-right.svg + + 0DpRQDEPEd8NaR4BMzAjDQbfEh8= + + Resources/core/icons/chevron-bar-up.svg + + biODH7kgn7qFUII7Bn2YF04VjG8= + + Resources/core/icons/chevron-compact-down.svg + + KJ+49sX98orlqduCUVaeln76Ffs= + + Resources/core/icons/chevron-compact-left.svg + + 9YGZrgxpsmMROLf5/VFUSpvb9lM= + + Resources/core/icons/chevron-compact-right.svg + + axgWC2VX73WPnHyGk42iQXlIjWs= + + Resources/core/icons/chevron-compact-up.svg + + rdFKhq/7o6y6Uo4RHOrbadZ5zYE= + + Resources/core/icons/chevron-contract.svg + + OWXgt06w2X1TGWT4+bvUQQMODbw= + + Resources/core/icons/chevron-double-down.svg + + 03Oa9chy5uGhqMJl304m4BXsWIQ= + + Resources/core/icons/chevron-double-left.svg + + lhDpTU9RMFh0FPoTv0QoIH7JbEg= + + Resources/core/icons/chevron-double-right.svg + + NXTbBhDVeoiYvbrdZ+n3o54KlpQ= + + Resources/core/icons/chevron-double-up.svg + + sohyDHGvZeBzxTlQ3wDJhfInjdI= + + Resources/core/icons/chevron-down.svg + + Povfvc95W9fX7SriRMq71gy+OpE= + + Resources/core/icons/chevron-expand.svg + + TwVS48nh+nQz1wEu003s7tppLmE= + + Resources/core/icons/chevron-left.svg + + sVReYFG/Cx7F0SL2E05cNk3qDhM= + + Resources/core/icons/chevron-right.svg + + Y1oB8mIipBTgSHeK5GH02VBWhrw= + + Resources/core/icons/chevron-up.svg + + Gg+qn7Td5Z8DvppOs6LBW6RQxes= + + Resources/core/icons/circle-fill.svg + + kZ5btNNPDb9DtrldfXd+JfuNGfY= + + Resources/core/icons/circle-half.svg + + ekQHJ+MXh9Z91qzOGCofQjYFZ04= + + Resources/core/icons/circle-square.svg + + kWOwJCk8XEyoLNj2TSSH0lxj6aY= + + Resources/core/icons/circle.svg + + t1lvpCSGGxhCPtYVCuN4pd8a/Ls= + + Resources/core/icons/claude.svg + + J6lOcKnccxkCyzD4QhJVuYeVZ3c= + + Resources/core/icons/clipboard-check-fill.svg + + d4sfdr8jz+bI1QNkZiZRvOuxb4Q= + + Resources/core/icons/clipboard-check.svg + + yaJECW5Eb6W9VLOp43oj61cR66g= + + Resources/core/icons/clipboard-data-fill.svg + + iVhOFSN5PvfNlKlcHOZC3+vRO6M= + + Resources/core/icons/clipboard-data.svg + + PAQpDwk9RO/1W6NREynYphJ8x2Q= + + Resources/core/icons/clipboard-fill.svg + + zHEz9OS7O/yYZ3ZBnUlSI4u3P9Q= + + Resources/core/icons/clipboard-heart-fill.svg + + RFh/t0ILSvjWfrcShCSsQUZqrDI= + + Resources/core/icons/clipboard-heart.svg + + 0MgE6MM0KgyH6C8dqdNEoHWPOr8= + + Resources/core/icons/clipboard-minus-fill.svg + + NtS/S9qKp5L3bwaQdYnUpmNwIQw= + + Resources/core/icons/clipboard-minus.svg + + n+4aKUCQYfI5I7OKRiJ9vL4w0cc= + + Resources/core/icons/clipboard-plus-fill.svg + + b7mGMmIHquAm73ht/2qBVvSkyOk= + + Resources/core/icons/clipboard-plus.svg + + LBsIhL183tL5uZFNKugdqr6rxT0= + + Resources/core/icons/clipboard-pulse.svg + + EDEpiItg/OtVgTLm9BQz2iwg6l0= + + Resources/core/icons/clipboard-x-fill.svg + + Ap026Boi+lvbPwuwkV4mBo3gAKs= + + Resources/core/icons/clipboard-x.svg + + TvZu1b1FOyQsfY/EjqT9f639zGA= + + Resources/core/icons/clipboard.svg + + lAMsVYKslpeL+NhyxbNwK62MsjU= + + Resources/core/icons/clipboard2-check-fill.svg + + enq3lNn4fvTPJa8sZZdhsdD2t34= + + Resources/core/icons/clipboard2-check.svg + + vpr9ytO+n2PRh+pBCzayfmpRbeY= + + Resources/core/icons/clipboard2-data-fill.svg + + bwYtVhwHGsHPlfPQGBOnZK0i/yo= + + Resources/core/icons/clipboard2-data.svg + + 4YHKIszWEu+krlNzUUhCiZnqFIg= + + Resources/core/icons/clipboard2-fill.svg + + jj9aJJUgPx3XNvZe7ip8t/t1CKs= + + Resources/core/icons/clipboard2-heart-fill.svg + + kGHi4a8TQ57sSYjWEXITbNTeJ94= + + Resources/core/icons/clipboard2-heart.svg + + JUPzYLct9yjXGE2u5IikA+plOjg= + + Resources/core/icons/clipboard2-minus-fill.svg + + 2nbG+MFb/B29H2I1IKYsCnEg3i0= + + Resources/core/icons/clipboard2-minus.svg + + TZUgEMi3wVgOC2fMllls1ueqEy4= + + Resources/core/icons/clipboard2-plus-fill.svg + + QFCaVJSekyMcdjwY1oMXnF+DP/w= + + Resources/core/icons/clipboard2-plus.svg + + vuhC+NnviQRL1L+jCGsvdi2R2iU= + + Resources/core/icons/clipboard2-pulse-fill.svg + + S30Zjd/pyADCtIPpTPqi3PgM8ls= + + Resources/core/icons/clipboard2-pulse.svg + + 7eXuiAJIxa0Wkgps7YmcrskF2Eo= + + Resources/core/icons/clipboard2-x-fill.svg + + X4tDSe9trDVeWPLRtwVUGvdmp/A= + + Resources/core/icons/clipboard2-x.svg + + 3TH4Lg8gLoUlD8/3Pre45Rec6Ik= + + Resources/core/icons/clipboard2.svg + + 95XFKHOZJVtI+2Z2XRIo6xCWpQk= + + Resources/core/icons/clock-fill.svg + + 78AYMk8JTNMbSbpykcj2I0O9gdY= + + Resources/core/icons/clock-history.svg + + lNK21I5iL1RmeHrniiWauiLbl+c= + + Resources/core/icons/clock.svg + + HjFI2JAODSo6FJrRPHKvIGQ6mOE= + + Resources/core/icons/cloud-arrow-down-fill.svg + + EQtLLRJgBHNrih0tgVrn40w3obc= + + Resources/core/icons/cloud-arrow-down.svg + + 2Rsq7aINsR0+oclppZC3Mc7mLoo= + + Resources/core/icons/cloud-arrow-up-fill.svg + + N42b2HBwXpdrDer+vymloQNXSyM= + + Resources/core/icons/cloud-arrow-up.svg + + SmNNyZklvXYnp7RYVUNjlE7d+/s= + + Resources/core/icons/cloud-check-fill.svg + + DrCVA59PU+/dw4hsOIOSVn5bN+g= + + Resources/core/icons/cloud-check.svg + + cTFHnJxborW14rhh/pWTUeHmgps= + + Resources/core/icons/cloud-download-fill.svg + + bjZV7HMS4CAEUlozIflp0caFW5E= + + Resources/core/icons/cloud-download.svg + + Tawxci6U56VsCXxlyzUpOlHCvHc= + + Resources/core/icons/cloud-drizzle-fill.svg + + Xp3gumzTMSlUTHqMQ21q9X848gE= + + Resources/core/icons/cloud-drizzle.svg + + ysnjaroKEqZKkSIvpoHOrCtiCUw= + + Resources/core/icons/cloud-fill.svg + + q4nBpA1UpM3yi0RRMiefopdqb3w= + + Resources/core/icons/cloud-fog-fill.svg + + z1BNsUkXl4OQJALE1crLTXGAaBI= + + Resources/core/icons/cloud-fog.svg + + OnUs1Z/hZxorVCO5fn64YGT+QXQ= + + Resources/core/icons/cloud-fog2-fill.svg + + WIyH6/Xf8D+c5xsVAeWgoEEcCIY= + + Resources/core/icons/cloud-fog2.svg + + OPdA25c1N2ZiwJ52aTEebsR4kqU= + + Resources/core/icons/cloud-hail-fill.svg + + 2mcHAchTXziAIahoiBdLLsJJG5U= + + Resources/core/icons/cloud-hail.svg + + bml0gK912BxzpsedrSiwD/pjRLk= + + Resources/core/icons/cloud-haze-fill.svg + + Q8LRhpoCy2w5XjiN/q4mKH5VcEs= + + Resources/core/icons/cloud-haze.svg + + UlsaKhKYUEViKVhKto/7f0/IE1o= + + Resources/core/icons/cloud-haze2-fill.svg + + cpLZ2+r8oNTkrdHPc89lb/HLFoE= + + Resources/core/icons/cloud-haze2.svg + + DRJZNfVfzMQQZNPhtez+Mu9zFsw= + + Resources/core/icons/cloud-lightning-fill.svg + + UT8ANPQQ7USrJKoXdo5ioBq4gao= + + Resources/core/icons/cloud-lightning-rain-fill.svg + + JXs+w1mu76I2YM5oubmJBXXTkT8= + + Resources/core/icons/cloud-lightning-rain.svg + + E+0iJ8VqMEENxQbHGpFgeikvse0= + + Resources/core/icons/cloud-lightning.svg + + 7pK10Pn6zG/BrZOTrVu6GeFnIj8= + + Resources/core/icons/cloud-minus-fill.svg + + ikisJWbozm5UgTSOfSk4pLbKPzQ= + + Resources/core/icons/cloud-minus.svg + + v4w782F/Y3UOjGHKccnX6Bm4khw= + + Resources/core/icons/cloud-moon-fill.svg + + Bt4ySSzme1PnI8UEpEorLWg2c6Q= + + Resources/core/icons/cloud-moon.svg + + rQfBvZ+vu48axxv2INeAG/lyVGM= + + Resources/core/icons/cloud-plus-fill.svg + + kU+rJnQaniH7oLLyZtNcm/UI/hI= + + Resources/core/icons/cloud-plus.svg + + tGRl//Ty+UbFdY4vuvFTEv0KXJY= + + Resources/core/icons/cloud-rain-fill.svg + + mNnMHCjgS1ZmgeJezZCIDcAvHg8= + + Resources/core/icons/cloud-rain-heavy-fill.svg + + U0h5oqYFRUM2AHXoi7XQaWEzeRE= + + Resources/core/icons/cloud-rain-heavy.svg + + BVTFdTDD872WhD2NxEWQbIjBgfU= + + Resources/core/icons/cloud-rain.svg + + VS+1X6nvzqXffbNXH2Ojip3UBdY= + + Resources/core/icons/cloud-slash-fill.svg + + DQlYO6bNY73d2Np8glozC/peZ+Y= + + Resources/core/icons/cloud-slash.svg + + mZ/oId+H4X1gorDZe29CRvv67lw= + + Resources/core/icons/cloud-sleet-fill.svg + + GhCKa0nw9zWCf2uL27r8ne+KwLk= + + Resources/core/icons/cloud-sleet.svg + + B5XRpI+s13O5mfP4fP6DY1ibW44= + + Resources/core/icons/cloud-snow-fill.svg + + Ix86v+Q1jWnaNJJ8OI0Jp8XcDbE= + + Resources/core/icons/cloud-snow.svg + + lib43qY15RQsfBurN0oByqoq4Wk= + + Resources/core/icons/cloud-sun-fill.svg + + T7pPZfZRPtIMtcAkurn74DEYwVk= + + Resources/core/icons/cloud-sun.svg + + 7qNedgusFsPxgh5h5ewYoUpuB+g= + + Resources/core/icons/cloud-upload-fill.svg + + 9MoTqy9Mm7m9To7Vqy8Qi1No3e8= + + Resources/core/icons/cloud-upload.svg + + ET8mBi678Sgxq4WCjtmoAVVLgJI= + + Resources/core/icons/cloud.svg + + 0GStnPZ96YAx7X8jyDIPmaqnQ1U= + + Resources/core/icons/clouds-fill.svg + + PUt7dO0ZPrZpBje5sjJ97X5y/uQ= + + Resources/core/icons/clouds.svg + + KQJZL5seVnSPiusL7DrittSVkVs= + + Resources/core/icons/cloudy-fill.svg + + YinvusyFZCZOiiyuJGbbDjzUPYA= + + Resources/core/icons/cloudy.svg + + xIQq2FQ4G+gTw9RzuAqqeKR/grk= + + Resources/core/icons/code-slash.svg + + aIexDo+pBQNDI4mymDOYENXp/P8= + + Resources/core/icons/code-square.svg + + NYBQY8o3j5u4L/mBAMDJkNzW49s= + + Resources/core/icons/code.svg + + R3RzFMTTVYRtwaTrC2pj1UwgtF4= + + Resources/core/icons/coin.svg + + tHmBagjnSUl1BzzQm5x0UQfDmI4= + + Resources/core/icons/collection-fill.svg + + cTPmEBH5V3SesWREFKdZCJSRj/M= + + Resources/core/icons/collection-play-fill.svg + + tudb0+ByU6spFf7Bpdrs2xxmvc8= + + Resources/core/icons/collection-play.svg + + 0ksMwXs1hnC8R8l4/XMekVzi4oI= + + Resources/core/icons/collection.svg + + n+UR99UwkRKXov14z4qY5JaOldk= + + Resources/core/icons/columns-gap.svg + + 7wRHAc689IcQuik2g7EmVWMdBnQ= + + Resources/core/icons/columns.svg + + q0Vr5YuD1IwNGMsUp11KrBztdJM= + + Resources/core/icons/command.svg + + Vt+x11b7SpIo2YKiiEOsTQwpnYU= + + Resources/core/icons/compass-fill.svg + + LGnC+7Sp6uSRve8q8b2m5Bfg50c= + + Resources/core/icons/compass.svg + + NlHFFy4n6EiwVMHxwi4tbQa6S8c= + + Resources/core/icons/cone-striped.svg + + sHmejiqxn4odRywLmBbdLJs5Csk= + + Resources/core/icons/cone.svg + + hsMSYhnPCrfuzk0GUHfCuyHO2Fo= + + Resources/core/icons/controller.svg + + ri7noOLHBBm3SL0mxOJLaZoQf0E= + + Resources/core/icons/cookie.svg + + q2BCVOf+ttnGv5P0FcrubGTeM2s= + + Resources/core/icons/copy.svg + + MwbMtg2EG2HxgUtT7rqVtBtEzO4= + + Resources/core/icons/cpu-fill.svg + + YMIn5wVkzxompZ64JDeWUWd0k24= + + Resources/core/icons/cpu.svg + + iWXRURqNUMYv6Y0V0UOsvkpKXFM= + + Resources/core/icons/credit-card-2-back-fill.svg + + G6F3wBS+51okVU2zYlnn+zpX2M0= + + Resources/core/icons/credit-card-2-back.svg + + q62eScSacpq5XJ2qcDY95nWelt4= + + Resources/core/icons/credit-card-2-front-fill.svg + + RlSrTmU8O7oSw4lhyKtN52eV3xk= + + Resources/core/icons/credit-card-2-front.svg + + shJC5d8pxmI84+jJpLn9H0+0Dkg= + + Resources/core/icons/credit-card-fill.svg + + Qcr6SY/CmX6gxI7ESpTT29Cyztk= + + Resources/core/icons/credit-card.svg + + zuI0waG2XwRT8+n7zeJ2LL4QBSE= + + Resources/core/icons/crop.svg + + E9q5rU808x0MG+1C4cvCBWboInc= + + Resources/core/icons/crosshair.svg + + P5CAyfvg5RsnrXSMuRAqbb98K6w= + + Resources/core/icons/crosshair2.svg + + 5I/9KXjyiVe5vE3+fuSNwOiCADk= + + Resources/core/icons/css.svg + + AsjPXt0FeFxpFtQ3WlIKw+yd1L0= + + Resources/core/icons/cup-fill.svg + + c5rnzMUvYxLSgYv74Fr6TieDMDc= + + Resources/core/icons/cup-hot-fill.svg + + yvW7OIFKb1s/o4cn22SjhVc5naU= + + Resources/core/icons/cup-hot.svg + + n6Xd/PnCDiNgO1OStoBPWKFHkHA= + + Resources/core/icons/cup-straw.svg + + Ol/L2LgrujtEg88rbMvIKrEY1Yw= + + Resources/core/icons/cup.svg + + aooc0AJ6j6+o1dBHuBsLDOJDPu4= + + Resources/core/icons/currency-bitcoin.svg + + HEHY5BKjGHq1GYlynQm1De28xMs= + + Resources/core/icons/currency-dollar.svg + + SB6Z2WZRQeLpaNCoGS6GOKkzrQY= + + Resources/core/icons/currency-euro.svg + + x2rW3A+3CeD2UJ/9ZADdaarPUVM= + + Resources/core/icons/currency-exchange.svg + + yfjyLwGYEz0P1Wgbpwna8IFdJJc= + + Resources/core/icons/currency-pound.svg + + w6QThQOSgbm+hIr4fswX46o/g80= + + Resources/core/icons/currency-rupee.svg + + LgJfg3SgnNOLacBut6rp9TI4lYQ= + + Resources/core/icons/currency-yen.svg + + y4RewQGNFGZUsVMg2SftRgd1w3c= + + Resources/core/icons/cursor-fill.svg + + UyoUF9rtuQL8PBr4+4vDlknYHsw= + + Resources/core/icons/cursor-text.svg + + NMGaqKICt1+SQSzuXsWVCGGvqio= + + Resources/core/icons/cursor.svg + + Y+PlzaztxKmd2BctKg6pE723Yns= + + Resources/core/icons/dash-circle-dotted.svg + + WO3w1xK5sB+ZPgXfoa8e/cj9Dpk= + + Resources/core/icons/dash-circle-fill.svg + + IhgbExFMo3sNbSk3dOdgkR3OqQA= + + Resources/core/icons/dash-circle.svg + + Ss29CDZHp18uHQFkLkvyIl+Q0v4= + + Resources/core/icons/dash-lg.svg + + szm+GgGyLRu6s81A7ZSo2mGYeg8= + + Resources/core/icons/dash-square-dotted.svg + + Cc1uNRDA85NylBg5+GrE0QJuyVE= + + Resources/core/icons/dash-square-fill.svg + + zjWphIn6Z9tOGfxoq6wS0lqobv0= + + Resources/core/icons/dash-square.svg + + 066gTT34liI+XMu5TooWVUqdQlw= + + Resources/core/icons/dash.svg + + 0fyRf3RZ6In5eoBGgrNY+5IxjRM= + + Resources/core/icons/database-add.svg + + rJ5QzvdXt+aYv8dGkzLQ9DLLqmg= + + Resources/core/icons/database-check.svg + + 745+INBKmjWQfHojKAkLW1ydfHA= + + Resources/core/icons/database-dash.svg + + 2qVdfPgjpG0zMAGWPDQFMlOkuGs= + + Resources/core/icons/database-down.svg + + gdz3AtGUbrbVXsSQIHVemIUV/PA= + + Resources/core/icons/database-exclamation.svg + + kPNTitlv/aWQxoXJsZy1U+gfHes= + + Resources/core/icons/database-fill-add.svg + + IA+ZWnyks2HZhugnUsq4M5qIiZE= + + Resources/core/icons/database-fill-check.svg + + WDpHqjiRKwelsXquyTD7juzPlXY= + + Resources/core/icons/database-fill-dash.svg + + +4QRTBERrzQ4y+QVTdgx0kk4N7k= + + Resources/core/icons/database-fill-down.svg + + EF8TZpRGw58JLP89+YsYvv0sPRg= + + Resources/core/icons/database-fill-exclamation.svg + + 2JNtUF3oY8mZ092LBBmeKqzEcoU= + + Resources/core/icons/database-fill-gear.svg + + OqpY50qiZ4R2YxVRkxzQZ54Z/xU= + + Resources/core/icons/database-fill-lock.svg + + yG2s+2Ncwwu7fn+wubNKy7bqv84= + + Resources/core/icons/database-fill-slash.svg + + 7ob2rQIXxNZVMFG9l21ed0moHlQ= + + Resources/core/icons/database-fill-up.svg + + slqYnGvpnxXww8MwY1NQSzUvQFc= + + Resources/core/icons/database-fill-x.svg + + 4bivwp2xkO40Qvxqo9oNj1oB5lw= + + Resources/core/icons/database-fill.svg + + 62GJVluIfQKc/ypLSInY/cA93MQ= + + Resources/core/icons/database-gear.svg + + ZmG4/Ul4BdXe1vDgCPlY8xSfNow= + + Resources/core/icons/database-lock.svg + + kzoY1ix9Ku/b7sfqzmlsmO1SwkY= + + Resources/core/icons/database-slash.svg + + 8RjxBqKZlxOBqCLTrQECQf2XCcw= + + Resources/core/icons/database-up.svg + + n0S974FNPad7SCrRLaOQgol+G80= + + Resources/core/icons/database-x.svg + + jgMvgIfJxhojX+xvqNfzNNBojD0= + + Resources/core/icons/database.svg + + 7URyv64TnvfiQbAeGaOg3imQbbg= + + Resources/core/icons/device-hdd-fill.svg + + ykr1OGqzAomBEKgNq908JBaIfRc= + + Resources/core/icons/device-hdd.svg + + 038016D1nWxusBEPr0vWAzKchCI= + + Resources/core/icons/device-ssd-fill.svg + + APKlOGKJMMEI+vIRDeEc7iKr/1w= + + Resources/core/icons/device-ssd.svg + + gR3tCeZVh5YKd4oj+b3JZeHJkVI= + + Resources/core/icons/diagram-2-fill.svg + + RBiE/OKYfavZ+LvNTFOc9i9+e9o= + + Resources/core/icons/diagram-2.svg + + ThXOSZ9EI8yRMBPxhYzLu7DXyPc= + + Resources/core/icons/diagram-3-fill.svg + + egQ54ZdPWqnUeIc2qwAD+V6tajw= + + Resources/core/icons/diagram-3.svg + + ZigRWPXqGDPMjVLMKA/EaMr7ZCk= + + Resources/core/icons/diamond-fill.svg + + OKMmVm9Hvkig5lpzkNVnLHFEEdU= + + Resources/core/icons/diamond-half.svg + + kczNBsXR7xitKhcWxROIYQta4Cs= + + Resources/core/icons/diamond.svg + + FMPxfG2UAA0m1N640unKjIJFMPc= + + Resources/core/icons/dice-1-fill.svg + + weMKrhhyPETfqFKhsTnAd+j59/o= + + Resources/core/icons/dice-1.svg + + 6ewuUsQPI1afk2vqFsY+JJOiIEM= + + Resources/core/icons/dice-2-fill.svg + + HkPrlh0iEHonwfRyjHP0B8NO548= + + Resources/core/icons/dice-2.svg + + tkJid90bGsuAIywf7h1evQch3zY= + + Resources/core/icons/dice-3-fill.svg + + Cf+vKnclrme2hlcMPI1WUwA4A9k= + + Resources/core/icons/dice-3.svg + + H2c46fTYLzUszfolb4sGYgscgEY= + + Resources/core/icons/dice-4-fill.svg + + 34LeZr4nWSAIK/Ln3n0JpngEFU0= + + Resources/core/icons/dice-4.svg + + rRInT0feVRqDeZXlw6Ir/GAR44k= + + Resources/core/icons/dice-5-fill.svg + + dL1Oj72akg5nBopxGCUe3kgRBCs= + + Resources/core/icons/dice-5.svg + + yCQ1GZPnLq649Cwl9HmFlTK3VbQ= + + Resources/core/icons/dice-6-fill.svg + + SjDYIvubgDSktl5ZB0zv3NMhrlc= + + Resources/core/icons/dice-6.svg + + WzSHsNVXnwqnK77+ZCYpHTLncFk= + + Resources/core/icons/disc-fill.svg + + 2wkDuGBL/S/Uxy6oArJsXoicniY= + + Resources/core/icons/disc.svg + + viATwDw5es2yGW9FT/5wdOXPjYg= + + Resources/core/icons/discord.svg + + rR3vVUfR9D5EkRIwLkCJUF2T2xg= + + Resources/core/icons/display-fill.svg + + qljK9NM8U80xUna/qvCwd1iXYzg= + + Resources/core/icons/display.svg + + tlLzgEs7FJ5vAt4QqdLL+Z8d+lo= + + Resources/core/icons/displayport-fill.svg + + 0oKa4Ise6NO1SWljnqz9uvyHz8I= + + Resources/core/icons/displayport.svg + + SeavJ6yTIVY9zgBQNdKvblx846w= + + Resources/core/icons/distribute-horizontal.svg + + R6+0NJJmS03Vl9pCC5XazppJ3fE= + + Resources/core/icons/distribute-vertical.svg + + T9TxV5V+MeZTd9seyx/29XMj1vE= + + Resources/core/icons/door-closed-fill.svg + + CcxDmVIPsW5nJKV3tgjtvwVQbKk= + + Resources/core/icons/door-closed.svg + + CNImdpABOCfVecbP9PHEJQe/sZM= + + Resources/core/icons/door-open-fill.svg + + 5ANgDwxnFHrKknJ6FarUkZeF3Ys= + + Resources/core/icons/door-open.svg + + 9yqXmrKS+2EImIazN2CWaG/gFOs= + + Resources/core/icons/dot.svg + + sUQRPYQBFxrfHFyd7bCyT7kJk6g= + + Resources/core/icons/download.svg + + Kaai+b1Adqy9FSC4I2ZpBMOA6lo= + + Resources/core/icons/dpad-fill.svg + + Ywq6AjUpDyxoMtoF5ke1QiQTYLU= + + Resources/core/icons/dpad.svg + + +B8/3qIreRuiNx3EhgvzYOGp/kM= + + Resources/core/icons/dribbble.svg + + YZbA70LFB00mKT7yg8cXJpbd9eQ= + + Resources/core/icons/dropbox.svg + + fy5s7SVY014Sg9C6qH+f8ctH6jo= + + Resources/core/icons/droplet-fill.svg + + uklyUPxY5s/GSpHqDC1zCsQY/cg= + + Resources/core/icons/droplet-half.svg + + qzg3HnkYaqXzCaqchw8jJPOadBU= + + Resources/core/icons/droplet.svg + + DxMPM8Q+e2LiRoR6LmVMu82mJZw= + + Resources/core/icons/duffle-fill.svg + + X2I2fSg0k1gd6qdKoW4srkvO/J8= + + Resources/core/icons/duffle.svg + + x2qVl70+LptsP+qDfPvC1r4FHM0= + + Resources/core/icons/ear-fill.svg + + /DYs6xUCJoLcjMcQai1uHN0RUuc= + + Resources/core/icons/ear.svg + + YvCRnOMknUushFy4wU8y5I0kF5o= + + Resources/core/icons/earbuds.svg + + sbBWEIjirVodoVYOGf/7U0ej2TE= + + Resources/core/icons/easel-fill.svg + + 7yJlxqZVB5f3emytBeDzEhPKfto= + + Resources/core/icons/easel.svg + + 9OTYuo0uY+qfBDCI01tVLHbaMlE= + + Resources/core/icons/easel2-fill.svg + + FE4J9+BHckNpLjWUJ4eHQFm6/ns= + + Resources/core/icons/easel2.svg + + Lp3gW3TUh0aiwrfI1TZOCrozhbI= + + Resources/core/icons/easel3-fill.svg + + qdlWes3l0SAQ1e78ofLRDNAWYSg= + + Resources/core/icons/easel3.svg + + uIx9t/uqs8lP/w733/fzrP7QBd8= + + Resources/core/icons/egg-fill.svg + + 3ufsmi+QqJbjpmcx4Lo4JrWZQ5s= + + Resources/core/icons/egg-fried.svg + + d2D+3e7LTYP1Oh5qyFOIxI9MzQI= + + Resources/core/icons/egg.svg + + u+Fqu5GxHvNIeMwOpemeEfK4JL4= + + Resources/core/icons/eject-fill.svg + + p9zZN4OF835Fwo7qt5OU6foFA+E= + + Resources/core/icons/eject.svg + + t5Zl5kXQCcbbuiqcGKIX/xUC4WY= + + Resources/core/icons/emoji-angry-fill.svg + + EcQBUsOUd5237gRIscqFW//F2GQ= + + Resources/core/icons/emoji-angry.svg + + jZI7qUrVsydYoJPNGTGgZjkG9gg= + + Resources/core/icons/emoji-astonished-fill.svg + + 4k5LF+110SkHzKEvgLQ6QyqBH1I= + + Resources/core/icons/emoji-astonished.svg + + 5SxEKOAZ/cYU6EHF+wmtyQM2++4= + + Resources/core/icons/emoji-dizzy-fill.svg + + cxeRB4FQCyd1rfSh4hrJ0vZejN4= + + Resources/core/icons/emoji-dizzy.svg + + +Q6WQ6XIBq0oyQ4t/8UeUrT5nN4= + + Resources/core/icons/emoji-expressionless-fill.svg + + H91qKNn+/fvkKDy7IViGxl5Oofw= + + Resources/core/icons/emoji-expressionless.svg + + iN3fkh3o7PuxosSFBhQs2nGWcCA= + + Resources/core/icons/emoji-frown-fill.svg + + 2j2QtLiYpscCEQ07r8I7eu3Ny74= + + Resources/core/icons/emoji-frown.svg + + kvIw65HrDRnGF1NSzCmhmjJ6abM= + + Resources/core/icons/emoji-grimace-fill.svg + + dID6LqiasIgGKdn0ABDBmGOMO28= + + Resources/core/icons/emoji-grimace.svg + + 6A2LJMyWEDLINlhMTwDGJqigeq8= + + Resources/core/icons/emoji-grin-fill.svg + + LwKX/GfmzGIz8kMxycBaklOu6Lo= + + Resources/core/icons/emoji-grin.svg + + DLXlIkQyqFgNMeBH5Xk0x6PPr00= + + Resources/core/icons/emoji-heart-eyes-fill.svg + + crPp8yiYDQFlPd9/vKXcp5iQfEE= + + Resources/core/icons/emoji-heart-eyes.svg + + t5dSaN7Zs+jP4txtsbAAj5LHruw= + + Resources/core/icons/emoji-kiss-fill.svg + + evaUa0qRuo5IHDha3ej46ATlw2w= + + Resources/core/icons/emoji-kiss.svg + + bgaDAVUSCzjI8k/Uj7yTK1pyR7M= + + Resources/core/icons/emoji-laughing-fill.svg + + w1t7Pxt2H+ijRX33ESPO+V8hUNw= + + Resources/core/icons/emoji-laughing.svg + + c/C/kYuTyTyM/lhF3fTKNpRrKdQ= + + Resources/core/icons/emoji-neutral-fill.svg + + KcgI/gJd6H0PRIhA41vtCBm7nLc= + + Resources/core/icons/emoji-neutral.svg + + tfKWTTd6pLa9zQ2sbo1EVlxDXmo= + + Resources/core/icons/emoji-smile-fill.svg + + KmvFY5n8+T5I7Er9/D5bmClC/AA= + + Resources/core/icons/emoji-smile-upside-down-fill.svg + + p2aFWpVqLC5Br4dFwW0X7y+OUbg= + + Resources/core/icons/emoji-smile-upside-down.svg + + UNpy3+tfQ/DUwCIKswYECxWd79U= + + Resources/core/icons/emoji-smile.svg + + WW/0owNi+1cx4hdsFxUDPqv7thY= + + Resources/core/icons/emoji-sunglasses-fill.svg + + a04denLA6THtoR1STZcdrrgnv28= + + Resources/core/icons/emoji-sunglasses.svg + + HlYrVQ9+B4kJ/Zx4kKGW/ATDbgg= + + Resources/core/icons/emoji-surprise-fill.svg + + 39hZAryjXtpHLKaYUEScOI5Jr2s= + + Resources/core/icons/emoji-surprise.svg + + EbGpz7h1RXgekckRY8J62gKOYLs= + + Resources/core/icons/emoji-tear-fill.svg + + H5J4L0Hq1x87nFZGdZXwr9iv+Bc= + + Resources/core/icons/emoji-tear.svg + + KLSuo5ZeOCXo5pVABBbUGxMKe84= + + Resources/core/icons/emoji-wink-fill.svg + + 8fNda7MREnBpSbnypiMrrRVDmtY= + + Resources/core/icons/emoji-wink.svg + + JvjAHtXw0spJc4SJgeDWBABL6tM= + + Resources/core/icons/envelope-arrow-down-fill.svg + + Yj/xVhIzyaJYOyRCLrclhfronrA= + + Resources/core/icons/envelope-arrow-down.svg + + hyJCVtQMi+07c5LAL7fFsVsyKAw= + + Resources/core/icons/envelope-arrow-up-fill.svg + + MbaOxteAwfejwUbJJ7RjE6lwJGE= + + Resources/core/icons/envelope-arrow-up.svg + + OI+ILflBM6lu6BxIG5IcK3KcmUU= + + Resources/core/icons/envelope-at-fill.svg + + +Qb+21yskYJNT28JwuXDvPGx8s0= + + Resources/core/icons/envelope-at.svg + + jRB7QbUUOVHAawOUzLAPtBio8GI= + + Resources/core/icons/envelope-check-fill.svg + + lb9R+3ROGOrsK4cLqM6k9Q7IJh8= + + Resources/core/icons/envelope-check.svg + + 1b8kKN2RaUvFpf3gaEarm6PGDk8= + + Resources/core/icons/envelope-dash-fill.svg + + +w0b65+z2BE5PQmx+UDgXWB22ek= + + Resources/core/icons/envelope-dash.svg + + oxyRfJ/a+0K0dRj8jXdFsMZCen0= + + Resources/core/icons/envelope-exclamation-fill.svg + + /gENKjRmcEpQuPoOVlq73Te2DKM= + + Resources/core/icons/envelope-exclamation.svg + + wSohAPnzhBmJIrtylnIVP73zieQ= + + Resources/core/icons/envelope-fill.svg + + Dwn/w1LsNIH6q8sSb2Sth1aFoWI= + + Resources/core/icons/envelope-heart-fill.svg + + kxGlMmI9RnYLsUT3OEMDiOjbwks= + + Resources/core/icons/envelope-heart.svg + + A69zD7q9I2MuFDqxYe0dKRpsiw4= + + Resources/core/icons/envelope-open-fill.svg + + HP9QA7AhdAjIwBC7z1VM+uQvS1I= + + Resources/core/icons/envelope-open-heart-fill.svg + + qUGcm5jrqXV/ds5xe0PXUgoHU9k= + + Resources/core/icons/envelope-open-heart.svg + + J2aJuhNO7I1vToJJkUAXjWJR08A= + + Resources/core/icons/envelope-open.svg + + +rxaD3g6KfgUO5Ni1meelOVwa60= + + Resources/core/icons/envelope-paper-fill.svg + + iSusQFiUQETyVaoBE7tLZZSRV8Y= + + Resources/core/icons/envelope-paper-heart-fill.svg + + 3kA0gz790T3ZBmQIN/SgiMDUyx4= + + Resources/core/icons/envelope-paper-heart.svg + + uloJckqDyVyQRHe/zw4kOxFISSg= + + Resources/core/icons/envelope-paper.svg + + zRIumPDwfM1iRXfi+WSLM1f29pE= + + Resources/core/icons/envelope-plus-fill.svg + + U4yV5w37qvRKziboV1hOgAx+IQI= + + Resources/core/icons/envelope-plus.svg + + aXSzaPnj09wpzSn87Mb+uxKmlKM= + + Resources/core/icons/envelope-slash-fill.svg + + 0md7Zpoig3+4oydC+oNMqS5fWbI= + + Resources/core/icons/envelope-slash.svg + + 5jmAZwCiPcPAAYxKOAO6XfMqgxw= + + Resources/core/icons/envelope-x-fill.svg + + OkftbYoVtEFxmut8wf8qR7pTTNw= + + Resources/core/icons/envelope-x.svg + + mzbxETFodxAk0oSmAf+O+bOWFyg= + + Resources/core/icons/envelope.svg + + cJJZp00FMd/tH6hKU9occkPFrsU= + + Resources/core/icons/eraser-fill.svg + + L7jTk/3FYn51E8LiYhUMuAduj9A= + + Resources/core/icons/eraser.svg + + Ypt7uX+Gr1HdzeRYfYdMNy4R3iQ= + + Resources/core/icons/error.svg + + voMrPTl2xlW6ap53cehqkv0h+4c= + + Resources/core/icons/escape.svg + + 8pwT+MUnaP5KalXBnHnr+f93D28= + + Resources/core/icons/ethernet.svg + + 6PDYQqY0AJ4C/zIt64Rb6mBHnfc= + + Resources/core/icons/ev-front-fill.svg + + 3P7QhploeFuG/vr2V+FjupM3s2g= + + Resources/core/icons/ev-front.svg + + VogaVC4ToH/V1Lqi58QiFjfp6PI= + + Resources/core/icons/ev-station-fill.svg + + mUqJyg1hEHmgrtDXJWIZd12tKBk= + + Resources/core/icons/ev-station.svg + + 0wkrJl8UOfh01a13Kgj1TczklyM= + + Resources/core/icons/exclamation-circle-fill.svg + + FB0aFPpoFYbOXWhrOuzhKdOM3rw= + + Resources/core/icons/exclamation-circle.svg + + SBPPvzioSV53Q7n7wBwPcWaEEeU= + + Resources/core/icons/exclamation-diamond-fill.svg + + U2AILFzOrbp2cmM/K0SJ4pyYnZY= + + Resources/core/icons/exclamation-diamond.svg + + Sp8NJp0JjwgM3y5s9dnFq8HNvCA= + + Resources/core/icons/exclamation-lg.svg + + /z2Jw3AixJPbNFSKQVlEPbdTlLE= + + Resources/core/icons/exclamation-octagon-fill.svg + + UWS3QPL/POGCkNyPKTuoOiiJmes= + + Resources/core/icons/exclamation-octagon.svg + + luNiNDV6tR9KIBks5xiz4QhB5Wc= + + Resources/core/icons/exclamation-square-fill.svg + + enY51igAgVoroPvg77/BFwbJXqM= + + Resources/core/icons/exclamation-square.svg + + VxD8GdaWGl9AWaCMF+B0Pd7zbEU= + + Resources/core/icons/exclamation-triangle-fill.svg + + 4abBK//KyEzK6IHEE/1Ryy7Pv7U= + + Resources/core/icons/exclamation-triangle.svg + + 6HQQdShpxA1vUa8X/vg/Fwuu+lw= + + Resources/core/icons/exclamation.svg + + F7ja9XjglUf7dpW4+P8XMVL2fhU= + + Resources/core/icons/exclude.svg + + Fk+zmcPnYxCYTc8rYCIgpE4YlEI= + + Resources/core/icons/explicit-fill.svg + + lyVrBHnPWIOJXPQaLIGU5lRqGDw= + + Resources/core/icons/explicit.svg + + TdykmcW1Z1/JfcfUL1m4XSZj070= + + Resources/core/icons/exposure.svg + + FSesU6h1bO4HA0qB6z4lmOzpOTI= + + Resources/core/icons/eye-fill.svg + + 6yfSh/G1NXGzJ4qtb0P2NwrG91I= + + Resources/core/icons/eye-slash-fill.svg + + WAodlBWZDboxaYxrI2cpRJE0YJ4= + + Resources/core/icons/eye-slash.svg + + bPo+Pd+LnhMXm/HdksTVmsklJuI= + + Resources/core/icons/eye.svg + + dyBm96/2O+0sa00kqH0H25m6K60= + + Resources/core/icons/eyedropper.svg + + fp7s6tP0IKktLtb+p2sYoBvfOw0= + + Resources/core/icons/eyeglasses.svg + + AjYBtq4MLjdMwYPOmLxAi8f/bLg= + + Resources/core/icons/facebook.svg + + 9Mhey2eyjsKupsPa+OQCnNFhwwc= + + Resources/core/icons/fan.svg + + +kVsNGfleZ0nQsG0i1bswfGJT8c= + + Resources/core/icons/fast-forward-btn-fill.svg + + 3SN/2Lm6+tfNOxEl8F8i/tFj7qs= + + Resources/core/icons/fast-forward-btn.svg + + Rjr7WGLENonsdLfDzBIsj5s7xHU= + + Resources/core/icons/fast-forward-circle-fill.svg + + aOHx6TsPzhFWrwR0savEuFugFfI= + + Resources/core/icons/fast-forward-circle.svg + + m+FUsk5Gk48FrCB0JLoI305Xs1s= + + Resources/core/icons/fast-forward-fill.svg + + kt8A/EJpJs6YXu6/fXWGeiE7H3g= + + Resources/core/icons/fast-forward.svg + + e0mcV7GgZifrEkIvB43OGNEon2Q= + + Resources/core/icons/feather.svg + + a6+HQC3MQ88qNpvGoIrSjrbiXeY= + + Resources/core/icons/feather2.svg + + sP1AElYoiwHz1DqQ3+eRpbP31+s= + + Resources/core/icons/file-arrow-down-fill.svg + + ydj3ihr5G4sgEiGjtHWCSk8jkGk= + + Resources/core/icons/file-arrow-down.svg + + /7rARB+HEOTjTLweIGtdawlWcX0= + + Resources/core/icons/file-arrow-up-fill.svg + + dIbg+n4SljUlqZl0QHnMERb5DNU= + + Resources/core/icons/file-arrow-up.svg + + pByYmGYWWSaPZxyOnf3mimy4LSw= + + Resources/core/icons/file-bar-graph-fill.svg + + A+VEQRLG/Pc2Z+d//02Z0Rfn2a4= + + Resources/core/icons/file-bar-graph.svg + + mGTho8JzB/u0SoWPfQbwblRCAL0= + + Resources/core/icons/file-binary-fill.svg + + b/ZiMIfOyR7Ys0q62Vt11xlQSrY= + + Resources/core/icons/file-binary.svg + + IR9jeEZZouTBQDqUZgV9S0usiHY= + + Resources/core/icons/file-break-fill.svg + + MksX/KMCVGcOHnxz2te3r4nRn4Q= + + Resources/core/icons/file-break.svg + + xxBRSskUEGajTB6rkow2u/Y+Og4= + + Resources/core/icons/file-check-fill.svg + + zDVU/gR6y+scdDk4ujzjDTtuv50= + + Resources/core/icons/file-check.svg + + e9IK0oTeWtuDDCN536oGAOWuOUA= + + Resources/core/icons/file-code-fill.svg + + QKKnvZAbsiH8gEg1GC+hsucReCA= + + Resources/core/icons/file-code.svg + + aVmV9zCI7IpN/JgWnGe+JlS2dxE= + + Resources/core/icons/file-diff-fill.svg + + JOgtPsoB8SVfx3kzf3rj4D+4VCc= + + Resources/core/icons/file-diff.svg + + NKxvcUZB4NyrHn9vkMEcmT7VRn4= + + Resources/core/icons/file-earmark-arrow-down-fill.svg + + kSgLasVoVnMaO5vP5QjEkTX8dd8= + + Resources/core/icons/file-earmark-arrow-down.svg + + lU0AaBBm0kmA7lmqIFk7Iews3G4= + + Resources/core/icons/file-earmark-arrow-up-fill.svg + + 3LFcIJ369LAmD6hyuORQYnLCOhQ= + + Resources/core/icons/file-earmark-arrow-up.svg + + fO/xFfvGaaQ0/xWRUMWomP+fHQk= + + Resources/core/icons/file-earmark-bar-graph-fill.svg + + RxUU7ReNo6plXl6iIjaeFVSK/bM= + + Resources/core/icons/file-earmark-bar-graph.svg + + hgrcG/robrA5wb57KRlGOvQ5bZQ= + + Resources/core/icons/file-earmark-binary-fill.svg + + iKtHrUktGVVdOtxDv7xwB4GHfZk= + + Resources/core/icons/file-earmark-binary.svg + + BKnCd+hR9lRaEEeEruCw+1xhFcA= + + Resources/core/icons/file-earmark-break-fill.svg + + g5klBMBrjBFSYco64uZPgrnBBIs= + + Resources/core/icons/file-earmark-break.svg + + MlZG4aAUIlokHE59a2qi7wbVGuI= + + Resources/core/icons/file-earmark-check-fill.svg + + o9fhbmv0oJUv8/T/shvon/gQYTY= + + Resources/core/icons/file-earmark-check.svg + + VaeWGUbDh2MsiiOSdPHtSIAktFo= + + Resources/core/icons/file-earmark-code-fill.svg + + Naox1vC8GGMgJwI2GeHHp3f0Sqg= + + Resources/core/icons/file-earmark-code.svg + + jI8XTgCRRMsfzhqryKp1GB+DzaQ= + + Resources/core/icons/file-earmark-diff-fill.svg + + JCdDYooMobgpUALP5BuHhY6+nH4= + + Resources/core/icons/file-earmark-diff.svg + + t95pvVDKXsSMXO3p2rAuvfxZ+JE= + + Resources/core/icons/file-earmark-easel-fill.svg + + BBjN4ZBPvxJUY9BaiEP8yemnreE= + + Resources/core/icons/file-earmark-easel.svg + + n6w/iWapdlJ8QBXV8d6yiQHAyIk= + + Resources/core/icons/file-earmark-excel-fill.svg + + qHhLbMYPbOaisAt04npdu6JrTkY= + + Resources/core/icons/file-earmark-excel.svg + + I02IdaUWhPABuOy4r1X+qQBSm9Y= + + Resources/core/icons/file-earmark-fill.svg + + 0qCl7Y8p9A5tEH6Y7FFunI06ow0= + + Resources/core/icons/file-earmark-font-fill.svg + + 5akW2XLEPyjMGZL5/PbjsdCNEOw= + + Resources/core/icons/file-earmark-font.svg + + coxk9t28plxuClQUQy532F7Gx40= + + Resources/core/icons/file-earmark-image-fill.svg + + oRYYnsySVltnTWqGaYb8wHtk7zM= + + Resources/core/icons/file-earmark-image.svg + + im1NjOct/GJdilYFVogQGCw1jcc= + + Resources/core/icons/file-earmark-lock-fill.svg + + fh8N7cZK08CdcrTmP+MUDQbNVbE= + + Resources/core/icons/file-earmark-lock.svg + + dtLF3mBgp1xc0dM1bBdE36NyJw4= + + Resources/core/icons/file-earmark-lock2-fill.svg + + YTA3CHj3xxKGmPHVnlUBaZx4gDA= + + Resources/core/icons/file-earmark-lock2.svg + + aZj3Pko/geKqesbH3itEm1uCMjI= + + Resources/core/icons/file-earmark-medical-fill.svg + + ZDmjYAgZ6W59GheQumYnoUoHDhY= + + Resources/core/icons/file-earmark-medical.svg + + iiU2BgkoLPePZ7nnAaNqOx0h4k8= + + Resources/core/icons/file-earmark-minus-fill.svg + + LU1zS1EhCYVfIqDXQ6aZ7i82Io0= + + Resources/core/icons/file-earmark-minus.svg + + PQsc4v34F1Cwl1/iz54Nirna27s= + + Resources/core/icons/file-earmark-music-fill.svg + + Xvn+3lWRaEPWlWHZGe8CAcMAVJs= + + Resources/core/icons/file-earmark-music.svg + + stGB8VmTBmqQeJx+Enukydp8IkI= + + Resources/core/icons/file-earmark-pdf-fill.svg + + QZNm50RRC5vk0qcuk0lJFI+m7Hs= + + Resources/core/icons/file-earmark-pdf.svg + + pvI9lV+boK42uYcy5TEr72JFPGs= + + Resources/core/icons/file-earmark-person-fill.svg + + gpj1TtrPkwU6kRm1mhJLUYn7dtA= + + Resources/core/icons/file-earmark-person.svg + + GPYAeEWkH6B5D7Y+qwdSJqeHJGE= + + Resources/core/icons/file-earmark-play-fill.svg + + vk7QeWmqxsUyW/2al8FCx6K4hbs= + + Resources/core/icons/file-earmark-play.svg + + uqjrFfV05NyzW24zTWzpNbOLuRE= + + Resources/core/icons/file-earmark-plus-fill.svg + + tTZKj55Oine7jYV49YU3gGmzZXE= + + Resources/core/icons/file-earmark-plus.svg + + k4TwJ8r1M55PJvboBGBOfbdjIb8= + + Resources/core/icons/file-earmark-post-fill.svg + + 5CAk5Qn+OFnQzydy/eJ8+f4i5x0= + + Resources/core/icons/file-earmark-post.svg + + 01k59IftFkHhu33ZjIheXgrm0PE= + + Resources/core/icons/file-earmark-ppt-fill.svg + + bgtEk0K4KnJd/RbsRxFEmdbvXEo= + + Resources/core/icons/file-earmark-ppt.svg + + 7LP1DaENcpx+QI/+wNOGPh2DmLo= + + Resources/core/icons/file-earmark-richtext-fill.svg + + 8BJ4PNxRpM5ARJjP5niCFQBo0O8= + + Resources/core/icons/file-earmark-richtext.svg + + Mco4QlDoDtUKrZIraq5jSy/xIJA= + + Resources/core/icons/file-earmark-ruled-fill.svg + + 8gjd+T4ZkwhJcpZmYmdMsAoW4pg= + + Resources/core/icons/file-earmark-ruled.svg + + WKcaNHkev4fwysisYPU1u7zatAU= + + Resources/core/icons/file-earmark-slides-fill.svg + + 4Q6QEQAC9WkormZJ9bY43fft+cA= + + Resources/core/icons/file-earmark-slides.svg + + EoZJgke5iDwD4PufOLxA9iC6Xh4= + + Resources/core/icons/file-earmark-spreadsheet-fill.svg + + i3e7k5mvTwCfhxrteyZQa9tm03M= + + Resources/core/icons/file-earmark-spreadsheet.svg + + Kx+x3bLZ7u/ff6bjBoCKUM8ctaU= + + Resources/core/icons/file-earmark-text-fill.svg + + oI0/kvyzMGuy8Pdaf8eevL6RXq0= + + Resources/core/icons/file-earmark-text.svg + + 2ZWEJHOi962ISePCQm3sPDP/LMI= + + Resources/core/icons/file-earmark-word-fill.svg + + gFx5KjD2ZKv4uz988C4U08DS2MM= + + Resources/core/icons/file-earmark-word.svg + + pyfdZDJSWLhCbQOS804ZRNaRw0k= + + Resources/core/icons/file-earmark-x-fill.svg + + WCoyI2LIa7/kxno51kVU7Fp3//0= + + Resources/core/icons/file-earmark-x.svg + + qYfsigtL6wRuDI87jITJbN9/E88= + + Resources/core/icons/file-earmark-zip-fill.svg + + YGfD4IVTUFvkpokkp8daq2yb2nk= + + Resources/core/icons/file-earmark-zip.svg + + xvCh0KdfboVapVZyKZ51LA58aPw= + + Resources/core/icons/file-earmark.svg + + V8N4+gvZMZX9XhqLmEuJwnFEA60= + + Resources/core/icons/file-easel-fill.svg + + YfW6LTmlnb7dLd9FdXMUc/FSlwA= + + Resources/core/icons/file-easel.svg + + gGQbb/aHuxt0Cuo7TEqHp3MmxKc= + + Resources/core/icons/file-excel-fill.svg + + BT31yQRb4eUfapOMoM742WbD9Uk= + + Resources/core/icons/file-excel.svg + + xetugRhlZyr5C9wwct8YpQT+xqE= + + Resources/core/icons/file-fill.svg + + YYhQeR4NuJkcGeFi317jcSG15tQ= + + Resources/core/icons/file-font-fill.svg + + hg3BDEPfRMXFgjAXVf/reeEincs= + + Resources/core/icons/file-font.svg + + WWf9YJkkujMPq7+QNI7C+1oPzVI= + + Resources/core/icons/file-image-fill.svg + + kSAE02lmYmqpjb54Ju6dVYcUD68= + + Resources/core/icons/file-image.svg + + ICUoKsyFl53Oth3jpRXGh90NwCI= + + Resources/core/icons/file-lock-fill.svg + + t3Xoe8ZoPnvtAoHOWFznWQacP6M= + + Resources/core/icons/file-lock.svg + + 64UpSzJwM7ufWxKjfXGvj6HmglA= + + Resources/core/icons/file-lock2-fill.svg + + rkm6sqon/RsPSdeQ3zxXzwgPcmk= + + Resources/core/icons/file-lock2.svg + + 8kejkAq6LXwJDPZynnX9V02ls44= + + Resources/core/icons/file-medical-fill.svg + + mh+tzcPrLP3jYjzNZ4LZcZdjzV8= + + Resources/core/icons/file-medical.svg + + 0TmES/w7MlrXhNrEn5uAUSYhQe4= + + Resources/core/icons/file-minus-fill.svg + + 5g9/B+2HB5xoYPbo6XNLoADCXos= + + Resources/core/icons/file-minus.svg + + TykECxQrIzdgrE458CXQavR3Ge8= + + Resources/core/icons/file-music-fill.svg + + u9SjPfg6cG0LE5+SOkoTHy31odA= + + Resources/core/icons/file-music.svg + + u7zawvnYKnlBljxI4sKy+IxPtFo= + + Resources/core/icons/file-pdf-fill.svg + + fhYpBUS/yb2+7tDuMFVyhckBuhI= + + Resources/core/icons/file-pdf.svg + + 1ApJiBTG9hvp/laEiMr6qk/T8kg= + + Resources/core/icons/file-person-fill.svg + + x7Pdhm0GGflwH53D8ueMPAnrVZc= + + Resources/core/icons/file-person.svg + + cAjRYS07VKH7DhL0xJPdGgLn7IE= + + Resources/core/icons/file-play-fill.svg + + LCCdJe0KC40VO4PBx9F/z3YvnL8= + + Resources/core/icons/file-play.svg + + eikpFuELTr6lWHaiUAY3ZJ4XCUg= + + Resources/core/icons/file-plus-fill.svg + + K4F7y4tlyt0BayJh/m63mI03+ko= + + Resources/core/icons/file-plus.svg + + 9fOKoJnCr+RMQS8YtY9Uc4+MJ/0= + + Resources/core/icons/file-post-fill.svg + + 5TBbNrXEap7X5JI2I5+r+HIp6wQ= + + Resources/core/icons/file-post.svg + + BIDpdSn56eEecQSaoxgPsGWUlSI= + + Resources/core/icons/file-ppt-fill.svg + + AhAg4fkLV7LM4uhbjp6gbe5JmaU= + + Resources/core/icons/file-ppt.svg + + jHIy8kr2Kbrh9ktdFkRsniyZQhU= + + Resources/core/icons/file-richtext-fill.svg + + /6DI42VLIQB2E3ywzrzLFR4uB+Y= + + Resources/core/icons/file-richtext.svg + + B/Ket8sPyqxl62hs7BkFVi82QRE= + + Resources/core/icons/file-ruled-fill.svg + + 1VQ0W6YiTNU+GECdBuK2P0cA7R0= + + Resources/core/icons/file-ruled.svg + + IYwBp3g8iaQ3GkvAs7QcoRTYQBw= + + Resources/core/icons/file-slides-fill.svg + + TGSX/PRxhQZk5BhgufkbBjmHw0o= + + Resources/core/icons/file-slides.svg + + HdGrT/MR3um1mhXOIbesEPWF4ew= + + Resources/core/icons/file-spreadsheet-fill.svg + + MlwECx3xWDGf2svGP3phOrZCccc= + + Resources/core/icons/file-spreadsheet.svg + + GgvFHIqrX34RCsfNWC3IS1arvkk= + + Resources/core/icons/file-text-fill.svg + + 302/AEauRp1Qf/cD65kpaOAl7O0= + + Resources/core/icons/file-text.svg + + KRxXMEbzIFi89L8JJcrx4ocj7dw= + + Resources/core/icons/file-word-fill.svg + + q0vm5/ilpvHo6ZHJPCic7IP+iZ4= + + Resources/core/icons/file-word.svg + + KRWiIJHellC6Gc+2+gUV4GwJFWA= + + Resources/core/icons/file-x-fill.svg + + 9b6SO3xRBbLQTA1R9Y6NxeKwG/Q= + + Resources/core/icons/file-x.svg + + Ah9lQ6X925wEgimls/GZpg9etC4= + + Resources/core/icons/file-zip-fill.svg + + EtcLFYc+5bneLsSAPucfXI+Gs00= + + Resources/core/icons/file-zip.svg + + RAPwERDtB6eO86M8Fp0mrjmErJ4= + + Resources/core/icons/file.svg + + 9x1mZ6znu56ElNLxGWS1gHgNMQc= + + Resources/core/icons/files-alt.svg + + EtOOV7jmLwUtEmf35PONrcuT8Kg= + + Resources/core/icons/files.svg + + 0aBXDz96RJkRRtcoU9L8m19OEZ4= + + Resources/core/icons/filetype-aac.svg + + AYIuxQ+JssAujG3R/XAHViYO9qo= + + Resources/core/icons/filetype-ai.svg + + DjRcqSHjZtvMvgqj0RpcsD6HL8g= + + Resources/core/icons/filetype-bmp.svg + + XgGCJxcHuH3D/xc1aGCIEzltGTU= + + Resources/core/icons/filetype-cs.svg + + Jmen/YdH77SDmoTCIYb/IH5v+CA= + + Resources/core/icons/filetype-css.svg + + dMkCrS5d/KOv0aapW+SXVqPmqfs= + + Resources/core/icons/filetype-csv.svg + + k9CK/oupW+VPgsbpxoJh8CuFmc8= + + Resources/core/icons/filetype-doc.svg + + mMFVvylRgBRfxs2wbYzf0vuQMj0= + + Resources/core/icons/filetype-docx.svg + + DNQCt4HOgmtrrJHddL27Y6KDw20= + + Resources/core/icons/filetype-exe.svg + + B4QuwKd2whIALZyDVlvie7oBH0w= + + Resources/core/icons/filetype-gif.svg + + bpQtV3iF0rVvAe/y+lKXmzkXIdU= + + Resources/core/icons/filetype-heic.svg + + TJcl416ep8N2g2OeQ2UGs3XphLo= + + Resources/core/icons/filetype-html.svg + + HtnyKjaAOAO7Ncf+FjejaUA9DlI= + + Resources/core/icons/filetype-java.svg + + fPcZ+sPs6D2EM+k/UxdN+Xrkvf4= + + Resources/core/icons/filetype-jpg.svg + + wr3Q7ec/f8h8tJ5QpoL0kY8oGRs= + + Resources/core/icons/filetype-js.svg + + 0UWhUSZlGYciNDfbY756RLqRfxg= + + Resources/core/icons/filetype-json.svg + + zgij4uKQRm/hbJCj7fpyiA8s5jo= + + Resources/core/icons/filetype-jsx.svg + + zRuJeRVejCxanTc8LBQ+jGHSslQ= + + Resources/core/icons/filetype-key.svg + + 3oVclA8uwEniGHfnyCePgx5DbXM= + + Resources/core/icons/filetype-m4p.svg + + JclbxXjW2evKUEECHOEuYbPgN4A= + + Resources/core/icons/filetype-md.svg + + XZzTJnXrEkORwpKDvs7qS87IS8I= + + Resources/core/icons/filetype-mdx.svg + + vPY+V1Vw3fmAhto3voUSNg2VU6Q= + + Resources/core/icons/filetype-mov.svg + + +3Bsdhb9ICD3Jy193X0OGsYTVVg= + + Resources/core/icons/filetype-mp3.svg + + 4AmFtPYatShfnE49zIE5pQHMgOQ= + + Resources/core/icons/filetype-mp4.svg + + WqJ4UzHxFkji6itxVT7FclB1ecE= + + Resources/core/icons/filetype-otf.svg + + yaKRWCS9YI7X02Hy6Sf51t4Syks= + + Resources/core/icons/filetype-pdf.svg + + TMuUIXqiPnTnpIqMbnWGtUqkqLw= + + Resources/core/icons/filetype-php.svg + + Z5LdZQh4b9Wa5rKA4DCWgNuKphc= + + Resources/core/icons/filetype-png.svg + + NRFx4rmk5ZYN3bTXZmebW94QynQ= + + Resources/core/icons/filetype-ppt.svg + + KzJl26k0mdViH56rijcyZpNx/7U= + + Resources/core/icons/filetype-pptx.svg + + FwSH4D7ZRBM0LNcALMsDsgKR6kI= + + Resources/core/icons/filetype-psd.svg + + 3ghhT86ksTHB8fUY+oAgpymwQz0= + + Resources/core/icons/filetype-py.svg + + A/YYUcAXdIJcG+eHBvEsp9sAAHA= + + Resources/core/icons/filetype-raw.svg + + iGtO2+cS5eOwiuFqKGFV/LHAFL0= + + Resources/core/icons/filetype-rb.svg + + LFay7PcP7ZNgYmhHwf9SSXQ8JT0= + + Resources/core/icons/filetype-sass.svg + + 3FVojLT1ae+i0BV0g2LZu+t115w= + + Resources/core/icons/filetype-scss.svg + + UYWbVmobGR5qSvs1mmvF1kLJhSk= + + Resources/core/icons/filetype-sh.svg + + COsKnsIa9S1FwTTlE7dBQh0Kbvs= + + Resources/core/icons/filetype-sql.svg + + JEHq2vvRVf5PtMGjSssz4r9Uivw= + + Resources/core/icons/filetype-svg.svg + + 3GaT5nHyEkDmqw8U3pda90P0CwI= + + Resources/core/icons/filetype-tiff.svg + + ZvYqJxzZyqstjvxKovaLxncHQlw= + + Resources/core/icons/filetype-tsx.svg + + JI9K+t7dnKp9iEUUiPsxjD2x+24= + + Resources/core/icons/filetype-ttf.svg + + 4O09VegioVsiKeBOz/XN4EzydTY= + + Resources/core/icons/filetype-txt.svg + + p0yX+3E3bDX2dqiTdvnuuvHYF4w= + + Resources/core/icons/filetype-wav.svg + + 98Lnad2i7qg6AOeeclzg+vKmdmw= + + Resources/core/icons/filetype-woff.svg + + UPJihLrJ1lgGVVOieG0AyK4Dc0c= + + Resources/core/icons/filetype-xls.svg + + U8hR7X7aKwW27ELr7cAw14bdkws= + + Resources/core/icons/filetype-xlsx.svg + + 7lwaR65CW26IMD7j1nPCnfvf9UQ= + + Resources/core/icons/filetype-xml.svg + + ciXtsmn+IUbogwZozHBJpce1hbs= + + Resources/core/icons/filetype-yml.svg + + NL8+q+gwk+i5RUa56LzLeLqt+jA= + + Resources/core/icons/film.svg + + PDu/JDoYGRc4xSld+P2F+OIKqhs= + + Resources/core/icons/filter-circle-fill.svg + + 9Oi2+uv2MKUB2wIy+23bQ8Ox/Gg= + + Resources/core/icons/filter-circle.svg + + s+1lhYNba79Qp+seFnh/DwWcuIM= + + Resources/core/icons/filter-left.svg + + P0Z6hwJ6X9IOnZBGJ7j+zmq0mUE= + + Resources/core/icons/filter-right.svg + + krtYnZKhaVJPH8EUyta2EpEP654= + + Resources/core/icons/filter-square-fill.svg + + 8Xo2T+MpCUhWwLarup6+3myPhgk= + + Resources/core/icons/filter-square.svg + + cWs275EaCL1Y8XS7OoPI7ehu2Yg= + + Resources/core/icons/filter.svg + + OiFK0YYvtN2AG840zzyorj0j6/U= + + Resources/core/icons/fingerprint.svg + + SxN5EEYglQmvnSv5ZlyaJp2njhk= + + Resources/core/icons/fire.svg + + 7xdLVnjfnC6PTS2ScnFCpusICr8= + + Resources/core/icons/flag-fill.svg + + OSl9RwOtUckl+08k7DBtUqBX0+c= + + Resources/core/icons/flag.svg + + 6iPPq0XO5ZYw9tnhpWKltpFoyLI= + + Resources/core/icons/flask-fill.svg + + 7hwnZK1zAMn6KAJqBZnoZwdPONY= + + Resources/core/icons/flask-florence-fill.svg + + 8f5jrhn2EzFvceNn8WN8QzpXyLk= + + Resources/core/icons/flask-florence.svg + + d4ScDKjVaWNBTtgYAjH9WYp0/r0= + + Resources/core/icons/flask.svg + + HFa53V2MQIfukkukLPVm/mDngDM= + + Resources/core/icons/floppy-fill.svg + + SKl3I+Fj50w+TfHmxIEMFPUcSss= + + Resources/core/icons/floppy.svg + + qOp2cyczAG+ZYdeDcRBM+lPl0Hk= + + Resources/core/icons/floppy2-fill.svg + + P6gIdowoBOUYwz2leUDZQCBiSWA= + + Resources/core/icons/floppy2.svg + + WyRjB0tLQj+0kpAGDMDruvJMlDY= + + Resources/core/icons/flower1.svg + + 4j1yoUtz9KZ/Vsx1N+OaJP70/3k= + + Resources/core/icons/flower2.svg + + dQpNgrjm3lfQv54oJgae5lXsgDc= + + Resources/core/icons/flower3.svg + + ig4QCvO1otZF365LgyYx8rfSoSU= + + Resources/core/icons/folder-check.svg + + IzLG5lWPw8SmdmmHp0bBhT1F9Kk= + + Resources/core/icons/folder-fill.svg + + yVI+wqtB4xESGI47DfVz0KJxEZo= + + Resources/core/icons/folder-minus.svg + + 2aBnppazaszHgkrgTgvBIC4IsJg= + + Resources/core/icons/folder-plus.svg + + 00GP7sFykG3icby3MCQPH+8P/ac= + + Resources/core/icons/folder-symlink-fill.svg + + JZ8O2NKK8appWNiC2qIqV/L+vL4= + + Resources/core/icons/folder-symlink.svg + + F4tykA5fbD1zJ/3T/Fsq93n6Kk4= + + Resources/core/icons/folder-x.svg + + t1Sw3POPL0rfVabI/Ao9PLs2FDk= + + Resources/core/icons/folder.svg + + qWWEnRvoMJ8pQPsnQZZPCttkSuU= + + Resources/core/icons/folder2-open.svg + + 2fIbLalG286JALMRLL3UIfMRFQI= + + Resources/core/icons/folder2.svg + + ksQ6R+9jD2Qyk0Z9FctVNhKY6MI= + + Resources/core/icons/fonts.svg + + M/3G+J+AVmwa6r8BXkh8oDVhXK0= + + Resources/core/icons/fonts/bootstrap-icons.woff + + diAQx5tKBeETH8j7Oxrv8yTYAz8= + + Resources/core/icons/fonts/bootstrap-icons.woff2 + + tEH8/5OeJPoJBqN7d4h4i5/du2g= + + Resources/core/icons/fork-knife.svg + + w8Oo5QddcwpOsiADaqLcfP9yusY= + + Resources/core/icons/forward-fill.svg + + Qi6ITVB6U6XRpLnWzVRXXlM9TxA= + + Resources/core/icons/forward.svg + + 2RLaJ1pGhv/ygPrhqC0nCVPFem0= + + Resources/core/icons/front.svg + + 9XiWl8Jz4W2oq+eP8yRpVbWkMlw= + + Resources/core/icons/fuel-pump-diesel-fill.svg + + 7EDmQPHDGtnyJTBLjkgJ6+goQuQ= + + Resources/core/icons/fuel-pump-diesel.svg + + EHFJ/DXCPhfZ+TEJmlxhqBT0ncM= + + Resources/core/icons/fuel-pump-fill.svg + + lMpkYiCt6sM8MrGczN3PrUoylfw= + + Resources/core/icons/fuel-pump.svg + + LcvSwXc/rgX2OHa9YSsjlgx9svo= + + Resources/core/icons/fullscreen-exit.svg + + 12H2P+3P57/BX23RUFLPKqKtoSA= + + Resources/core/icons/fullscreen.svg + + GUb+qjck7NN7cO1tjRwkovfDl6k= + + Resources/core/icons/funnel-fill.svg + + 3ulztOmJjN2JqaxT5q5Xhu0XuH4= + + Resources/core/icons/funnel.svg + + XtHzrELgB/4rqj6ca2yf5qp0180= + + Resources/core/icons/gear-fill.svg + + cfQN74ac4X/TtXyQQ0ZRymONjLs= + + Resources/core/icons/gear-wide-connected.svg + + Of20HusDw4BaYJLePSKnLv+ZVSw= + + Resources/core/icons/gear-wide.svg + + OzFv0Ibb2MgJfcG6UBhTuc/gAkA= + + Resources/core/icons/gear.svg + + oZ8vZOBA8E39oI6I2nSGKwZQhtM= + + Resources/core/icons/gem.svg + + 1oM7MnVa1rdbkXJ2vFcRDQJtwco= + + Resources/core/icons/gender-ambiguous.svg + + eTaA7o1RPbARKQbTjc7JEZmdPXA= + + Resources/core/icons/gender-female.svg + + juTv1Wf2Ef18mHU/aEPKpvRIJpM= + + Resources/core/icons/gender-male.svg + + DWZFLP6Lzd4aqTW899Dbnmis8dI= + + Resources/core/icons/gender-neuter.svg + + bXhMXwdSMYdRczAbvwqGmK1sAEA= + + Resources/core/icons/gender-trans.svg + + HeJNQx01Sg3KVw8uvQ183GvGm9M= + + Resources/core/icons/geo-alt-fill.svg + + hOCEuFdYmdFXrguM+Hc8F4IaT3I= + + Resources/core/icons/geo-alt.svg + + xQRdJWOb4qPoSgVWdIP5ONHgvWk= + + Resources/core/icons/geo-fill.svg + + XkdnLivH0jPcMJM5D6JAMHfwcW4= + + Resources/core/icons/geo.svg + + ThDKeZIplyLzFaM0UYpjecKQZ74= + + Resources/core/icons/gift-fill.svg + + J4AggNfQnOwBdnjoor5Pf7qZpos= + + Resources/core/icons/gift.svg + + uteVJmSomWJXDNHf1y5FwS6DuL0= + + Resources/core/icons/git.svg + + We4hqUn+/JSh5LjBw2cuNZ+ghcQ= + + Resources/core/icons/github.svg + + urUkkucd2vV7s/KfGPckU6azWtY= + + Resources/core/icons/gitlab.svg + + rT2GUnwlW7WQ7UJa/2Y/hQuA0SI= + + Resources/core/icons/globe-americas-fill.svg + + GLcqLZ81BvOSUPBPqUL9GH2Hbp4= + + Resources/core/icons/globe-americas.svg + + IfFS7PBM10wkBpTvKg75Jx4ohM8= + + Resources/core/icons/globe-asia-australia-fill.svg + + GS+UqedtFj1Q0TGPREz9ysiwKZ0= + + Resources/core/icons/globe-asia-australia.svg + + yyzV/4BT0KFwqJzFD4xJLaVZvMc= + + Resources/core/icons/globe-central-south-asia-fill.svg + + gEEYx0Bb/Zzgm6agh0LEIkncmfI= + + Resources/core/icons/globe-central-south-asia.svg + + XbCq6Z3VYMBZTNku9ci2E3uUgrE= + + Resources/core/icons/globe-europe-africa-fill.svg + + ysqHNBpAm516++UB+dJhT2WWeno= + + Resources/core/icons/globe-europe-africa.svg + + GjH/qUMtS7SqalRSPOB1UtrAlSU= + + Resources/core/icons/globe.svg + + 0tzTRmNMmf4p7swpLnOM7sTRjeo= + + Resources/core/icons/globe2.svg + + SguxVyqhdndXmZs8GooelHwcKW4= + + Resources/core/icons/google-play.svg + + ykPMTmgAeJksnepbjqC8Obp9oyM= + + Resources/core/icons/google.svg + + 3zn8ptQp0WKdqXvT+S25kBhKHsY= + + Resources/core/icons/gpu-card.svg + + CraVoVr4GyMkXTHOjyGhPraBcD4= + + Resources/core/icons/graph-down-arrow.svg + + CChCiQoe3poo2g/6KENvhURHCwM= + + Resources/core/icons/graph-down.svg + + g5I9bPgRUMVJBgUgbCF+rjk23Ig= + + Resources/core/icons/graph-up-arrow.svg + + O8q17I8xoll5HQ2zJd6SfcKyscQ= + + Resources/core/icons/graph-up.svg + + QueLGA/mQsMz0LqWKQV2hvXKUGg= + + Resources/core/icons/grid-1x2-fill.svg + + D5tWfA7Yjvs+9lUMtz1yD0oud5w= + + Resources/core/icons/grid-1x2.svg + + DhYSTYDOMvfYVKeW0yojOQ1c+zk= + + Resources/core/icons/grid-3x2-gap-fill.svg + + 62dqm3NXEzVebVAMxp+S8bzE3DM= + + Resources/core/icons/grid-3x2-gap.svg + + XwHHHe3q9Ur+Z14t6p3pwSgeDes= + + Resources/core/icons/grid-3x2.svg + + EV5CWavTAr2XFJMA379T2DPT+Hw= + + Resources/core/icons/grid-3x3-gap-fill.svg + + NxkhNcq0Eh3l64uyyVMtlg0fkB4= + + Resources/core/icons/grid-3x3-gap.svg + + I+/6YVWBJJNfY/lWKmTKkMQ0bAw= + + Resources/core/icons/grid-3x3.svg + + PhUyP+DuYrYUbZZERAouw/vSxq4= + + Resources/core/icons/grid-fill.svg + + jJ+4KHGAZupVwpPce35RAmq3nEQ= + + Resources/core/icons/grid.svg + + 5wKez8UEdNNEXwtZLG8NuHD1skI= + + Resources/core/icons/grip-horizontal.svg + + bSROEaTCwjXelPL0nVcyOR9Pt2E= + + Resources/core/icons/grip-vertical.svg + + Sgy8ImzeOAeRBzYs1QSPwpYdDSs= + + Resources/core/icons/h-circle-fill.svg + + IzG5dQuZe5GSDHVzQFGTi177EMw= + + Resources/core/icons/h-circle.svg + + K1dz1Hv3fmJjTASTSg0aUiuUPrg= + + Resources/core/icons/h-square-fill.svg + + E3BvcyeB/jys4E5m2yRxE2RVT0Q= + + Resources/core/icons/h-square.svg + + zkAmjoLj60tkrzUjAWsnPAV4TgU= + + Resources/core/icons/hammer.svg + + Ikf0MjfZg1IdzqrH5cCSJZ+wHOg= + + Resources/core/icons/hand-index-fill.svg + + 2EwhblSqWCFtoyUr24MzLV8DkGk= + + Resources/core/icons/hand-index-thumb-fill.svg + + glzi33qSDxnJYwxwL+hAq/0ALP8= + + Resources/core/icons/hand-index-thumb.svg + + rlWfzTPqfPjAVG9zyCNcqMC56ks= + + Resources/core/icons/hand-index.svg + + DytWgT4svOTvHnM5L8QUj9x+6PI= + + Resources/core/icons/hand-thumbs-down-fill.svg + + C9f3TU8eybIF0qOG7eFGVjgXPqw= + + Resources/core/icons/hand-thumbs-down.svg + + H7c2KbCSolQSjvhdJ+A6O1x9VAY= + + Resources/core/icons/hand-thumbs-up-fill.svg + + iGjEz7zzlwOQXPEXilOBYhWlVUw= + + Resources/core/icons/hand-thumbs-up.svg + + lV45DRgSIo0yvG2XITNfYefRbb0= + + Resources/core/icons/handbag-fill.svg + + DxpAhC+TfSgjk1SWvqMYYF3r69A= + + Resources/core/icons/handbag.svg + + tqxnFdyu7YLxsuHhTWNVr/HfnTs= + + Resources/core/icons/hash.svg + + cV2BX8FvxAFf0FJkye1Ji87opAk= + + Resources/core/icons/hdd-fill.svg + + aynp2eP6IF/bLSqxmOix2s4wLzI= + + Resources/core/icons/hdd-network-fill.svg + + cgW9hbq5C6D0YLdiBWC2Uh8KK8c= + + Resources/core/icons/hdd-network.svg + + ev4oPy19AR5eVkks+fFioSou4eA= + + Resources/core/icons/hdd-rack-fill.svg + + 2JNkj+y+fRf5QAWnK/uDZgXoKgY= + + Resources/core/icons/hdd-rack.svg + + lj0C5GE3AaCIe9m0g5yNc40dDoo= + + Resources/core/icons/hdd-stack-fill.svg + + skDBy//RRD7hmZoKB/Piw3IxAwI= + + Resources/core/icons/hdd-stack.svg + + oSAlfZDNx6vhwuZLOktheOU8zXc= + + Resources/core/icons/hdd.svg + + y3kK4EmZ9lJH/vbXmJFmIONLhiI= + + Resources/core/icons/hdmi-fill.svg + + zChhM3q67B3DXXRDU/M1vSi6ub0= + + Resources/core/icons/hdmi.svg + + A+rh2LY5GBy/LkGGeoNp4ila4fA= + + Resources/core/icons/headphones.svg + + lG7uC0HtZQr7SPHlJun6HQvJhr8= + + Resources/core/icons/headset-vr.svg + + 8r6/Qu2As8z3N+QqVXxDE7bW6Gw= + + Resources/core/icons/headset.svg + + ORCJrrsP3TdyMGdtEeiOZoh7VLs= + + Resources/core/icons/heart-arrow.svg + + 0NZ4m/qQy2uXWug4dPm556j2kL8= + + Resources/core/icons/heart-fill.svg + + bzaP6ZaG6+GnuYTsChHa9YiMk04= + + Resources/core/icons/heart-half.svg + + yuUtr+1+rpmCq0KArkZdxdaYvZ8= + + Resources/core/icons/heart-pulse-fill.svg + + TD6FruXNjBXKxmcXPHcrMlbm6Uc= + + Resources/core/icons/heart-pulse.svg + + kDI2q/eAZWjoEtJkwjtRifwaYbw= + + Resources/core/icons/heart.svg + + mNdlzYmq5B4/Xu3KcSM2+u7koSs= + + Resources/core/icons/heartbreak-fill.svg + + 6eXz9nlmibh9HD2AHPYyoOrubmo= + + Resources/core/icons/heartbreak.svg + + t1XNkBoVco5ET3t7Z7LK6vsmdYk= + + Resources/core/icons/hearts.svg + + Pycn7OJlNNegGpUWuAR/LtWyDDY= + + Resources/core/icons/heptagon-fill.svg + + Ihtbage/OEmDOwq2r8bqjkOH6gg= + + Resources/core/icons/heptagon-half.svg + + 69xjAmMO8O5o/ttMHNdHn/l/zNs= + + Resources/core/icons/heptagon.svg + + 4eh9sCQKmqMjCIeE+25ROmZORSM= + + Resources/core/icons/hexagon-fill.svg + + 9RVyF86I8Wd8Vr7GACU+8kn0ZjE= + + Resources/core/icons/hexagon-half.svg + + zR6DnIqn4BaF2lxAKChg8zUK8iM= + + Resources/core/icons/hexagon.svg + + VrUQ9+Nbe10J6sJAw+iuG8dYbNA= + + Resources/core/icons/highlighter.svg + + B2O2wZoxpMn1GrqnXnMzu/3hkOw= + + Resources/core/icons/highlights.svg + + Uz+CQ23w1eyaqY5StK7ySpLgYUU= + + Resources/core/icons/hospital-fill.svg + + mQudwXn5rXCjn7G5kANrPix98xY= + + Resources/core/icons/hospital.svg + + urQK+sIRN1PIhBnLlbmAm7exdQQ= + + Resources/core/icons/hourglass-bottom.svg + + 73Y1Cw6+pgcj9Sem+E3ieEg4b4I= + + Resources/core/icons/hourglass-split.svg + + TJkTQ1jV/FRYgp8tQYK0hIcOq/E= + + Resources/core/icons/hourglass-top.svg + + EjFVWFMb8u7ZFGlQgZe+TvvDamk= + + Resources/core/icons/hourglass.svg + + 1DAf59e/cdKZ09cSeEFJlJytWdU= + + Resources/core/icons/house-add-fill.svg + + 9iTf5qKyp+VAu1J4OP5OeNUvhUI= + + Resources/core/icons/house-add.svg + + P8lMA7NPO7cZbuaKzwROYGCTIAw= + + Resources/core/icons/house-check-fill.svg + + 2PQJOt2PudDCfIkKR8vyZyH1jxo= + + Resources/core/icons/house-check.svg + + c+UqIg8TUnlBzuCaS8Ixxu+0Uc0= + + Resources/core/icons/house-dash-fill.svg + + +t/K8ROt1/8lPtyxQmU9qtjo+iE= + + Resources/core/icons/house-dash.svg + + JtGkCTOEqcaw5yVXJRkV2tBWl20= + + Resources/core/icons/house-door-fill.svg + + N3tzi6Cx4m0renHOKaed5A61tic= + + Resources/core/icons/house-door.svg + + R+1+L/rhCJpM7I7sH84TwLbZDcs= + + Resources/core/icons/house-down-fill.svg + + 2nqgUxHsv8I7sgarOcUiZwlKcGk= + + Resources/core/icons/house-down.svg + + 5uCihXo5AiZ0FckHJihvgoEU9jY= + + Resources/core/icons/house-exclamation-fill.svg + + olyyUm1HseUdG9ZJqJcrpcg9CZI= + + Resources/core/icons/house-exclamation.svg + + DceSuo2SZl3L92GQl8R4wKXQqKs= + + Resources/core/icons/house-fill.svg + + B2Yf8TgQ/9vWQoDZTv0E2dhi/xo= + + Resources/core/icons/house-gear-fill.svg + + de+GmB3dkGQDhHxhXwbD0FpHJMA= + + Resources/core/icons/house-gear.svg + + 3fZ7q28uWGaAslAQqj/ZlELeSwI= + + Resources/core/icons/house-heart-fill.svg + + aRjM4JkrkKdGckmtQZobpPuJ61s= + + Resources/core/icons/house-heart.svg + + Va6CKbeJNUNRgzjqyP+funFi1wc= + + Resources/core/icons/house-lock-fill.svg + + NTunOLb8B+fFFrkNZjo+fJRtNdU= + + Resources/core/icons/house-lock.svg + + aEOkQwVj5Jn8N132GLRGPN+LQP8= + + Resources/core/icons/house-slash-fill.svg + + lsGc9Yd/Qf17yzO1TY52+rlIQNA= + + Resources/core/icons/house-slash.svg + + VYRYfYNYIXY/HvRGbVamOvIS408= + + Resources/core/icons/house-up-fill.svg + + MhyjNJfD7E9NAONtqi2diSq2C0w= + + Resources/core/icons/house-up.svg + + 2b1m0HDEcpq76lXy5xEl6BsMg+E= + + Resources/core/icons/house-x-fill.svg + + 4FY8V2fDmnWdWVsqiBEr39+P/MA= + + Resources/core/icons/house-x.svg + + C3TUTaEbZjGZ0nfkTUzQOszHcnA= + + Resources/core/icons/house.svg + + sxt883g5inFm23UgEz8DnoBDxhg= + + Resources/core/icons/houses-fill.svg + + vRTqK24WEw0gdyOOC/nQ7bnRgtA= + + Resources/core/icons/houses.svg + + XrovmyZA4vYWVGvqL/gCg7WtX1s= + + Resources/core/icons/hr.svg + + OWuXvQnreN292NU2xJlxu5ZBucI= + + Resources/core/icons/hurricane.svg + + gNEiXaC1BztaO7ZzigYGNgn0m5w= + + Resources/core/icons/hypnotize.svg + + XMJPFdDNYy11QOSjxDtcUrlSnS4= + + Resources/core/icons/image-alt.svg + + mcupESjPpIoBsU1KVULdpixHyGw= + + Resources/core/icons/image-fill.svg + + 09YtakNlTi+Zb0/n2VsIW4FRYgU= + + Resources/core/icons/image.svg + + ujFmN78PoPl2rzL/xZkd61oKlws= + + Resources/core/icons/images.svg + + Q+GpwMxK6LWOmWjS6xtIoNsdjzk= + + Resources/core/icons/inbox-fill.svg + + MPT9SFoUjCKd/ZLqIFUDpfEXirc= + + Resources/core/icons/inbox.svg + + QrOpDOGxJuULlLQ4FB9951nDuxU= + + Resources/core/icons/inboxes-fill.svg + + 1YDhe7RH2txSzoiAbJMjJl4bqZU= + + Resources/core/icons/inboxes.svg + + +TviLEcmbKL4B+qEF93AedA6aHU= + + Resources/core/icons/incognito.svg + + Q5ufDybeZGMbNNvypUYnmfyvU6w= + + Resources/core/icons/indent.svg + + 8RhAKEi5m/4qFE8cMMnsqBMfaRc= + + Resources/core/icons/infinity.svg + + 0xtdI+HCglCk5KXdQdbH7jrpmlc= + + Resources/core/icons/info-circle-fill.svg + + yeeWIRn+8TZPsGYDYR1IME00UGY= + + Resources/core/icons/info-circle.svg + + sS5xi9yDPZ0uGPXVoiaj0QODTIg= + + Resources/core/icons/info-lg.svg + + THLxTGXs1zIxkCQPGFmd98wrvUI= + + Resources/core/icons/info-square-fill.svg + + ZDMyw1Fstb/gkl+6jqpCQtpvNh4= + + Resources/core/icons/info-square.svg + + sAioHFlyXGsDmAxu0wgkore0kwQ= + + Resources/core/icons/info.svg + + fxfc+5ylCsbikEfHlT6F5FE6tPo= + + Resources/core/icons/input-cursor-text.svg + + Pra3BVKKhwsqSopyaDbfZsB/ThM= + + Resources/core/icons/input-cursor.svg + + d8ma+CMBe7slncULuIlD1eSaukk= + + Resources/core/icons/instagram.svg + + 9AVBmkrr5gpnVCJ2fetp4Wy7YL4= + + Resources/core/icons/intersect.svg + + 4gXKnZFfxODwGuqIrN7LMC6oo4w= + + Resources/core/icons/javascript.svg + + w2s8VN1Qswaap5mZmDlDe+WAZqI= + + Resources/core/icons/journal-album.svg + + 3A5ctHoCu11AvbAbrnHgZkPe1CE= + + Resources/core/icons/journal-arrow-down.svg + + 6hxx4fg6EJtdy0W9RqGphcHMa80= + + Resources/core/icons/journal-arrow-up.svg + + C30b1iCH8Hhhn/FNzkv+ODutiDI= + + Resources/core/icons/journal-bookmark-fill.svg + + xD7lDVCe98L6i0ilUQk1RRW0VcA= + + Resources/core/icons/journal-bookmark.svg + + i6ADsX658h3DMvQz1LM7aTT6Ly4= + + Resources/core/icons/journal-check.svg + + lDbsx0SxTWEI51IcCAH2XqRfRVQ= + + Resources/core/icons/journal-code.svg + + PAjt/ADtaPC7fIw4nBq7bBiMUd8= + + Resources/core/icons/journal-medical.svg + + vXod38AZWxdLXDXKSo6EmoclI34= + + Resources/core/icons/journal-minus.svg + + RmFh0KftA5kVwIK5yQ8NCl7qdFM= + + Resources/core/icons/journal-plus.svg + + Y/G7lXXT4pEGDfRNyKYs1wR4tyI= + + Resources/core/icons/journal-richtext.svg + + CAztD9yyDSrHvRdblgL8WHg/r7g= + + Resources/core/icons/journal-text.svg + + KpS3MXy14wDmid7PMxE7McjqlUI= + + Resources/core/icons/journal-x.svg + + HuTQ/SYchHfSLVMV3HdJ0Moj7tA= + + Resources/core/icons/journal.svg + + 9vb6seRZbzUpagVH7hTy7OlniO0= + + Resources/core/icons/journals.svg + + BFFDvJk2M1Ry0RudjDZMIb5fdi4= + + Resources/core/icons/joystick.svg + + ReW4Xvg0GOoqiCeyNnQv+ADd5vk= + + Resources/core/icons/justify-left.svg + + juAU4545lfGY0sXpUvFIpl4egks= + + Resources/core/icons/justify-right.svg + + pjEQwdaTosXc2xfHHs7/N/vpmMw= + + Resources/core/icons/justify.svg + + TwaRIBkpGoHrx1lL6jg+JjuCM1k= + + Resources/core/icons/kanban-fill.svg + + ZT6Ah6NZLCSnu8TqG4Tz4q+C3lA= + + Resources/core/icons/kanban.svg + + vJJBlS2x4X/vmc77f1Md34IYA3g= + + Resources/core/icons/key-fill.svg + + z6qua/vn/zNC+UAs9ata/g0BGtA= + + Resources/core/icons/key.svg + + sYJyWnAVVcFQgqbEEzntMmCa7+k= + + Resources/core/icons/keyboard-fill.svg + + agLwGmDS8Bg+FtZawwOlDXCs5kY= + + Resources/core/icons/keyboard.svg + + g8oGSC5IJe0paD69AkvYK0phaiU= + + Resources/core/icons/ladder.svg + + gMbDvCFiKcjxHjFv42z70xND/7c= + + Resources/core/icons/lamp-fill.svg + + f6+i5YETZxKNbxVNAaPu3b+dkE8= + + Resources/core/icons/lamp.svg + + 1pdj5qkQJAxQNyP3L5SgYp6d1Qk= + + Resources/core/icons/laptop-fill.svg + + 6JjKdhrC1ZB/GiOAVfk7YTTZh60= + + Resources/core/icons/laptop.svg + + o+UVFQplTsLzUNG9vDuUoABmYdM= + + Resources/core/icons/layer-backward.svg + + XFj1SilbKoLb3+vv8lbyYwRtcII= + + Resources/core/icons/layer-forward.svg + + C2CJEtBvEsGf76dNrXxISh3p2Qg= + + Resources/core/icons/layers-fill.svg + + onM8Gz3CKoRetWQjP+xL19MeoXs= + + Resources/core/icons/layers-half.svg + + xetjUKTrltF/jngLx662XK1Lm84= + + Resources/core/icons/layers.svg + + bQEcDqbqVaPy/1goKdqXFW4/66A= + + Resources/core/icons/layout-sidebar-inset-reverse.svg + + 4dZ94J3nuQW7Tip+W7DOUKxbK0I= + + Resources/core/icons/layout-sidebar-inset.svg + + GLcMkY1qfdADuUb3i3h35xjtHOs= + + Resources/core/icons/layout-sidebar-reverse.svg + + w+LRbM8oJz7GfkSw6GZF8VqkEZA= + + Resources/core/icons/layout-sidebar.svg + + SD4hUZP/95nDKtQ8AQCc938H4/E= + + Resources/core/icons/layout-split.svg + + Fsb5dsLtzByV/FK0BrBMzM6zUrw= + + Resources/core/icons/layout-text-sidebar-reverse.svg + + K6Pl8kEE1J607Dnd3qoWOu1WrCQ= + + Resources/core/icons/layout-text-sidebar.svg + + vz/279sn4zIl5UH3nL8n+E8mCSo= + + Resources/core/icons/layout-text-window-reverse.svg + + GbuJhjVhLfWqtr1LuZxGJaRE+0k= + + Resources/core/icons/layout-text-window.svg + + acA0cYsdlluV4JOcAESuCp6aDdo= + + Resources/core/icons/layout-three-columns.svg + + s0gqyOskIujs+iyF/rokmZ+F6ik= + + Resources/core/icons/layout-wtf.svg + + NDs97nmOI2ol7NUi+NvSMCwDeUQ= + + Resources/core/icons/leaf-fill.svg + + TAIfz9La59YkOuM58bLbiNijiyU= + + Resources/core/icons/leaf.svg + + soVSqJtoWmQdZFZIlzPSoCyymcQ= + + Resources/core/icons/life-preserver.svg + + kWwUXRH7YS45u6pLtVzTFmX/7Dc= + + Resources/core/icons/lightbulb-fill.svg + + vHem/QFFaC+hBbFZZvjAYv37YIs= + + Resources/core/icons/lightbulb-off-fill.svg + + uG+7ABTMg/ruDYE6mvQcSZkHSRE= + + Resources/core/icons/lightbulb-off.svg + + +4vXOfsKlqiNsVwHm32skaBoEyM= + + Resources/core/icons/lightbulb.svg + + 2pmrZBI+ST8UkQwT3ULSelNN7bk= + + Resources/core/icons/lightning-charge-fill.svg + + 3/S4xzWjc7uN0lDF/VqFz0NaD6k= + + Resources/core/icons/lightning-charge.svg + + miy2Cg/QC9QQ0fHuqqlpIyg+82o= + + Resources/core/icons/lightning-fill.svg + + /0I/MNbggAkGbfp/NMYUETaRGYo= + + Resources/core/icons/lightning.svg + + v/Rr4kzMl8OYEEmrwPe6s+K+jUA= + + Resources/core/icons/line.svg + + DQc8n7+3MfngxvJH0Qq4YYpYhgE= + + Resources/core/icons/link-45deg.svg + + iqTM3WLITIRpJKRowBLtF+FAQA8= + + Resources/core/icons/link.svg + + cWy6zj3PaH7R8oWhCGRbst1E9/o= + + Resources/core/icons/linkedin.svg + + OCRL7Z6pswA0f0R6dYNhSpbgDRg= + + Resources/core/icons/list-check.svg + + uctng+1kTGffqWmjRL3td8CjzBw= + + Resources/core/icons/list-columns-reverse.svg + + r2rajAUVuHwDIL1VI/+tM84dVps= + + Resources/core/icons/list-columns.svg + + /D7feut2gaA4vye7Sa5j9+LDpJA= + + Resources/core/icons/list-nested.svg + + qpAF+UBj/9R7EfjJTZscqBeEpRw= + + Resources/core/icons/list-ol.svg + + ayvknLkwjt/pb1kmLZYibBN6kkY= + + Resources/core/icons/list-stars.svg + + P8Oq5+fYA32ESDDxEX/XX62384A= + + Resources/core/icons/list-task.svg + + sG5dJ7IBPaX6Dc5UUkE9GDyaJFc= + + Resources/core/icons/list-ul.svg + + 7o30vMCqgutBTklyg/08pyS5sTo= + + Resources/core/icons/list.svg + + BQBE+LGvsUlRyeQqIeLR1mx2xek= + + Resources/core/icons/lock-fill.svg + + 1XypV7zKfK25dtO7xrNcitAM6NM= + + Resources/core/icons/lock.svg + + q+PA/WNbwsH+Ex9p+9+LfasB4QU= + + Resources/core/icons/luggage-fill.svg + + uEj4WiQAs/UaoWlvYdRlig0XKmw= + + Resources/core/icons/luggage.svg + + syBdFVN9lh89gfzj6bhts3Psmt0= + + Resources/core/icons/lungs-fill.svg + + H0JkUp/JjPWyFN5I1XeE4ENUgDc= + + Resources/core/icons/lungs.svg + + jz4qAyBGOQpnjCCbNnCEh6Wf980= + + Resources/core/icons/magic.svg + + HfHf/KQG5Yj8mHeDz/ULNTg0SXI= + + Resources/core/icons/magnet-fill.svg + + v6nCh/IOBdm0hdYzp31I2UzbAt0= + + Resources/core/icons/magnet.svg + + DRVf9wmxqzxyhTBQFrpl8gwpnw4= + + Resources/core/icons/mailbox-flag.svg + + dfXvOyJM+3GVPW4IOvpmLhJX0oU= + + Resources/core/icons/mailbox.svg + + qI63lD5sUFVLBO2e5lKHPWBzN8M= + + Resources/core/icons/mailbox2-flag.svg + + d8VtmtdkCD6JJrykwRgIruo/+yE= + + Resources/core/icons/mailbox2.svg + + p9VLPijZ7gIq02HM9UVbaHEsl04= + + Resources/core/icons/map-fill.svg + + Rs3hbuoJ0dBrlZwCVQGQ7CIk3yA= + + Resources/core/icons/map.svg + + F5V5E1wy+Lz4Fb2x3gO7yibUO+s= + + Resources/core/icons/markdown-fill.svg + + cprslnpYAdP0mQwczIwRtXlRQt0= + + Resources/core/icons/markdown.svg + + ofAlSPQ91qqDSV8uAY/8fUyIaP0= + + Resources/core/icons/marker-tip.svg + + Fhy7d9p37YwRRcqaaq6Gfzlc9aQ= + + Resources/core/icons/mask.svg + + StHWMF9uTdZYEVXVW3fK6pwFhPo= + + Resources/core/icons/mastodon.svg + + rtMaZDV7qmZcqZY8RBy3LX5SfRo= + + Resources/core/icons/measuring-cup-fill.svg + + b1mt18po/Byo4DihpXgEi9DYx08= + + Resources/core/icons/measuring-cup.svg + + kJn+subsgNaOtJSy6EfF4d3BFKw= + + Resources/core/icons/medium.svg + + wKLoULJ14V/crRau19zcnVVBzrw= + + Resources/core/icons/megaphone-fill.svg + + Ou93i8VaLgKiY7EedwPLAeNTFhY= + + Resources/core/icons/megaphone.svg + + j764Y8v9Jk63Y0Pw9OHbDmFLu/Q= + + Resources/core/icons/memory.svg + + Hh0NaUmktw4d8LT7aX1ihFszpZs= + + Resources/core/icons/menu-app-fill.svg + + WJlYtOTSdfRI/eJQEBc9SYPWGjA= + + Resources/core/icons/menu-app.svg + + dVIqeNIFOSeSFNoaMZqpndft2g4= + + Resources/core/icons/menu-button-fill.svg + + 0a80emJw2o/Ws/8FiFixtugX6Zo= + + Resources/core/icons/menu-button-wide-fill.svg + + 2pSFtZ9K8wLz/CX3wHQbH0ldF9s= + + Resources/core/icons/menu-button-wide.svg + + PdbH+bIxC0KgMd8YS3uC4rYecRo= + + Resources/core/icons/menu-button.svg + + ct6WZ+4LVh6X08Hq6I6d+UPY3zY= + + Resources/core/icons/menu-down.svg + + LMy/CAKmxftCwS4bNPt+vVvxjZE= + + Resources/core/icons/menu-up.svg + + wdKc2pHlM6m8GH31v8ZsMeX07hY= + + Resources/core/icons/messenger.svg + + VjJRS6kJRVh82sYIiT+Koji0/SQ= + + Resources/core/icons/meta.svg + + 230LDSJDdPnROE7frAJrFUeo8Mc= + + Resources/core/icons/mic-fill.svg + + 7YiuaDJl+irc2Vr62tpABsGXwyU= + + Resources/core/icons/mic-mute-fill.svg + + WrH5OU878YX/wqVwwwcBceNKWjc= + + Resources/core/icons/mic-mute.svg + + S7C0s4fJiKqFyhD5Qr4ySyIV7Ks= + + Resources/core/icons/mic.svg + + EbGAKYRa0ByDRiPi46Dz7FWyqKU= + + Resources/core/icons/microsoft-teams.svg + + iB4pDpeza0R2+xaeb7IogxIbP7o= + + Resources/core/icons/microsoft.svg + + mLXHv0rCwhBm6ZTgWH0PzYOFrM0= + + Resources/core/icons/minecart-loaded.svg + + XfortWDAQhQKirSg0139nkTU9vE= + + Resources/core/icons/minecart.svg + + 6N5pSVyWdCC0ZOI5kMQ5c691XtQ= + + Resources/core/icons/modem-fill.svg + + h7sVYRihl5fYM27DgZF1uP6s1RE= + + Resources/core/icons/modem.svg + + g0cUxkexF6G5/23WfIh0fO+U8D8= + + Resources/core/icons/moisture.svg + + hnM39sAu51WVFH8ser5yyNetV+s= + + Resources/core/icons/moon-fill.svg + + CBRwG0XnvuKT0qF272Trnw+p4k4= + + Resources/core/icons/moon-stars-fill.svg + + 04hg0NzB65bxB4XfgFBDZykKWEs= + + Resources/core/icons/moon-stars.svg + + 7pYlScg9fyKAjrzdrDELtRz5rDk= + + Resources/core/icons/moon.svg + + nkCKvOYuFof4AdAs1d5KV+bITZo= + + Resources/core/icons/mortarboard-fill.svg + + JAUxT+MdPsJNJGY5uY8dfx5Mm68= + + Resources/core/icons/mortarboard.svg + + pf9b++trHZOaF+HPfLNBCoDiasg= + + Resources/core/icons/motherboard-fill.svg + + azSAyH4a3QE7vkIqstZI0DR9QTA= + + Resources/core/icons/motherboard.svg + + C60KMKhdDDjDld34dJXDFt8Tt2g= + + Resources/core/icons/mouse-fill.svg + + 8GSi8O4QQlHC5weL6KX5gMMRQNI= + + Resources/core/icons/mouse.svg + + o/RcxLRl3QnGkm0Qmjso8bhSUCs= + + Resources/core/icons/mouse2-fill.svg + + FhrGGrw97qzL5bg81yZ6r1Pt9v8= + + Resources/core/icons/mouse2.svg + + 92nWSnd21NQwBoQB4vhRcekBo+o= + + Resources/core/icons/mouse3-fill.svg + + 77Qk/S4HJbelbFS2f8C8JEMcS2s= + + Resources/core/icons/mouse3.svg + + TCdkzXgZo6mlXX3wVAzbO0QNATU= + + Resources/core/icons/music-note-beamed.svg + + C6Z1peJkDhP5ewm7ohkh+/l3btI= + + Resources/core/icons/music-note-list.svg + + 5PzYUNPeb17sAasA6umNaHWnXNc= + + Resources/core/icons/music-note.svg + + 2mx/Qm25AFWmdqNAiYM9fsyzCTk= + + Resources/core/icons/music-player-fill.svg + + BuiW5XMTjlcJg827GmCaZqIfDdw= + + Resources/core/icons/music-player.svg + + b9IXkbaeCkf05GJp8iEsEemFYN0= + + Resources/core/icons/newspaper.svg + + acX36T/j1+k723vfShDm/k/uvY4= + + Resources/core/icons/nintendo-switch.svg + + aBPg+Yysf8PjA3RtaWHqNYDRQR8= + + Resources/core/icons/node-minus-fill.svg + + Z/RXYovwfmto2n+tT7E283v/mno= + + Resources/core/icons/node-minus.svg + + 3Cuui6BaDSho1Gjh3iyz7WnyouU= + + Resources/core/icons/node-plus-fill.svg + + Bz0omgIYidcvdUoa5GFTtnLkLe8= + + Resources/core/icons/node-plus.svg + + pJghsEy0owLBmZIgWkBP1K4YQhU= + + Resources/core/icons/noise-reduction.svg + + y9XQB1PXw/b20HIJ5VBX2f5otTs= + + Resources/core/icons/nut-fill.svg + + FW+v0XvN8aB7iyywk3fIMZd73MY= + + Resources/core/icons/nut.svg + + 2/B7AfxgxMsBxJAjU2/VvxN/YVk= + + Resources/core/icons/nvidia.svg + + XeyondYfrkuThlV4pTtbzLQU76Q= + + Resources/core/icons/nvme-fill.svg + + vXVMCKjDuVcDnHb/5cOHlmgUdPQ= + + Resources/core/icons/nvme.svg + + Q7YZqVCA1db7Dykp5EVgrwG5pLQ= + + Resources/core/icons/octagon-fill.svg + + Oj7vNlaUYWXYecySV8GpxDIPjko= + + Resources/core/icons/octagon-half.svg + + S3fzYXRycAKD6VALoJRu0VfavaU= + + Resources/core/icons/octagon.svg + + kVAL9cpHKYFVMNRj3k3EAaarNOA= + + Resources/core/icons/openai.svg + + 9W9eLbHRwy8YlXqV7jdaxHLZtcw= + + Resources/core/icons/opencollective.svg + + JGJvWl1wOkr8kzeLHkd3kHM/OOU= + + Resources/core/icons/optical-audio-fill.svg + + +ZH3elrv+it2xOGDibv1D6gJ/uY= + + Resources/core/icons/optical-audio.svg + + jxXWGO9U2PqHS7o0GPBa1hz0BIk= + + Resources/core/icons/option.svg + + j8E7GA5oldgaqToMO6VzjMcWGEQ= + + Resources/core/icons/outlet.svg + + z6ZA/qwCsJIiNw5jsZ63Yi7Ghhc= + + Resources/core/icons/p-circle-fill.svg + + WpHPEApSjjRQ3yEQsQXVeJqAaOA= + + Resources/core/icons/p-circle.svg + + AkAdQd3VyxTmSaXgiBxQ+XkGVww= + + Resources/core/icons/p-square-fill.svg + + UOlkYo9AtoAJSqQg878qUUl5keM= + + Resources/core/icons/p-square.svg + + gd/vo+6/o1466W2j0C+XJU2Z+7Y= + + Resources/core/icons/paint-bucket.svg + + yFUnPJF9KHfgpSyIO4J/vg0XGnA= + + Resources/core/icons/palette-fill.svg + + dj3wd2zKS2uAEwbL8XBuNVhY+0g= + + Resources/core/icons/palette.svg + + DlUie1GGUMOvi63yxoQPs1bo4eQ= + + Resources/core/icons/palette2.svg + + VzzxavF7tx2frcNfA1xl7fK92Bg= + + Resources/core/icons/paperclip.svg + + W5DCcWUz0HgWP93sZ3nYKLSE+nY= + + Resources/core/icons/paragraph.svg + + li5Nazi+xTcvhP6ZY4HsVkiBlyA= + + Resources/core/icons/pass-fill.svg + + 49ditOuma8Q/ArrWhGJiHHUW1/U= + + Resources/core/icons/pass.svg + + 5U2IRLlwRKvTskHqlNVo1LWscfI= + + Resources/core/icons/passport-fill.svg + + StkAlJ4KImxVM0mN53+HAmeL3p8= + + Resources/core/icons/passport.svg + + SmAJfgmmKtTPUy7HhuIzBJiSeZ4= + + Resources/core/icons/patch-check-fill.svg + + EaG/pK9TKuHiqOAYcOwfFtCyL8A= + + Resources/core/icons/patch-check.svg + + ApuAYOo2A3UY8PiQRbrnvx9Eoxc= + + Resources/core/icons/patch-exclamation-fill.svg + + crPhTWbx+oPn3JcEbhEhgdcZQrE= + + Resources/core/icons/patch-exclamation.svg + + CXvtIzgznmvSE+H1w9SPojseG18= + + Resources/core/icons/patch-minus-fill.svg + + MliqUKajQnorM11cyPO60rMbyRY= + + Resources/core/icons/patch-minus.svg + + UNFDw2+GOdHWSh4zjqzePx8K5cw= + + Resources/core/icons/patch-plus-fill.svg + + Fn0A9V5rbGkLW9vTD9I5lgYwJzw= + + Resources/core/icons/patch-plus.svg + + T3JmmS4Ig1di5sYr2yG9554b7fk= + + Resources/core/icons/patch-question-fill.svg + + mSZTbn5q+2yhLzGzac6aRtOWma8= + + Resources/core/icons/patch-question.svg + + OWxTb+8jxXcqgWDnPdecOyxnjvM= + + Resources/core/icons/pause-btn-fill.svg + + Ic2ZuXFlFYsG7a+eOZxH1wBnZcw= + + Resources/core/icons/pause-btn.svg + + 4nzJibsqkbwYwTiQ3v2OLHD6rjA= + + Resources/core/icons/pause-circle-fill.svg + + YqR0CbQ7ZfIOwtN88zEsJp7u6AU= + + Resources/core/icons/pause-circle.svg + + wHgqYZrDuooZBHVXbtGXZqMvxcY= + + Resources/core/icons/pause-fill.svg + + BOgthmkGjwyxhdaG1LftsQZMXKg= + + Resources/core/icons/pause.svg + + 0ndH+fDfdQ4OlkxRT8WoVGa6Pno= + + Resources/core/icons/paypal.svg + + nmrcLFY+tGgXXZlnVUJ4v68iZ3M= + + Resources/core/icons/pc-display-horizontal.svg + + emnxr3RdUr0E2u4wAQr+34/4oh0= + + Resources/core/icons/pc-display.svg + + 3kmEmmp61ZYQLE29w0tKbNzPTQc= + + Resources/core/icons/pc-horizontal.svg + + RTC37RrgAcDfJisxPtzVb8VYlS4= + + Resources/core/icons/pc.svg + + wnkOohMxCKZmFtpRUAtkSIfV9fw= + + Resources/core/icons/pci-card-network.svg + + 5+IkcAY+8vr1x8MpC7cZVVfYrF0= + + Resources/core/icons/pci-card-sound.svg + + NT9Jeh+aJFM55pr04fgY3kjYbt0= + + Resources/core/icons/pci-card.svg + + BFMW4qlW5pS2dBAekwKae//xII4= + + Resources/core/icons/peace-fill.svg + + DWw8cysWHhAjhaOcS6AB/MTuOHc= + + Resources/core/icons/peace.svg + + 0EeatEkgJsp67kdrAMfT60krzW8= + + Resources/core/icons/pen-fill.svg + + 3qV7opj0hSJMpyb32c4kNpc35WI= + + Resources/core/icons/pen.svg + + ZzD20LfCTBi+WG8wsEJGMok1v3Q= + + Resources/core/icons/pencil-fill.svg + + 5nKk3mDuDsOsOLktrDWUW4qxHmE= + + Resources/core/icons/pencil-square.svg + + 59UUIYImDVexT5cN8UWzaUPzuhI= + + Resources/core/icons/pencil.svg + + VP0EWicrxV/Rc9vokcATAtcfACs= + + Resources/core/icons/pentagon-fill.svg + + jjLCWVXKayQFodWuePTZNsjPI6c= + + Resources/core/icons/pentagon-half.svg + + uofPdYrPNy0uNAyYWfOTUIqnx+Q= + + Resources/core/icons/pentagon.svg + + IbV4cIU4n+yh30KJnYXkWrWp9xc= + + Resources/core/icons/people-fill.svg + + hzY1Wqx7vwz9De9m3wStl067Y1g= + + Resources/core/icons/people.svg + + 1ZZAiHAwb3Epqdcuswbg8+Bb/w8= + + Resources/core/icons/percent.svg + + JE8TQflxPo4KHzn7pMSq9gcY6JY= + + Resources/core/icons/perplexity.svg + + Mr0mDoUQkWwmpSTB0F6pLt6cS6c= + + Resources/core/icons/person-add.svg + + U68x+g/qqdGsuYFRU85FqXDd0W4= + + Resources/core/icons/person-arms-up.svg + + OBGvhLCv62aezZwVTWzc+GO1wDw= + + Resources/core/icons/person-badge-fill.svg + + AEh900m4JlENB13VgxXAykwXxsw= + + Resources/core/icons/person-badge.svg + + 9WEZonUZgLnm8/WOYc9cS/xNFXI= + + Resources/core/icons/person-bounding-box.svg + + MZOH33uG5kupPYq1yCxWvKM1H3w= + + Resources/core/icons/person-check-fill.svg + + YbvFH0KSRWKpVFcsBlWi8Z+tOzE= + + Resources/core/icons/person-check.svg + + as0iLLV1tiG1Krj5YZyhYqOFdQA= + + Resources/core/icons/person-circle.svg + + a7ZOfDWeLNxT0v6fQRHdRjAp6Ho= + + Resources/core/icons/person-dash-fill.svg + + avZd97Tm3pfO1aopTjOUdqaMnpg= + + Resources/core/icons/person-dash.svg + + drLHMEUMyV4PWxdq+NQrWjY+W3w= + + Resources/core/icons/person-down.svg + + wjoM3AldXk9mZGnsm1n+UF5ZNNA= + + Resources/core/icons/person-exclamation.svg + + OG2lHsFGQBLr6ZWjLYlubNM3mNM= + + Resources/core/icons/person-fill-add.svg + + zDbe5x/LesSTNX/96y1JAl8Sfy8= + + Resources/core/icons/person-fill-check.svg + + ChirKswP5kJnV1Z6Llj3WwpFMTE= + + Resources/core/icons/person-fill-dash.svg + + oi1BJcPPmwhkRSd4BXtHIbLFNg0= + + Resources/core/icons/person-fill-down.svg + + KI7UbiWgDIX96lPhibJuinjGfeI= + + Resources/core/icons/person-fill-exclamation.svg + + iYd/+Uo502DAjbl+aN3q6XHO/5M= + + Resources/core/icons/person-fill-gear.svg + + ySrxe9ZCROsVaEqWhmGnKLz3jEY= + + Resources/core/icons/person-fill-lock.svg + + RhPCP+2WbOjfV4A+uGDMitdtaEo= + + Resources/core/icons/person-fill-slash.svg + + cFyK5tdxo19jIvG9vFgri5v86eQ= + + Resources/core/icons/person-fill-up.svg + + q9K8sZf4wwBg2cPijGeYqTGOlYE= + + Resources/core/icons/person-fill-x.svg + + e1I9g4+bRDMEzxi5OPNAMau2VLg= + + Resources/core/icons/person-fill.svg + + iC2gEitmVRdznttA6Ly5GVyoiNk= + + Resources/core/icons/person-gear.svg + + FP1XtydjpTA2R34g3t+X7Z0ZHoo= + + Resources/core/icons/person-heart.svg + + V1ga1ilip5ODF8IYkF7lpM8j1fA= + + Resources/core/icons/person-hearts.svg + + ZNro1uAxb/YRAsi9TkclBkCps70= + + Resources/core/icons/person-lines-fill.svg + + 25Y2q4b6YXo91k41XHu4p5hyNs0= + + Resources/core/icons/person-lock.svg + + Vzw+/HMnHupuCAQF4HJ5e432iqs= + + Resources/core/icons/person-plus-fill.svg + + 53ipquA2CwglcD3heiJfia9hEqA= + + Resources/core/icons/person-plus.svg + + yew1u4csQTE2Btn0aW/HIk9PDcU= + + Resources/core/icons/person-raised-hand.svg + + mAYa0wTZJVNMa6KptoJKR06j2hQ= + + Resources/core/icons/person-rolodex.svg + + 0yRhQB63lkbFopiqFrNm9Ij1hsc= + + Resources/core/icons/person-slash.svg + + N0UDUJqQfwLh8g/MSjCXez5txes= + + Resources/core/icons/person-square.svg + + ArgXTMI+jA+Ekfmv/QsC6ZwITi4= + + Resources/core/icons/person-standing-dress.svg + + F0FIFnvCn67xZR8ZDZ3yzpmAn6c= + + Resources/core/icons/person-standing.svg + + vhN9EduuPh91SW3JFmqtLZkxLS8= + + Resources/core/icons/person-up.svg + + ylNM2so04/jSqmyqhDynndFJWsk= + + Resources/core/icons/person-vcard-fill.svg + + TgBldjIRdXOeMjIFXqJQsaZiNig= + + Resources/core/icons/person-vcard.svg + + dNux3o7or9n9FODixg1stCaTVfQ= + + Resources/core/icons/person-video.svg + + bZMId/d3pb5VupfXN0VT0o0IA3c= + + Resources/core/icons/person-video2.svg + + MIdC/Y7861/xXatvT4UQWh+8MVo= + + Resources/core/icons/person-video3.svg + + sBjvrcIgRP1XL6GQi9CNKjASY5A= + + Resources/core/icons/person-walking.svg + + LGRD7v5q+6XRcezgTArIVNhacBE= + + Resources/core/icons/person-wheelchair.svg + + nrj3ydbwwC9gpP8M2cypaJDgN4Y= + + Resources/core/icons/person-workspace.svg + + 5CS0XRhEuCQqgdrhdLaBvIH8AvE= + + Resources/core/icons/person-x-fill.svg + + jPvspVQDpiefKoXGpxpXmp9T740= + + Resources/core/icons/person-x.svg + + cvd14P62xC7KbdCjGpL3RP5wi+o= + + Resources/core/icons/person.svg + + sQeEgrNNXyoR0rnMtsUJsyoazE0= + + Resources/core/icons/phone-fill.svg + + Ze8Y/JptRLKAOcUNkZmsfwvxgM0= + + Resources/core/icons/phone-flip.svg + + ZYDeVPx1oWPVBfB0lhSwF6ZPNe8= + + Resources/core/icons/phone-landscape-fill.svg + + W6H+E23WOTStcY7RmKW+8ayX1Ro= + + Resources/core/icons/phone-landscape.svg + + I+XTGEgXo7L83Sm0AQsXzbB4P44= + + Resources/core/icons/phone-vibrate-fill.svg + + Vf63ydsnJ3TFWtprITtsCdqIRLM= + + Resources/core/icons/phone-vibrate.svg + + xX8b2EFY4IZzSy876mfFkwFEx6U= + + Resources/core/icons/phone.svg + + bOjm6zCYPdE14D4/oIPs9xsWKs0= + + Resources/core/icons/pie-chart-fill.svg + + q1eGclEMApmqOk66jefwt+B/hdM= + + Resources/core/icons/pie-chart.svg + + VQPj49C+wgFQthPD2bzeNKN2HKw= + + Resources/core/icons/piggy-bank-fill.svg + + 9o45fJyHQNU259D8bWbPccf3qG0= + + Resources/core/icons/piggy-bank.svg + + r1lbFLEfymWsNOFV04oufTKNGJ0= + + Resources/core/icons/pin-angle-fill.svg + + WjXaJ07if1SlOHHH3jJiImY+g9c= + + Resources/core/icons/pin-angle.svg + + RdRhIwxb8fdNoeBLT31trfOJpIU= + + Resources/core/icons/pin-fill.svg + + gHjFjjJfqChKGCLqnywbf+IYmYw= + + Resources/core/icons/pin-map-fill.svg + + g6FVGdWAkH9hzUM57uzafRIQS0E= + + Resources/core/icons/pin-map.svg + + wqO2XZGWGPPOg7Hwllex221HnsI= + + Resources/core/icons/pin.svg + + xMAFdKpLwNSsTK6WprE8Wg1LMpc= + + Resources/core/icons/pinterest.svg + + aA6jYBACdf3TO5zomx9q0McQps0= + + Resources/core/icons/pip-fill.svg + + PKcLu9+up1cpD5wi0l6BlBt1QKI= + + Resources/core/icons/pip.svg + + P5mIrHH6kO45urCkfmIRbQS0iQg= + + Resources/core/icons/play-btn-fill.svg + + zs0bpDDBMJadb8a2skOBLBzjNlw= + + Resources/core/icons/play-btn.svg + + 3f+WqI0n0FhtnUbxsPyEeNdTOH4= + + Resources/core/icons/play-circle-fill.svg + + AqkS9pOlKkayUC0W+ywSjSe19Jo= + + Resources/core/icons/play-circle.svg + + ozS1Dngn43MyaRsewKfNfFEQ2qs= + + Resources/core/icons/play-fill.svg + + 35dDc+spcCiE3Vlm9gfYFE1dkhs= + + Resources/core/icons/play.svg + + 2vjwNApAYcsafvsoJ8ybaKLZYKw= + + Resources/core/icons/playstation.svg + + pxqx7K2Mcd82o0bUWLqASzoOxtk= + + Resources/core/icons/plug-fill.svg + + vWKWzK034ADpQydIb3uNLjKBgJM= + + Resources/core/icons/plug.svg + + HRsxnbdU4pSSwRHJoq7yjT1fB4Q= + + Resources/core/icons/plugin.svg + + zxNpBMrgmLIzJDCiWVuctpWC24Q= + + Resources/core/icons/plus-circle-dotted.svg + + eo6U6ZD3PXB99P7E3QFQ8HMpK+k= + + Resources/core/icons/plus-circle-fill.svg + + cEQUMz2TvtwD54OB2BfdY7H+14E= + + Resources/core/icons/plus-circle.svg + + ozr9UsbAgGZeKVYCMVA2Y4RbtlE= + + Resources/core/icons/plus-lg.svg + + Goc+G7y4iIrrQw5MoV9jtfXWQ1M= + + Resources/core/icons/plus-slash-minus.svg + + Rto+EWP1/QdXZsM7+/ELeD/ISgA= + + Resources/core/icons/plus-square-dotted.svg + + 0RTBi++UZz4QjJ4c+YITziUPtEg= + + Resources/core/icons/plus-square-fill.svg + + coeyDvlHiPK2DLOjoaopqtoIfic= + + Resources/core/icons/plus-square.svg + + faQbAUMz35qT3+STmbwzz/sJS5k= + + Resources/core/icons/plus.svg + + ax2OPewx6nBhG175LAsQhbREBJM= + + Resources/core/icons/postage-fill.svg + + Ul7yc63RwKJKogvb4Osq/gpDktg= + + Resources/core/icons/postage-heart-fill.svg + + 6Gm8x30NJJQiooQd0CZpzQpzqd4= + + Resources/core/icons/postage-heart.svg + + 96wjeigswsfrVBSSNmdZEm6uoFY= + + Resources/core/icons/postage.svg + + z5TIeBEPDJ02OVBNStzpqBDDl+w= + + Resources/core/icons/postcard-fill.svg + + xIw5CtLK4IKXqL4873gTo7XV5bY= + + Resources/core/icons/postcard-heart-fill.svg + + NvwoP1u3gP7L5jiCNrPKEJWuGVg= + + Resources/core/icons/postcard-heart.svg + + 9B8JDfYML0gzqopMbAtwak9iqQA= + + Resources/core/icons/postcard.svg + + 4BYJjv49qAPRCzcLCEVCqp5e8Zo= + + Resources/core/icons/power.svg + + 9rZH7ayehdPlDbFkNgQDqBAi8jo= + + Resources/core/icons/prescription.svg + + XVAG7MMqwjpCV848XHcwCyZ/lLc= + + Resources/core/icons/prescription2.svg + + fBex4tO7l+f1Qk2bORqC2+s3Z6M= + + Resources/core/icons/printer-fill.svg + + mKcwoKZusMV/oAk2pPUwLYEbegQ= + + Resources/core/icons/printer.svg + + qCg74HUTwG0nH62/IgoJyN86F5Q= + + Resources/core/icons/projector-fill.svg + + 71Eczd0mhzKTANxrbtRMnx9xYUY= + + Resources/core/icons/projector.svg + + ehdJea3VtLpXTr4WRykngN0nXSA= + + Resources/core/icons/puzzle-fill.svg + + iXegpIOS3+DeOwM61oFJ0HGvts0= + + Resources/core/icons/puzzle.svg + + opaRtwGoZTQ9ykUzV0eQStmitMY= + + Resources/core/icons/qr-code-scan.svg + + DueXOSZbtvFTC/Y+UJvRrBRFm4M= + + Resources/core/icons/qr-code.svg + + Z+1w+DPJhneLb1qmAhRw8k4h1X8= + + Resources/core/icons/question-circle-fill.svg + + 69cmvCXK/blgll8hA6rcpvdLkEM= + + Resources/core/icons/question-circle.svg + + Kpl5rzYr7NQLAQUC6FdX7met66Y= + + Resources/core/icons/question-diamond-fill.svg + + rBWI1gdjMku3XNA6SDWNkGvxOlw= + + Resources/core/icons/question-diamond.svg + + 5810I2PhlAY9oPMP95EY/0tB8Qw= + + Resources/core/icons/question-lg.svg + + 84hctui7+YGlDhNQuocrPTCHFyU= + + Resources/core/icons/question-octagon-fill.svg + + huZu7OOK/BOR9q0wLtAXacVKADI= + + Resources/core/icons/question-octagon.svg + + 5jwUHU3jzMcGBCc8mfkaRh97S7Y= + + Resources/core/icons/question-square-fill.svg + + EYxoCZCTEY7R3csKXN7uJNjq1g4= + + Resources/core/icons/question-square.svg + + RhJv0LWqPu741gHLaI32iszCLBM= + + Resources/core/icons/question.svg + + EiNKiPqTg2zmMxV+S7/NE72lUyc= + + Resources/core/icons/quora.svg + + 5K5ZBbtl5/r2N0JkcjwpAb1lfF0= + + Resources/core/icons/quote.svg + + xhsVJcO4Fu8qyw47V4A1Nkh5QR0= + + Resources/core/icons/r-circle-fill.svg + + GEbmskA7SO9k0iGiZAUoSOZd6q0= + + Resources/core/icons/r-circle.svg + + p+LNlGQ8NubIalaZ2UjE/J58vPU= + + Resources/core/icons/r-square-fill.svg + + JGDIkMQ0PwAck2txny0ojjYjHvg= + + Resources/core/icons/r-square.svg + + +W6YrM2N2JH+hi/L5fm3YXfKNww= + + Resources/core/icons/radar.svg + + ExOTMz49KW/BarXqYO5ZICkCDC0= + + Resources/core/icons/radioactive.svg + + GxQk6R5qsoiw04Qy1hinKbpj/c4= + + Resources/core/icons/rainbow.svg + + VieMwhrN+0dhgxSP/s4bp0jE7QQ= + + Resources/core/icons/receipt-cutoff.svg + + 0QP5uYuT8DuwMLY3zU9G9gDzLzw= + + Resources/core/icons/receipt.svg + + d61JValUQ4MsdXn+cStHdlSfIzI= + + Resources/core/icons/reception-0.svg + + 6RftUSx7rKr0C6ZlExnr4Ic2R20= + + Resources/core/icons/reception-1.svg + + Oyqbv03IORrHuN62NBaNokITLU0= + + Resources/core/icons/reception-2.svg + + C5pCfGl05GATIqAqEJkVd1Ve6dE= + + Resources/core/icons/reception-3.svg + + KnDxd70WxR7v3xK/tveFpkQzb4U= + + Resources/core/icons/reception-4.svg + + bHY1qkMYf3pzZedXlt3JgLsaKbI= + + Resources/core/icons/record-btn-fill.svg + + 1e2S1uLTuX/OLoGdh1bYgi8qkgM= + + Resources/core/icons/record-btn.svg + + Zedw+KEHCo9R0RO+bwfdsK1WIPk= + + Resources/core/icons/record-circle-fill.svg + + 3z5bnWuijxmDYBJG5IZ6mABK5Gc= + + Resources/core/icons/record-circle.svg + + YnceC42XFwsccn4vRza6WqkZYWk= + + Resources/core/icons/record-fill.svg + + HwNGz8kz+COX3CGDS98wkx3O8M0= + + Resources/core/icons/record.svg + + aevRopdTW9Lm+k/SorQLSjsHbgM= + + Resources/core/icons/record2-fill.svg + + 4Z7wIBY4iM8Bx71IHoBzSLz7UuY= + + Resources/core/icons/record2.svg + + UzfS1MMoo5ayyXN7k8pqW8iz0fw= + + Resources/core/icons/recycle.svg + + LVS/EcH6ZxS6qU8cSYy3161ahy4= + + Resources/core/icons/reddit.svg + + 39PNaCvgUtw39ziimhmACO5yd4g= + + Resources/core/icons/regex.svg + + 22c9/3HljLJYZOeI4TXGyU1JOik= + + Resources/core/icons/repeat-1.svg + + iGJ3qapIv1WpnlklfW6SfpOvz30= + + Resources/core/icons/repeat.svg + + zaQe5tR169CEn8N/gBHykMZLQ7k= + + Resources/core/icons/reply-all-fill.svg + + Rv4gBboHHOtAHbEQ4CrWHjUns8I= + + Resources/core/icons/reply-all.svg + + fXszfBfr89PzAQl2C8X1cKA4nKU= + + Resources/core/icons/reply-fill.svg + + 3j6PAs86Y9tKpsryjM+rxab/bYY= + + Resources/core/icons/reply.svg + + SJ1RnEK+hwxTZTtMhXAGiNbsCtg= + + Resources/core/icons/rewind-btn-fill.svg + + NTAxrF8KsMiIdLQrJme5ovL9siU= + + Resources/core/icons/rewind-btn.svg + + 775m4wxlkpLufoy7OgpeY6r0df4= + + Resources/core/icons/rewind-circle-fill.svg + + fG+caFnzartJzeWWJF9FDShuRC8= + + Resources/core/icons/rewind-circle.svg + + s1NidBhTlzuOPQAP9X1FEr9VvYg= + + Resources/core/icons/rewind-fill.svg + + ouEtHGj5s+Ze3jXp8ogxUoNahuY= + + Resources/core/icons/rewind.svg + + BZsW3d104hRmFpdNhgm202gffsQ= + + Resources/core/icons/robot.svg + + YEhOVSSxoLTNY/yMRyWMW4LUZnE= + + Resources/core/icons/rocket-fill.svg + + nmA0MXq7SxZixu/+DVRWybBgfFs= + + Resources/core/icons/rocket-takeoff-fill.svg + + HeFoosYwCtYD2EkPuzU/5ylIE2A= + + Resources/core/icons/rocket-takeoff.svg + + NfuUQKtteBpOo32EJl7+JDbmeD0= + + Resources/core/icons/rocket.svg + + 1X7n/xoPvElN/ldZNy0bmNn/J3o= + + Resources/core/icons/router-fill.svg + + QOfIBdqohX7gj6U5diMuXCylYeU= + + Resources/core/icons/router.svg + + A9dMwYn6iiHdkww6ZJ6p+vsniEA= + + Resources/core/icons/rss-fill.svg + + jyp5IOSWB3Ha1HgTb5HFvJNbDUk= + + Resources/core/icons/rss.svg + + hmnt8G5vFdLAHRKBb8fmDTFXdpA= + + Resources/core/icons/rulers.svg + + kVQ3MKYNmbIRMbqfrsJxPInlgiU= + + Resources/core/icons/safe-fill.svg + + ivm4gBW03RQakj1BLtTylqOh2eU= + + Resources/core/icons/safe.svg + + 64YpMYOZsJFWU1riSoHjxP9vXws= + + Resources/core/icons/safe2-fill.svg + + Vjh9eYeqquX+k6gMuKZ9bTYIHAM= + + Resources/core/icons/safe2.svg + + qajHOsFbz9ckDH/izseNGwcWa30= + + Resources/core/icons/save-fill.svg + + RJDdBPCbph/dSk0GPXlN8MCzFjQ= + + Resources/core/icons/save.svg + + g67Zlcvz8l5KaIH8mR5iYfWsChc= + + Resources/core/icons/save2-fill.svg + + oH3ApOcYgBx6ZK2kzVX/LqI/SpY= + + Resources/core/icons/save2.svg + + P1uPbLZLPTZ0lW3OlSkDq0xNLig= + + Resources/core/icons/scissors.svg + + ZrlPSh1QLokmoaQdoNkkc8qh8Cs= + + Resources/core/icons/scooter.svg + + 2HdtfJZljwcO9/1t8a8rZ4rxfrs= + + Resources/core/icons/screwdriver.svg + + d4ATVdIodso86sHbJIuz2MPXIYY= + + Resources/core/icons/sd-card-fill.svg + + I8XnVKHQnRYIZECcQnToF9O2g8A= + + Resources/core/icons/sd-card.svg + + z9EDNTkpp78cSQv7H5FbLRvKG54= + + Resources/core/icons/search-heart-fill.svg + + K1u/YMMkcAxyvoBD/0aqZinLx1M= + + Resources/core/icons/search-heart.svg + + 4zzZ6Er8ukPUwb7vUWpRoBcjiD4= + + Resources/core/icons/search.svg + + kJrak3LDerHM1PvTxF54cqcjt7s= + + Resources/core/icons/segmented-nav.svg + + uTjoFwBt+um/da0H/IiIL+ZEOl8= + + Resources/core/icons/send-arrow-down-fill.svg + + JfD8kNuxnlAD8U2NxkT07fREqME= + + Resources/core/icons/send-arrow-down.svg + + mN363d+Zx8OWN9DzV5yQD09qPPg= + + Resources/core/icons/send-arrow-up-fill.svg + + 29sWbncLhMaMK0g6dG0etPS3E5c= + + Resources/core/icons/send-arrow-up.svg + + 1qSyQA1r3mGha+Pj/+XGkCHqRhw= + + Resources/core/icons/send-check-fill.svg + + P7qr9DA10ZsTa7+oz7jGtY+j7RY= + + Resources/core/icons/send-check.svg + + MeXOdrMy1/m1mWwgxfcfqDWcMhw= + + Resources/core/icons/send-dash-fill.svg + + 8vlLpjOiMER9mSz81twQdMxNFYM= + + Resources/core/icons/send-dash.svg + + Mnvnm3MQj7fx9BXJH0okNrbVhgg= + + Resources/core/icons/send-exclamation-fill.svg + + Of2i5FSCYjKULg7njD2KBETUSDw= + + Resources/core/icons/send-exclamation.svg + + MGRhQuqXN0MNOqcMMBrKYEunu6M= + + Resources/core/icons/send-fill.svg + + cXngIY6OdHW+upPO3m4Xg9c3XsU= + + Resources/core/icons/send-plus-fill.svg + + xQjXHIHjUm45hegR5RzXqppkXVQ= + + Resources/core/icons/send-plus.svg + + POM/iAALA+LndXfZmTilFt6h1UY= + + Resources/core/icons/send-slash-fill.svg + + 1OLBtZl1qMKk96fAbnw1a18/tFs= + + Resources/core/icons/send-slash.svg + + 7FYNcaV7YqGGUg7t3LZiDh36Glw= + + Resources/core/icons/send-x-fill.svg + + djtb4NNfKiC/azgnxUDbfJ3S1r0= + + Resources/core/icons/send-x.svg + + xinP/nHG2q9BLLysAGS8XB+0X1s= + + Resources/core/icons/send.svg + + oniiJtemznUKwc4ifdcbK84jIXk= + + Resources/core/icons/server.svg + + hTpc+VMSxkVnJ2dc+4K2qzTZTs8= + + Resources/core/icons/shadows.svg + + xsvK53tq/PqtR3nVKu/6b41E694= + + Resources/core/icons/share-fill.svg + + OFqWJ/13iVQnUWoEsbFqYUCAJ9A= + + Resources/core/icons/share.svg + + TZOkbkVrwNBb6lqh2rGlrw3n0+8= + + Resources/core/icons/shield-check.svg + + fXSd7OGgiJnlTU6DRzVTj4GflNM= + + Resources/core/icons/shield-exclamation.svg + + AbdbhjJlwxxeE/ZSJ+NnzQInX0c= + + Resources/core/icons/shield-fill-check.svg + + JF6grEzY9L+8PwPyRlRnHUt6UVg= + + Resources/core/icons/shield-fill-exclamation.svg + + ajPJhm2nWLP13btrAceol6C1u/s= + + Resources/core/icons/shield-fill-minus.svg + + XqrVK7ee3B7EUwEUEmo7yD6K1X8= + + Resources/core/icons/shield-fill-plus.svg + + 1BsBNO76mYh/AAm+GAP9pshbZwQ= + + Resources/core/icons/shield-fill-x.svg + + GLNTliTio3YIq7QsVD/SHjCoLpI= + + Resources/core/icons/shield-fill.svg + + ap28yn9hQYg0lbd9lYVrVcG/0pQ= + + Resources/core/icons/shield-lock-fill.svg + + 9jn9VMeNMPzpu5L/AGzP8oqW2Cw= + + Resources/core/icons/shield-lock.svg + + m5ShI0/M3Lqj8Ux+uIF6C1lty+Y= + + Resources/core/icons/shield-minus.svg + + ve3RClcW3uSF89yF6hWOBFi6Fr0= + + Resources/core/icons/shield-plus.svg + + cIhTDAV9DRCS+cWtUADVHGB4sZ0= + + Resources/core/icons/shield-shaded.svg + + rR1UcYwA5YUYjAnAb1ROX3rAGiI= + + Resources/core/icons/shield-slash-fill.svg + + zcw0bNYyz2DN23sbsJNynr2Thac= + + Resources/core/icons/shield-slash.svg + + nObv9NZQeG5HzB19LU/McFQjsh4= + + Resources/core/icons/shield-x.svg + + GKT81jgP6ILIAW7SqagrBx8yO3U= + + Resources/core/icons/shield.svg + + Y1IrlfwJxzrlv29RwY+3zQWxRzw= + + Resources/core/icons/shift-fill.svg + + 6pVRX3bskSv0jfQtliGLUUaw+BA= + + Resources/core/icons/shift.svg + + YLx60s3w7OwjbN3gHwt8QEXJCOE= + + Resources/core/icons/shop-window.svg + + ehuvSzamb/UyPSmougGWs/EdqhI= + + Resources/core/icons/shop.svg + + XjsO38UnhWAMHkxTtr6h6y9Ahns= + + Resources/core/icons/shuffle.svg + + iwzyxJp5H+etTxUimJBN3A6RL3A= + + Resources/core/icons/sign-dead-end-fill.svg + + uuKRojFWJC+Xco7U0IuhaKSTP0w= + + Resources/core/icons/sign-dead-end.svg + + v0OhRgCxpkONyJhOHzS8hkfaU1c= + + Resources/core/icons/sign-do-not-enter-fill.svg + + O2KOzavQ/ZshEvhS2dXewb2OdCE= + + Resources/core/icons/sign-do-not-enter.svg + + 1Vzd2G0m2VcIx1kw3dTIWV4Tsdg= + + Resources/core/icons/sign-intersection-fill.svg + + pAfxqIH+vHD7vEdIvC44fv0SGeY= + + Resources/core/icons/sign-intersection-side-fill.svg + + 4H//pNXJNiAjZ6KJNJfT7D5gTk0= + + Resources/core/icons/sign-intersection-side.svg + + Oq+iVYS0C2V9GvZsBeKUw4dfCKs= + + Resources/core/icons/sign-intersection-t-fill.svg + + mbKjqLTazW/SavCEYCWUmhtU7CI= + + Resources/core/icons/sign-intersection-t.svg + + QkIwvwkfXTD1gjiAsyZUOG/zBP8= + + Resources/core/icons/sign-intersection-y-fill.svg + + F3kbM48JaY8EHRNTbAWlPvMPhZM= + + Resources/core/icons/sign-intersection-y.svg + + wOPka2taqvtd9MGm+chZumDuDPo= + + Resources/core/icons/sign-intersection.svg + + L9ceN6Wk2eCZor5B5mYnEzT0rfw= + + Resources/core/icons/sign-merge-left-fill.svg + + 1DvYZK0l4ZTkK2qxuLRsjghiHXY= + + Resources/core/icons/sign-merge-left.svg + + nd/ScRzUEdmZXttnuz1pIz4/q+o= + + Resources/core/icons/sign-merge-right-fill.svg + + pSKJyONDMyq52sIs6K/OC+98GYs= + + Resources/core/icons/sign-merge-right.svg + + aZyMQ0Qw+rXufxfqHu/FpyXyeuM= + + Resources/core/icons/sign-no-left-turn-fill.svg + + +p08OcyXjkuBtUA+T15GCsdDpSY= + + Resources/core/icons/sign-no-left-turn.svg + + 1SwyV6uf6jHCitOOCYQ2eo6tlXs= + + Resources/core/icons/sign-no-parking-fill.svg + + mrl1y9VU7hOLXw+mmL4VV4xYjFE= + + Resources/core/icons/sign-no-parking.svg + + qiQ1GxiLgSvB0O7ACnDGXHQP2Ys= + + Resources/core/icons/sign-no-right-turn-fill.svg + + TVwhzHuI1iwfiLUzD7kMOGj35Co= + + Resources/core/icons/sign-no-right-turn.svg + + kx3OZ+mSq/08S295+MrX5KlKwcs= + + Resources/core/icons/sign-railroad-fill.svg + + e1GJhdE/Xrx2RGmKFzzZ6HjZqYA= + + Resources/core/icons/sign-railroad.svg + + 6Fd/EwEImwaBcPFOtp38V7d8Y4A= + + Resources/core/icons/sign-stop-fill.svg + + IzVGLkWlGZ9nhLXE+96GeO1+uhI= + + Resources/core/icons/sign-stop-lights-fill.svg + + LyV+sWWjDdllhZMrCrcwrr/+rfI= + + Resources/core/icons/sign-stop-lights.svg + + vxee9geoKePrhIEJsqTCWHyhi/g= + + Resources/core/icons/sign-stop.svg + + b8E1hOH4t822wSslzz/gZc8Ksrk= + + Resources/core/icons/sign-turn-left-fill.svg + + TmggbtNvVvYMvGh0pC3QaAaWAUY= + + Resources/core/icons/sign-turn-left.svg + + dlop0QivCz6QqfuIhKTYZ2XDqL4= + + Resources/core/icons/sign-turn-right-fill.svg + + 0jmXaq2/7iG87xySekz0Nyg+gEo= + + Resources/core/icons/sign-turn-right.svg + + d+ZxtNLa0sc4WhVS24hPe+p6jcU= + + Resources/core/icons/sign-turn-slight-left-fill.svg + + AFGnn6QJ9RL39Xe/x+bfZU7U/Rw= + + Resources/core/icons/sign-turn-slight-left.svg + + E1P6w8EJ5C9ibym4jfwKvBimZEI= + + Resources/core/icons/sign-turn-slight-right-fill.svg + + MHV+T9irR6fpTqf9Ec+tGZ0u9RA= + + Resources/core/icons/sign-turn-slight-right.svg + + wLkVBX/2XDOkKiHxL1vPLzkzRFY= + + Resources/core/icons/sign-yield-fill.svg + + UHLe0VQo8mR5ymBJPB7an+NKWKM= + + Resources/core/icons/sign-yield.svg + + rpfyKhNSSy6/12GBi4msh/5elhA= + + Resources/core/icons/signal.svg + + 8YIS2FL02JD6GqxPHnruMeHwqAw= + + Resources/core/icons/signpost-2-fill.svg + + uxj3lin2NsU9qedcVAeYmFhGE2k= + + Resources/core/icons/signpost-2.svg + + Z3nkRHjx8nxJ+9JYXLtM8qlHIQ8= + + Resources/core/icons/signpost-fill.svg + + F7xSpnRKA4q+PLwrZQ3e7LbFJ+c= + + Resources/core/icons/signpost-split-fill.svg + + gObz/x8AgGXLLUZ+q0UdG1VSE2c= + + Resources/core/icons/signpost-split.svg + + MG1OWMb41b3c0nOUWQta8mSvBtI= + + Resources/core/icons/signpost.svg + + 8MswXY4XcGQ1QPKU8xgTPIKpTxA= + + Resources/core/icons/sim-fill.svg + + 2RmumAwgEXeCFs7Rt/79cZWjg1k= + + Resources/core/icons/sim-slash-fill.svg + + 2AYpMANUyhVoPNhV4efbXFuHDsA= + + Resources/core/icons/sim-slash.svg + + 3FHMF+I3NUSB3yRbRw8n4MVIzbo= + + Resources/core/icons/sim.svg + + QgdQ54Nw5/mKnmXH7nMq3Jiq2aY= + + Resources/core/icons/sina-weibo.svg + + gwSSGyfI0m4Eo/HwXEaREFARBCM= + + Resources/core/icons/skip-backward-btn-fill.svg + + IlXcXP0o/ZtpayHwO1Ymu6mfS78= + + Resources/core/icons/skip-backward-btn.svg + + YleY430SntvmisegJ3CbL08iZFA= + + Resources/core/icons/skip-backward-circle-fill.svg + + IgNHwJGH3hnC7idrTYMJsH63xzQ= + + Resources/core/icons/skip-backward-circle.svg + + 2ZIbvosPMp4NrOtDJaZRl/W50GU= + + Resources/core/icons/skip-backward-fill.svg + + IhHuSj8PY+wLkn0zFaeglfpCovk= + + Resources/core/icons/skip-backward.svg + + 8Z4znWeq43+rV3fFu+0N8bfRCkE= + + Resources/core/icons/skip-end-btn-fill.svg + + bMa0x7E18/Um9wVWfiSlYYI2eMA= + + Resources/core/icons/skip-end-btn.svg + + 8N8iRa3TMiJG5oQoEHZMz0kYai8= + + Resources/core/icons/skip-end-circle-fill.svg + + XMrFnrDjuFYcZNUD4BmLzZcLRVQ= + + Resources/core/icons/skip-end-circle.svg + + An+K0D1g59w9pQy0qqaCNCxL0es= + + Resources/core/icons/skip-end-fill.svg + + RRNoKzy4KGwwQT/y1ihdCw4YBvo= + + Resources/core/icons/skip-end.svg + + uvEmyDLvWs3EuoPrXjC+mNtqvD8= + + Resources/core/icons/skip-forward-btn-fill.svg + + KHVI9gYyTNomFV4Qm6/J1Ad/jpg= + + Resources/core/icons/skip-forward-btn.svg + + HOc4yKLPah7kstyIlQa+zOVfb4o= + + Resources/core/icons/skip-forward-circle-fill.svg + + 8pb+tfpkG4KuzOExYNJhBzQ2xlo= + + Resources/core/icons/skip-forward-circle.svg + + iGJSyX4bx1DRRXlmioEQ1dpiBRE= + + Resources/core/icons/skip-forward-fill.svg + + pnhWQmhILluHFYUr2JD+pFd8UZ4= + + Resources/core/icons/skip-forward.svg + + ND7OX9L7ZStmrMYHLhs3+n4CuMk= + + Resources/core/icons/skip-start-btn-fill.svg + + 888cNZ7PFAse/4tdZhUQujcUKxQ= + + Resources/core/icons/skip-start-btn.svg + + s/8/upzyWkt/O09BLXP9TvF+Ivo= + + Resources/core/icons/skip-start-circle-fill.svg + + M3TlCGKwWyAoLbq4sxjye8bCo6c= + + Resources/core/icons/skip-start-circle.svg + + ZLFk41NlqbSDi+cMzU2OMbAcitU= + + Resources/core/icons/skip-start-fill.svg + + MVvR8WlqYHH4+kbnuOXvhi53RvM= + + Resources/core/icons/skip-start.svg + + +O5mQJcn7AQu8891Sv2+aVODJl0= + + Resources/core/icons/skype.svg + + 4YKeIT5AeJZpeW6Hv7y5MEmDE04= + + Resources/core/icons/slack.svg + + Tfkw3fR0NXInqUzW+Eij4nVT+ik= + + Resources/core/icons/slash-circle-fill.svg + + RslYbZWf98TwTWTt/FSmxkoC9hw= + + Resources/core/icons/slash-circle.svg + + o9dQj8n8cdRrqEzC09DX85rPFps= + + Resources/core/icons/slash-lg.svg + + uCjfAUwSU4NDJCy6zofj1foZhzc= + + Resources/core/icons/slash-square-fill.svg + + kLRJqXp1HIIiLaO/pUa29YsLa2Y= + + Resources/core/icons/slash-square.svg + + MPpi5Zf40ggpZ6DsgL9duHEkJoQ= + + Resources/core/icons/slash.svg + + h0tABcoZIV+CI3z+3QQvqCqc/VA= + + Resources/core/icons/sliders.svg + + 9XAXsbwZi76qdJbY07+PzUHrfYY= + + Resources/core/icons/sliders2-vertical.svg + + HzK/yyD+JG0L1R+9y8LG1avX4JE= + + Resources/core/icons/sliders2.svg + + WvCbH69tqEhdzpr4LwhzMZGUNyk= + + Resources/core/icons/smartwatch.svg + + oG6H2CudydD598WzIC2EgnEhZro= + + Resources/core/icons/snapchat.svg + + Yv0M3j5qZki8zDugzEY5VcTwy3Y= + + Resources/core/icons/snow.svg + + 0f5LdOnWF9GvDcie8IwY3jjycoE= + + Resources/core/icons/snow2.svg + + Xe7uUkTvXnXLXfbPX4a+WjqFFjQ= + + Resources/core/icons/snow3.svg + + IglZ8AMk8CBQlBw5hYiN/VWVYFQ= + + Resources/core/icons/sort-alpha-down-alt.svg + + YqDepZqgB/SXKOasvY+XCq554jM= + + Resources/core/icons/sort-alpha-down.svg + + 17edOzajo9ybhNg6w7w+3JD9SjE= + + Resources/core/icons/sort-alpha-up-alt.svg + + OFRyP8RdO94XX2EeUj2tUpb7La0= + + Resources/core/icons/sort-alpha-up.svg + + Dv+HLFFWDcAwX1cfzD7Zyt8M69w= + + Resources/core/icons/sort-down-alt.svg + + 1jRxnOfBPQubl/a22ThWGsCBTCE= + + Resources/core/icons/sort-down.svg + + 6ekJHsLffreFdSYggRnzMDKNOIs= + + Resources/core/icons/sort-numeric-down-alt.svg + + yC50JjDwJQ8ThxD+UDAY1f/GQYQ= + + Resources/core/icons/sort-numeric-down.svg + + lO+pVORaSB7ipyAEfUxdecuV9h0= + + Resources/core/icons/sort-numeric-up-alt.svg + + szzZbW6si4y4YwL+ypQITpSAqiU= + + Resources/core/icons/sort-numeric-up.svg + + 8RMYw69cJ10F/ITWj3dGYELJn/I= + + Resources/core/icons/sort-up-alt.svg + + 8m4hMV/ByZOeT6GiolFtMI2uXoI= + + Resources/core/icons/sort-up.svg + + yT+rCamgrAGX356KCAh34gwV3m4= + + Resources/core/icons/soundwave.svg + + sW8fu/UfbiCATHnw6ezINSZQ0oY= + + Resources/core/icons/sourceforge.svg + + EIVqu+yLWdMPWoOj7y9Ia+usxX8= + + Resources/core/icons/speaker-fill.svg + + kQlze/anJToSv2j3I6WauzKsu9I= + + Resources/core/icons/speaker.svg + + 4XIB1MLW4nn8lFEHT4F7NtgQ1Hc= + + Resources/core/icons/speedometer.svg + + r+NO/CJeJVLM/FPMElHZvTLWnOQ= + + Resources/core/icons/speedometer2.svg + + 51alQhimKgdv4uKN3ok0b0Lz+9w= + + Resources/core/icons/spellcheck.svg + + k6ODJYiaXPPUf3oaVDHBcYK3nCc= + + Resources/core/icons/spinner.svg + + RV9O255pHr8J3PWX3rcpu/GimN0= + + Resources/core/icons/spotify.svg + + ZEIqSCESWDJeXSkTHeAVy2UDSYs= + + Resources/core/icons/square-fill.svg + + 3nIWeR8kfLyDWrtW6eZmYES/MSI= + + Resources/core/icons/square-half.svg + + nbrt41WLGZDyrqSTTNP7i0hahCg= + + Resources/core/icons/square.svg + + l7gmVkd1nBuvDxbUAyRLojTnIH8= + + Resources/core/icons/stack-overflow.svg + + XhN+B0PmZqChryf8UsEwWo/WWpY= + + Resources/core/icons/stack.svg + + nW8EMUJymdwn7iEF8bNgAp/GJCA= + + Resources/core/icons/star-fill.svg + + OeVARN1mqBKXDeok5CYeuBAB5H0= + + Resources/core/icons/star-half.svg + + 3wniLAE2wkix7Vlsj06I7Bp/vOg= + + Resources/core/icons/star.svg + + rOM+X5Va7m25QIaBjXLUem/QB3Y= + + Resources/core/icons/stars.svg + + bg6a6nUNyE14iVzdY7WRtTIIpbI= + + Resources/core/icons/steam.svg + + atvTqZJ0gE0B69AJAvZdEnKL+w4= + + Resources/core/icons/stickies-fill.svg + + 2rfu8/GRYX3cB1yRHdcgjDiuvj0= + + Resources/core/icons/stickies.svg + + vOiOou5QIHUWIJC5UxugZB59EwI= + + Resources/core/icons/sticky-fill.svg + + sdMbN7P0qL1WQHZVeENWcKLucKg= + + Resources/core/icons/sticky.svg + + Ka9VcIT95z+02gGGvYACeDSUDow= + + Resources/core/icons/stop-btn-fill.svg + + +rbKj3CQde14rt6iW4vfRORWGcY= + + Resources/core/icons/stop-btn.svg + + 8mCY5pqFweD72h8DYelYs2pDW2I= + + Resources/core/icons/stop-circle-fill.svg + + 9rK9XjDsF86IGC4PsKzAFE29PHk= + + Resources/core/icons/stop-circle.svg + + g9AS9S6qimcPO9GQE2b4bqWMjiE= + + Resources/core/icons/stop-fill.svg + + KIB6i5+NuYje+Ki9RsGQFUS5z9E= + + Resources/core/icons/stop.svg + + XqzRbYHRHhHJuyVroBsXTyGThCA= + + Resources/core/icons/stoplights-fill.svg + + VY1Hnw71RCrD2zWKpLQqVnr7ER0= + + Resources/core/icons/stoplights.svg + + KWjHinOSXDTXO7dZK1fViD3THcA= + + Resources/core/icons/stopwatch-fill.svg + + iAjR5Pn5GVba9sm3mqBiQ0z+L+w= + + Resources/core/icons/stopwatch.svg + + ZpyBGbpyX3bTu67hhR+rXXE2ftE= + + Resources/core/icons/strava.svg + + f402zNXbgGV/ntZv6ATQpywfldc= + + Resources/core/icons/stripe.svg + + LoSaODyoKzwHt6J2P3V1jaT6M18= + + Resources/core/icons/subscript.svg + + hDEhuY+8KudGlMqe4laoY8jUXUs= + + Resources/core/icons/substack.svg + + oGn/trdlZ/7tb7MLokjaKsOmDqI= + + Resources/core/icons/subtract.svg + + JgAI4t/ctw8I84lb7B6RfWW/Cvc= + + Resources/core/icons/success.svg + + ijGT01WFNyBl/RG3YIxetJHDQ0Y= + + Resources/core/icons/suit-club-fill.svg + + Wjbm4tHkq45yvYdlZRQOKEkyr1c= + + Resources/core/icons/suit-club.svg + + 0WfN1UNUHG3zMLFHfR6vOc3w5i4= + + Resources/core/icons/suit-diamond-fill.svg + + j4lJfanZpH9X1WhZK7OYJHM5UYE= + + Resources/core/icons/suit-diamond.svg + + hPg0MBPd8KQq0KT5V6jHB6ycZkc= + + Resources/core/icons/suit-heart-fill.svg + + QrRo+/GYLD5Zg2DqshythxenKQs= + + Resources/core/icons/suit-heart.svg + + 89K2TaH3/aI2/izduFemYKhE4zA= + + Resources/core/icons/suit-spade-fill.svg + + SPLv6BRMmdPiVhBKKUV901XD6e8= + + Resources/core/icons/suit-spade.svg + + oBUc4Us2Mj29o2S+2MpXtUa7vIE= + + Resources/core/icons/suitcase-fill.svg + + siA/0nob2mBbv9r8GtlRMxcnJtg= + + Resources/core/icons/suitcase-lg-fill.svg + + eLq0+0rTcLmfmSB7i3owIbTN+sU= + + Resources/core/icons/suitcase-lg.svg + + gT0GPYi/VUjxMBa4uZYWCnhbAhw= + + Resources/core/icons/suitcase.svg + + DbweZmkE9Z0Fsv4TtQhlmx4aKwo= + + Resources/core/icons/suitcase2-fill.svg + + MjG2PLyhVgwyW7AW4Frb21Kij68= + + Resources/core/icons/suitcase2.svg + + 4XmBDM/dcy0Th76nYRzwjafNfYA= + + Resources/core/icons/sun-fill.svg + + U3mvcJeWGpGAQToCJ7Zs8ecr5cw= + + Resources/core/icons/sun.svg + + oRMwan0wejUxmksCrLmkPsKvBI4= + + Resources/core/icons/sunglasses.svg + + nZ/s9nHmyv6mbxMjqvpGbbemIl8= + + Resources/core/icons/sunrise-fill.svg + + hdhMG1GzvP7J3JhHrXDFtCiXK3U= + + Resources/core/icons/sunrise.svg + + w3CwVzVE/46Ux0TifHFxZ6ZyOtk= + + Resources/core/icons/sunset-fill.svg + + wpQDuKYkM1hUrmrEMcKC8/4jojA= + + Resources/core/icons/sunset.svg + + U+S8+Ni+NxiZENOQWy9lrzgjG7o= + + Resources/core/icons/superscript.svg + + ejjplD+5D0m/oeM304ZyfFoL3zo= + + Resources/core/icons/symmetry-horizontal.svg + + VbrmyTxVx4m+taL1g9FB2ZMcbps= + + Resources/core/icons/symmetry-vertical.svg + + i/356RKJ7ZTVhJGOm5VUye4YA9g= + + Resources/core/icons/table.svg + + 2cK5B+MdNnrt+ywTwdsxp3k06Ss= + + Resources/core/icons/tablet-fill.svg + + cObYk4O7U87LpRaiLIctwHMWugw= + + Resources/core/icons/tablet-landscape-fill.svg + + Qc0iGHcVK2GpVX/OMnI5q4oakcc= + + Resources/core/icons/tablet-landscape.svg + + +CvnT8Pr2IGeJPRpaiExdSCZMR0= + + Resources/core/icons/tablet.svg + + HkFwozJBMnCCFbVwts7o5QcWWnw= + + Resources/core/icons/tag-fill.svg + + zsDNDayyP372w72MPxqnRPRLSmo= + + Resources/core/icons/tag.svg + + zmmvpWui1QLgcy2tXscLbZqMMCo= + + Resources/core/icons/tags-fill.svg + + Uh1LTzHZkU9j6hRGt1K1B2G0MYA= + + Resources/core/icons/tags.svg + + DZFmZyT0ZS8KDDhSTPtNvU77Vo4= + + Resources/core/icons/taxi-front-fill.svg + + IgxNOxvBiKJGShA6IcyASLddATw= + + Resources/core/icons/taxi-front.svg + + socuElKWoZenU3QPdkudn8Ijq/s= + + Resources/core/icons/telegram.svg + + DZ5gj6X0Ij0IzTWMXgD99gUM2UM= + + Resources/core/icons/telephone-fill.svg + + 8MZz9VcFF1ALICCEu40jmlvsExM= + + Resources/core/icons/telephone-forward-fill.svg + + 40a9i9KN5gG0br33/kHS/+oRmIw= + + Resources/core/icons/telephone-forward.svg + + peMVqv7l5+ZMrTpdCLv8t9E1s8A= + + Resources/core/icons/telephone-inbound-fill.svg + + XDhMpiSXGYPQBwEp4lxtsROp1qQ= + + Resources/core/icons/telephone-inbound.svg + + QK40X61MjknMh6hbQdx7OLbVtR0= + + Resources/core/icons/telephone-minus-fill.svg + + Vqlj8LuLTi+F16DT477TyqZ6vz0= + + Resources/core/icons/telephone-minus.svg + + qesTQHpvMLBXq1eSEfIg70hp/zE= + + Resources/core/icons/telephone-outbound-fill.svg + + EqAVA0gvd3ErUPGGTuPcDdIstDY= + + Resources/core/icons/telephone-outbound.svg + + lFAXDRyW624iF9fMdzhhRVR/KhA= + + Resources/core/icons/telephone-plus-fill.svg + + PCK0HbGclGVhfnuTU/o5lPEK4Xk= + + Resources/core/icons/telephone-plus.svg + + XdLmSEzpnRB7Y6cGac/t7sfeoco= + + Resources/core/icons/telephone-x-fill.svg + + 3Akd7FmIHe8XVyfmkGtn7utkK+8= + + Resources/core/icons/telephone-x.svg + + iTlCM6skJFsdK+d2+8VgAZmRSc8= + + Resources/core/icons/telephone.svg + + 932aQYxC5MP7l4RJ4bn24SPDtbI= + + Resources/core/icons/tencent-qq.svg + + i42tnyNxKvNkqytxCyjnBZC4/sk= + + Resources/core/icons/terminal-dash.svg + + agS5FwNjrC3kMwE42GL07C0UlF4= + + Resources/core/icons/terminal-fill.svg + + 1QSQtnWJL5Sin0VMZgH0wBtZxf4= + + Resources/core/icons/terminal-plus.svg + + vqC0Xj8J4oUHr4tXYMLM/ql67a8= + + Resources/core/icons/terminal-split.svg + + YhFY4wtHHMs9kEkdIwvHdi/RWYg= + + Resources/core/icons/terminal-x.svg + + IMxc2zX1C2LFAf5tr0EpJoDdOhY= + + Resources/core/icons/terminal.svg + + bHe3ZFsJSB2mISiu3on1tczxcUc= + + Resources/core/icons/text-center.svg + + 41XgpG4xHEz9btV1T+Dxtpn9YkA= + + Resources/core/icons/text-indent-left.svg + + qGBN4SP7CONU351BAlUjKUNDCgs= + + Resources/core/icons/text-indent-right.svg + + a6KuQ5VjAXchC1Y0kRn6bGCusfY= + + Resources/core/icons/text-left.svg + + /vlvRV6B+eXMYbQkRNhkaD3P+Wk= + + Resources/core/icons/text-paragraph.svg + + N+d+EHWWMdIsxuhKNA92rNRuTDk= + + Resources/core/icons/text-right.svg + + 9PfiGKdwUeOFkZP58Qr+ExoXmp4= + + Resources/core/icons/text-wrap.svg + + gnleaXPlvirQDzvO1FbHLkxKy58= + + Resources/core/icons/textarea-resize.svg + + OmbPI8jU6RS2S5Io2OTlpwIeqyc= + + Resources/core/icons/textarea-t.svg + + CDZkcmlnXw1nM6wFMORBPrkkiA4= + + Resources/core/icons/textarea.svg + + ShaWoletdI89NMCHu+LnXREy9ms= + + Resources/core/icons/thermometer-half.svg + + /4HdDwK76PYWFvvAD4XyC9zEutw= + + Resources/core/icons/thermometer-high.svg + + OwFko2vBnkMmka5FO6KEn68jnq0= + + Resources/core/icons/thermometer-low.svg + + QRG44fdwEK1zJfye9Up7t6kSHrw= + + Resources/core/icons/thermometer-snow.svg + + Ub5r02nC2X6qLjyrsu6ogmzfzcI= + + Resources/core/icons/thermometer-sun.svg + + 4qnpCJQ52QLEWYShGGZd4CdRoCg= + + Resources/core/icons/thermometer.svg + + uUEgWNhWva9DLWLCKOzYkh7ygk0= + + Resources/core/icons/threads-fill.svg + + Np0Sy+MDnFRX8/YWh1O/PLCFSqM= + + Resources/core/icons/threads.svg + + /z/2h6HIFDPZgWL7mT+SG5QpsiI= + + Resources/core/icons/three-dots-vertical.svg + + ZUfKZ8j9ifaMIVBpwYTmVKjRwp8= + + Resources/core/icons/three-dots.svg + + eePk57EQTv6SPob9HmHk3FEFu+g= + + Resources/core/icons/thunderbolt-fill.svg + + UW/5of2c1Cb2opxIzGkfNQB6Zjk= + + Resources/core/icons/thunderbolt.svg + + bswl6qmbCr2J6sPyyDqVVZZUqjQ= + + Resources/core/icons/ticket-detailed-fill.svg + + MlZ72iBYFcrXcx4Jyoq60BUHoRU= + + Resources/core/icons/ticket-detailed.svg + + SvwFAjnw3WfUm12ld5k+SQXeqsU= + + Resources/core/icons/ticket-fill.svg + + NThKvnGZeMT89kjx1mXdsH1sDiA= + + Resources/core/icons/ticket-perforated-fill.svg + + IAk9LDk/axICHQy0Au2b49nJijc= + + Resources/core/icons/ticket-perforated.svg + + BenkbYHcQR3jheEFzDFS+YGf5Ds= + + Resources/core/icons/ticket.svg + + 3RJF+Ba3wNUfTuE16Vbgxt89oac= + + Resources/core/icons/tiktok.svg + + yDJ7ASCh8yKZeQPKJ1q16hpy4Cg= + + Resources/core/icons/toggle-off.svg + + W/V7W06Mnl/8DfFpVpwWDt8gPHM= + + Resources/core/icons/toggle-on.svg + + PDSx3ffgXMwrey2i7L/vehjw01c= + + Resources/core/icons/toggle2-off.svg + + DvIN/Hp98cP4pEKXlzeg1NFfgzQ= + + Resources/core/icons/toggle2-on.svg + + PvvAihrlc0cve3M2O5AcEvnBXQQ= + + Resources/core/icons/toggles.svg + + 88ZCjTiYJy01/pCm8alMHpd0bsU= + + Resources/core/icons/toggles2.svg + + 0SzyYHNKXqy2gonQ0w3lYtPLfC0= + + Resources/core/icons/tools.svg + + 7WxX5Er9Xf4JEUFBIMe8WZNt4G8= + + Resources/core/icons/tornado.svg + + /gJ1+MDpBJzMPUeSmgEXazJGNnA= + + Resources/core/icons/train-freight-front-fill.svg + + iWt0PiIHPe0QebsMQZ7iu/Lh+EA= + + Resources/core/icons/train-freight-front.svg + + yZxS97dYPTnBZFZZ/l/1Yu4QI+I= + + Resources/core/icons/train-front-fill.svg + + pN+dXK+MH7rpRPAxF21OgFBahek= + + Resources/core/icons/train-front.svg + + mX04rUCvkm4Gi1rNfIhEPdiD4sc= + + Resources/core/icons/train-lightrail-front-fill.svg + + G2V+EhR4iFDeWw4El3fmVGNmv3w= + + Resources/core/icons/train-lightrail-front.svg + + WURvmHZzaDMy3fdIp8gvCx/cSc0= + + Resources/core/icons/translate.svg + + +8gA++0Uy8GUrQC3Taiguc6s8Do= + + Resources/core/icons/transparency.svg + + r1nq+elDv7+yO1MqxgYycghY/jQ= + + Resources/core/icons/trash-fill.svg + + kPHm9/65FPe6Invz7sNyle5BPuM= + + Resources/core/icons/trash.svg + + Oif4b0u4IBtnyR09PCPVRIgUuNw= + + Resources/core/icons/trash2-fill.svg + + MJ5a2YYzMnKApYx/Y9OkPeCn9Cs= + + Resources/core/icons/trash2.svg + + 7ySZP06gMsPVI0SdcbFX7Jr0+3c= + + Resources/core/icons/trash3-fill.svg + + nowK7VxoyTXOpSZE0cl4ZPMFErE= + + Resources/core/icons/trash3.svg + + YxZxtEDLfY3myma2vQ2fq7AZiJo= + + Resources/core/icons/tree-fill.svg + + k/SSRhuQQyikCfI+KT4SVBjaw4g= + + Resources/core/icons/tree.svg + + QyF9wH5fOxchuZfiIZ+n9k4/dE0= + + Resources/core/icons/trello.svg + + WZfOcyb8hbrrkGJfV1xaxENtBHE= + + Resources/core/icons/triangle-fill.svg + + uV7Cwx0rvFmVjSxlTDLhU5lMMZg= + + Resources/core/icons/triangle-half.svg + + OhY1kaBGewrFiIrMt2KKEq2iSa8= + + Resources/core/icons/triangle.svg + + RDIpUbFHyGUufkG7Fm8/5s7qNe8= + + Resources/core/icons/trophy-fill.svg + + XHhJ7d3udN3PrWEF2VL+VZoAa6A= + + Resources/core/icons/trophy.svg + + XqgmQSvu0bQ7GqAPIgOT07Picfc= + + Resources/core/icons/tropical-storm.svg + + 7CX9uE7CvEMarHvv6jdoUsS9JMA= + + Resources/core/icons/truck-flatbed.svg + + JuPyM1Xlkjd8HKznVSBut0uJkp8= + + Resources/core/icons/truck-front-fill.svg + + vd91EeEVfwYg2IusnqCtj2g+l+M= + + Resources/core/icons/truck-front.svg + + rVyTbdu4XlQjEZ2/pWZiKW/BWeQ= + + Resources/core/icons/truck.svg + + dF7sc1s0B/b4QYLi5rfTiUxeciE= + + Resources/core/icons/tsunami.svg + + j2TsZWv9uvOsm5JXVOWGzYJQqDw= + + Resources/core/icons/tux.svg + + /o0AILbvS2nMTOe6xIDvBCuAFto= + + Resources/core/icons/tv-fill.svg + + WPM0T6TBRHiT9lbAmCpcvlg+97Y= + + Resources/core/icons/tv.svg + + xLNoONwu2JYMD1lxVhFgJTsJ0u8= + + Resources/core/icons/twitch.svg + + fvd0knUU/AT9Xr4beTa0R2ArcGs= + + Resources/core/icons/twitter-x.svg + + FIrSjQeE6iwf12cCMWNOQ/b9t6o= + + Resources/core/icons/twitter.svg + + RlbP0wgB1wb4lym5DzexE0Yfh90= + + Resources/core/icons/type-bold.svg + + Xr+JJ1up9XyNTN/TSjFZBFMavbo= + + Resources/core/icons/type-h1.svg + + MkS1rR8GCctdJrY9mQKbKAgpHs8= + + Resources/core/icons/type-h2.svg + + wcDquUrIZxB+55nlw6882iCBvRI= + + Resources/core/icons/type-h3.svg + + e762zWH1ml662xjnH3ielq1Mjas= + + Resources/core/icons/type-h4.svg + + oVduvSoGhYARc75Gv9jaKVdOMwA= + + Resources/core/icons/type-h5.svg + + txoAnOz52+z8dCsRUIZY7su4HSg= + + Resources/core/icons/type-h6.svg + + 4bRi/iOnxj45VXLJtSAfLhOXz9k= + + Resources/core/icons/type-italic.svg + + hpKKRLn8wSqmJmLFSPpeL8MO5a4= + + Resources/core/icons/type-strikethrough.svg + + hE1py5z6hoi296M71/SJv7nZhgM= + + Resources/core/icons/type-underline.svg + + omPHABehycoCRFTEkOEQ413DYd8= + + Resources/core/icons/type.svg + + lvUbua86ZGsK/Vi2K8vKfMUs8hk= + + Resources/core/icons/typescript.svg + + LjcXvPp+YdyHpgGbY/CxZcJKink= + + Resources/core/icons/ubuntu.svg + + wohNojyrFX02o6Tx5hkNJMZVbqQ= + + Resources/core/icons/ui-checks-grid.svg + + eZn+DeYP+J695YijUtgNwXEg7rI= + + Resources/core/icons/ui-checks.svg + + GfNLNLEo+XAuf/eQPz4TIFGlG5I= + + Resources/core/icons/ui-radios-grid.svg + + /hCHm1uyJywTs6AdJ4/8NQmmRP4= + + Resources/core/icons/ui-radios.svg + + Zb4oqUUc0aCdGaem3ivqjmM6/8M= + + Resources/core/icons/umbrella-fill.svg + + llLCw5WzPEgHRqubN+lWgE2Qpvc= + + Resources/core/icons/umbrella.svg + + CG9gfi0s7gwajqYzWmSztavlAhc= + + Resources/core/icons/unindent.svg + + 1q6kuW9sQ8cYhRBaxXx+IMq5nfQ= + + Resources/core/icons/union.svg + + 7DlWJT+ebxNwen0kPPmvvr/LGvc= + + Resources/core/icons/unity.svg + + +TJXLz9F9JtFxXsWMHoGpo68PaI= + + Resources/core/icons/universal-access-circle.svg + + 7ONB5dyME30LabAs1lyxqsdId8A= + + Resources/core/icons/universal-access.svg + + 8jmul/eu36Khj9RzYNy0QNB6r+Q= + + Resources/core/icons/unlock-fill.svg + + /0E8rTvNTRO/4+1FAtYeZ0Vfw24= + + Resources/core/icons/unlock.svg + + BcXyTkfq202K2nOquvTO+ADMWqs= + + Resources/core/icons/unlock2-fill.svg + + oy/EUD6n6BszTNw8XwxMqVCwNsU= + + Resources/core/icons/unlock2.svg + + 9fGP6VosOnSTxbHMl+52ZtKq2Ww= + + Resources/core/icons/upc-scan.svg + + o30h9sVL8RXKkP5iP+YpdqGyjsw= + + Resources/core/icons/upc.svg + + eZEDQds/DlO3sIKYrGcvCGMeYNI= + + Resources/core/icons/upload.svg + + MNgcmVdBicn4ntHDNuKTbTyXbj0= + + Resources/core/icons/usb-c-fill.svg + + oCRkB+XvgkiNjAavVHbCbCkMhok= + + Resources/core/icons/usb-c.svg + + mBIAyx/F6horI3BuP7GxPqCH8ps= + + Resources/core/icons/usb-drive-fill.svg + + jlnWDhdGdAEARf9ptX/ULzpXuhY= + + Resources/core/icons/usb-drive.svg + + N2jQoExbDclS0Ihslecd9i6Ezcg= + + Resources/core/icons/usb-fill.svg + + HP4sljQueLt9JAprNZ5a6q/Rqy0= + + Resources/core/icons/usb-micro-fill.svg + + u5cSjlG9TQiBdARISlZXbHNZvPs= + + Resources/core/icons/usb-micro.svg + + hkWA8Fk0eDrwUrVSOcOW5MRDD7k= + + Resources/core/icons/usb-mini-fill.svg + + mZv+4tZyPoS6PiQrTsUBEhVUt90= + + Resources/core/icons/usb-mini.svg + + 5jUfqEfiu7Q/7Q+7k7WzPOL7IGc= + + Resources/core/icons/usb-plug-fill.svg + + Jz+ZmpULrhl1b4cSQkozld3bcBE= + + Resources/core/icons/usb-plug.svg + + mAk6djEDMqBDbx8oD1OtJ4JL0zk= + + Resources/core/icons/usb-symbol.svg + + p3wDzmEpC9q399Cq9P4LYF4fN0A= + + Resources/core/icons/usb.svg + + Z4oNYd/y8Pm68lFM9stKNCdR7C8= + + Resources/core/icons/valentine.svg + + AHcrSDi7jxmogEBqwALTfPL7Ne0= + + Resources/core/icons/valentine2.svg + + KWm7tUPRRss7bnQLfBrk+UNNDVw= + + Resources/core/icons/vector-pen.svg + + kcKrIVAMU+gaCnPA7niAFzG6Cyo= + + Resources/core/icons/view-list.svg + + ahSBJ8uwEWqZUxy38hxH2zxXxK0= + + Resources/core/icons/view-stacked.svg + + DVkzae5llHtsMvJsGJj+dqGnWhU= + + Resources/core/icons/vignette.svg + + IYx7+iBRL/eoSn0o+lsZyWjlRM0= + + Resources/core/icons/vimeo.svg + + 5NTTZnesjdSdvyKwNLSbPa+QJKs= + + Resources/core/icons/vinyl-fill.svg + + aach744DkOF/dRyfAwF/ziFLWCg= + + Resources/core/icons/vinyl.svg + + PEwy+2QByrdL6H4+ZGlLF48xNYQ= + + Resources/core/icons/virus.svg + + svzJhRHV/ql4JHABLoR55XhFzJ0= + + Resources/core/icons/virus2.svg + + lxFXHMAmxupxlATj9H8DYk6DMD8= + + Resources/core/icons/voicemail.svg + + AvuuUEjNqkp8IXDT4TScEz2H0nY= + + Resources/core/icons/volume-down-fill.svg + + Agwoex4c0tuKPDvVjkWVBibGhAo= + + Resources/core/icons/volume-down.svg + + mhD041DTzPEJFZpRtMI14cE9E4U= + + Resources/core/icons/volume-mute-fill.svg + + n6Uy6p2269UQgnka4Ziddsb8vKY= + + Resources/core/icons/volume-mute.svg + + 8x/UEDahkgf0fZZI66aFaavT+Tc= + + Resources/core/icons/volume-off-fill.svg + + vtRYYYt0D3T1gruU3rTGCWuSTGQ= + + Resources/core/icons/volume-off.svg + + zsGDyVe6bgukLKQW784jEaD0ziY= + + Resources/core/icons/volume-up-fill.svg + + 5QS55k6rhRanGJ8bZr3J8cfPnco= + + Resources/core/icons/volume-up.svg + + KIdWiWUBH8VmoCh3loCjQAulCac= + + Resources/core/icons/vr.svg + + h+ux1rNjjp06GRAPfKKpXanIXxU= + + Resources/core/icons/wallet-fill.svg + + BZTus0610STisAw10CHsn7gO03U= + + Resources/core/icons/wallet.svg + + Cb+fbZi/BbUGityX3JiSrUQ/D7Q= + + Resources/core/icons/wallet2.svg + + xnBmJaqAAPSxrSNCMUXO6ALtkbM= + + Resources/core/icons/warning.svg + + H8fFp9OH57BGObxiJoDWo0gRYGo= + + Resources/core/icons/watch.svg + + RjxDimHBJSqAtwL+3vkyugThNec= + + Resources/core/icons/water.svg + + SRZ0osWFQLOYATwgyhXiGBErG/U= + + Resources/core/icons/webcam-fill.svg + + zu+OV3oqJlyf/RKjaB4FCGSqG+w= + + Resources/core/icons/webcam.svg + + vu+gcQTiPsSnPw2Nmh8tuXz1biw= + + Resources/core/icons/wechat.svg + + 0oIV5D95yMr4hclWOUrNdqEnn+M= + + Resources/core/icons/whatsapp.svg + + 5We2BDbdqqMx+tvgs/o8XHe7bgM= + + Resources/core/icons/wifi-1.svg + + oPuUK+44d0Zv+KnwNAg75k8VrAM= + + Resources/core/icons/wifi-2.svg + + anmimVALk7SlTfZ6rATqUsDs+pc= + + Resources/core/icons/wifi-off.svg + + WqOcgb+pzKCiwu5COeoFQjx5Xec= + + Resources/core/icons/wifi.svg + + kHDZGJ/Hjd/QnkGgomBWq9k5lTU= + + Resources/core/icons/wikipedia.svg + + fnDe9tEptoVByrOLpgTE/h4GXQE= + + Resources/core/icons/wind.svg + + F1TyctB3zUerhGqkWZC06wJl56U= + + Resources/core/icons/window-dash.svg + + LPzNZ5opKtbvtj6sMAxk5qxhXpU= + + Resources/core/icons/window-desktop.svg + + NQH5IYnDIIn7ByPX45FXsepJQMM= + + Resources/core/icons/window-dock.svg + + VI5O3BKSVKh6j4pg3Z8HeypP9iY= + + Resources/core/icons/window-fullscreen.svg + + E5gSOkE4df7CVHtcAdyOZ2PvfJ4= + + Resources/core/icons/window-plus.svg + + KKT9ZlMrIw1dHWt4EHf3pXUN5FA= + + Resources/core/icons/window-sidebar.svg + + Ai/gxJ5Ucc45yuCMoAbXekn/3JY= + + Resources/core/icons/window-split.svg + + RV6cZIH6zP6OjPnf+jf6Oi6lJlc= + + Resources/core/icons/window-stack.svg + + OlipyP9nyRRIQ2ZaJA437l0+fq0= + + Resources/core/icons/window-x.svg + + e0lUwf3BJUVeDoY6/mQw0v4dgrU= + + Resources/core/icons/window.svg + + Aj0NJv2/gThNhqLJG+XfK5Z/NZg= + + Resources/core/icons/windows.svg + + ZtncWh5yzzp215IALHjliLY5V3A= + + Resources/core/icons/wordpress.svg + + gMyPxUMErM2wglyXE1EDj5pzYnk= + + Resources/core/icons/wrench-adjustable-circle-fill.svg + + T5xwej+TmbqUnq3tVF1LNcHtpaQ= + + Resources/core/icons/wrench-adjustable-circle.svg + + LVJzz1bIgFsREVQLXImTeMxPigo= + + Resources/core/icons/wrench-adjustable.svg + + Wn4ColfRx4VbcEHoDZQk4KWFSec= + + Resources/core/icons/wrench.svg + + NoQq3Utd1nS848z1dnxlBmC8v9M= + + Resources/core/icons/x-circle-fill.svg + + xsvaA0iTxSC7IR1Senx30knLHug= + + Resources/core/icons/x-circle.svg + + znaok3J4JSzM6bMbkNuetZ24aM8= + + Resources/core/icons/x-diamond-fill.svg + + rUAQ/4+4+fo/EByDhlDrEz6unxw= + + Resources/core/icons/x-diamond.svg + + XtqLIdzemCzSYxuFBe0cnMDvoZY= + + Resources/core/icons/x-lg.svg + + /iLDqFWUjR5PkdvuwWe5gEbiLgc= + + Resources/core/icons/x-octagon-fill.svg + + qOmqXlOfiTzEgu524gvxoDE69n0= + + Resources/core/icons/x-octagon.svg + + Tu8HfH2HHhXbq58akNnwYbTwDLo= + + Resources/core/icons/x-square-fill.svg + + b/uPNx89wHmAOWrISXzMFwUNPFE= + + Resources/core/icons/x-square.svg + + zFizkSi6DNZHjg6klw8BKosAxnU= + + Resources/core/icons/x.svg + + eAKaaXn0UT7BRHHtazXazEfZN2E= + + Resources/core/icons/xbox.svg + + 8xzF9B7P4jkkDC9jS/XjGbB1kJs= + + Resources/core/icons/yelp.svg + + vLHPR/HUvAAJjxRofhOssIlVjfg= + + Resources/core/icons/yin-yang.svg + + QfRGuyXUA8uuxniJhO3TvhjNIRQ= + + Resources/core/icons/youtube.svg + + D6BzC0zqQp7nsrXjZjgAbC2Wv3I= + + Resources/core/icons/zoom-in.svg + + v7Y6J66/ltkXgXXRDS9qg8uQFfo= + + Resources/core/icons/zoom-out.svg + + 6T8wOdEwqXyon1wGP3nxMJzJb4E= + + Resources/core/log.py + + C8YrIBMgMjfRAZD1afE591UBOzY= + + Resources/core/network/__pycache__/diagnostic.cpython-311.pyc + + fhVXchMis8MxtBml+sguF43MAOw= + + Resources/core/network/__pycache__/diagnostic.cpython-312.pyc + + eEV/DX4mwLib8eauDrGLjLHBqS4= + + Resources/core/network/__pycache__/tools.cpython-311.pyc + + 2mUO9UKhQYOzRzPcfkfmCCn7VKU= + + Resources/core/network/__pycache__/tools.cpython-312.pyc + + eWt2RaFIHFDldApjbp2ga5FLOPY= + + Resources/core/network/diagnostic.py + + jcLiDzKmqK3jaR7LXBxy5d/KsRs= + + Resources/core/network/tools.py + + bjootV4sYY9Pta+3+GqetZH+TOs= + + Resources/core/service.py + + TfQRkS2pzEqi+Eyhe7R4g10mvbY= + + Resources/core/src/bin/nssm/windows/x86/nssm.exe + + 4ZCMqrb5OEBK+Fp98PgPh3pNnuY= + + Resources/core/src/bin/nssm/windows/x86_64/nssm.exe + + R8ESwjx73yrySiC9US+R/2r3a8Y= + + Resources/core/styles/style.css + + IRkhZG9q4R4qgXwIW+BmQoNqC50= + + Resources/core/ui.py + + nWXYVuUIybrpeYkSY0Pz26BFgIU= + + Resources/core/update.sh + + /FK0L2hD8TgmZm/H0dWwdK1+JaE= + + Resources/icon.icns + + BzKKBxC+CzqBFuCZKK8Uo7IQeaE= + + Resources/icons/icon.icns + + BzKKBxC+CzqBFuCZKK8Uo7IQeaE= + + Resources/icons/icon.png + + poFazYnMTEgJBkAWjX8odyt0TaA= + + Resources/icons/icon.svg + + hsAVtbFJ4qB/ItbW2abydhPN+k0= + + Resources/replicator/__init__.py + + JzqmZlW5rxhyunqsitH5Q1GZCik= + + Resources/replicator/__pycache__/__init__.cpython-311.pyc + + b8QLu3agshhtsFHcljqWCO5ree4= + + Resources/replicator/__pycache__/__init__.cpython-312.pyc + + bUdlYyuAhMBfeuydL3vxtP1lLuw= + + Resources/replicator/__pycache__/job.cpython-311.pyc + + Nh/jsQTyuAHwGbEikeETBoNX+4Y= + + Resources/replicator/__pycache__/job.cpython-312.pyc + + UkQqyeeQc1tBMPNCYwh+zPjLzlk= + + Resources/replicator/__pycache__/migration.cpython-311.pyc + + Ku9d+KJVAH5XScB5wpS0Y2MiCHA= + + Resources/replicator/__pycache__/migration.cpython-312.pyc + + +FuveDiUH7Ey1Pgk/fTVqS5CIPY= + + Resources/replicator/__pycache__/mount.cpython-311.pyc + + XQSwt/VJOu+mUa/E+ZTD9WcH9DE= + + Resources/replicator/__pycache__/replicator.cpython-311.pyc + + Uvr4Q7B5Iy3e+uZoJSD7Ej5nY/U= + + Resources/replicator/__pycache__/replicator.cpython-312.pyc + + WIoYYlfOMRST5tq1j6g0V+PNGOA= + + Resources/replicator/__pycache__/ui.cpython-311.pyc + + 4RkS9ItXSdgYWXPqRzXdWegh348= + + Resources/replicator/__pycache__/ui.cpython-312.pyc + + wswzQpgQk5MxUQR9OHw/ksuxNbQ= + + Resources/replicator/job.py + + zNx1kBktxANmubeLd2eY026TliU= + + Resources/replicator/migration.py + + E9zz2FzkYuxbIELfbjjDEdy5lVo= + + Resources/replicator/mount.py + + dPKq+1iWr8lrxivCaND7BI0FcQE= + + Resources/replicator/replicator.py + + 9nY6T1KzMgUvjAIzBxfeaK5X1Vs= + + Resources/replicator/ui.py + + zV3CIrON2KKUc58GCta2DmSFhlA= + + + files2 + + Frameworks/PyQt5/Qt5/lib/QtCore.framework + + cdhash + + 6eaCwyZXpQpkftm6en8H8kjoeDU= + + requirement + cdhash H"e9e682c32657a50a647ed9ba7a7f07f248e87835" + + Frameworks/PyQt5/Qt5/lib/QtDBus.framework + + cdhash + + 4PmbAraz6Z74Y1w0oxa2ZUByabM= + + requirement + cdhash H"e0f99b02b6b3e99ef8635c34a316b665407269b3" + + Frameworks/PyQt5/Qt5/lib/QtGui.framework + + cdhash + + dpyF3eiSDuwVZyw8n/mqqUuSrSM= + + requirement + cdhash H"769c85dde8920eec15672c3c9ff9aaa94b92ad23" + + Frameworks/PyQt5/Qt5/lib/QtNetwork.framework + + cdhash + + Nz2RYTKj/FhsWOYKER5kaXXkHUs= + + requirement + cdhash H"373d916132a3fc586c58e60a111e646975e41d4b" + + Frameworks/PyQt5/Qt5/lib/QtPrintSupport.framework + + cdhash + + BWu2O2z1lAvIjg4Hd/PgGUki8R4= + + requirement + cdhash H"056bb63b6cf5940bc88e0e0777f3e0194922f11e" + + Frameworks/PyQt5/Qt5/lib/QtQml.framework + + cdhash + + ifgZcYuvyH62XzD8jWt00V33mvw= + + requirement + cdhash H"89f819718bafc87eb65f30fc8d6b74d15df79afc" + + Frameworks/PyQt5/Qt5/lib/QtQmlModels.framework + + cdhash + + 9niWvyMAlxDpOiyXJx1Xs0qyoso= + + requirement + cdhash H"f67896bf23009710e93a2c97271d57b34ab2a2ca" + + Frameworks/PyQt5/Qt5/lib/QtQuick.framework + + cdhash + + fvAj5AXoLtL3fjUNZkyFlAvjfms= + + requirement + cdhash H"7ef023e405e82ed2f77e350d664c85940be37e6b" + + Frameworks/PyQt5/Qt5/lib/QtSvg.framework + + cdhash + + Oh5Fvh6j+CBI50K8L0FMSWg683s= + + requirement + cdhash H"3a1e45be1ea3f82048e742bc2f414c49683af37b" + + Frameworks/PyQt5/Qt5/lib/QtWebSockets.framework + + cdhash + + +2uE+74GTYcSxLnGCbusA2P+FDk= + + requirement + cdhash H"fb6b84fbbe064d8712c4b9c609bbac0363fe1439" + + Frameworks/PyQt5/Qt5/lib/QtWidgets.framework + + cdhash + + fmaqAq5NJO64+/juY4XiPcN9cOo= + + requirement + cdhash H"7e66aa02ae4d24eeb8fbf8ee6385e23dc37d70ea" + + Frameworks/PyQt5/Qt5/plugins/generic/libqtuiotouchplugin.dylib + + cdhash + + 2RhBY5o3lbD6gbEBqAATG8Th/Rw= + + requirement + cdhash H"d91841639a3795b0fa81b101a800131bc4e1fd1c" + + Frameworks/PyQt5/Qt5/plugins/iconengines/libqsvgicon.dylib + + cdhash + + D++3TC0Wbz13A+RRNXwRumFlJGc= + + requirement + cdhash H"0fefb74c2d166f3d7703e451357c11ba61652467" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqgif.dylib + + cdhash + + cUH5D4tQYpGRrOxR9JtLW0OtcWY= + + requirement + cdhash H"7141f90f8b50629191acec51f49b4b5b43ad7166" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqicns.dylib + + cdhash + + qzBrbR2PYWIFIDaN/6cKIe7iT3A= + + requirement + cdhash H"ab306b6d1d8f61620520368dffa70a21eee24f70" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqico.dylib + + cdhash + + ZwjpgqjUyl+5gZt+aVWj8PUKXtA= + + requirement + cdhash H"6708e982a8d4ca5fb9819b7e6955a3f0f50a5ed0" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqjpeg.dylib + + cdhash + + uTxeAbYF92+tJUpYuwwEcRclgUo= + + requirement + cdhash H"b93c5e01b605f76fad254a58bb0c04711725814a" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqmacheif.dylib + + cdhash + + F+hEJObhZc5/avixzTMMkbPp3E4= + + requirement + cdhash H"17e84424e6e165ce7f6af8b1cd330c91b3e9dc4e" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqmacjp2.dylib + + cdhash + + 1e+rBmvrugYYmTVWX8eRlxDzwq0= + + requirement + cdhash H"d5efab066bebba06189935565fc7919710f3c2ad" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqsvg.dylib + + cdhash + + ActOB6CJmGC39Jb+AHjVyuLVsok= + + requirement + cdhash H"01cb4e07a0899860b7f496fe0078d5cae2d5b289" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqtga.dylib + + cdhash + + Sxlif4wfNbsb9yTePH4jMtlgEVo= + + requirement + cdhash H"4b19627f8c1f35bb1bf724de3c7e2332d960115a" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqtiff.dylib + + cdhash + + xWPZbYN8Et7P18nJqCZxwvSC8v8= + + requirement + cdhash H"c563d96d837c12decfd7c9c9a82671c2f482f2ff" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqwbmp.dylib + + cdhash + + wVid0U4jO5xfTDS44x++mMRCRiA= + + requirement + cdhash H"c1589dd14e233b9c5f4c34b8e31fbe98c4424620" + + Frameworks/PyQt5/Qt5/plugins/imageformats/libqwebp.dylib + + cdhash + + +7X617OdoWJBufcjvT+Qcylo6kU= + + requirement + cdhash H"fbb5fad7b39da16241b9f723bd3f90732968ea45" + + Frameworks/PyQt5/Qt5/plugins/platforms/libqcocoa.dylib + + cdhash + + P1s3oGV5lCdpZK+wLLo/I/F2t9U= + + requirement + cdhash H"3f5b37a0657994276964afb02cba3f23f176b7d5" + + Frameworks/PyQt5/Qt5/plugins/platforms/libqminimal.dylib + + cdhash + + C6k4M0F++ubal5f4uSeb8dwCpyU= + + requirement + cdhash H"0ba93833417efae6da9797f8b9279bf1dc02a725" + + Frameworks/PyQt5/Qt5/plugins/platforms/libqoffscreen.dylib + + cdhash + + GqNA4GyCjXph9Up2mpCOYX/2UeU= + + requirement + cdhash H"1aa340e06c828d7a61f54a769a908e617ff651e5" + + Frameworks/PyQt5/Qt5/plugins/platforms/libqwebgl.dylib + + cdhash + + WVKjFn3kUgQtG5YaNynMY/QHSMQ= + + requirement + cdhash H"5952a3167de452042d1b961a3729cc63f40748c4" + + Frameworks/PyQt5/Qt5/plugins/platformthemes/libqxdgdesktopportal.dylib + + cdhash + + nMUlHtvejCYITSGTmAnvBQqExFA= + + requirement + cdhash H"9cc5251edbde8c26084d21939809ef050a84c450" + + Frameworks/PyQt5/Qt5/plugins/styles/libqmacstyle.dylib + + cdhash + + fwORC0ajua0Tzl76rIth/u51uHA= + + requirement + cdhash H"7f03910b46a3b9ad13ce5efaac8b61feee75b870" + + Frameworks/PyQt5/Qt5/translations + + symlink + ../../../Resources/PyQt5/Qt5/translations + + Frameworks/PyQt5/QtCore.abi3.so + + cdhash + + vgF/x3xh3Yt/oy4PzgLIZtkO/mc= + + requirement + cdhash H"be017fc77c61dd8b7fa32e0fce02c866d90efe67" + + Frameworks/PyQt5/QtGui.abi3.so + + cdhash + + wDy4mgkOoYMUodyWpRxLbredGYQ= + + requirement + cdhash H"c03cb89a090ea18314a1dc96a51c4b6eb79d1984" + + Frameworks/PyQt5/QtSvg.abi3.so + + cdhash + + D6Rz4VO+iuDm8phTFx3/6Wwz5JE= + + requirement + cdhash H"0fa473e153be8ae0e6f29853171dffe96c33e491" + + Frameworks/PyQt5/QtWidgets.abi3.so + + cdhash + + rYWPQX/Yg75c126RBzFeBZ2iXgY= + + requirement + cdhash H"ad858f417fd883be5cd76e9107315e059da25e06" + + Frameworks/PyQt5/sip.cpython-311-darwin.so + + cdhash + + Xg7oTNlf1ydWgtFYovTtYUixfd4= + + requirement + cdhash H"5e0ee84cd95fd7275682d158a2f4ed6148b17dde" + + Frameworks/Python + + symlink + Python.framework/Versions/3.11/Python + + Frameworks/Python.framework + + cdhash + + GxCPFcP4vkxxIc/mjH6J2ZPJfRo= + + requirement + cdhash H"1b108f15c3f8be4c7121cfe68c7e89d993c97d1a" + + Frameworks/QtCore + + symlink + PyQt5/Qt5/lib/QtCore.framework/Versions/5/QtCore + + Frameworks/QtDBus + + symlink + PyQt5/Qt5/lib/QtDBus.framework/Versions/5/QtDBus + + Frameworks/QtGui + + symlink + PyQt5/Qt5/lib/QtGui.framework/Versions/5/QtGui + + Frameworks/QtNetwork + + symlink + PyQt5/Qt5/lib/QtNetwork.framework/Versions/5/QtNetwork + + Frameworks/QtPrintSupport + + symlink + PyQt5/Qt5/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport + + Frameworks/QtQml + + symlink + PyQt5/Qt5/lib/QtQml.framework/Versions/5/QtQml + + Frameworks/QtQmlModels + + symlink + PyQt5/Qt5/lib/QtQmlModels.framework/Versions/5/QtQmlModels + + Frameworks/QtQuick + + symlink + PyQt5/Qt5/lib/QtQuick.framework/Versions/5/QtQuick + + Frameworks/QtSvg + + symlink + PyQt5/Qt5/lib/QtSvg.framework/Versions/5/QtSvg + + Frameworks/QtWebSockets + + symlink + PyQt5/Qt5/lib/QtWebSockets.framework/Versions/5/QtWebSockets + + Frameworks/QtWidgets + + symlink + PyQt5/Qt5/lib/QtWidgets.framework/Versions/5/QtWidgets + + Frameworks/base_library.zip + + symlink + ../Resources/base_library.zip + + Frameworks/bin + + symlink + ../Resources/bin + + Frameworks/core + + symlink + ../Resources/core + + Frameworks/icons + + symlink + ../Resources/icons + + Frameworks/libcrypto.3.dylib + + cdhash + + 499KuqQqoojFqZLiAKZIJHfWA4g= + + requirement + cdhash H"e3df4abaa42aa288c5a992e200a6482477d60388" + + Frameworks/liblzma.5.dylib + + cdhash + + idC7TO0NtChAHeq+77tLuA1pnNM= + + requirement + cdhash H"89d0bb4ced0db428401deabeefbb4bb80d699cd3" + + Frameworks/libmpdec.4.dylib + + cdhash + + Mk0vDwHinPNBhHA4tGEREhMWeHs= + + requirement + cdhash H"324d2f0f01e29cf341847038b46111121316787b" + + Frameworks/libsqlite3.dylib + + cdhash + + 0Hsq2CrcvPan30Rh+UJp13tns3s= + + requirement + cdhash H"d07b2ad82adcbcf6a7df4461f94269d77b67b37b" + + Frameworks/libssl.3.dylib + + cdhash + + btIgKtyB1/Wpa8Hs2nIbGK7uOtA= + + requirement + cdhash H"6ed2202adc81d7f5a96bc1ecda721b18aeee3ad0" + + Frameworks/python3.11 + + symlink + python3__dot__11 + + Frameworks/python3__dot__11/lib-dynload/_bisect.cpython-311-darwin.so + + cdhash + + Bx/UA6pTuYXCFhf8XfP2QuFSc9g= + + requirement + cdhash H"071fd403aa53b985c21617fc5df3f642e15273d8" + + Frameworks/python3__dot__11/lib-dynload/_blake2.cpython-311-darwin.so + + cdhash + + 4RncA5422fqG/O5KkFwX6Ha/dRY= + + requirement + cdhash H"e119dc039e36d9fa86fcee4a905c17e876bf7516" + + Frameworks/python3__dot__11/lib-dynload/_bz2.cpython-311-darwin.so + + cdhash + + 1NtZPm0vRQqcGicdTB4ntkxtpQQ= + + requirement + cdhash H"d4db593e6d2f450a9c1a271d4c1e27b64c6da504" + + Frameworks/python3__dot__11/lib-dynload/_codecs_cn.cpython-311-darwin.so + + cdhash + + WibonEillh7xUyl0lsy/Pp+XOf0= + + requirement + cdhash H"5a26e89c48a5961ef153297496ccbf3e9f9739fd" + + Frameworks/python3__dot__11/lib-dynload/_codecs_hk.cpython-311-darwin.so + + cdhash + + 2KDZxUiAaWQ+p6zdWvbkBzw4W/I= + + requirement + cdhash H"d8a0d9c5488069643ea7acdd5af6e4073c385bf2" + + Frameworks/python3__dot__11/lib-dynload/_codecs_iso2022.cpython-311-darwin.so + + cdhash + + FysbWVdJNIfsG9IXunsQM15vIOI= + + requirement + cdhash H"172b1b5957493487ec1bd217ba7b10335e6f20e2" + + Frameworks/python3__dot__11/lib-dynload/_codecs_jp.cpython-311-darwin.so + + cdhash + + WX9YkY8tdiwSZVG08vJylBjc1ow= + + requirement + cdhash H"597f58918f2d762c126551b4f2f2729418dcd68c" + + Frameworks/python3__dot__11/lib-dynload/_codecs_kr.cpython-311-darwin.so + + cdhash + + 9fwYU5UDexSSWqDSaBNvXTP9FjI= + + requirement + cdhash H"f5fc185395037b14925aa0d268136f5d33fd1632" + + Frameworks/python3__dot__11/lib-dynload/_codecs_tw.cpython-311-darwin.so + + cdhash + + q1vGidA7UatqW7r89iNvxEpo9Gs= + + requirement + cdhash H"ab5bc689d03b51ab6a5bbafcf6236fc44a68f46b" + + Frameworks/python3__dot__11/lib-dynload/_contextvars.cpython-311-darwin.so + + cdhash + + cg1wwf7pEi4MFJrjk/2s2g307zk= + + requirement + cdhash H"720d70c1fee9122e0c149ae393fdacda0df4ef39" + + Frameworks/python3__dot__11/lib-dynload/_csv.cpython-311-darwin.so + + cdhash + + 3ZeKOIDcvjrOIf0VzOMh/SlfS6Y= + + requirement + cdhash H"dd978a3880dcbe3ace21fd15cce321fd295f4ba6" + + Frameworks/python3__dot__11/lib-dynload/_ctypes.cpython-311-darwin.so + + cdhash + + /Z9MI/tiQtBfSBmEUJtCAusWCHc= + + requirement + cdhash H"fd9f4c23fb6242d05f481984509b4202eb160877" + + Frameworks/python3__dot__11/lib-dynload/_datetime.cpython-311-darwin.so + + cdhash + + +CZ+Y7/26qZ6c9gzqrNAZ0trtCE= + + requirement + cdhash H"f8267e63bff6eaa67a73d833aab340674b6bb421" + + Frameworks/python3__dot__11/lib-dynload/_decimal.cpython-311-darwin.so + + cdhash + + itxdbhIknBISj5AajxfRAjU/NFg= + + requirement + cdhash H"8adc5d6e12249c12128f901a8f17d102353f3458" + + Frameworks/python3__dot__11/lib-dynload/_hashlib.cpython-311-darwin.so + + cdhash + + WdZNKYqsD2YRkw41ieH12xbBQvw= + + requirement + cdhash H"59d64d298aac0f6611930e3589e1f5db16c142fc" + + Frameworks/python3__dot__11/lib-dynload/_heapq.cpython-311-darwin.so + + cdhash + + ft4nh3R7Bcwy3Gf+Kzj2l1g+3/Q= + + requirement + cdhash H"7ede2787747b05cc32dc67fe2b38f697583edff4" + + Frameworks/python3__dot__11/lib-dynload/_json.cpython-311-darwin.so + + cdhash + + l0wzV/+x2iDWpvD8Ytu9fP8DpR0= + + requirement + cdhash H"974c3357ffb1da20d6a6f0fc62dbbd7cff03a51d" + + Frameworks/python3__dot__11/lib-dynload/_lzma.cpython-311-darwin.so + + cdhash + + pKrGpwX23ZCTLvpOYnkogL6l4rU= + + requirement + cdhash H"a4aac6a705f6dd90932efa4e62792880bea5e2b5" + + Frameworks/python3__dot__11/lib-dynload/_md5.cpython-311-darwin.so + + cdhash + + IybsYVubywtFmHvrnzNeSHDmW1g= + + requirement + cdhash H"2326ec615b9bcb0b45987beb9f335e4870e65b58" + + Frameworks/python3__dot__11/lib-dynload/_multibytecodec.cpython-311-darwin.so + + cdhash + + zytxk6aJI3ZPTKwZiUau0eDjyoM= + + requirement + cdhash H"cf2b7193a68923764f4cac198946aed1e0e3ca83" + + Frameworks/python3__dot__11/lib-dynload/_opcode.cpython-311-darwin.so + + cdhash + + wQEIRhJskn8hwd9ZPr+KmrwVExY= + + requirement + cdhash H"c1010846126c927f21c1df593ebf8a9abc151316" + + Frameworks/python3__dot__11/lib-dynload/_pickle.cpython-311-darwin.so + + cdhash + + 9eB/x3hkKbUi0p8UyDJ/sUsMbNw= + + requirement + cdhash H"f5e07fc7786429b522d29f14c8327fb14b0c6cdc" + + Frameworks/python3__dot__11/lib-dynload/_posixsubprocess.cpython-311-darwin.so + + cdhash + + 1otc3TyWxSAo12Z3zj52f6bR3M0= + + requirement + cdhash H"d68b5cdd3c96c52028d76677ce3e767fa6d1dccd" + + Frameworks/python3__dot__11/lib-dynload/_random.cpython-311-darwin.so + + cdhash + + LJzHv0qm4yRanQkD/VAXhg9DNtg= + + requirement + cdhash H"2c9cc7bf4aa6e3245a9d0903fd5017860f4336d8" + + Frameworks/python3__dot__11/lib-dynload/_scproxy.cpython-311-darwin.so + + cdhash + + 4q8RvcoNYlgeNi108OvB3StZZUQ= + + requirement + cdhash H"e2af11bdca0d62581e362d74f0ebc1dd2b596544" + + Frameworks/python3__dot__11/lib-dynload/_sha1.cpython-311-darwin.so + + cdhash + + 00YsQ+tGL2utl1YxKvvhfOwmvs0= + + requirement + cdhash H"d3462c43eb462f6bad9756312afbe17cec26becd" + + Frameworks/python3__dot__11/lib-dynload/_sha256.cpython-311-darwin.so + + cdhash + + upoWE7fasaZ7jXhtjMG/Thme11k= + + requirement + cdhash H"ba9a1613b7dab1a67b8d786d8cc1bf4e199ed759" + + Frameworks/python3__dot__11/lib-dynload/_sha3.cpython-311-darwin.so + + cdhash + + t/kR1KvlfpyvZm4rJ1NLytu604c= + + requirement + cdhash H"b7f911d4abe57e9caf666e2b27534bcadbbad387" + + Frameworks/python3__dot__11/lib-dynload/_sha512.cpython-311-darwin.so + + cdhash + + 12j2MhIu43eNIzd0Wip/GhEFb48= + + requirement + cdhash H"d768f632122ee3778d2337745a2a7f1a11056f8f" + + Frameworks/python3__dot__11/lib-dynload/_socket.cpython-311-darwin.so + + cdhash + + I5Av94svblj/+olgWhCkhp9Xdes= + + requirement + cdhash H"23902ff78b2f6e58fffa89605a10a4869f5775eb" + + Frameworks/python3__dot__11/lib-dynload/_sqlite3.cpython-311-darwin.so + + cdhash + + Yq0XdmYDGoikKkEoLPhlXBzyxe0= + + requirement + cdhash H"62ad177666031a88a42a41282cf8655c1cf2c5ed" + + Frameworks/python3__dot__11/lib-dynload/_ssl.cpython-311-darwin.so + + cdhash + + BEtXmmuCeJVkorWAkxkFfo5cG6I= + + requirement + cdhash H"044b579a6b82789564a2b5809319057e8e5c1ba2" + + Frameworks/python3__dot__11/lib-dynload/_statistics.cpython-311-darwin.so + + cdhash + + Q5oaSz6P3MmhmzNztIT4zaocSrk= + + requirement + cdhash H"439a1a4b3e8fdcc9a19b3373b484f8cdaa1c4ab9" + + Frameworks/python3__dot__11/lib-dynload/_struct.cpython-311-darwin.so + + cdhash + + xyNo8zDTzVm3+6la2U5DWkdd1Rg= + + requirement + cdhash H"c72368f330d3cd59b7fba95ad94e435a475dd518" + + Frameworks/python3__dot__11/lib-dynload/_typing.cpython-311-darwin.so + + cdhash + + L+kSKzycD0PX1ZQEPx8qgrpPcvI= + + requirement + cdhash H"2fe9122b3c9c0f43d7d594043f1f2a82ba4f72f2" + + Frameworks/python3__dot__11/lib-dynload/array.cpython-311-darwin.so + + cdhash + + E1Av6WzVg1JLZoWNzViEDMywhA0= + + requirement + cdhash H"13502fe96cd583524b66858dcd58840cccb0840d" + + Frameworks/python3__dot__11/lib-dynload/binascii.cpython-311-darwin.so + + cdhash + + pj0uo0nGV7UIIIWOD2E8Gh2fj9I= + + requirement + cdhash H"a63d2ea349c657b50820858e0f613c1a1d9f8fd2" + + Frameworks/python3__dot__11/lib-dynload/fcntl.cpython-311-darwin.so + + cdhash + + J04Chpr4qgnYqufXybZlCRc+kIU= + + requirement + cdhash H"274e02869af8aa09d8aae7d7c9b66509173e9085" + + Frameworks/python3__dot__11/lib-dynload/grp.cpython-311-darwin.so + + cdhash + + MYC6Y9Z1rZ64wJoERVP5T/J5nQc= + + requirement + cdhash H"3180ba63d675ad9eb8c09a044553f94ff2799d07" + + Frameworks/python3__dot__11/lib-dynload/math.cpython-311-darwin.so + + cdhash + + ap9+ozd2trtGq/NdlF3E8KU2AoI= + + requirement + cdhash H"6a9f7ea33776b6bb46abf35d945dc4f0a5360282" + + Frameworks/python3__dot__11/lib-dynload/pyexpat.cpython-311-darwin.so + + cdhash + + LbqJ8FJv04vp5UBciCC4IlgqXRU= + + requirement + cdhash H"2dba89f0526fd38be9e5405c8820b822582a5d15" + + Frameworks/python3__dot__11/lib-dynload/resource.cpython-311-darwin.so + + cdhash + + SJ4mmtuIWhr35sAq3lfY+ZtHPhA= + + requirement + cdhash H"489e269adb885a1af7e6c02ade57d8f99b473e10" + + Frameworks/python3__dot__11/lib-dynload/select.cpython-311-darwin.so + + cdhash + + vSw8n8BC3j64rnOKA7geLMNdkQA= + + requirement + cdhash H"bd2c3c9fc042de3eb8ae738a03b81e2cc35d9100" + + Frameworks/python3__dot__11/lib-dynload/termios.cpython-311-darwin.so + + cdhash + + 4SvnSWHEHAmZBCOYM8hdnIILcxo= + + requirement + cdhash H"e12be74961c41c099904239833c85d9c820b731a" + + Frameworks/python3__dot__11/lib-dynload/unicodedata.cpython-311-darwin.so + + cdhash + + iKKD4q00uMvUuQ2+47DJGh8YCQc= + + requirement + cdhash H"88a283e2ad34b8cbd4b90dbee3b0c91a1f180907" + + Frameworks/python3__dot__11/lib-dynload/zlib.cpython-311-darwin.so + + cdhash + + yWqGVV5aJFiugSJjYxCOz2v82kY= + + requirement + cdhash H"c96a86555e5a2458ae81226363108ecf6bfcda46" + + Frameworks/replicator + + symlink + ../Resources/replicator + + Resources/PyQt5/Qt5/lib + + symlink + ../../../Frameworks/PyQt5/Qt5/lib + + Resources/PyQt5/Qt5/plugins + + symlink + ../../../Frameworks/PyQt5/Qt5/plugins + + Resources/PyQt5/Qt5/translations/qt_ar.qm + + hash2 + + qKGw1vlY5zZtHIVr5hAAEG0+f8mT+5MWdTaYkrkALQs= + + + Resources/PyQt5/Qt5/translations/qt_bg.qm + + hash2 + + nhzk2RhSNSBD2RkfGpkoOPkZy6fi8tm7EWHklOi/X14= + + + Resources/PyQt5/Qt5/translations/qt_ca.qm + + hash2 + + Fxx0JLJNhQKrU8s3hP802Pz64mVXz4r0393sZIWswv4= + + + Resources/PyQt5/Qt5/translations/qt_cs.qm + + hash2 + + PAy/0ZSQ1n0bO56UTDpNmp5/h9euNeiNXVoAdzSbWyE= + + + Resources/PyQt5/Qt5/translations/qt_da.qm + + hash2 + + tQNhYc6AjHKOX9qYX3kttWWDH9Ac8AsoJUd5DANzU6I= + + + Resources/PyQt5/Qt5/translations/qt_de.qm + + hash2 + + WAW4/zdHhJeU4tcGYdc3xpwV8a52PDjhcISx5agekVM= + + + Resources/PyQt5/Qt5/translations/qt_en.qm + + hash2 + + mVm1ELFdGJN4SK0TAH4wRZ0umTxn5WS62/wY+TVpXIU= + + + Resources/PyQt5/Qt5/translations/qt_es.qm + + hash2 + + 4l5D8Eb2ECL/6HGi9zxqEu38XD79lYwOAZpyGGCgU7A= + + + Resources/PyQt5/Qt5/translations/qt_fa.qm + + hash2 + + X3wXFT3SzlwZ5OIZgF5CbsKIZ7l7lCxLLJJuYbeSq0s= + + + Resources/PyQt5/Qt5/translations/qt_fi.qm + + hash2 + + BIykLc5Pr1/CHYQ1duPG/ZYxRuzHhVTn5fNNB/ZPshM= + + + Resources/PyQt5/Qt5/translations/qt_fr.qm + + hash2 + + hiQDPYSeZwsSyVMjN/y/Jg8ghI4ET+53h8/irJK+KNs= + + + Resources/PyQt5/Qt5/translations/qt_gd.qm + + hash2 + + Sd+FWgBKF5UDOK8xRkZvbfTVhSQQvQtY6oDg0CA6nSQ= + + + Resources/PyQt5/Qt5/translations/qt_gl.qm + + hash2 + + IEoBrH3ra1uuGTr+y9HlDRjHO/fZS63rK7/fYSPE7ZM= + + + Resources/PyQt5/Qt5/translations/qt_he.qm + + hash2 + + wRPRTiGNVAK2Ftq+onlpxvg4UmdkaMXvBR3d77PuAjU= + + + Resources/PyQt5/Qt5/translations/qt_help_ar.qm + + hash2 + + IiCIyXUtHMO6uYXvLcd+WueFeNzhimHsFbOfAuWIFj0= + + + Resources/PyQt5/Qt5/translations/qt_help_bg.qm + + hash2 + + y83R4LuuMy2A3bCihgVvF8gk+ijTU9f98S/JfZ9v4FQ= + + + Resources/PyQt5/Qt5/translations/qt_help_ca.qm + + hash2 + + x/At4KZE/27jKeZS1HwXX+7ATuJ0QAzWg2tpF93vyBM= + + + Resources/PyQt5/Qt5/translations/qt_help_cs.qm + + hash2 + + SsVvxj5ACUO6sT8dTEGFAhOJCOHUiMJK7mEx09F1Uqo= + + + Resources/PyQt5/Qt5/translations/qt_help_da.qm + + hash2 + + a7CSVSo5hocRn21SFF8Ev4Nzl3RG2PAMDcvVa5aCnw8= + + + Resources/PyQt5/Qt5/translations/qt_help_de.qm + + hash2 + + mWJSP7rp8eTDtcPBaGDQWSkcsw3F6+Wl7aTINqA/7R4= + + + Resources/PyQt5/Qt5/translations/qt_help_en.qm + + hash2 + + mVm1ELFdGJN4SK0TAH4wRZ0umTxn5WS62/wY+TVpXIU= + + + Resources/PyQt5/Qt5/translations/qt_help_es.qm + + hash2 + + /RayefjPaQd/delNkMnAeir/85SKV543ifX/teX0IC0= + + + Resources/PyQt5/Qt5/translations/qt_help_fr.qm + + hash2 + + aH41HAYvaIqv9s8FIY1gF7gLGhtCONHTAlClXuQcX+0= + + + Resources/PyQt5/Qt5/translations/qt_help_gl.qm + + hash2 + + c5miSGCZdHc/YIZsh7eOp9+8T3UDE9aS94hs12OIPJ8= + + + Resources/PyQt5/Qt5/translations/qt_help_hr.qm + + hash2 + + jIzDxbGrKwdPgpNwAbiWYDQg73VZKzt4FyF3Ng3X6mE= + + + Resources/PyQt5/Qt5/translations/qt_help_hu.qm + + hash2 + + cPM7VpwpQvQcbWNOpqYcuNgOsscBG61I72266Wd5YNU= + + + Resources/PyQt5/Qt5/translations/qt_help_it.qm + + hash2 + + MW/o0IFeK0s5aJW+s47xpAQxkVteBU34D0wM1Vbybks= + + + Resources/PyQt5/Qt5/translations/qt_help_ja.qm + + hash2 + + rmA7LA1DTUDN5DP/y6ZfnuJ5eKnhkxYAe+f+eCpbi0c= + + + Resources/PyQt5/Qt5/translations/qt_help_ko.qm + + hash2 + + 8RxkaU6ONOHSxGwaHRXWup8tt7Yd5P31TspauXfD4FI= + + + Resources/PyQt5/Qt5/translations/qt_help_nl.qm + + hash2 + + RKig2vd10UNSGABS0T9iOBTXvfmOLFyAFEt790IU47A= + + + Resources/PyQt5/Qt5/translations/qt_help_nn.qm + + hash2 + + TIpyE5QgeOT3L1ur0mxBt3rOcBiXFKWLVQSn1a0Bk9w= + + + Resources/PyQt5/Qt5/translations/qt_help_pl.qm + + hash2 + + zGy02MVAhiJGcvLknmI8jLfAwc1luNXs1C/JujpgZb0= + + + Resources/PyQt5/Qt5/translations/qt_help_pt_BR.qm + + hash2 + + F6FkBFwPxT0FB8/JDDlw/hr9+hxKjlyIHTT6H4aoIb8= + + + Resources/PyQt5/Qt5/translations/qt_help_ru.qm + + hash2 + + VXtkTm2l8exyDvk5ZWFwh+TR9AsklMxapSTPN5YQjec= + + + Resources/PyQt5/Qt5/translations/qt_help_sk.qm + + hash2 + + 9B4z4deQvQ0+sYDx+HW8GR/nR3NijyXCytleFALmaGc= + + + Resources/PyQt5/Qt5/translations/qt_help_sl.qm + + hash2 + + LslV5mJAfrzY3NrlqqIeQQjgtbCu4OnbcSwnBylDU18= + + + Resources/PyQt5/Qt5/translations/qt_help_tr.qm + + hash2 + + 697KDP7nqUQd64ALq/2XxjvE5CHaiFxVs71Jcl66zSU= + + + Resources/PyQt5/Qt5/translations/qt_help_uk.qm + + hash2 + + SXz8RzaEaS7kTXo3lej7InDFcGn9nrmKYV3Smrm+inw= + + + Resources/PyQt5/Qt5/translations/qt_help_zh_CN.qm + + hash2 + + 4lbR9gNKWlUhxi8Sn5FzEhbkdPceHZyuo9PcsRtnDes= + + + Resources/PyQt5/Qt5/translations/qt_help_zh_TW.qm + + hash2 + + Z+bfCmxl4PzzN5jftBf5u/DN5FErVunjFJql0Y97AZg= + + + Resources/PyQt5/Qt5/translations/qt_hr.qm + + hash2 + + q4sscqwH3SK7IBlmVaC+DCxvockki86wTW5nBxhg2eg= + + + Resources/PyQt5/Qt5/translations/qt_hu.qm + + hash2 + + uyRqq9UB4Uztix/8E2nj1dJlZ6rmKz6tTZTCL7d8NHE= + + + Resources/PyQt5/Qt5/translations/qt_it.qm + + hash2 + + kReqwtB7yG36VaKbiCXtJ8cJMwD8yQ4UPhNeAOhfCdc= + + + Resources/PyQt5/Qt5/translations/qt_ja.qm + + hash2 + + I0V86OROIzxvhdVqTuaizs2Hyce93m2LipJZAu7RzZw= + + + Resources/PyQt5/Qt5/translations/qt_ko.qm + + hash2 + + TMGvN+dx8KQ4mISc/yzUKoIEUbjSsuiJMQMWKdeB2wU= + + + Resources/PyQt5/Qt5/translations/qt_lt.qm + + hash2 + + R+tfl0Z992kmFCHVSlvqETHJ+5tjiHkdOLtldDNbZL8= + + + Resources/PyQt5/Qt5/translations/qt_lv.qm + + hash2 + + A0Z3OAQqFWduUEugLLMm3Nt3OxcfraPNYreg4FZDFKA= + + + Resources/PyQt5/Qt5/translations/qt_nl.qm + + hash2 + + uSjkOApLXUc44+x6rMeleiJZJMyW2vLTDhhS8Ug24Cg= + + + Resources/PyQt5/Qt5/translations/qt_nn.qm + + hash2 + + LBi3+va8KYFU0pEbiK/YCvj32AgNCyyJ2974aBYs9Ss= + + + Resources/PyQt5/Qt5/translations/qt_pl.qm + + hash2 + + vX3QwsqxGalz3BDDv/dJnZcouSi1QfhgVpIbMMjbeOY= + + + Resources/PyQt5/Qt5/translations/qt_pt_BR.qm + + hash2 + + 7Pq4gLC/9Yqo7/LlvR+rUwp7SVxzohx94fUor8Mqf4U= + + + Resources/PyQt5/Qt5/translations/qt_pt_PT.qm + + hash2 + + LB57v1FopktDdS3UxUdgHAvebWEPhnH6PjrzhZfoR4M= + + + Resources/PyQt5/Qt5/translations/qt_ru.qm + + hash2 + + ZJKyZ2CMb7dpB72Pz8jx71fp9Ou8LoGsqBcVqIOI+Uo= + + + Resources/PyQt5/Qt5/translations/qt_sk.qm + + hash2 + + tq3/2In/lr8ZXLmXMn59cAWoFcrWeCP6aRWhnC2btmg= + + + Resources/PyQt5/Qt5/translations/qt_sl.qm + + hash2 + + xE4DE6lBTMDkkLZbDANvoRvKlZNTsiiIZUe8LISSA08= + + + Resources/PyQt5/Qt5/translations/qt_sv.qm + + hash2 + + S0tv9/0jfJ2gMBtJRhMuaGU9Fetfrzjkxfv+uxLdl/c= + + + Resources/PyQt5/Qt5/translations/qt_tr.qm + + hash2 + + 9XSiz9RxWIXD299a5gmVJSZzvZT9qpWG9+BYb2wawO4= + + + Resources/PyQt5/Qt5/translations/qt_uk.qm + + hash2 + + 8WIeaA4WQvlGPksH5+eLUPmnvbfDIdcwIDnLNAXL3qQ= + + + Resources/PyQt5/Qt5/translations/qt_zh_CN.qm + + hash2 + + ao+JzNJQ/A8AKiWB37e/ukNmp661qdmB6kL9yY38mV4= + + + Resources/PyQt5/Qt5/translations/qt_zh_TW.qm + + hash2 + + dR7NoMM+Bh2RJBJoNX+9L2t/cKERbnFPKNIu/WHseho= + + + Resources/PyQt5/Qt5/translations/qtbase_ar.qm + + hash2 + + 4D/mjYMgFUNpj9f+Jn3V38W/0ZUUfnT/LxmsNJFAEmM= + + + Resources/PyQt5/Qt5/translations/qtbase_bg.qm + + hash2 + + 5Eisnj8Wwp6yevMBLv4hBS2qePq/s0zW3/L2nuO9PNs= + + + Resources/PyQt5/Qt5/translations/qtbase_ca.qm + + hash2 + + 5OKmeENU8W+EC0kKASVhKe1WeJX+SzAnaO1FNNJEv9s= + + + Resources/PyQt5/Qt5/translations/qtbase_cs.qm + + hash2 + + AwKLQt9UeScDceTDvcffL1bLvm3alWooZKxvZBWGH+g= + + + Resources/PyQt5/Qt5/translations/qtbase_da.qm + + hash2 + + fR5cozELVNEEwZvyq9QCs45YTocDmnDhU8Spr3SyXCI= + + + Resources/PyQt5/Qt5/translations/qtbase_de.qm + + hash2 + + VTwEaDXbmt7xWVT6mldmJTZrqL/RZjcDjEvNKOXrrOE= + + + Resources/PyQt5/Qt5/translations/qtbase_en.qm + + hash2 + + mVm1ELFdGJN4SK0TAH4wRZ0umTxn5WS62/wY+TVpXIU= + + + Resources/PyQt5/Qt5/translations/qtbase_es.qm + + hash2 + + T/2la6O7VBSrBILR3eZKbyJuNIj2t/PxGhUOAfU/pMg= + + + Resources/PyQt5/Qt5/translations/qtbase_fa.qm + + hash2 + + 945Ztb3VhhgamZA0ukGIaO0X/pwFcH+2XlI/cOkiU9I= + + + Resources/PyQt5/Qt5/translations/qtbase_fi.qm + + hash2 + + 5H/hNxPhhNB/pEld3gxYmw6PVi6RV0o1WKk2NEOk+nI= + + + Resources/PyQt5/Qt5/translations/qtbase_fr.qm + + hash2 + + 7bMqkzzvN2omNmNOFOKXfO1ihOSqmkrH4ikvnKVMOEo= + + + Resources/PyQt5/Qt5/translations/qtbase_gd.qm + + hash2 + + Y7Q53UQTmqOu1UwuvgP6m8d/IsFO2Puo7/JghEW7Iz0= + + + Resources/PyQt5/Qt5/translations/qtbase_he.qm + + hash2 + + 4evKFq/omUNW+BygB/vbnd+GWEIBD+kIkj2HO2h8rT8= + + + Resources/PyQt5/Qt5/translations/qtbase_hr.qm + + hash2 + + u57smpplLBNA3HXrLnSb5Q3wD4hbPWkA38dnmcRbJE0= + + + Resources/PyQt5/Qt5/translations/qtbase_hu.qm + + hash2 + + xhtnu50ehPCrB5K2UY/gVUFKaORNDHvHyGJ3OAD6gpk= + + + Resources/PyQt5/Qt5/translations/qtbase_it.qm + + hash2 + + eAjtVCp4M8S9lOyL37vKALtPL+FZebkSHOMkkyNocwA= + + + Resources/PyQt5/Qt5/translations/qtbase_ja.qm + + hash2 + + y6OCrMRNNoDUAPLGJd6T0MS9cqkBAnae39H+kcubYXs= + + + Resources/PyQt5/Qt5/translations/qtbase_ko.qm + + hash2 + + AXntGxNuHLP1gzUeqixUW6PYOm7j+CwyUFkmoaX18YM= + + + Resources/PyQt5/Qt5/translations/qtbase_lv.qm + + hash2 + + hG4EdXOuQMg2ccO6f3PifvwkuYyCcB2g35lz5XQXi7I= + + + Resources/PyQt5/Qt5/translations/qtbase_nl.qm + + hash2 + + 9hUTvNu2rYAFhflDepXQGKqxf6Eu5BSqMUYv8nnYJA4= + + + Resources/PyQt5/Qt5/translations/qtbase_nn.qm + + hash2 + + mDc0tAqk0lBCG6DRYUQWy4tCTW8UD0p9v4sR5l7vY9w= + + + Resources/PyQt5/Qt5/translations/qtbase_pl.qm + + hash2 + + zpkDKjsL+KutdYiVzCKDcIjq2Z/S0lFOLRgGkwgc/lc= + + + Resources/PyQt5/Qt5/translations/qtbase_pt_BR.qm + + hash2 + + g0T1vDM8RdN8/UJaCRJOsR8SQ58zc37AuGg9BKQWdG4= + + + Resources/PyQt5/Qt5/translations/qtbase_ru.qm + + hash2 + + PaZgVmj5F40RqDjEUVR4CE3PtPnPIvmdepK0ktucIks= + + + Resources/PyQt5/Qt5/translations/qtbase_sk.qm + + hash2 + + 1YauLDFAdM85hBf97LQHCdVHjf6wpnwv5g1Qnum1ntc= + + + Resources/PyQt5/Qt5/translations/qtbase_tr.qm + + hash2 + + agv25w55IMKxk+dukvePMVk2lV07BqwDnZF/LgbEMoE= + + + Resources/PyQt5/Qt5/translations/qtbase_uk.qm + + hash2 + + Ubj/VbN9xZB9Y3qN3aEvvoFoUrAkTHTrTw+4SGenhuA= + + + Resources/PyQt5/Qt5/translations/qtbase_zh_CN.qm + + hash2 + + mP1Ll9vsivXN0V+FoWwz78dzAbGusEadqvwEuasvNXA= + + + Resources/PyQt5/Qt5/translations/qtbase_zh_TW.qm + + hash2 + + IQErK0J/jQnTHOnK5YLKJ5VbR4yj3C7BijBo2AhjjGo= + + + Resources/PyQt5/QtCore.abi3.so + + symlink + ../../Frameworks/PyQt5/QtCore.abi3.so + + Resources/PyQt5/QtGui.abi3.so + + symlink + ../../Frameworks/PyQt5/QtGui.abi3.so + + Resources/PyQt5/QtSvg.abi3.so + + symlink + ../../Frameworks/PyQt5/QtSvg.abi3.so + + Resources/PyQt5/QtWidgets.abi3.so + + symlink + ../../Frameworks/PyQt5/QtWidgets.abi3.so + + Resources/PyQt5/sip.cpython-311-darwin.so + + symlink + ../../Frameworks/PyQt5/sip.cpython-311-darwin.so + + Resources/Python + + symlink + Python.framework/Versions/3.11/Python + + Resources/Python.framework + + symlink + ../Frameworks/Python.framework + + Resources/QtCore + + symlink + PyQt5/Qt5/lib/QtCore.framework/Versions/5/QtCore + + Resources/QtDBus + + symlink + PyQt5/Qt5/lib/QtDBus.framework/Versions/5/QtDBus + + Resources/QtGui + + symlink + PyQt5/Qt5/lib/QtGui.framework/Versions/5/QtGui + + Resources/QtNetwork + + symlink + PyQt5/Qt5/lib/QtNetwork.framework/Versions/5/QtNetwork + + Resources/QtPrintSupport + + symlink + PyQt5/Qt5/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport + + Resources/QtQml + + symlink + PyQt5/Qt5/lib/QtQml.framework/Versions/5/QtQml + + Resources/QtQmlModels + + symlink + PyQt5/Qt5/lib/QtQmlModels.framework/Versions/5/QtQmlModels + + Resources/QtQuick + + symlink + PyQt5/Qt5/lib/QtQuick.framework/Versions/5/QtQuick + + Resources/QtSvg + + symlink + PyQt5/Qt5/lib/QtSvg.framework/Versions/5/QtSvg + + Resources/QtWebSockets + + symlink + PyQt5/Qt5/lib/QtWebSockets.framework/Versions/5/QtWebSockets + + Resources/QtWidgets + + symlink + PyQt5/Qt5/lib/QtWidgets.framework/Versions/5/QtWidgets + + Resources/base_library.zip + + hash2 + + 3KeLPTdCSyQ579wV+NNlryctvaHsvse0kCXKVnT7N5I= + + + Resources/bin/nssm/windows/x86/nssm.exe + + hash2 + + RyIyyoIbXC71YqsH9TY4vCzILq6EzqE/vmdNYCK2SBw= + + + Resources/bin/nssm/windows/x86_64/nssm.exe + + hash2 + + 9onumvlLAOnj8LsHKzTKryB/Mty09Xgvyco1HfmgbJc= + + + Resources/core/.editorconfig + + hash2 + + tNDGpaKw/Q8OOGEnxKpy+g/2CSuSCDXjBTiihuxb/GE= + + + Resources/core/.git + + hash2 + + xj1mDyPITuk9lhgsZwi3sv20wAqz0EuRwceGsMAzcPI= + + + Resources/core/.github/FUNDING.yml + + hash2 + + ZMUx3UQ0ivlcI+qPMIivEbXzJjALGa0On/ajweoJ2SE= + + + Resources/core/.github/ISSUE_TEMPLATE/bug_report.md + + hash2 + + YP2Ftg6yXgwXAZft9M4SX6qwKNPIf464uKsoE6pRysM= + + + Resources/core/.github/ISSUE_TEMPLATE/feature_request.md + + hash2 + + OaV+amDHIOBF4gZHorVC5D/GFr/wHehaKDcoprAY/eA= + + + Resources/core/.github/no-response.yml + + hash2 + + 3CvFSMBT1OnXiFtrUe/YF3R2i7xaKshQUrwShfZaIQw= + + + Resources/core/.github/workflows/release.yml + + hash2 + + /ZBa79W7C/qz1Hz887wjNIILe3LqtykEsRr2HPo3MQY= + + + Resources/core/.gitignore + + hash2 + + bd9immDtsDrbVhktTdaOQM79FrNPJMcuVr2ASnd8bL0= + + + Resources/core/LICENSE + + hash2 + + OXLcl0T2SZ8Pmy2/dmlvKuetivmyPd5m1q+Gyd+zaYY= + + + Resources/core/README.md + + hash2 + + IuUAyRieDr+Imb8Q1FvfuE+1yH7eT7grnZVT3ncIa2w= + + + Resources/core/SECURITY.md + + hash2 + + kAB0rp/FR18JvnDluda2Hf6a2C+/7dC33dmjU/KQgQg= + + + Resources/core/VERSION + + hash2 + + R66OVItaS1LbFQIiGypKiJUodzsHvSNzccxHXDa15Ks= + + + Resources/core/__init__.py + + hash2 + + u/Tck6/CSMvuKphQO+GLmen5M9ZN0WUFutKHCJskQRE= + + + Resources/core/__pycache__/__init__.cpython-311.pyc + + hash2 + + iX/jHrkwXsG132X2TTmStFIa+urij6t/G7DKgylVU64= + + + Resources/core/__pycache__/__init__.cpython-312.pyc + + hash2 + + JxjyhVdPu9G+pKwnbTl8nJxX038C99TzyItGMg4Piww= + + + Resources/core/__pycache__/__init__.cpython-314.pyc + + hash2 + + FqsvlDDaArJy71DKdir79VvzCHE34awQ6d6kb43GgS4= + + + Resources/core/__pycache__/application.cpython-311.pyc + + hash2 + + 948ySdJv3u1CCtUKYlr/YC2AzCUkixZim5yLuI68kbA= + + + Resources/core/__pycache__/application.cpython-312.pyc + + hash2 + + ieXkCb8sA+Wbvo59NeXKQALiCFtilSjeKMML/d3pYyY= + + + Resources/core/__pycache__/application.cpython-314.pyc + + hash2 + + pGp9ORrc8Mk/68joknmJfMtVEcodyS+G5+ixkaAWW4A= + + + Resources/core/__pycache__/cli.cpython-311.pyc + + hash2 + + RabnrQ8LshapZkgDycCKNdKiJ1isQ274mtNULqAEOTM= + + + Resources/core/__pycache__/cli.cpython-312.pyc + + hash2 + + UxXLgieqeMZjAs2AwXv11hAd6ksxamQhLuwedwqkizw= + + + Resources/core/__pycache__/configuration.cpython-311.pyc + + hash2 + + 4OAzlZIvmIGgLqgqYPJEoSFjKpo/OXMYorKRoKqUQWA= + + + Resources/core/__pycache__/configuration.cpython-312.pyc + + hash2 + + nnqE4LRAZaFSAQTrZzZPr6iUCL7RZ30UnFa2vPzfX8s= + + + Resources/core/__pycache__/helper.cpython-311.pyc + + hash2 + + ibfi7J9FXPefaEtbISlmUkz1BCx+CNzkqoxFU+C1zN8= + + + Resources/core/__pycache__/helper.cpython-312.pyc + + hash2 + + DP5TX+7HDAmtKW+KGEMT0aQ3LPFTG7xESTEYxZUI7yo= + + + Resources/core/__pycache__/log.cpython-311.pyc + + hash2 + + zhhkshQxjHS8kz0z7bKnMviHAF/hwx4MckmVjpZFFR4= + + + Resources/core/__pycache__/log.cpython-312.pyc + + hash2 + + SNaVbA+KkYQKR3nStSQLGQpzu+CFmj/t6H2Yibg6HzI= + + + Resources/core/__pycache__/service.cpython-311.pyc + + hash2 + + 4+mcEQE/m0qgD40iCxTfUdQ0cdcfD9Ot/sltF6YM7uw= + + + Resources/core/__pycache__/service.cpython-312.pyc + + hash2 + + OOZjYUUNjgtuYdo+wpoYBcEOrv6BK0hJuL8zFi4mVxE= + + + Resources/core/__pycache__/ui.cpython-311.pyc + + hash2 + + DumSS97ITm1Rn8kUK/PmcnYCABzIPEUe68F4KFCEQFY= + + + Resources/core/__pycache__/ui.cpython-312.pyc + + hash2 + + cXwrrikpd7MtCcCaSdwVxC5+QITVaKsiS7GH2/FMGB4= + + + Resources/core/application.py + + hash2 + + 9diZqiQMmVPVpVOgIAVRT54BhIGqt0dVkH4U9QQz6U0= + + + Resources/core/build.sh + + hash2 + + QQcvQIAicRkAHVzo8c7uWYNsirwM5LyayOodY4PoxwY= + + + Resources/core/bundle.sh + + hash2 + + Q2a6hf4PtneSf+lbv7bjwOjdjlFciUixl47pTBql10A= + + + Resources/core/cli.py + + hash2 + + P8ZtwzaSw2atDhngNpcHODdsrfPDA2S6/K0Lm1hcubM= + + + Resources/core/configuration.py + + hash2 + + WwdazvFucuthJ5eTfXtoCWK+xntpZ0UpiN+sM3UkSAM= + + + Resources/core/database/__init__.py + + hash2 + + lnIR6Wy31LsnLPfgX3/QDRyfR6bskkTDLxGbcyZFAE4= + + + Resources/core/database/__pycache__/__init__.cpython-311.pyc + + hash2 + + NPNhkpY1WedGBQ5kt9+anw+/SUWKuE5GVG77eQYTynI= + + + Resources/core/database/__pycache__/__init__.cpython-312.pyc + + hash2 + + e7+6USsnq2CNndE2VRbrvUHGhonSG0wrgvqOy2XOACk= + + + Resources/core/database/__pycache__/sqlite.cpython-311.pyc + + hash2 + + Dz/vsEfjyMf4LQQP35gS+dKslsVtLq2oYkOblGZofWY= + + + Resources/core/database/__pycache__/sqlite.cpython-312.pyc + + hash2 + + OwwOIFU9KTdcATLL4QCaWWtZxtIWpMMk3dPdF9aBCK0= + + + Resources/core/database/sqlite.py + + hash2 + + 4JskES8eD8FFp8RImnr0iJ41m95HIvJWOfVrzqwrep4= + + + Resources/core/filesystem/__init__.py + + hash2 + + sdWCKEeB7ful9NZltmqhz4/L+OVVdxj3UEhMhghoT54= + + + Resources/core/filesystem/__pycache__/__init__.cpython-311.pyc + + hash2 + + eIeyiqBPiRvv0btDuPY8PqfI4m2ljMcddW+s/MoyUTk= + + + Resources/core/filesystem/__pycache__/__init__.cpython-312.pyc + + hash2 + + 8nJP1ZekxS9jAEE7x9uUykVlVcHjxTSoV7wAYsqvw+Q= + + + Resources/core/filesystem/__pycache__/filesystem.cpython-311.pyc + + hash2 + + G1QcxSHVfDiMBiZ0NMGJKHUazEYyZ5IYYBFxlNDIdfQ= + + + Resources/core/filesystem/__pycache__/filesystem.cpython-312.pyc + + hash2 + + e4aJq+sXQf2ENxfWu5EWi0epnENNSF7l07Bl9zAODwo= + + + Resources/core/filesystem/__pycache__/share.cpython-311.pyc + + hash2 + + Fxl/8kPu+EDmEMXPMwC81dg1c9xsRZcDlmNQ0DvOucQ= + + + Resources/core/filesystem/filesystem.py + + hash2 + + QyNxzgcOTuiPmR32W+5uONAJMdc4A7hnbsfvLJKIw+I= + + + Resources/core/filesystem/share.py + + hash2 + + 5Ev6QACs2vDancwefrfR82MCVrlzM43xDyKS3BH33Ms= + + + Resources/core/helper.py + + hash2 + + fSO75POLf4qGOnVM/TSyvbVU/XzhD9Ne6CNi4fRi/3E= + + + Resources/core/icons/0-circle-fill.svg + + hash2 + + xGuS/VDrkvC/Bpv8FolBPpgMf/uWw7DhE7aMfmMkSpQ= + + + Resources/core/icons/0-circle.svg + + hash2 + + YfYgygYBI9Ypi/OT395dugeJ5UZ9aCBY2DaHzXkhzgE= + + + Resources/core/icons/0-square-fill.svg + + hash2 + + NPDSKNyN7LzbrakbxutwP5YEdsBCSbMGFR++wdiX7Zs= + + + Resources/core/icons/0-square.svg + + hash2 + + knqWQrVdC/QxKpuHZAQ4c13A6K0NjEpCW3oNXkbATtk= + + + Resources/core/icons/1-circle-fill.svg + + hash2 + + i4j8vPkpY0UhFMYHXQ5oETQKzGanqgng4C1t+uh/VvQ= + + + Resources/core/icons/1-circle.svg + + hash2 + + 70mahrpzej5yrdwVxenvWXbK+TPadc1C1/KHuFjlAjM= + + + Resources/core/icons/1-square-fill.svg + + hash2 + + J3GGghKLYQz853DNNpmXLbG4UAcflwwAbIfIPefNYvU= + + + Resources/core/icons/1-square.svg + + hash2 + + mh8/FqADxc1pZGmL9urqaijlhUENouNtTJZ0HjZ/bTg= + + + Resources/core/icons/123.svg + + hash2 + + 8u2Dd7Wiv7OB2UByLXg6dLA6Se1hyeDVcsRpVMoLV9o= + + + Resources/core/icons/2-circle-fill.svg + + hash2 + + apTkeZukbHEpnaVVWHQwaO+P/NUJA3brCnfFp0uyODc= + + + Resources/core/icons/2-circle.svg + + hash2 + + jYvgGnlGAB4+lGqRjWfT5kLAOkWTvB1k9cgqzrvwHZk= + + + Resources/core/icons/2-square-fill.svg + + hash2 + + IJSsDyplu9IZ1QmHKwhYdTCMZhREJpB9Os/RVkgWM7I= + + + Resources/core/icons/2-square.svg + + hash2 + + MSmMTcesI6MoQKss9fgQeQFS5VzmkwZlA3akRM1MayA= + + + Resources/core/icons/3-circle-fill.svg + + hash2 + + AxVkyTxtQZYVRnpFf+X58xsDVvlYCTUCMA/AVb2e7zg= + + + Resources/core/icons/3-circle.svg + + hash2 + + tIT9qoR/KG1FG2VurMQKB7RJknL54uNmKirz6HyHop4= + + + Resources/core/icons/3-square-fill.svg + + hash2 + + 4n+EtHzWo+yzFQcSmNe5jeaArgJ+Mo2Xlbpl+rxnTGc= + + + Resources/core/icons/3-square.svg + + hash2 + + p2yXLgeWsPAKlchCkrKXieX0RXwsbuy4Li3e6EZweyM= + + + Resources/core/icons/4-circle-fill.svg + + hash2 + + GBSrePcoOPCF3q1T2AyFZXR6Oq6WiXbP1+Zip9DBj6g= + + + Resources/core/icons/4-circle.svg + + hash2 + + pjIBJPVtH5X7EgyvyV9F3Dg3WXoVOIq4f8Otb0YANa0= + + + Resources/core/icons/4-square-fill.svg + + hash2 + + 0cWf1ld7q8rtYnxSlA/jSXHr0da90M5iKYX/L5mgNzQ= + + + Resources/core/icons/4-square.svg + + hash2 + + yv2xc0y9W6XQAIhEZX8fFZfpe+kC6qR4mwxYQXsoNqo= + + + Resources/core/icons/5-circle-fill.svg + + hash2 + + bsgaPM8zZS+v7nalXjpklNoqVJtAomye9Re+ORx/dN4= + + + Resources/core/icons/5-circle.svg + + hash2 + + AwhyanhgjjfgEhNvUBY1VkUwUenm+kU/Au3UIcIm3+o= + + + Resources/core/icons/5-square-fill.svg + + hash2 + + 3DYnyIy0nCH7FQGzYDnWrfpcXAZ5J8GTjulx438hV2Y= + + + Resources/core/icons/5-square.svg + + hash2 + + nbiiA2EdHDrJCc9sJ3lCDQUTr9Zw3bNFfrQikzN5aLg= + + + Resources/core/icons/6-circle-fill.svg + + hash2 + + BlrvzB/Eufz5grpjDJw45enZwuBZNm3+tCZQrZgKbNY= + + + Resources/core/icons/6-circle.svg + + hash2 + + fHeyK2r+PdnjQHEtE0lXQeBoDxBYZlpJVYEPI6D7Q04= + + + Resources/core/icons/6-square-fill.svg + + hash2 + + mGDIA4j2MnmOwa3MpJuSv/bRC/w50zRSdej3D/lGG0k= + + + Resources/core/icons/6-square.svg + + hash2 + + dJeOt/i7f2w8rASDDnCuCSiKvfw+Cdv+jG6I2Yxe9TM= + + + Resources/core/icons/7-circle-fill.svg + + hash2 + + 4LkghVL1CiYRxaIbnm+3/qh1/kShkJegyWFNAK3+tP8= + + + Resources/core/icons/7-circle.svg + + hash2 + + JZRo1h61IQzglM9eGcspHvFwnV7TFvWR/bNDfSfeZU4= + + + Resources/core/icons/7-square-fill.svg + + hash2 + + fAxPP0akhkABmo4gjgEfyFnj5n0PlOSzwqiRFhHhtio= + + + Resources/core/icons/7-square.svg + + hash2 + + us6i39+pKuRM8o9Npe8zn8DGyi4CfrcqGWX253nvQOw= + + + Resources/core/icons/8-circle-fill.svg + + hash2 + + QsmSCgzH0UGEpxKwKxIhDiaVL+Z4aDiuFG1+dkP82SY= + + + Resources/core/icons/8-circle.svg + + hash2 + + te2RZNxXFdWZFrCidE/vs/2AaVM8tmZGgiCjRXVKGdk= + + + Resources/core/icons/8-square-fill.svg + + hash2 + + WjQi4/5QwhG3Pnyb8f986JihuOHXs1PT4AocV5295hc= + + + Resources/core/icons/8-square.svg + + hash2 + + IYY3qQklfthXFub8wvscuKrLiJ42+Op3blgPWr/xti4= + + + Resources/core/icons/9-circle-fill.svg + + hash2 + + 0zYg+A958V/D2KDGZPdshVy8Q7DcMpGPXuWZA4eXSTw= + + + Resources/core/icons/9-circle.svg + + hash2 + + gBtBiMwPJE3smQjbdhbRcsj4RB24hVTTXm62gswFB48= + + + Resources/core/icons/9-square-fill.svg + + hash2 + + heTsZI4U89RrDvNiJZW0DThy3vj2jMtrSerf4/GC8C8= + + + Resources/core/icons/9-square.svg + + hash2 + + FF/pw1wz0lkZoipye3UexEfQOz2fcaPz/4wS2+ApTDc= + + + Resources/core/icons/activity.svg + + hash2 + + J/wsj6j9+gRP91mdyZReIH0CobhCx49ChAi/mlBl0Lg= + + + Resources/core/icons/airplane-engines-fill.svg + + hash2 + + p2E12d8LmCJ8b7CHve60trxG7yxzY6G5a2+DpyYO/yg= + + + Resources/core/icons/airplane-engines.svg + + hash2 + + yOePuoxYux14pgYqaOxUBr54wAULSegF1rohZl9AmaI= + + + Resources/core/icons/airplane-fill.svg + + hash2 + + yj64m7wVI/ujT5AZMbZFHlkKXK8pt7sbi0ENMVmP6XU= + + + Resources/core/icons/airplane.svg + + hash2 + + i3IA0zdajGMDWeBa7jBG/Bm7O8q8cexBlVMU1e1y1tM= + + + Resources/core/icons/alarm-fill.svg + + hash2 + + 6h1qks2x7oTYWVMpjQb00fbC3vnjvp5GHkx8XxVxvAM= + + + Resources/core/icons/alarm.svg + + hash2 + + /2MDYYMCChXR6fNJux25VJii/H3cGda4zIA5azdBo78= + + + Resources/core/icons/alexa.svg + + hash2 + + O0r0PRHWAg0WT0jagdDvxMtGC052jad8zozLBXHk3I0= + + + Resources/core/icons/align-bottom.svg + + hash2 + + JCZOBWxp+q5qoLUrlTGYdIV6Pr9ao5OMDQMJZiyOpsk= + + + Resources/core/icons/align-center.svg + + hash2 + + rUAhNdkM5gDs2STmSFzFT51pDIKE0IFbbjuG22D15Jw= + + + Resources/core/icons/align-end.svg + + hash2 + + oV1wDFxrkvWfMUNXwV3kqLWhx4BTeuEoy74OD6FLPjQ= + + + Resources/core/icons/align-middle.svg + + hash2 + + Tm7K7OdoubJoIvOBOeDC11fjJRrlHAFEGzekyP8xFPc= + + + Resources/core/icons/align-start.svg + + hash2 + + ey3ss8Gtzg7QaQRy/D0AxOA40XIpqRpqJIz8exsZDQM= + + + Resources/core/icons/align-top.svg + + hash2 + + jE2XhhbEZ9y3PbtTNRJLhweSv9tNIAr0cwaqK8Vuypk= + + + Resources/core/icons/alipay.svg + + hash2 + + YbQoQelni3ivZUSzA1EtAIHxBldSzoKbssbL2lXFINA= + + + Resources/core/icons/alphabet-uppercase.svg + + hash2 + + jpsCwdxW1kfPMxTLirCrnkLDjS1UaJgeJnCIYfFDipE= + + + Resources/core/icons/alphabet.svg + + hash2 + + R5+AvDUeFMaavEl30FHa3F51+7MrsuKtrvY3wGSzMms= + + + Resources/core/icons/alt.svg + + hash2 + + 6gxglSZovn2sV2dfC7GhX4NKjvc6VJ/zxz0K8FbbRjQ= + + + Resources/core/icons/amazon.svg + + hash2 + + PmfB6O9tu3vJGlDz5hq0NSpVNKlg14vAR/IlPhqxpHQ= + + + Resources/core/icons/amd.svg + + hash2 + + 8LvPNBKgfJZ1H83bXzykl/Bls8VTycfTOixsX+mcE1g= + + + Resources/core/icons/android.svg + + hash2 + + cBE4bgUnCd2gPEuv4aR9cBGDyTaZKW/Bpy+3zTdo6z8= + + + Resources/core/icons/android2.svg + + hash2 + + CU5zR2Mds1QUXRf2sPU0Q4Fz6aFrGiQenU6jb95Qt5Y= + + + Resources/core/icons/anthropic.svg + + hash2 + + 5KUQ4b16UQrtfNNqUn4mBatPG1H6NebGPXv5ji5AuX4= + + + Resources/core/icons/app-indicator.svg + + hash2 + + NIMvog5WGxLstgnQ15FHMy3+pS3D5nLIgSUECJMK9RA= + + + Resources/core/icons/app.svg + + hash2 + + rSItDdkTDXXi7a4mVquSR0J7MpcJwsHneAuwEn0io24= + + + Resources/core/icons/apple-music.svg + + hash2 + + q4dC6jdb9bexUUaQuwVlEhZL8F9ZUcF7ucrjIfBZ+sI= + + + Resources/core/icons/apple.svg + + hash2 + + VuR5Wz5CakXYx/POKQOEObg82pZn+a07vLE6SCjEBCA= + + + Resources/core/icons/archive-fill.svg + + hash2 + + RCX629+t/ZeuFZiW6J/jw+hxHufuLtTazJ/AfPdtCW8= + + + Resources/core/icons/archive.svg + + hash2 + + l0S00maKFKwXuA0Wm+iCP3gODmvC9g9iD9Z8YSUwc70= + + + Resources/core/icons/arrow-90deg-down.svg + + hash2 + + EwLSs+NokO6NN+y2kdX4UcB/qRrPQJChl/kTHbR8sCo= + + + Resources/core/icons/arrow-90deg-left.svg + + hash2 + + XBy3PgEOXsNXR6FM1v1ZOOreLU28eGSPuLkKsJLj1IY= + + + Resources/core/icons/arrow-90deg-right.svg + + hash2 + + BLZg8fg7vsx07sRBr/G2XbTp6TUCZL4Le0m/GNeXqOo= + + + Resources/core/icons/arrow-90deg-up.svg + + hash2 + + J7HP7bgysS91BW1OvwbUtVudnFYJ5LTVSOXPEh++WVQ= + + + Resources/core/icons/arrow-bar-down.svg + + hash2 + + K0UZ9n/VQhpfP6S2t7I0XK6mE8QaDPIsh1aK3bI7h8o= + + + Resources/core/icons/arrow-bar-left.svg + + hash2 + + vJ9c21UKb2OSM8/26xHmvZ+daCTQyiSpQmZAnjyPIVY= + + + Resources/core/icons/arrow-bar-right.svg + + hash2 + + bGDbb6DUCpTzMRnQRizebxyjLhLzxbSYdmdYor7goeA= + + + Resources/core/icons/arrow-bar-up.svg + + hash2 + + qERgbPK28ufnOehYyi/090rnDMyd3aGeA6tI7TIpybA= + + + Resources/core/icons/arrow-clockwise.svg + + hash2 + + V/v4mbkfhynlnRUpnzFye5Gl4sRqL2125ed1sjXFioo= + + + Resources/core/icons/arrow-counterclockwise.svg + + hash2 + + YTQ9nw0ILmwrP+EcnZjO/oWqS/SKYqk3vyCzQlFMUOU= + + + Resources/core/icons/arrow-down-circle-fill.svg + + hash2 + + 5i/2NrCHDGMyX3vhIW14FkPjZBwk7JbuledHtjbbaU0= + + + Resources/core/icons/arrow-down-circle.svg + + hash2 + + j491AEdPYLLH1tJR/1OlW9XGy5qdKGdIwi9q5lPIDYo= + + + Resources/core/icons/arrow-down-left-circle-fill.svg + + hash2 + + m/zsetaQCYFH8m5tWW+pSn2I6TWBBuCD/0O7X2IDto0= + + + Resources/core/icons/arrow-down-left-circle.svg + + hash2 + + Ga2JzHfUDNKK8hYqUeH4b5Gaf3KAxrq1mMWPB9Unofk= + + + Resources/core/icons/arrow-down-left-square-fill.svg + + hash2 + + wgxKgqRYQIL7CLwn3mYF/Ci9rEXkhOBrUZd/FbcRqcw= + + + Resources/core/icons/arrow-down-left-square.svg + + hash2 + + PqTedJa/jtS2aJ2pzJnxs1OyOp6WtBkyRV1EuYPtDkQ= + + + Resources/core/icons/arrow-down-left.svg + + hash2 + + tsNRZgC57aGbW0tiLy6zfBSD8tellxzdfq3gB2bUe3Q= + + + Resources/core/icons/arrow-down-right-circle-fill.svg + + hash2 + + EaPcL77Tt2fXuelo7QlnTO1mivbL0cunPLbzpxJQ+Z4= + + + Resources/core/icons/arrow-down-right-circle.svg + + hash2 + + 7VinWjfuceFcmN6axOHHRnZ7y1ANS5lv0P344WQXzok= + + + Resources/core/icons/arrow-down-right-square-fill.svg + + hash2 + + RRQ5gUZVpHgHlpCavaRoyM4vqimQSX+zEcHB4hPQA0s= + + + Resources/core/icons/arrow-down-right-square.svg + + hash2 + + 9UciChR7eKNC/AJnjveQGVepkJWfJcwsKdFWfCOJcvw= + + + Resources/core/icons/arrow-down-right.svg + + hash2 + + I0ulft6khce604vF3kyjRsVWbJlNpBz+qBah6AVzNCI= + + + Resources/core/icons/arrow-down-short.svg + + hash2 + + JSHQFEQqopeug7F2G6kGUmg5sVgcUrln0C7lsvM+bUw= + + + Resources/core/icons/arrow-down-square-fill.svg + + hash2 + + +Z3ckkLfiLyN1BJ/3es/csEcSQCR8M5ExZKr7NOCeF0= + + + Resources/core/icons/arrow-down-square.svg + + hash2 + + KaTmtjBaqIjjVlFoxYnWNY6k/4Zmw86NgiReS++i2fg= + + + Resources/core/icons/arrow-down-up.svg + + hash2 + + bT/v9PEp1a7K8vYP4cuyOGa/C7Nmvwdsmpo2XE4Z0XA= + + + Resources/core/icons/arrow-down.svg + + hash2 + + r7Y+nffSGuaW4GioEiZ1rnwC5yMq2J2QEGMJNvJ7tBI= + + + Resources/core/icons/arrow-left-circle-fill.svg + + hash2 + + cijx80dQxU3EDvI6sGCn7xNCXT33E4jhJ3barJafyBI= + + + Resources/core/icons/arrow-left-circle.svg + + hash2 + + 7APW6YVllfcrMEkK7rAnjOLq+ynIv98FL57UTvcikCw= + + + Resources/core/icons/arrow-left-right.svg + + hash2 + + 45isqVGd5AaMn8QE1AYvl4xgBms74GKn1u5zrA6SXO8= + + + Resources/core/icons/arrow-left-short.svg + + hash2 + + l60rUIq892S+DyxUZUYU+9aWmkuvSZttWF7xQ8ui/fc= + + + Resources/core/icons/arrow-left-square-fill.svg + + hash2 + + DlKjlSJTFrUiq8mV5XfZYrlhmsf99Xw916AuxHa7TFg= + + + Resources/core/icons/arrow-left-square.svg + + hash2 + + p9+7g+LeOQ9ih/0QCQs17FoQQR4P/LCDugdI+GdARXo= + + + Resources/core/icons/arrow-left.svg + + hash2 + + qh0mfjUV+JeYdWUbSLFChfA0lp4vXmo6vve3MpJVq38= + + + Resources/core/icons/arrow-repeat.svg + + hash2 + + Cs6+B9x6WDZlKDTx3YvINg9XRrWn1nbri0CT/iBPoL8= + + + Resources/core/icons/arrow-return-left.svg + + hash2 + + y44c0wnC8+RhE57jiJIFcu8zpJTbKAIEWb2HJ74N9sk= + + + Resources/core/icons/arrow-return-right.svg + + hash2 + + 6FYTD9rWycMqVTw5ZVCifpfm4M9qJUpeAcWwEuldIfk= + + + Resources/core/icons/arrow-right-circle-fill.svg + + hash2 + + YIjreP/CJ3OHHhwbiS/pixG7uyeZr5rqvTA8wDvQnvk= + + + Resources/core/icons/arrow-right-circle.svg + + hash2 + + XkTHI2dbPcBU0lwIdTJDFCxIf59E/bO7gMOY3V70uYg= + + + Resources/core/icons/arrow-right-short.svg + + hash2 + + FUxWSGsQOrqvpMOPlbeo8/GkwzO4Ch/1DqPuftxfjZU= + + + Resources/core/icons/arrow-right-square-fill.svg + + hash2 + + krfZcxugR8hfnwlkEP7QiUBUvmamYF9CQ0dSk0dfynY= + + + Resources/core/icons/arrow-right-square.svg + + hash2 + + 5diJYUiIwyA9InOzEI/8b624/OHEhSAiFrDFKhZz/EI= + + + Resources/core/icons/arrow-right.svg + + hash2 + + mvEFEQXa/ovEZwsGMwrZx+A2dlxj+deLMeXOB+Y7nQQ= + + + Resources/core/icons/arrow-through-heart-fill.svg + + hash2 + + KSbGUXAZ9gRsPL1rIZ5ueBuUZjOl+lYd+4h6sNmVNuA= + + + Resources/core/icons/arrow-through-heart.svg + + hash2 + + ZDjt6lyto5P6gn50EIAdPhAXSvKx8xQOjvLWBGx9ahk= + + + Resources/core/icons/arrow-up-circle-fill.svg + + hash2 + + aPaUyVWaPuASxo3ZaPje3hCvj7EBsedm65AO2R8HtIE= + + + Resources/core/icons/arrow-up-circle.svg + + hash2 + + ZWv0x2dHJsta0Q9Q3l4KAJafD4PrX/29uRuthZobRL8= + + + Resources/core/icons/arrow-up-left-circle-fill.svg + + hash2 + + wj/NibvO+UwjhGJzjzjY0ZD8rHq4W3MQPh/RH2QQSqA= + + + Resources/core/icons/arrow-up-left-circle.svg + + hash2 + + fs9d8byEV0ghOwzr4QMr6ckJXCOXZWLjpQwA/lwKl88= + + + Resources/core/icons/arrow-up-left-square-fill.svg + + hash2 + + 7MJZIZ9LafPScRXxCcxi1kZf6q/0MiZFd+aFk9vrUxE= + + + Resources/core/icons/arrow-up-left-square.svg + + hash2 + + 52sTdoGCLVWxux/ontwl0Rpc7/V+3mUHV1fSmINvjFA= + + + Resources/core/icons/arrow-up-left.svg + + hash2 + + Y7hDWYc9+RXCQaFDtfmWqo4a+jl/lEq167c/ppqKDsg= + + + Resources/core/icons/arrow-up-right-circle-fill.svg + + hash2 + + 7d3Kg8sQz5rMuiZRnK9SwJAZix6uhBWYM9uvdUkrNnM= + + + Resources/core/icons/arrow-up-right-circle.svg + + hash2 + + TKUZjUCCoVqW9vIvUo8H5bIfJK/ROqwvb4SLS1Pb4SY= + + + Resources/core/icons/arrow-up-right-square-fill.svg + + hash2 + + DKIKSgNteZ/BSHuDwQr3X8zAPhGBo+Zov0yQ61VfCg0= + + + Resources/core/icons/arrow-up-right-square.svg + + hash2 + + GxKTom4n6lH/2uXmrrBtkuepWLgZ8z4hqqOCGT+twro= + + + Resources/core/icons/arrow-up-right.svg + + hash2 + + 7vbQ3vB0ZN5PCUDURHlWftpp9z7Wc3SLw6KvUjJvq6M= + + + Resources/core/icons/arrow-up-short.svg + + hash2 + + 7Kqf3Bg3nCRXhy+oMtTVjpulwJm+U8XeZ9KbWNvAqDY= + + + Resources/core/icons/arrow-up-square-fill.svg + + hash2 + + dJcKYHjxJCiRKTbBw6Dyp2D2QssHVWWsmuF5mgwuWOI= + + + Resources/core/icons/arrow-up-square.svg + + hash2 + + KYoYolrR+0Iw6idvC8geFAZblQAPrOJFOuCSPfNcfQo= + + + Resources/core/icons/arrow-up.svg + + hash2 + + ALINMZDXtJfjWQBehOeDeJA8mrNriWm6DFFw61aDTKs= + + + Resources/core/icons/arrows-angle-contract.svg + + hash2 + + aUAzJ/p3rcrP1R5x+Lcee/iE7yNMfN3/7q9I/9CwUJI= + + + Resources/core/icons/arrows-angle-expand.svg + + hash2 + + BR2dB879Gk1qt4vZc8MeMt3taZ6IaOxezQRkyQxBZDU= + + + Resources/core/icons/arrows-collapse-vertical.svg + + hash2 + + C4TQSdVGxTGxgsRkCArRhND9o7EYLK7G+UJiTuJs/c0= + + + Resources/core/icons/arrows-collapse.svg + + hash2 + + E9en5TNzeXoBgqmzkkWHuezl1yB57hlns/qFBnlrjdI= + + + Resources/core/icons/arrows-expand-vertical.svg + + hash2 + + ZuW5TQncYsebtlaLVFigPmsZPbeyinCXOuM37ldTaJY= + + + Resources/core/icons/arrows-expand.svg + + hash2 + + 5Q15k7XqXWxBtDL/D3sUFmLrMxjYENcJCeEkK9EvOvg= + + + Resources/core/icons/arrows-fullscreen.svg + + hash2 + + EudkR73KNw6XLrjjK0aVdTFc7CwBxdbr1i6THwmQioE= + + + Resources/core/icons/arrows-move.svg + + hash2 + + hkznOC/Lco7XVgfgemPD/W7fm40MfSzy61se79pVcLs= + + + Resources/core/icons/arrows-vertical.svg + + hash2 + + Qce5p7oiH7KCQDMhvBcOxxJ1tP5O9awCt7hKnxAdY1Y= + + + Resources/core/icons/arrows.svg + + hash2 + + c23pdV9rGLTaew7b6LjCIlmLPxBph8X4d07DFX36f/I= + + + Resources/core/icons/aspect-ratio-fill.svg + + hash2 + + HWDJzxGYSExUQycSwFRrHXKQDrMFIevgiwYHORnCIwA= + + + Resources/core/icons/aspect-ratio.svg + + hash2 + + E1qd14c7+ChXci9FXUKzhm2Bz6U3DprgSGZyHgBMKOE= + + + Resources/core/icons/asterisk.svg + + hash2 + + 0zPEckq23tImSoK1OjG4JpuannxpfUq4Tw/WJX7WLfo= + + + Resources/core/icons/at.svg + + hash2 + + E27XjL3QBR60wBeyLIQnaklnNexChkVsqLBCH2abFus= + + + Resources/core/icons/award-fill.svg + + hash2 + + EJAMkNMFN/WvqX+kFC2SvHysAZcEEHhrWFthWMeKd84= + + + Resources/core/icons/award.svg + + hash2 + + Wvq4c5lKF4CDZfll2hYOeIHMhFUGDbT6QxaIvPdLoyw= + + + Resources/core/icons/back.svg + + hash2 + + avpG5/fpStZEIx5SKpdBLQZKFt7Kwxdm6Cz+AsR8AQQ= + + + Resources/core/icons/backpack-fill.svg + + hash2 + + gUyKiI9QnR/bdaH1ANoTeepr0Ep0mErao1QzfgfGGwM= + + + Resources/core/icons/backpack.svg + + hash2 + + 23dv1CE3Qcl2CqfPkM7G1heLoF2/mtFtDWbDa0Nkqvw= + + + Resources/core/icons/backpack2-fill.svg + + hash2 + + DQwxZObAeKgPx62FzhCRTtOIFsJhm/ofdicGFuQRMT8= + + + Resources/core/icons/backpack2.svg + + hash2 + + ZY1FaWjXuDx33zP1cTJbDl3pWonk7zzyHZ+xsnBkLjU= + + + Resources/core/icons/backpack3-fill.svg + + hash2 + + duNfb6uNX2JBJRbEYUlBo/RgyePrl3cX+s2TPPxD8hQ= + + + Resources/core/icons/backpack3.svg + + hash2 + + 9pQSvzf2RVTtf5/ryrBd+pu4FahW7EeHTmAGkPZYIV8= + + + Resources/core/icons/backpack4-fill.svg + + hash2 + + k16Ya55DYSiziv7TyvTBpE1ERnEtaB4hBQCPumMnSi8= + + + Resources/core/icons/backpack4.svg + + hash2 + + 49EnC6NFSxVkyH2hmQg7VVa7X/Fn1HhjiNfO6lsaUlo= + + + Resources/core/icons/backspace-fill.svg + + hash2 + + Ge95kZ6gXJGW+xe/ght0aJlH9c6SJSq2y9RcbkECWz8= + + + Resources/core/icons/backspace-reverse-fill.svg + + hash2 + + 4gn7zg4KkDoE84oU0i675Ro9Uj13KYbTK9Yen4CeFCY= + + + Resources/core/icons/backspace-reverse.svg + + hash2 + + 8kIDyvbVdVpSon45pyTSb10gKQ2CYZHxEufD73pTiKA= + + + Resources/core/icons/backspace.svg + + hash2 + + y/ixa1pNTCDE5WDVoNn57dip1oCxHqZzevK6YsiQ/+w= + + + Resources/core/icons/badge-3d-fill.svg + + hash2 + + r3n1k4fWmJOneaDzrLHNDEWWbHk0u8Pudjkc87y4FEw= + + + Resources/core/icons/badge-3d.svg + + hash2 + + JTCkwp9BOWX5Bohm6eSdIbDuKzwtiLeGTJ/LDXEMxgg= + + + Resources/core/icons/badge-4k-fill.svg + + hash2 + + Q7HGe6BvFggkiqFM6ZWcUa8Lk8KWGymgTVkiaZ3utvo= + + + Resources/core/icons/badge-4k.svg + + hash2 + + VhSFKytjdUJwpXKYZ3xZai/riRFYbU/tRUWqSn5TFIY= + + + Resources/core/icons/badge-8k-fill.svg + + hash2 + + Yeg7A6RIzqyRC7883WllaHRcx+NpOlT2uPYC2N28xUE= + + + Resources/core/icons/badge-8k.svg + + hash2 + + 77XyLONJJ2XkHjCU70sPWOvOBsSnt44BU2deO8qYruw= + + + Resources/core/icons/badge-ad-fill.svg + + hash2 + + 6pflI3cnHe2xr0LQnFoOvXKd+JQaSWrRhr2k/aSGKNo= + + + Resources/core/icons/badge-ad.svg + + hash2 + + 8Iu2X0iDInw0C7LMOYNUGU/H8s/MPO3aGSvzKTgq+ho= + + + Resources/core/icons/badge-ar-fill.svg + + hash2 + + nCj7LsSwcgCKGqrukGXiJKsiQeRvDRw4MPRMg2LXXqk= + + + Resources/core/icons/badge-ar.svg + + hash2 + + kWVPyShHcEr6kabKZEW5J0OOpnihbOr6Y9qL0JYsM78= + + + Resources/core/icons/badge-cc-fill.svg + + hash2 + + VpkGhjAtcItsAAgUiHxZang/fBKLSW6DT0WhewBN1sw= + + + Resources/core/icons/badge-cc.svg + + hash2 + + UmVR2O/ybaUBVwRrTyW0UFUmpr4yoaDwJStJsj54wAU= + + + Resources/core/icons/badge-hd-fill.svg + + hash2 + + S5pzZuG5Xx78Rq4D8mCAchG2l8ZjJXQMjiotGxeU0lY= + + + Resources/core/icons/badge-hd.svg + + hash2 + + 4UgU+ykbe2Uz/qJ5GjweUSJDEWJSa08Bak+lRQEq3kk= + + + Resources/core/icons/badge-sd-fill.svg + + hash2 + + zePuLouPUDvtVyJPkR+s1V6TczOllF1lCWkpq90Ach4= + + + Resources/core/icons/badge-sd.svg + + hash2 + + 6vqmLMsX4McE16BgQrRjho7aQWHLK4qXIzFJYzaw4YA= + + + Resources/core/icons/badge-tm-fill.svg + + hash2 + + 0zhvCJraKZ0fX568mfBDoJB3vfOOg11CCyfr24enzaY= + + + Resources/core/icons/badge-tm.svg + + hash2 + + trGeUQnblmPRb9g/pWJyOCo9kS0cxI/GpFTEyhgeo4E= + + + Resources/core/icons/badge-vo-fill.svg + + hash2 + + 4SQax5vWFidvvnKMtxSryPexv0xB1IvqulOXcybZhm8= + + + Resources/core/icons/badge-vo.svg + + hash2 + + xhMQ5GYc3eij9sj4WBbihhTM6U6fFeE0TkpIkOq7YR4= + + + Resources/core/icons/badge-vr-fill.svg + + hash2 + + NMjjsYmIm5fAV1Mfu4wEhixj/HGwE1pFB6vZkVTngpg= + + + Resources/core/icons/badge-vr.svg + + hash2 + + ojBJGnK21m9GPuCBHa71ns+5r0P/vVSH7N1nfcviA6I= + + + Resources/core/icons/badge-wc-fill.svg + + hash2 + + JYGJUDabIBCRoXNubZeezjC6J6Hx4EnfUg8FQwzK09M= + + + Resources/core/icons/badge-wc.svg + + hash2 + + eAQShfJVjL8vFgwjTDMgWFcOyDApjEvdlg7abcCPpww= + + + Resources/core/icons/bag-check-fill.svg + + hash2 + + REXvyag5DniJvKKm0xgBSOiIBpeHdj3GkReN3uoK/G0= + + + Resources/core/icons/bag-check.svg + + hash2 + + DlVQtCb/YyUDdl4ZZRF0Aj0kPd7VIbxLY31xF4UVR6I= + + + Resources/core/icons/bag-dash-fill.svg + + hash2 + + mwkFs0ehFC1GJ9ngPgMo3ydIENDzCGVus+jxzld3Mcs= + + + Resources/core/icons/bag-dash.svg + + hash2 + + VzliNDCAk5hC1pCATIFKMb1DotGk8NjPoTpt8LtO88U= + + + Resources/core/icons/bag-fill.svg + + hash2 + + e3tU2Oc/AGVwzLs5eyw4Zq1jr3YH7voCQAsl3YX1LSg= + + + Resources/core/icons/bag-heart-fill.svg + + hash2 + + yYQkI6MadMmCDi5rU4Mph8egRjeSjQVF2j4+2cFhXnw= + + + Resources/core/icons/bag-heart.svg + + hash2 + + c5abo2YgBE1O7a6jiXkpB5yBYvdAiGGvSqvuuOLKMfU= + + + Resources/core/icons/bag-plus-fill.svg + + hash2 + + bN3SSYV9Fn07tAl2Jaz75YQJB9t05hrQ+MMaGbe2Ryk= + + + Resources/core/icons/bag-plus.svg + + hash2 + + Gi8VPRqiSbaZMySuul2vH7EI0rnR6m2k1Rc5xRSceV4= + + + Resources/core/icons/bag-x-fill.svg + + hash2 + + iEADPL1+Z4LEFa/W3WbizckQW5cd1yVVgdW5V1M5OwA= + + + Resources/core/icons/bag-x.svg + + hash2 + + gxsabsqOpIQLzFFtfep7JOn/t3KdGSQvZcK0q1h7p0o= + + + Resources/core/icons/bag.svg + + hash2 + + 098f3Tx9NKGBG5R1Em9KGy9HjPKn8V0RoIiHMn1hwos= + + + Resources/core/icons/balloon-fill.svg + + hash2 + + X3MA0hY+scu51KOkncbxdZ7VEsU0eEmwlwLpZTpAP/Y= + + + Resources/core/icons/balloon-heart-fill.svg + + hash2 + + aKL9BHaMjzdpwa6oCopjtW9zDLhD28ONvqp+QvaCBjI= + + + Resources/core/icons/balloon-heart.svg + + hash2 + + 7FUlIccNzhWinJixIytmT0snapiJVtDd2T7WRq8Da+0= + + + Resources/core/icons/balloon.svg + + hash2 + + RP5dHUTL8vqffFIvZmKyv+mKv/NM/59TuzKnW+F5SzE= + + + Resources/core/icons/ban-fill.svg + + hash2 + + qOaxlKfkiykkmvF1kWDVhVJZqd/vMdHy7WrX6Xkp0mg= + + + Resources/core/icons/ban.svg + + hash2 + + UMcQU/Sf6tXDvZDTdcMe3KXChClJE4tg9kHlAYMftwM= + + + Resources/core/icons/bandaid-fill.svg + + hash2 + + DzUd9/NilA9DrjHOhLJL0VtDnBGRKUmsxQDbYP4H3Gg= + + + Resources/core/icons/bandaid.svg + + hash2 + + ecuE+7Hvc2chB6LH7ABY4l67CJmJ+j7hur/WPVyFZco= + + + Resources/core/icons/bank.svg + + hash2 + + YinnH5DSsq+S7S6BhsDIV9Dgz4ALt+WxEjOcgIyK34U= + + + Resources/core/icons/bank2.svg + + hash2 + + xW7Rr9f5/EwCSFQ/qy7vudPfAe2gq1xAc2lfW7jwfik= + + + Resources/core/icons/bar-chart-fill.svg + + hash2 + + j48qcUFriy0762SYjBFCaddF8XtH7o62hdfVcyV/4Es= + + + Resources/core/icons/bar-chart-line-fill.svg + + hash2 + + MTJwf7QkJZ2C+pRR2T9GmFCyTInukMg/XqcKm2E3NSg= + + + Resources/core/icons/bar-chart-line.svg + + hash2 + + NPqAFUR6fOny172T92mwcQjaKnNdag3xBa/CHeIVAMk= + + + Resources/core/icons/bar-chart-steps.svg + + hash2 + + UJ1pJgJVysLyppTpjuJRAncr2Kz7NDxdgxZm1B7p1zY= + + + Resources/core/icons/bar-chart.svg + + hash2 + + q9WJ54yYNu2DhnuPX6hJfX1XWkKgnemTR14pZnkuc7U= + + + Resources/core/icons/basket-fill.svg + + hash2 + + YNhnxD/jhtJPAcWRnsjkM7oz536tv3Y+r8rYz2nh3xo= + + + Resources/core/icons/basket.svg + + hash2 + + +k6Y2UQ+lS+VS+cMAZy7DByF3Hilij1utdV1ynoZXu8= + + + Resources/core/icons/basket2-fill.svg + + hash2 + + T3Ne5uXiwmDfpHKiTcJLUGVUTca/Tud8+rXjX0iOIaQ= + + + Resources/core/icons/basket2.svg + + hash2 + + BhMGgs7L5P80Z/vn1nUmluSYjQuKWM4zODOD9Lws5CI= + + + Resources/core/icons/basket3-fill.svg + + hash2 + + xfeSJjwSPs0jmwHbNUEVw+FGJJQG4OiNrEvvJGPzKfU= + + + Resources/core/icons/basket3.svg + + hash2 + + JbYrhJSwjJNtZyH1I7EmafeQEBChIfpm/HpI0Po1JME= + + + Resources/core/icons/battery-charging.svg + + hash2 + + v8aTbKXBK5h4t6/pctYNK3UeXWgVHhigvSMbFEuRbGA= + + + Resources/core/icons/battery-full.svg + + hash2 + + kOu/LzuZ9rWt84opc2131ktQ20XYC152P0DDgndgFMU= + + + Resources/core/icons/battery-half.svg + + hash2 + + 2eqma2Q7CkYBhdZU6bZLTKsxYpZwoxr3OTlMRT96Cf8= + + + Resources/core/icons/battery-low.svg + + hash2 + + KO4w710/MYv9gx62j65T5czWYff1kEZDlDURaclidVg= + + + Resources/core/icons/battery.svg + + hash2 + + 69VIz5DnEg2sntM3Tdcaf3pR/Gi9Jv0OH40HA1ceHEc= + + + Resources/core/icons/beaker-fill.svg + + hash2 + + M3aSG7umhpEhl3xPsBC4TnukGoJ2KJHMBPY2MpL3mVI= + + + Resources/core/icons/beaker.svg + + hash2 + + LYe/r0EjXQyuGvOzOy/pedD/5EFTXuBsmBovJqde7Vc= + + + Resources/core/icons/behance.svg + + hash2 + + kIvoaOSvAmiAfc4unZz+6M3hwXLOUNURavnTFgbVl68= + + + Resources/core/icons/bell-fill.svg + + hash2 + + AlpZriB31oH8Fzdzjx5tJMU/4+hQkXuKrtafnCAkWE8= + + + Resources/core/icons/bell-slash-fill.svg + + hash2 + + DY4z7Uiz0m1jRxUNcDqvykNgpe2gI1J3XEaoPEh8Erg= + + + Resources/core/icons/bell-slash.svg + + hash2 + + m+FkLUN8hblBE3xPnNBvUcTkPggQQ7ypbrtE6+wCE+Q= + + + Resources/core/icons/bell.svg + + hash2 + + tJx2yTXBtlRMssJngouCaixB0EaqQ18+jvL9Asxh+9I= + + + Resources/core/icons/bezier.svg + + hash2 + + 578kRJqg6AUjPYKGKC/uKLQMLBFu4EEn9hBMP5pd714= + + + Resources/core/icons/bezier2.svg + + hash2 + + 8Kx04QuDNhDOUzuzJaL3Lp2kYb5ClsakIcJK7enpFJI= + + + Resources/core/icons/bicycle.svg + + hash2 + + gDcqWP6SuIveTStHE2F35lkP4Q+xhXKYiHeFmumfqAs= + + + Resources/core/icons/bing.svg + + hash2 + + NWKGOk6SRZxvIMxHH3AvB4ihWIbzOy8gZ31QCyxXUgI= + + + Resources/core/icons/binoculars-fill.svg + + hash2 + + eTZYxeBiK5K8bq2fH//tb6wPgfPrYljlx1Yt7emW7hE= + + + Resources/core/icons/binoculars.svg + + hash2 + + Goi81EpGz5NMaPiFE0WQemw8TYO0H3ju9wr/tzH33ow= + + + Resources/core/icons/blockquote-left.svg + + hash2 + + ORrDWA+sqoofzesJDnhPNj1H/984fuqoclsAhIwiBkE= + + + Resources/core/icons/blockquote-right.svg + + hash2 + + 6hDKGXdKddH+rj8/EcymwaFmkMhN/zt3zgfkRH6WU8A= + + + Resources/core/icons/bluesky.svg + + hash2 + + spTznmLMN8/HqUoGZDR8q7Kn5Tlk+7jODKhu+VDPTs0= + + + Resources/core/icons/bluetooth.svg + + hash2 + + F3W2R23p0GtNQ5zp55nWImWlifzF+9UUQKWKCxESL38= + + + Resources/core/icons/body-text.svg + + hash2 + + wdtHFIK2Z2NGgpeTSB6fOVb8B0urqwQQEjx+3U/nrrQ= + + + Resources/core/icons/book-fill.svg + + hash2 + + /831oI6vlutyLG3L9dGhbn1pfHBppig2zMR5qPpagX0= + + + Resources/core/icons/book-half.svg + + hash2 + + SC6p7gNTmZvIcVK/BNlyeO/EmUVZWN/ZRDIMoSmtBWc= + + + Resources/core/icons/book.svg + + hash2 + + 5RIoeNfxbwWFvc6z+YW2ffP6jgm2ZiWsWLVbqd9e6X0= + + + Resources/core/icons/bookmark-check-fill.svg + + hash2 + + fDx+32SRkGIUG5cSm5KRZBxxKB0Fp8yW39hh+86dcs8= + + + Resources/core/icons/bookmark-check.svg + + hash2 + + 1u/0AobiSWMEtAFM3xpEbUtiGiqGkNNkWcIin3hauEo= + + + Resources/core/icons/bookmark-dash-fill.svg + + hash2 + + DoGx8Dp9Mnlm4cir0tmwfZjLRlmhx3eGjI0s8gRF4+w= + + + Resources/core/icons/bookmark-dash.svg + + hash2 + + rOoJHnNCpfe0+BqIqblTeQ9nPM+Hl8HhLgFOBgKvO0g= + + + Resources/core/icons/bookmark-fill.svg + + hash2 + + eTzlPXG0kampQxykSrcp0DUjLZwR3E1OhjXurT6NkPg= + + + Resources/core/icons/bookmark-heart-fill.svg + + hash2 + + CwDy8rE1tZr2QM7WTUxeydZlBWsYIUuTlXP5vaAjE5I= + + + Resources/core/icons/bookmark-heart.svg + + hash2 + + VM3JAUxF04tN5f51+LDKcYnfNHF5m5Zegnv8pBSqM6I= + + + Resources/core/icons/bookmark-plus-fill.svg + + hash2 + + nT9oHhk/r3STrr1KNpJFF/sRww++/p7Bb/ZIuC3IjKo= + + + Resources/core/icons/bookmark-plus.svg + + hash2 + + kpUEmkgJvzKdqpoD27sG6P9Y1cSUhPSCuIcNEnb4r/U= + + + Resources/core/icons/bookmark-star-fill.svg + + hash2 + + 6aKK+KURPiKXEYgYeaG36bwwlK3HzRQUJYuapePvJCE= + + + Resources/core/icons/bookmark-star.svg + + hash2 + + /O8gL7fUIQMG0WFMjTbr2lNqSlwDTVOZmdz1qBZCl0w= + + + Resources/core/icons/bookmark-x-fill.svg + + hash2 + + dNwiQAN9bQVUSwyMOem1LSbHG8gVzGe+RHlPzi3O29o= + + + Resources/core/icons/bookmark-x.svg + + hash2 + + ngJScBLUyzy51mes+ZjUQAxdR5GBjxAUxoe2KOHoCuQ= + + + Resources/core/icons/bookmark.svg + + hash2 + + vE42e3nWJiib9k/F6EywP93Jkf8XAs9Ci5sVyDK/9XM= + + + Resources/core/icons/bookmarks-fill.svg + + hash2 + + /1q48VKa+pHrHLOu64JNfikIeMdhmITbcCjTy3m63UQ= + + + Resources/core/icons/bookmarks.svg + + hash2 + + UAdUI7juooIBp+/vhzZwEqjnFJFE1YM4xWttLiNKixI= + + + Resources/core/icons/bookshelf.svg + + hash2 + + w4aIjKD6Xa0pO4VXeDLhvwZZ9UqaV03Y5pKjUULa7iw= + + + Resources/core/icons/boombox-fill.svg + + hash2 + + AF76OudcJW2XukZFWi1FLwqHTLAIcxR+BLewWx5SXp4= + + + Resources/core/icons/boombox.svg + + hash2 + + 7kMwKT2MuiUbqb7S8ROGdpLT/G/9D59VocMhavLj8XE= + + + Resources/core/icons/bootstrap-fill.svg + + hash2 + + t9lG+FoBz5GPIQLyYvAypL+jE6TyfoetWrkJk0kX1CI= + + + Resources/core/icons/bootstrap-icons.css + + hash2 + + AEMichyFVzMXWbxt2qy7aJsPBxXWiK7IK9BW0tW1zDs= + + + Resources/core/icons/bootstrap-icons.json + + hash2 + + HJ3h46qqG7pZZ7rH6tp5R1CC3Ya0pBlV5Y08JWmyPPA= + + + Resources/core/icons/bootstrap-icons.min.css + + hash2 + + pdY4ejLKO67E0CM2tbPtq1DJ3VGDVVdqAR6j3ZwdiE4= + + + Resources/core/icons/bootstrap-icons.scss + + hash2 + + Wl4+JO5suK8BkJCDXbUj6Pnj1guy6s8mdASQtqRdD78= + + + Resources/core/icons/bootstrap-icons.svg + + hash2 + + /nthMD7osWCqLVltq7tw9P/q+OokiRAE6bHQ0od2OLE= + + + Resources/core/icons/bootstrap-reboot.svg + + hash2 + + jjP9onmvSLwObdv6ubcWFbSe6Kcpz3CgNnScl5wm+Bs= + + + Resources/core/icons/bootstrap.svg + + hash2 + + yildZa2jun9CZCeN7aq3wYQgSWF9pBzBk8NTHGOtXdk= + + + Resources/core/icons/border-all.svg + + hash2 + + aCWbFIqeN2DGwcrlRQh31e3srbToGu0YuilKo81y76E= + + + Resources/core/icons/border-bottom.svg + + hash2 + + tKmpc9IFBrHU/brqGPDZEMzeo9Bzsc5nO46p91tY+sA= + + + Resources/core/icons/border-center.svg + + hash2 + + aZpXDqFhVcfEqLETLj5zMRvI8FSiWBPmvBH9TC2Zp1g= + + + Resources/core/icons/border-inner.svg + + hash2 + + S9NlHpHtVgtSs0nZQWtwBfPoq8yZ4Tgd0FGEk1q2iv8= + + + Resources/core/icons/border-left.svg + + hash2 + + BFtBE55KcMcAkGOuda7QIghWFPmgs3LMkDhrUyhns54= + + + Resources/core/icons/border-middle.svg + + hash2 + + zRhFwZ2hHWUr+i7s53OJppYcNBuc0ITMm8AkS/kntos= + + + Resources/core/icons/border-outer.svg + + hash2 + + mKqUqMVKpAIBCZHc73tm0EoNbYBDSb4KyTPdps4H1ZU= + + + Resources/core/icons/border-right.svg + + hash2 + + gccs+BnPpxYJ2xcn3Cn/PgMXPUQzTdpwevyPlAxpaTc= + + + Resources/core/icons/border-style.svg + + hash2 + + xb1aLtVYUJh11qut95Rz89a9vgXYspFc3FVMQAttruc= + + + Resources/core/icons/border-top.svg + + hash2 + + ZeX0odesSG1TsvdXooB0bPy/je31KFfIcQ61MGYO6+g= + + + Resources/core/icons/border-width.svg + + hash2 + + ji1H8uXcVVhm/bkmNt/YWgAKYdJbqCM+dPP0scMrTZs= + + + Resources/core/icons/border.svg + + hash2 + + 6z+OgT7G9Va0zBUpzx8pY9kxyrSeBEkQZA3vAi/b6Qc= + + + Resources/core/icons/bounding-box-circles.svg + + hash2 + + rPdKjmmmYedo/soj5RtLa13qa/qkRXSrj3nVBO4LBS0= + + + Resources/core/icons/bounding-box.svg + + hash2 + + rmZ8F9jVA4BIurpfXJrr9VSO+GEcHZGZbeiEnQioOME= + + + Resources/core/icons/box-arrow-down-left.svg + + hash2 + + oyIFeoIoYjxDkuEnvPlmNQD2+FOXsc5AsUE0bR6Legw= + + + Resources/core/icons/box-arrow-down-right.svg + + hash2 + + /l7II4xTFAN5zV/zF6ahtWfRlfHJ39jAX8Yu4MCnM1Y= + + + Resources/core/icons/box-arrow-down.svg + + hash2 + + lHU0Y0sDGKl1n06m/SCS7NnkiBFgGlacmyDHAXhmFv8= + + + Resources/core/icons/box-arrow-in-down-left.svg + + hash2 + + pGkAuerxwM1uJydYHEvCH2HdsBt5SW20iXfH1APCn8k= + + + Resources/core/icons/box-arrow-in-down-right.svg + + hash2 + + vQ5uC/lithejMPxiNU2vMoPuhWCl+iESw8nvBF1BmKI= + + + Resources/core/icons/box-arrow-in-down.svg + + hash2 + + XKg37VSR3DKULaYBdQeME4hnN8jNe66bWm4uaVlhRZc= + + + Resources/core/icons/box-arrow-in-left.svg + + hash2 + + giX0Tb3l4jiXOUFJ6Ia17wS524AQq+mzGtUiO8CoKaA= + + + Resources/core/icons/box-arrow-in-right.svg + + hash2 + + a3oNdlisMMTUrBWkJ4FhMYIbMdy4aS/LvGcDVA4DzD0= + + + Resources/core/icons/box-arrow-in-up-left.svg + + hash2 + + JjbwRuM6uNCQO0zEupoL2mVyS9XiO2JWgsxhE067hDU= + + + Resources/core/icons/box-arrow-in-up-right.svg + + hash2 + + s8eZcr7KkDLYpjyivMZAz94oSqA/v29YUdYgJpIAMM4= + + + Resources/core/icons/box-arrow-in-up.svg + + hash2 + + BIop7CvmOfHgZQG3ivo08QHyAuIeJsKt5B4P3hL/8KU= + + + Resources/core/icons/box-arrow-left.svg + + hash2 + + sjS8HxATaBooTZ/PQlldM99rQA2bU5ofxdA/qTaAleo= + + + Resources/core/icons/box-arrow-right.svg + + hash2 + + omBOi25ir1b1+62GN8PpU64f+7y0Bd3RwZ31I4v5e1I= + + + Resources/core/icons/box-arrow-up-left.svg + + hash2 + + JkH/afdD/S4EctbkTqFnP4Bn8tt9Rwd6HkDqSyEOho4= + + + Resources/core/icons/box-arrow-up-right.svg + + hash2 + + azFNUAYYcEG0l2va17rEG2TRQlDzCym3/Ot8dUX4z7k= + + + Resources/core/icons/box-arrow-up.svg + + hash2 + + aqUmU6twC+tQMuf0jBpr5svZOTTHxEe8LO2VFBvery0= + + + Resources/core/icons/box-fill.svg + + hash2 + + yU5yDdf2bS0krY50/rU//7XItnC0q8vXBh65Uka3BS4= + + + Resources/core/icons/box-seam-fill.svg + + hash2 + + BuwhXaBFFBFCc7+WwTQqK72L7SENwJFxYpPR08xHF/s= + + + Resources/core/icons/box-seam.svg + + hash2 + + iNQU4GBnGU/gTryJfYIKhRP65XvQulbpYE/bDMalCeo= + + + Resources/core/icons/box.svg + + hash2 + + s76DYb6Fi8gDLzYqK4KGnXv7ouRWfFKLY1BytOJoIUM= + + + Resources/core/icons/box2-fill.svg + + hash2 + + 30IpYxU7fmpyVnuc9oTzwzryL3Dcc9PD73TeKARLOi8= + + + Resources/core/icons/box2-heart-fill.svg + + hash2 + + Z36eV/O9x46HZ3/cREB8LqmfLfoP6pW97iBpZZdn/4w= + + + Resources/core/icons/box2-heart.svg + + hash2 + + Gkt00mfQ2bquy5TLD79fJwUMVhDLU+uwD4mHln6wM04= + + + Resources/core/icons/box2.svg + + hash2 + + 8JElCaoD15Sg/OLR2zTpUlj33AbpDW8y+gttabPTRhM= + + + Resources/core/icons/boxes.svg + + hash2 + + jsI/+s2VNGSu1+tDMzGEt22DBF5Sq1hfUgehrADDyBA= + + + Resources/core/icons/braces-asterisk.svg + + hash2 + + P22PLh9PPs/z9aAtTsWQ7KY5EX8ln23fgOK4liPkPy8= + + + Resources/core/icons/braces.svg + + hash2 + + eQW9l4YRoUF/c07aA2o353elIKbs1e6eMX/kCEi4rVg= + + + Resources/core/icons/bricks.svg + + hash2 + + BnUMN00FI83I0ymY1CzpCF2ev19esLhKJmAoDrUutko= + + + Resources/core/icons/briefcase-fill.svg + + hash2 + + V+N26YbXWvclPDkcFc9iercVzUTUiX3SbVMwcogxRGk= + + + Resources/core/icons/briefcase.svg + + hash2 + + dv7abopkI+C5s1Bvy18zBGoQpMqwYKDlFmvOvCyhSJc= + + + Resources/core/icons/brightness-alt-high-fill.svg + + hash2 + + nw53X5s+xBjAyakPuR4Stmz/hzxWQqGZAvgpFo7WB5A= + + + Resources/core/icons/brightness-alt-high.svg + + hash2 + + t4ffPjp1eJKv/PtM52//uMTyzxk1xgTBzACUKPL4jL8= + + + Resources/core/icons/brightness-alt-low-fill.svg + + hash2 + + uYcLHupcRmACMIhHXwdUklplaUr5Ae62XfpILyRcdDU= + + + Resources/core/icons/brightness-alt-low.svg + + hash2 + + wjNbxDqvYI3I9luCl/h0XPbQuC5Dt6pO/+dUzShRFls= + + + Resources/core/icons/brightness-high-fill.svg + + hash2 + + pT51uTsupzGTDLL7cfZbhDQJ62QsuzAnigUTXvhQt0o= + + + Resources/core/icons/brightness-high.svg + + hash2 + + Tn7iXczcvbu0lMQEGJ6mLXEdA4WKhbR51C97TwRaBRE= + + + Resources/core/icons/brightness-low-fill.svg + + hash2 + + 9cas66uG3fykr8ia3wor9FJ2oulMkPV5FQ+Vn03w8/w= + + + Resources/core/icons/brightness-low.svg + + hash2 + + 1yVZ7t0ClL3mZKAjIcyKfrTnFIESwasLlhcdRzN+Sbk= + + + Resources/core/icons/brilliance.svg + + hash2 + + ymEHFY/RAeAoIT1Jsub7JvJUlY/SFhNkm1yX4OqnhoM= + + + Resources/core/icons/broadcast-pin.svg + + hash2 + + jXnOKO0VpJt0T14QFIZxCAic2a0x32+ZgfUdwBKQMW4= + + + Resources/core/icons/broadcast.svg + + hash2 + + uGhk+j03113BlNAcxMgbqPRn/A2j63PvWCpXIl7C8hc= + + + Resources/core/icons/browser-chrome.svg + + hash2 + + zDujwRA7i6nylwIKEXk5MyQJ9T9Ful8z/6bceokDdHs= + + + Resources/core/icons/browser-edge.svg + + hash2 + + kybGuZl1Z/mxtcrLx1IJNrtAeNSIR7TsQno5CuKNWt0= + + + Resources/core/icons/browser-firefox.svg + + hash2 + + Jwsgj5xHI1at9P/d0yeIIbUbdcOKkUPD9KNgRIHTYRo= + + + Resources/core/icons/browser-safari.svg + + hash2 + + Z0tmQH1IFopBQAPuUvnpXwHYVm/MUmW7GKSqR4Tx1SY= + + + Resources/core/icons/brush-fill.svg + + hash2 + + VzB0TYSOpvRiSIHgzwTUztRBt9SwZqJKa0j82sKAsmE= + + + Resources/core/icons/brush.svg + + hash2 + + w/QCDI2Jlf5PZ3FStsDGuCLGSJ81d6ls/+Z2YViJrNk= + + + Resources/core/icons/bucket-fill.svg + + hash2 + + 93ehTRMPK8iB6AHr2eGNnAsFgGq5+uzt9GyyU7I3xBs= + + + Resources/core/icons/bucket.svg + + hash2 + + XxxLSZhrOxMG1Q4tq0KKP7Q7Fk6jdNW/FJ92mSOLR1U= + + + Resources/core/icons/bug-fill.svg + + hash2 + + +EeNSiR17qW5HSiGRD/DO3qeQPEH1MWanJvNnXDXlk4= + + + Resources/core/icons/bug.svg + + hash2 + + 375/ZT+Jh4U3EPkEcEYq10H7CBmLHgabFSJEOufvH8E= + + + Resources/core/icons/building-add.svg + + hash2 + + OQWSfJ8pfDasK46fAqjgExFaXjZIs2Hs5r6g5mgcbd4= + + + Resources/core/icons/building-check.svg + + hash2 + + CPjSEjxgaOLYyRkq4bWAYoYEhNVMlfgS8uPUKe6baWI= + + + Resources/core/icons/building-dash.svg + + hash2 + + qD9Loi4mODSdsyt2rT0bXe+JCYB0JsXEo5ewlNmXzLE= + + + Resources/core/icons/building-down.svg + + hash2 + + buuWf9SavKSEijen6MpveFFBROTKghi4C7nn26tELaA= + + + Resources/core/icons/building-exclamation.svg + + hash2 + + Ti+tI2j+ZeAQ8rkrBbgCQ7Q3jaWh70wFk2QvXpIxq3M= + + + Resources/core/icons/building-fill-add.svg + + hash2 + + JVRSf4pbM2UhTWzWetGuSfaTrvoVShTs4TwZu+96Md0= + + + Resources/core/icons/building-fill-check.svg + + hash2 + + AbQ5ggmle6t7nwfsZ+cTNl4t79x9whTS7cvWr7E3t1U= + + + Resources/core/icons/building-fill-dash.svg + + hash2 + + pNgpz8WMf72xyz87ANoejD4PBZthGuOXBd9Pb15Lr9c= + + + Resources/core/icons/building-fill-down.svg + + hash2 + + NIHTb1mz0Kh7bbznYOYGHZOrVF8SWlFFkU12UkxTycE= + + + Resources/core/icons/building-fill-exclamation.svg + + hash2 + + waLrbZuxfpduN0k0RbJAtNtMueYTuMWBR66T63NiV/k= + + + Resources/core/icons/building-fill-gear.svg + + hash2 + + 0OLORo9I7QklE2JFXIwJtEhvn8qa6Bzh1px1yNk6Xmw= + + + Resources/core/icons/building-fill-lock.svg + + hash2 + + 7oWNe0qMrf7/e8RW4NbJN+9MSuNyyZR79C2G1VLiEX4= + + + Resources/core/icons/building-fill-slash.svg + + hash2 + + y8RYfsw/tI4A1jAJTl98t40NlKJno813cbGg/UWBDw0= + + + Resources/core/icons/building-fill-up.svg + + hash2 + + SnU0YUidJxuF/IFJZpPDU/CPUTUMdYsdTnAfRhYttL0= + + + Resources/core/icons/building-fill-x.svg + + hash2 + + 9p6YKcDgqp3TxpRtvsJh3mpWpmnDLrB5Tt+DCAOjRRI= + + + Resources/core/icons/building-fill.svg + + hash2 + + 2wAoB8ww8Cnh06qcdqTjXzHVkIABBoSfqZnjVaCTdl4= + + + Resources/core/icons/building-gear.svg + + hash2 + + r+kqT1CqjlJVBr2CfFkpi6iQHltM4sydCqe3sDg78Gs= + + + Resources/core/icons/building-lock.svg + + hash2 + + Afqno6cWvKGKu1ibCLugD7WGi30PVvlOx8NPsopHJ4Y= + + + Resources/core/icons/building-slash.svg + + hash2 + + x5ioeZw40RNQ5r9uDTd2lKilAJDUkkagrTvbVB5P72s= + + + Resources/core/icons/building-up.svg + + hash2 + + qRkgXi2JmicbCu8+imU8TJoGAc4V9MFUc9j8LnEBTcQ= + + + Resources/core/icons/building-x.svg + + hash2 + + jw39k8QPWT49V4sVovogfI3z2kgTPeKvaoNt42yBLHc= + + + Resources/core/icons/building.svg + + hash2 + + 9vfqKCkICupKbU0HqIQzuUk16PJGobJkQRr8qDrgANw= + + + Resources/core/icons/buildings-fill.svg + + hash2 + + GtvWiLRHnGeIh+bxQe2xCcC7ClwV+ZGpwjAP/6/mWOY= + + + Resources/core/icons/buildings.svg + + hash2 + + qKboqnGkmo92YwhU/QjLoBLutNplh2IsY6t/ePNGRoM= + + + Resources/core/icons/bullseye.svg + + hash2 + + SbcN5Y3q2SAscf5EjyTjiRltyijK6Hx8SZD1wBVrkd8= + + + Resources/core/icons/bus-front-fill.svg + + hash2 + + bcaaiCG2OF1gpapSSv1bEnTOAjGOWuMCmPGG+1Hqrz4= + + + Resources/core/icons/bus-front.svg + + hash2 + + 7/bEbpYOc7VKY501D+wUWvL4toWhZrbMHYZLjE0v6ug= + + + Resources/core/icons/c-circle-fill.svg + + hash2 + + V6tzChvOwWp4w89EmVHk/bvIQllDTN/fkO9F3rdUuFc= + + + Resources/core/icons/c-circle.svg + + hash2 + + po7gWZDATY9k+2579s343qezCmaEpjZ+Jz7YR+fH0jA= + + + Resources/core/icons/c-square-fill.svg + + hash2 + + v6n0py6llNFMnpR4QhmXIXmffChy0Ku8cePwRuY5Ns8= + + + Resources/core/icons/c-square.svg + + hash2 + + I88jvSTUshn5PxzHW5A9TEbh+GlU4/Talr8/Nf5R57w= + + + Resources/core/icons/cake-fill.svg + + hash2 + + Kjgzc0iIxg9bUXKNuZdzEBhK0Pal/Liy+VUUq1cJ+oo= + + + Resources/core/icons/cake.svg + + hash2 + + ALToVl3LTOPTeWHVjH/GqTSe1bvfXYufejohN4sEZWk= + + + Resources/core/icons/cake2-fill.svg + + hash2 + + HGUykg/Tk/dyezHX8RM94XCooLT1IQAtzfe2TIj4k78= + + + Resources/core/icons/cake2.svg + + hash2 + + KnyR1MKl2ISsW5m8nm9vlTTFfkCgaelDrfWDWuny720= + + + Resources/core/icons/calculator-fill.svg + + hash2 + + eX/TEEwJ2QB2KlyebYIuyx728yKJjgvfptsXVcUTafk= + + + Resources/core/icons/calculator.svg + + hash2 + + U5FY+i9mYE9Nh+imtXjj7bzefUq1AWDP6sxQak26Vos= + + + Resources/core/icons/calendar-check-fill.svg + + hash2 + + DTivnJKYMrSkUnSLGyO6RUAeur1GDX035I7rz6XssgE= + + + Resources/core/icons/calendar-check.svg + + hash2 + + sV0jLc+NMDHF5OQ4RImPplQBIRmSe6njfB7nI9PDsq0= + + + Resources/core/icons/calendar-date-fill.svg + + hash2 + + OuI1NjJ2DHWTC8EbL08Gb+DakBEWFm+WuBJ6AgvrIZY= + + + Resources/core/icons/calendar-date.svg + + hash2 + + WkxRmGmde5tUYcQa3cmWFqyuE8qhHL2hw6m9IDU+fhY= + + + Resources/core/icons/calendar-day-fill.svg + + hash2 + + 1cNUGGN+biFFHddVJbj5uqHOp0LWWwC5h2e1bNqBceQ= + + + Resources/core/icons/calendar-day.svg + + hash2 + + V+Gq1zj46HzhybW1dF5TsosIzaaeJbVf2BRZCwDsT/A= + + + Resources/core/icons/calendar-event-fill.svg + + hash2 + + p8l1sE0PmNSdLcSOKjTmVnkAH97jxZtjeL2MpLPPuY0= + + + Resources/core/icons/calendar-event.svg + + hash2 + + cqt6V/61sD63+LZ4FGQVTdHHrfmDMS02FVAlYR53iCo= + + + Resources/core/icons/calendar-fill.svg + + hash2 + + E0EgdYC5VKA2aTlPc+eiuW8UFL918pjO4hQbo+YjTns= + + + Resources/core/icons/calendar-heart-fill.svg + + hash2 + + F3zZYoUQzoIlRoIzz6Xsz4NUru2PSRvqfSJVhX2MqzM= + + + Resources/core/icons/calendar-heart.svg + + hash2 + + RMiKiFZjopjg+aF0zCyGRadAaH3GdjOv6ZsC2qUiOiI= + + + Resources/core/icons/calendar-minus-fill.svg + + hash2 + + L6f9bcKqm84v61xqyF7qLq16CD+ajqx97mYqdzndDkA= + + + Resources/core/icons/calendar-minus.svg + + hash2 + + PVT6YBNMTzK4KlbflhT6WWyU/4sRQ8VvYTic6+zlunc= + + + Resources/core/icons/calendar-month-fill.svg + + hash2 + + sDc+QbmACVsBo4HpeUaGYR7hx7EqagqDz1f0b+hIKiA= + + + Resources/core/icons/calendar-month.svg + + hash2 + + Ac36dkgzKyIYUjuypBD0BLUcfV1c4wMqzyqVkKryoA0= + + + Resources/core/icons/calendar-plus-fill.svg + + hash2 + + ZpjPxqZWPKTWZVsQFu6Y+Bxy6XkjRqmBDi6LSjC7X0M= + + + Resources/core/icons/calendar-plus.svg + + hash2 + + XEbZYnFAXxTKcvGGh3xa1rSbXle0+rGrkCxD/1iJ9WE= + + + Resources/core/icons/calendar-range-fill.svg + + hash2 + + jK7RYc7mQGZVsiA7lbrm62GsTKMXsn8gRx5qmuBVx/o= + + + Resources/core/icons/calendar-range.svg + + hash2 + + ETSsZhxgwSF5NwKNmgvv1wWjk5Q3xqvXMIgc5qVqVBo= + + + Resources/core/icons/calendar-week-fill.svg + + hash2 + + U2wsyvgY6XSI5LZFT8ainC2DXrSkpwm+u8JKZgXsLQQ= + + + Resources/core/icons/calendar-week.svg + + hash2 + + t0d+kFxDWT/LDzhPA9rVG83KjeDDfWPEZfaF4/E0XOE= + + + Resources/core/icons/calendar-x-fill.svg + + hash2 + + 7+6TSnngUiPzbPh4+sFAJHUa+oiVczlio0lxPJwI6h4= + + + Resources/core/icons/calendar-x.svg + + hash2 + + x0N6Ct/chf0IMubf62qHJokepx2WO+WUzzB0Xee09Jg= + + + Resources/core/icons/calendar.svg + + hash2 + + ir5ba4Q8sSyaoJLDYoMDayb/a05xXLzX+Z4RCY5SC4o= + + + Resources/core/icons/calendar2-check-fill.svg + + hash2 + + T9AjmnbFRMlej1baiLKZKDxWTUtCg/b09jpFAq7i3xg= + + + Resources/core/icons/calendar2-check.svg + + hash2 + + Xxvspc4ZHiPLiSFwg0ALLLy2L/UG5c8xRcckqdQ3V+w= + + + Resources/core/icons/calendar2-date-fill.svg + + hash2 + + DO2n7/xIBZA41duLJlXr7ceJ6ka62eqg7ePlfpTs4L4= + + + Resources/core/icons/calendar2-date.svg + + hash2 + + iusTnIdFL7L/S+BQCcJrYcrNy1Vf2dIn8foUfB2R5/o= + + + Resources/core/icons/calendar2-day-fill.svg + + hash2 + + hLvooIXS+6tWkLmKQHurpBERduh97xxTwoplUFyWylo= + + + Resources/core/icons/calendar2-day.svg + + hash2 + + 7UeERF5FcyttHXFk2BsznH97Xwkk9vBWEiA2vaLRlnY= + + + Resources/core/icons/calendar2-event-fill.svg + + hash2 + + VqZsxPXSea4KMkdCmLYRcYvaBR7ols/QdWQYRKgGl3k= + + + Resources/core/icons/calendar2-event.svg + + hash2 + + OPNpLrUPTrLcflZlWD6XeZu5TDIwGaxjlqbXV86fawM= + + + Resources/core/icons/calendar2-fill.svg + + hash2 + + TWp+zNTH36sSZWmbQbrLmE8q89nyfhQZjj9Z1l7B1wc= + + + Resources/core/icons/calendar2-heart-fill.svg + + hash2 + + QiJl6H7CoEzLqwwjroIh/fwln6zOwq7di1KcxWj1iBg= + + + Resources/core/icons/calendar2-heart.svg + + hash2 + + mHnjJuyahZMA2nBT0v+Ee/zMmeJEszdzjBxs0YVM91U= + + + Resources/core/icons/calendar2-minus-fill.svg + + hash2 + + Q8/dx7Ki0VP7ozhS5XtsEFIzDNp2bhQ2z0aIvcJfTRk= + + + Resources/core/icons/calendar2-minus.svg + + hash2 + + vhQ+3A+wH66pF9N6eIBOUhF2UJylL0VKbeiU0Rwk3ik= + + + Resources/core/icons/calendar2-month-fill.svg + + hash2 + + Y0YKEQWeiAZjbBhBZFGBClSEL+6J1nRSWj60XRKrK/w= + + + Resources/core/icons/calendar2-month.svg + + hash2 + + T6DTuFhQAm6vQ/tP6kb2UH/SSyEMEyPdzRxJNFOAUho= + + + Resources/core/icons/calendar2-plus-fill.svg + + hash2 + + IJXTUXL7ob8J4hSHRUba9C1E5KTFLxkh0OSIbZq2f2c= + + + Resources/core/icons/calendar2-plus.svg + + hash2 + + VYPk6lbFHCi+WNmCRrrbbxC+KKP/EubucBXifeXySOQ= + + + Resources/core/icons/calendar2-range-fill.svg + + hash2 + + ukQoBEbKJx75e4tVvU04Kv2PwKjlibDh7NFB2qTrUOU= + + + Resources/core/icons/calendar2-range.svg + + hash2 + + J50nQKqbY8k9QaR6+ZZo9aJFVpp27vcF7eIkruAu7Wo= + + + Resources/core/icons/calendar2-week-fill.svg + + hash2 + + bA3Dk/bTRM7LXZN5G2NNat6a2HLHS+fdcGk9aFmkLTY= + + + Resources/core/icons/calendar2-week.svg + + hash2 + + r3xjyw8YhDxVLQi7IraIywM7wbWn9ynsfUxobKgebD8= + + + Resources/core/icons/calendar2-x-fill.svg + + hash2 + + z7TQ+XNwR66XbZ0/CY9ZGhGyvSIuGVzH8y4ZqKoVHcc= + + + Resources/core/icons/calendar2-x.svg + + hash2 + + YSkncMarzHbR5afJePCl9t96nlchCA+CLB3XqehcXgA= + + + Resources/core/icons/calendar2.svg + + hash2 + + eIkgUhgaj9WbZjoNRaRbIxk0Z8XUoFfZ0XCpKhLMW7M= + + + Resources/core/icons/calendar3-event-fill.svg + + hash2 + + B9J4Qcuq4zM7LZGbLpecXMZ+9u3rAkeAV8xNzNguKTQ= + + + Resources/core/icons/calendar3-event.svg + + hash2 + + NEP5sqEZr8XuU4GvAahDNGeN5eSXG3THeO7ErYR0/mE= + + + Resources/core/icons/calendar3-fill.svg + + hash2 + + 0G3ANJNlTZyQHrFjx63RpE/489QSy47uW6b6xAogR5o= + + + Resources/core/icons/calendar3-range-fill.svg + + hash2 + + 3W5RZoXrwJmrIGXjCvx+kMxKqTW+qliaOuphuoFnFsQ= + + + Resources/core/icons/calendar3-range.svg + + hash2 + + rs32u/H05CYBHoQXaf/w3ELT7Pe8FZ+wXhPg66LTHJ8= + + + Resources/core/icons/calendar3-week-fill.svg + + hash2 + + dF89QFuVDOpeAX9N41KMl7THip/JTubemkRtBAbhl2M= + + + Resources/core/icons/calendar3-week.svg + + hash2 + + JTs3/ElhDCqxQEUCZIS7C+NHdmc6jWCp78MTmuNAIKg= + + + Resources/core/icons/calendar3.svg + + hash2 + + 4x+ChgbHxxaVrBSu57s/7WMJ6GgtAwLJFJ8h+vhHWkI= + + + Resources/core/icons/calendar4-event.svg + + hash2 + + X+Xz81xNmEGo37gT9V1YhX5GMkKnpt15DD62frJ4feM= + + + Resources/core/icons/calendar4-range.svg + + hash2 + + M7dz1nHf1d0bhczboAxD9zZA/aYTSAZe6UcwEQtNixA= + + + Resources/core/icons/calendar4-week.svg + + hash2 + + vSDKgxGCHzHs+NV0hFH6aoFupnsRRPLTmJ9p3XNCCuI= + + + Resources/core/icons/calendar4.svg + + hash2 + + vtim/oTPHiZeoGM+nP1v/fusBlez6v4W07QJxxYDCSs= + + + Resources/core/icons/camera-fill.svg + + hash2 + + 62mh2rEDP9GPj1Wq/MrHlEde6Cj1mRaM0at60+/xChY= + + + Resources/core/icons/camera-reels-fill.svg + + hash2 + + jB8wT/k66Hlcb9E7A6BkV8JlMw5fxxVM8Dg2AlPkO50= + + + Resources/core/icons/camera-reels.svg + + hash2 + + TrcN45QOxX/l02tj6tam4qeKFP/G3Xd2TqMqk1bcHgI= + + + Resources/core/icons/camera-video-fill.svg + + hash2 + + W6A8+9+NwOQS6fWNIK9DoCnlN2CFBmu1IfeWQTvDj1s= + + + Resources/core/icons/camera-video-off-fill.svg + + hash2 + + q2F3Gcp7aEvsb36QIU9FmgQXAelUt06gSAPi3aTMgNY= + + + Resources/core/icons/camera-video-off.svg + + hash2 + + MtAQz5nM6ijgPo2aw8fTGhG7J+9spdOlonCU3UlP+C8= + + + Resources/core/icons/camera-video.svg + + hash2 + + dVaumKBWT5Ohofa3Bch8vmLyyrBGTF4xDia7KprLPyw= + + + Resources/core/icons/camera.svg + + hash2 + + RY3/unYZ2KXHA/u8UzAJqg5FdYf3vewP8G1NZlklkYk= + + + Resources/core/icons/camera2.svg + + hash2 + + hN1GDS444/sh7xe5jXLzYCMmyJlQ4P3l0IGKY/cLqoc= + + + Resources/core/icons/capslock-fill.svg + + hash2 + + /6V7f52bG9rAc0Yt0VbMObrr1X+TcCxLy4FKNqmQB4c= + + + Resources/core/icons/capslock.svg + + hash2 + + 5zKs+pov+iyRmJzLmKxIo3B9BbNVAcCb9n8cktmjZxU= + + + Resources/core/icons/capsule-pill.svg + + hash2 + + AwCJq1RcAe7Q4R1P8JQrKREXiSu5tVzCUEMj7s4l/Sc= + + + Resources/core/icons/capsule.svg + + hash2 + + Qs7m8Khg8M5RuFouUZWTWaKWCaJtoPBRAf/28fx5R4U= + + + Resources/core/icons/car-front-fill.svg + + hash2 + + 3hFvrK3PQMq/seFyw4u9AQN5WymRelhUUYDOY1JHMIc= + + + Resources/core/icons/car-front.svg + + hash2 + + Z66feICkiNmC/No0naFJHRA+KWEoohMnQWwYa2R8sfA= + + + Resources/core/icons/card-checklist.svg + + hash2 + + /FKvOMJtyy5wcVNtBhrpDMzPG5ljlyHxHXJIwN3AxVU= + + + Resources/core/icons/card-heading.svg + + hash2 + + yKQ+yWuXDtvg/8Y3OdujAE5Tilhccc0dhjSaeUnlKpY= + + + Resources/core/icons/card-image.svg + + hash2 + + g22Xu3PeKqQP/ZAJ1Zzq8mSUlCCFpj6MFOlpRo7iHEc= + + + Resources/core/icons/card-list.svg + + hash2 + + OOjw5tkHTBsIQxTp822BrHoobE8zOQOolS621A0fiA4= + + + Resources/core/icons/card-text.svg + + hash2 + + dnmtA27RbtlDZQlp/fT3yE2VYv3gfbmYTLH54raOykM= + + + Resources/core/icons/caret-down-fill.svg + + hash2 + + hCrzNjQMTiwWLkhxek/AO/X2Q80p4Cw8IKHA/9laoQw= + + + Resources/core/icons/caret-down-square-fill.svg + + hash2 + + b5D2lRhUwagITjjp9fqZOiXJZ2Jc7vKcaC9DCXkt1g4= + + + Resources/core/icons/caret-down-square.svg + + hash2 + + huETM+i13GgAY3V1ZSOzYQGFOhkYa2je3VH/vR59fAg= + + + Resources/core/icons/caret-down.svg + + hash2 + + uG8WYf6hl/uaskxZ1rgRtBw+Qnx2czyl9l2MprlH/Dw= + + + Resources/core/icons/caret-left-fill.svg + + hash2 + + FxHRlYgOmJWElWMP4vhA2QPEfqawoz9K0YyqyEf8EiI= + + + Resources/core/icons/caret-left-square-fill.svg + + hash2 + + XOVBhptHVithcZwYXls5yj8u/zcNN2IvkaiR7g4e9G0= + + + Resources/core/icons/caret-left-square.svg + + hash2 + + y+65zk8axd8b90h6nJcFANSZWlyUY8nqXB/HNSiUAKc= + + + Resources/core/icons/caret-left.svg + + hash2 + + 2oIA4qN5HQVz1YVz0aWdw7a3kV9h/2hPMBX8NGVwpLA= + + + Resources/core/icons/caret-right-fill.svg + + hash2 + + cgCq1uloZQU9c2qxWJGqZrqqKfxT+HRA0Cx6mD0u+CY= + + + Resources/core/icons/caret-right-square-fill.svg + + hash2 + + SDAufmqhRkUz7ODHtjfw2+FQOdKs0zN2xXoYMExjYe4= + + + Resources/core/icons/caret-right-square.svg + + hash2 + + AEIswnKaYVo9C/x+mRKPbHVtp4w1ArsA15DShPJhwz0= + + + Resources/core/icons/caret-right.svg + + hash2 + + 3M1QYLcRK3fAF7nZpCeaMyn3CnQFpqChKPGfR37rLBs= + + + Resources/core/icons/caret-up-fill.svg + + hash2 + + aKyeU5IQ8ChnFb/x4kBzh+dg5Gi5WMbP/S52mx4aTvo= + + + Resources/core/icons/caret-up-square-fill.svg + + hash2 + + +plfXWrKSUWcFCZlZ1JKUEHKpD3TBK/fyTkbqH0v82c= + + + Resources/core/icons/caret-up-square.svg + + hash2 + + c5SwDaNvwbIbFxedc7mVJSV3CPIrGPydOPlsaS+MOC8= + + + Resources/core/icons/caret-up.svg + + hash2 + + kJgXM9x3bGsyrHjZgp9lUqzYiSMFw6obgfu2lu/H3FA= + + + Resources/core/icons/cart-check-fill.svg + + hash2 + + znCCT8IEDd6GixJBLKmT2odIMwZ8cy3cx3hbzLthXYc= + + + Resources/core/icons/cart-check.svg + + hash2 + + ld0Y6Gul4qqPEgsL5jFhDAFIu32Xxyw48r6nzLtX8LE= + + + Resources/core/icons/cart-dash-fill.svg + + hash2 + + ZqU5JGedDI5o/yPhzBu0QdRXB0kg5DIVEDJk85GbkDo= + + + Resources/core/icons/cart-dash.svg + + hash2 + + 0g4ZvUgrVFUb9i6w2/34yc0udYxCTutgmAleHCz6yac= + + + Resources/core/icons/cart-fill.svg + + hash2 + + 37HPP12ENbm8eHVnGywRxHzcludYarRmOaadxQo41Sg= + + + Resources/core/icons/cart-plus-fill.svg + + hash2 + + jw8w6+x0utTmK8OfekFKFHw+kFaSzgzFW6HdguJu9Sg= + + + Resources/core/icons/cart-plus.svg + + hash2 + + kvcjMblN/ki9jEewHIp/8tUhSkNF6qdNo3wgbCZXr7E= + + + Resources/core/icons/cart-x-fill.svg + + hash2 + + apcZxsV9og0sWdXp+u7R+A7Pgn9R6lUcTo2RQDonaiM= + + + Resources/core/icons/cart-x.svg + + hash2 + + lB4cgx2YVMJgErLGavY6wRoYwGv7APc8eJ6piaJBBdc= + + + Resources/core/icons/cart.svg + + hash2 + + b37y1jH2c39cSXL+XMWptLFgbCeouHyn32UG1Jreysg= + + + Resources/core/icons/cart2.svg + + hash2 + + 6HuQwLbTiXH3zEoK7O/ZOM5Ov+urbMdbdXldmSMyBLQ= + + + Resources/core/icons/cart3.svg + + hash2 + + GVuhCueY+NE8R34A4tsPpTT/WsCPpgKTixQ/zwW3S6A= + + + Resources/core/icons/cart4.svg + + hash2 + + X7crhNoSOR2ozcYhrAN+WPDhWV46z1wU38O9AnMjSuw= + + + Resources/core/icons/cash-coin.svg + + hash2 + + dyqzIDEfz7hgsQ1k5Fy+Z1D71xzkZ5Nff30JQIKK7QE= + + + Resources/core/icons/cash-stack.svg + + hash2 + + gjexE6wiADJipx0/siZZPFBp/8gslrMF6tImAGNyrlU= + + + Resources/core/icons/cash.svg + + hash2 + + wNMxq/ss9TPA8VnuWjX5Tl4DWxIDLlCwFdYKZ2e5Hag= + + + Resources/core/icons/cassette-fill.svg + + hash2 + + ZbXUT6UWubaY3ZbeqXGdI2pIeZT0po0k9fUskt50jJQ= + + + Resources/core/icons/cassette.svg + + hash2 + + pJM0RkreyVpsvOLHUibVmouHWmACAINcklqVgmxk6Q4= + + + Resources/core/icons/cast.svg + + hash2 + + lKs7vZdvDxKKSAMBCzTUoWATmuUMvXhxHi2t90w8lqI= + + + Resources/core/icons/cc-circle-fill.svg + + hash2 + + X3zA8emz7dVl/Af46amucP6+EdRhtmxPjjdCTxnBMIo= + + + Resources/core/icons/cc-circle.svg + + hash2 + + dyovKYvt0Ks+6JhvZYVgYKiwKJByP3NEGmNHUHD5Y74= + + + Resources/core/icons/cc-square-fill.svg + + hash2 + + 7twDfcU+W2RxdgJ4Qt56R+IEXlPE4VMeDiKD8LBtjjc= + + + Resources/core/icons/cc-square.svg + + hash2 + + VyUbOzmi1whHOJefYYZ6IWxwmNjs5S3WS6WhZsAsJi0= + + + Resources/core/icons/chat-dots-fill.svg + + hash2 + + 6HiGNmmCRYs9Sav7/01/2Bn9BAtZMB30WWffD+NP91E= + + + Resources/core/icons/chat-dots.svg + + hash2 + + f6bJn5qIC6FE/Xp5j7kE7vwpc4nAjOyomcboobXdrSQ= + + + Resources/core/icons/chat-fill.svg + + hash2 + + 5AsNPclVHpwQg3Kjy0EOFBHTslDJ06MQkJjsxz4NyIw= + + + Resources/core/icons/chat-heart-fill.svg + + hash2 + + wigrdcQ1T1oMwHE02CI+rErykh4Y6Kmh5fa9di6tMCc= + + + Resources/core/icons/chat-heart.svg + + hash2 + + 51plb6sxwTWiplPp6MToYQl603SawT/IDaEhH6VmhbY= + + + Resources/core/icons/chat-left-dots-fill.svg + + hash2 + + auln22xmtARkWaAZj+y2M0qs87nxXerzFw8hTthqLZ0= + + + Resources/core/icons/chat-left-dots.svg + + hash2 + + wncWVIyn/Y+YkBPwbpQt8WWIRvrUMerrTbhI6Q+TO30= + + + Resources/core/icons/chat-left-fill.svg + + hash2 + + gnb1SD+PauyVxJYKd9yZ3Zr4bgH9nfHB1X1+lDWMGWo= + + + Resources/core/icons/chat-left-heart-fill.svg + + hash2 + + SVP7dFtkOLJzg+uXKLnWpKqTGz57259JJJxpYLBQV+Q= + + + Resources/core/icons/chat-left-heart.svg + + hash2 + + ODM0xGumyLHsBm1snu/K/15Y+w9z9ADzouHI29e1tCo= + + + Resources/core/icons/chat-left-quote-fill.svg + + hash2 + + YEwUdpIoAquswCNNDh8o4tShG6cHl0ZqAgQIB3BnNqc= + + + Resources/core/icons/chat-left-quote.svg + + hash2 + + oAWx9MVrsR7L81Y+J1wt2BJ6tyqlKIfIhZGgqi0vgek= + + + Resources/core/icons/chat-left-text-fill.svg + + hash2 + + 7MdZnVitTapdE1daG790Oiih1rIOHgSpG8s+H89TZ8E= + + + Resources/core/icons/chat-left-text.svg + + hash2 + + bivyJr78OQPGYiiZQzdWSYe1NGw3oeXD/Wm1dQ/9his= + + + Resources/core/icons/chat-left.svg + + hash2 + + WRY8ayM9B6N6cTAWDV/kgv/CHAkU3vsbNVtunXbd97c= + + + Resources/core/icons/chat-quote-fill.svg + + hash2 + + WXlXZ4CT1oL8i7ZWDtnlV6MB8lBkuVceh+B5iKdYryU= + + + Resources/core/icons/chat-quote.svg + + hash2 + + xsfyNSYvFvcKwtxEtz/vzVw0q7cODaY85ok5ZTqnj38= + + + Resources/core/icons/chat-right-dots-fill.svg + + hash2 + + zDF31csbyxOuvKioiUBfhicYkPI/c/fdC7vf7/JkBNY= + + + Resources/core/icons/chat-right-dots.svg + + hash2 + + rZpLOf9x3gViRpd/cZs+E16FltBSsPWDnR8RcDmQUaM= + + + Resources/core/icons/chat-right-fill.svg + + hash2 + + hR5l9KXIEQvd84mXCIFc7l4xioJxgRQMGxTOo+Es8EM= + + + Resources/core/icons/chat-right-heart-fill.svg + + hash2 + + lE5SyG0DhDIMXkMlymZnNHC67GxJE6FmKKjdGYNpNF4= + + + Resources/core/icons/chat-right-heart.svg + + hash2 + + t2X7dGNe5+NSaaHqyCWZGkjagUsO/2alnx1vra2fQok= + + + Resources/core/icons/chat-right-quote-fill.svg + + hash2 + + 6k0WVteB7ZBqSQLCXwysEIqmaL5Ulyuy40H7EQmKmk8= + + + Resources/core/icons/chat-right-quote.svg + + hash2 + + ytytuuyroofgu6UvslXxXa4+d03qWA4HRbwvoCPkmQo= + + + Resources/core/icons/chat-right-text-fill.svg + + hash2 + + 84ue/AL/r2yYqonjvKqJ+H/4tqnY1vAAyTBV3rpkml4= + + + Resources/core/icons/chat-right-text.svg + + hash2 + + eb0DIWG7unjb3aZ7szUEMrivSHGTPjyVvyo1nvU365o= + + + Resources/core/icons/chat-right.svg + + hash2 + + xxigDSAIk4AzjTCVLQla458i/l8ybXS5nzOy2nRA+KE= + + + Resources/core/icons/chat-square-dots-fill.svg + + hash2 + + 86h8DzdSlrW7H+9Fl90svpYFY2rngslRwfDzY9bELcU= + + + Resources/core/icons/chat-square-dots.svg + + hash2 + + bt3NnPfe0oNNpEDieTISV2GRs6ZvmDWS5yNbWB2UyYs= + + + Resources/core/icons/chat-square-fill.svg + + hash2 + + Sh70btUonS0DWOoeYyejHZT+sABfjC0D1nw3nD/tr4Y= + + + Resources/core/icons/chat-square-heart-fill.svg + + hash2 + + bMGyc7ETWvNMGu4e05GBC1rQi69+XaDzwimQuUUFrpA= + + + Resources/core/icons/chat-square-heart.svg + + hash2 + + ZTWwNHYVU0kK90kQJpKhb+H4rKTKA8ppRjm902Gi4i0= + + + Resources/core/icons/chat-square-quote-fill.svg + + hash2 + + q3FqtJ1RM128j2Y7iDddpjCvYBTMsW8M+II73WhCqjI= + + + Resources/core/icons/chat-square-quote.svg + + hash2 + + wmEFQM+YsN7W5bFDMW6G1UmBAL8+cW7TRIS7ATFeBIk= + + + Resources/core/icons/chat-square-text-fill.svg + + hash2 + + /1kMBMdPGLAgDt4keMCqeTZqjJRv1YDMNAsjqAKc2ac= + + + Resources/core/icons/chat-square-text.svg + + hash2 + + mCYNXuni7/zdZaVRY29uH5KlU1kUxhfayJsNy/FLsFg= + + + Resources/core/icons/chat-square.svg + + hash2 + + jqNohowmdjp36QF5LlcisrpWklC9tcB9K4frY6iiOhE= + + + Resources/core/icons/chat-text-fill.svg + + hash2 + + LU0wwhLl2bf4y+gxhCcQN1hWmP2OgN5Sq3s7YBntYPw= + + + Resources/core/icons/chat-text.svg + + hash2 + + twBmtDyfdyZ0U4C9lSohXdPrdZ7eVOYoyeR/0vEjFLQ= + + + Resources/core/icons/chat.svg + + hash2 + + Kn3s8Y9bLgAYhA95wmhI5by0YZdKbkMkPjlEL93FXYU= + + + Resources/core/icons/check-all.svg + + hash2 + + RPfMbFrmeqEFR29fgTFnvIyTgw3W3ZcIYZoxQVTSNRU= + + + Resources/core/icons/check-circle-fill.svg + + hash2 + + xkYKC0yG0cudn+s8kASpQfvGWDlzntZuFu/nORccwbs= + + + Resources/core/icons/check-circle.svg + + hash2 + + cjogFT4faoEB73311eOfpCrCLY9fkhkyF6D/URfJ5k0= + + + Resources/core/icons/check-lg.svg + + hash2 + + kYIUH/8LFiDoKykAJI4xT1utH2eT2nJhQ+GSTBYlM2I= + + + Resources/core/icons/check-square-fill.svg + + hash2 + + 6om1MjqcarRViLMYVtFwgd4x8HZWvQuRTWlvcCMg4wY= + + + Resources/core/icons/check-square.svg + + hash2 + + j/9MtY2RUIptjcuMMO1twvQdxmSJeNy1eDH2BnlSSdQ= + + + Resources/core/icons/check.svg + + hash2 + + 3b72S/Pqmg1SIz63U2KWTiX74BwUYXH2u/qvQ2nG52o= + + + Resources/core/icons/check2-all.svg + + hash2 + + gqsgnDvKeNBD8RFE7RLD5EeaSpZ//Bj2XZ+peClsrKw= + + + Resources/core/icons/check2-circle.svg + + hash2 + + TRweF6l3NbEbO+X9qpZv0nPdx6WK25kyBaf47mIlCGc= + + + Resources/core/icons/check2-square.svg + + hash2 + + vkjX/TrogwKUoZF3aO+h3kZRMmskOCRtvOAF7QRm2NY= + + + Resources/core/icons/check2.svg + + hash2 + + t1+0I1a9FBtS0RK5eBQItJpWwD85Q84NUsmZ5RF1vKM= + + + Resources/core/icons/chevron-bar-contract.svg + + hash2 + + 74iwuQtKCXf2NUYIKglpdPyS8lwymG+5666AajqjSgw= + + + Resources/core/icons/chevron-bar-down.svg + + hash2 + + ceDRYUzPGCPEKJDExo8sgt55qdJ5ERGYk9K4YlnnqPE= + + + Resources/core/icons/chevron-bar-expand.svg + + hash2 + + gI/6sgN/lJbaK4dH6aFXcv1SlUnaPy02tFpI3QdJu7s= + + + Resources/core/icons/chevron-bar-left.svg + + hash2 + + nzyz/v1MrJv2JlFcuuUQRzTDe0KWVEfH74YznDYhr5M= + + + Resources/core/icons/chevron-bar-right.svg + + hash2 + + 1LiWJwE7ieHJQlbeaasM9hMLzqvHHpFzHVP1kCdgodQ= + + + Resources/core/icons/chevron-bar-up.svg + + hash2 + + 0k0cSIGxJLSNzrshE01RO3VusX8cmSrbhXoQS4fieiA= + + + Resources/core/icons/chevron-compact-down.svg + + hash2 + + vIWwkK1U/QNg/5sHyi3xW2qGFaJBtcoN9lmB3VtQGMc= + + + Resources/core/icons/chevron-compact-left.svg + + hash2 + + MIlE0hpz26ZN4PNMJMyO9yDJDN6al1yG2jwYfqjlb8g= + + + Resources/core/icons/chevron-compact-right.svg + + hash2 + + 5cj1Wu76boq7qvipcoTf2tXQaBLnbDG+XGwnd4kVq1k= + + + Resources/core/icons/chevron-compact-up.svg + + hash2 + + QWk4HY+7hbJlDiPyqtzaiTgr+G+ShPatMkEGkpemHoQ= + + + Resources/core/icons/chevron-contract.svg + + hash2 + + 1cWKvPXoJcLeUQHQbBqsUpeYp5B7xC8jQ2Kt8l5wHLo= + + + Resources/core/icons/chevron-double-down.svg + + hash2 + + g8hfuAGmAjUSWHepjGPzOJL90boFINXEdXeWaIOe6wo= + + + Resources/core/icons/chevron-double-left.svg + + hash2 + + +q6iEHG51tYZwTlfuLcyYfXxeduigdfrG66PO2/HtI0= + + + Resources/core/icons/chevron-double-right.svg + + hash2 + + GAIOx2Czv3CbGsTNpHlkO/EO4A0yg925fIleGeg8Gtc= + + + Resources/core/icons/chevron-double-up.svg + + hash2 + + yUt7DANPJ+V3RLzivYNxM4KqamUD3FVuDpxS4k/QCtM= + + + Resources/core/icons/chevron-down.svg + + hash2 + + 7CNqM0FQgqmgY3N/ePaPWXgzvFo36hL4FAjznD+i5jM= + + + Resources/core/icons/chevron-expand.svg + + hash2 + + 2+wkMUfSYt/GVN75adffBEsFvzRdXdy3BZE7SWlQH8k= + + + Resources/core/icons/chevron-left.svg + + hash2 + + CMr3ZMQ5jDBJ9a02/w+seOEutP5UvSBKdePhGbfbecY= + + + Resources/core/icons/chevron-right.svg + + hash2 + + jHbHrZ6pbd4rsCXF1sRsFNYqKQeB4z4QU3fp1GSV6s8= + + + Resources/core/icons/chevron-up.svg + + hash2 + + 4F79yrfk/xuYGuhLxGAMr0i13zUZ9s8G1ZMHjF0GgXs= + + + Resources/core/icons/circle-fill.svg + + hash2 + + BmV59hBMde3vz6Dtuxu2engMU2SpGL34BkqcbKFUJk0= + + + Resources/core/icons/circle-half.svg + + hash2 + + 0p7fW0AYEvUWnCvrTUEbCNjjWwNIhHM3uAK2RPHXMPA= + + + Resources/core/icons/circle-square.svg + + hash2 + + vkqsKz2//AeiGcgOX/di0XRnjeGe+NatQfoHItz0d74= + + + Resources/core/icons/circle.svg + + hash2 + + QQghuzGfiT+WYI1ExFiTJEsQD+6RHfH6t7Oh3d+B1yo= + + + Resources/core/icons/claude.svg + + hash2 + + IAk/FNMCnutzGjpIitulzAoT5E79M6VG+TDDna6tL/M= + + + Resources/core/icons/clipboard-check-fill.svg + + hash2 + + voL0mGX/yyYipYSX+aD0ouvOK6DYLGYHJpAIFY+YqsI= + + + Resources/core/icons/clipboard-check.svg + + hash2 + + +hdOVIw0K2YtwV6i16PbIQn+wVtILUNcNhLcctyPm18= + + + Resources/core/icons/clipboard-data-fill.svg + + hash2 + + uNSKG5psSRtSxRP8ZCmK/z/urmcb26RaHkj1fJwG8Do= + + + Resources/core/icons/clipboard-data.svg + + hash2 + + 3MegKlfbsA/EtRo9pvdkXs3tY2XKOx9JT/m+E5E70FU= + + + Resources/core/icons/clipboard-fill.svg + + hash2 + + eBHZYc4p1UFXrfNAN13IceuFUoxYU2jWW2OU3Q870fU= + + + Resources/core/icons/clipboard-heart-fill.svg + + hash2 + + X39J8mOcUwlgQBrqhGdzAEzRKVawOWzznrmEYAEcBMg= + + + Resources/core/icons/clipboard-heart.svg + + hash2 + + wJv0/Q5ZPVqh++0Slmh2flEP0lszX7Ys2WXvcCZdj5k= + + + Resources/core/icons/clipboard-minus-fill.svg + + hash2 + + ouQVgxy7AaGZmzUqIGmN8r7LB6VHr0Qb547IKGzm5RI= + + + Resources/core/icons/clipboard-minus.svg + + hash2 + + Y7FvrszT962rLDcqeEqv7HnffI9k7vYciqNSFMbDBEk= + + + Resources/core/icons/clipboard-plus-fill.svg + + hash2 + + 5tr1WUN+bDUEjon+sV1WzQynASGAgGKP3n0cjj/XEU0= + + + Resources/core/icons/clipboard-plus.svg + + hash2 + + TgSfbwfxGjXpKMdSlU7/QQOXQanRVrm3z+UlZCW/HdU= + + + Resources/core/icons/clipboard-pulse.svg + + hash2 + + yE8A+qTZbi2PgowZ6dD1fkD7WyqCxFpt/v+j/IE/4K4= + + + Resources/core/icons/clipboard-x-fill.svg + + hash2 + + Tfz3CSBljlUcPFufb3VU3RpEOlDTvHct75lJa0DuONk= + + + Resources/core/icons/clipboard-x.svg + + hash2 + + o31BSbzsUWblNKcL/UdmCa+OD2PjoWah+Cv9ncdPzTM= + + + Resources/core/icons/clipboard.svg + + hash2 + + tCliwKRu/sC6tW9287lFKWc0+dShGFf/zcBHiFowX9k= + + + Resources/core/icons/clipboard2-check-fill.svg + + hash2 + + 0d4dVFhzQxSWi7H3jQRHzYmKH5z1RegvXPr0SzH7BvI= + + + Resources/core/icons/clipboard2-check.svg + + hash2 + + P6w0SAa/W1uTWRAq4NpMoiKwEmWTtrPGZIohKIyhIqw= + + + Resources/core/icons/clipboard2-data-fill.svg + + hash2 + + slApv0u528/NsNNMKo82fiq+/uuBLhbXDMBCATGTZt8= + + + Resources/core/icons/clipboard2-data.svg + + hash2 + + FLIDpX1xCY70y96L+Xr0GFYFkkv/WolTCoLn3cQYdmA= + + + Resources/core/icons/clipboard2-fill.svg + + hash2 + + Rkta41YrSR3olXKh4gzWNtow/rw4nQwIKwfF8DeiHtw= + + + Resources/core/icons/clipboard2-heart-fill.svg + + hash2 + + cyCN8g3i5mMxi/SS0L0BSsdUfYUi3jKDaITR0FVIJA8= + + + Resources/core/icons/clipboard2-heart.svg + + hash2 + + S1Y9Tebvt71IdAMlugmvRY7V3JC004DUgkJw+SFD+nQ= + + + Resources/core/icons/clipboard2-minus-fill.svg + + hash2 + + AAvrGD1bW0AVvcgh6tX51KP3RLyJwa6sMcjzbmVheHo= + + + Resources/core/icons/clipboard2-minus.svg + + hash2 + + 1EZlXJf564T6p76Ath87vZYDG+HvCW//Mv7TYxI/Z68= + + + Resources/core/icons/clipboard2-plus-fill.svg + + hash2 + + TXk0/Y3qkAxH7mK0LjKhPC9uePD3n5Z0ONU6m/TdKR8= + + + Resources/core/icons/clipboard2-plus.svg + + hash2 + + dbBsWl6kEHvUfTdPnyp1s55qhIklDO7snrBBBDMUMdk= + + + Resources/core/icons/clipboard2-pulse-fill.svg + + hash2 + + /xg0GOzd69Qi2ML2BJs6MqWBsK2Ch16M+DN6WBku8KM= + + + Resources/core/icons/clipboard2-pulse.svg + + hash2 + + K7SCq/GAcUDfKg7muqL+PxcIMZeK64TbSV1G2jGIX10= + + + Resources/core/icons/clipboard2-x-fill.svg + + hash2 + + mi2iWloMRbj2NDjIsYDg2jg3mVp0m8pc82pIJHn1FDA= + + + Resources/core/icons/clipboard2-x.svg + + hash2 + + x6iaOpxe9/zOyQyTmD++2O8CRBOCGWC45KCE4+GVr/g= + + + Resources/core/icons/clipboard2.svg + + hash2 + + b7yn9bfx330cdvxX+6Yv6FacC9fz4zNKceLo0YgpRgM= + + + Resources/core/icons/clock-fill.svg + + hash2 + + PinUAe99et+UVD+KubvjjyeqFOXe4FzKi504ezecuZM= + + + Resources/core/icons/clock-history.svg + + hash2 + + G4Ms4XQY1SU9CktlQ/W8VVTDmWStfQ+7fJ9ycVYQ0K0= + + + Resources/core/icons/clock.svg + + hash2 + + uq/G9wSQaz9zoxqs6UL0+a6fV8TgLz6N55MDp3HEXgA= + + + Resources/core/icons/cloud-arrow-down-fill.svg + + hash2 + + 4GjcTkaqc8gDsnNP9+YRYw3bf6CeMczLKlLxYy0KkSU= + + + Resources/core/icons/cloud-arrow-down.svg + + hash2 + + CCaIEtZ9hne5UM4eC3tDlATIBl2Zvq/djavpURFxwQM= + + + Resources/core/icons/cloud-arrow-up-fill.svg + + hash2 + + RhNVIjkON5PySIIUMDtY6LVg2HUOunmkgOKn8G0yQpY= + + + Resources/core/icons/cloud-arrow-up.svg + + hash2 + + LhO/UK/KEOOVTPv/Pg0xZNMoYl/SpWzhnc+qxyIT/+M= + + + Resources/core/icons/cloud-check-fill.svg + + hash2 + + uN+s3jbl4n1WLmclb1QZ8EPMbU7tF+Byv8tIdffwbHA= + + + Resources/core/icons/cloud-check.svg + + hash2 + + kBFh/ZQ0oKpp2MaPkk9UMqUQMWaXdsYweUbx3do3/Ao= + + + Resources/core/icons/cloud-download-fill.svg + + hash2 + + MeS/osSD60zx2noyITSqiKwhHMbbWOmAQWrJacvSwDg= + + + Resources/core/icons/cloud-download.svg + + hash2 + + Q3uuH2mt/w52UcJ4yF7iJhZt1NMymy3cFMt4jOsReAI= + + + Resources/core/icons/cloud-drizzle-fill.svg + + hash2 + + NiMuaVpv/yWZvzVSug/yT+F1W1Asa6s+r2WbVXbeOKU= + + + Resources/core/icons/cloud-drizzle.svg + + hash2 + + Szkc7nSmOL2PGBr7mNVn1NB5xThnjsBWlqOFm/jhHd8= + + + Resources/core/icons/cloud-fill.svg + + hash2 + + +ACBdhxlQ7y6oZUyGzuAQCMmtxW8CbcD64JpqPw6468= + + + Resources/core/icons/cloud-fog-fill.svg + + hash2 + + HAnWvAM9uHiT5zv7fsoSUf2iNvpZsr6ksH17sM3XuJ0= + + + Resources/core/icons/cloud-fog.svg + + hash2 + + dWLacHUMhpFHgC7gxAmo3j1Vl8b1sz1bqp48jy0GXGk= + + + Resources/core/icons/cloud-fog2-fill.svg + + hash2 + + LRClen4R8O787/qoKZPXqacxU5TXTE5GQbKEvzRzXC8= + + + Resources/core/icons/cloud-fog2.svg + + hash2 + + BRI8xH8yglKXwPnRvS06IR6lVQeGneT7flNE8DqwaTE= + + + Resources/core/icons/cloud-hail-fill.svg + + hash2 + + ScaXCjJKQQisCakjCyRqBpDjW0vW85uFy1X0MFGsjLA= + + + Resources/core/icons/cloud-hail.svg + + hash2 + + YFSOmOVPVJ0m7wX1jLKOPh9tkSh+v/+rRPNOjm7BnSg= + + + Resources/core/icons/cloud-haze-fill.svg + + hash2 + + S5JMargfKZzVsHWpUw6SBUaLCY1aypgaBs+6nAEDjG4= + + + Resources/core/icons/cloud-haze.svg + + hash2 + + 9S3JK/kMqbvQjPkb4YgaOrkoZZSOe5lAWITGrLa/0aA= + + + Resources/core/icons/cloud-haze2-fill.svg + + hash2 + + 3/Vk/qH/5CgWaxLgv1boKxXi0Z2v/m4N1mYz93UmYw8= + + + Resources/core/icons/cloud-haze2.svg + + hash2 + + ICOLytR40SlFVLqxBqw6SlRj1ZikpWC+mwEhdseZBMA= + + + Resources/core/icons/cloud-lightning-fill.svg + + hash2 + + LPc3aaZNDVZTgBT75UKUKFHg502zRVWsPzOqLFdmdjg= + + + Resources/core/icons/cloud-lightning-rain-fill.svg + + hash2 + + +wFtG+/pLy5VcKHaT2N8Gy5SNT5ZuYqWIVGh8kLqDck= + + + Resources/core/icons/cloud-lightning-rain.svg + + hash2 + + x4CSWzGZUwYoPIe7eINZdPt4t3uM22osmEF2Y18hKtA= + + + Resources/core/icons/cloud-lightning.svg + + hash2 + + 4gdk0UJwTYLADAGT5cXyu/AzkneD9En+pvDwj5RauBM= + + + Resources/core/icons/cloud-minus-fill.svg + + hash2 + + Y2peb2rTyU3UdhPeu/AqcfuSFVAspsC0dVjuntBRLmA= + + + Resources/core/icons/cloud-minus.svg + + hash2 + + 20oTnh2i1+zgcYSy+ZSEZNQcceX3l7SdWGTo32ZB+Ng= + + + Resources/core/icons/cloud-moon-fill.svg + + hash2 + + 6q99InogtfPOgQnidfvXKp6k3KaiXA4pTdZfqJohVAA= + + + Resources/core/icons/cloud-moon.svg + + hash2 + + 7/W8mDLPQb1TfMuinpvWLoUFLDnqLlxnPUy0+IfKkv4= + + + Resources/core/icons/cloud-plus-fill.svg + + hash2 + + kedl3sACr39iRvtw4iWg/dbzA6c1ug/i5GYyg96/9jE= + + + Resources/core/icons/cloud-plus.svg + + hash2 + + G1SYzYejIVj4XCT78G+NBA59qnOxyzRnf1RaZBfj1rg= + + + Resources/core/icons/cloud-rain-fill.svg + + hash2 + + x49U6qPGp15mUMOAy1zXWfozIBaTba6Mf5AtqR/z1qA= + + + Resources/core/icons/cloud-rain-heavy-fill.svg + + hash2 + + GM7Ej464K/Mwmb2C9bh4V0tj6Mf/d4FEXRiIvyxHok4= + + + Resources/core/icons/cloud-rain-heavy.svg + + hash2 + + Kf/XP/tFLiO2mXDGPlPMBIvdu6NsU/8TAQZ1GGqfBPU= + + + Resources/core/icons/cloud-rain.svg + + hash2 + + JiIEfWP2VKjYx+zCewFrPDwTx86MriosifHK3jGv97g= + + + Resources/core/icons/cloud-slash-fill.svg + + hash2 + + WSR0bCQc0tueqjKlQjXNxPN+HgEmriO7V3fh0UZdmZs= + + + Resources/core/icons/cloud-slash.svg + + hash2 + + ekTkVHXAqlVRZEuJjCJfcB5owz+c/taNXKIJy8YJMPI= + + + Resources/core/icons/cloud-sleet-fill.svg + + hash2 + + CpZ4ghXJBlRa2aUF8bnzgFn92t46o7wRl39P4oOn4mk= + + + Resources/core/icons/cloud-sleet.svg + + hash2 + + l0qxtxwVMy66z1WyboWohw0vjtkGuFhREW/D6WUpfEg= + + + Resources/core/icons/cloud-snow-fill.svg + + hash2 + + SAnIcwRs46tXJ+9zfHbU83crajT+RZSJ5ehfyvIHRF4= + + + Resources/core/icons/cloud-snow.svg + + hash2 + + 3unz8zh3LtAS3qM1cNr8nuWJOMG+l8Ly64Ir3cMpt+M= + + + Resources/core/icons/cloud-sun-fill.svg + + hash2 + + QkwzVEZcFzVrxHNP+f8gT9SC4Xrl5jN2GXaAP9jX/Jk= + + + Resources/core/icons/cloud-sun.svg + + hash2 + + N0b+Gazlr3GpWxGhYg5RbpPZ+x+ojZprZEt6dObZ51c= + + + Resources/core/icons/cloud-upload-fill.svg + + hash2 + + ryfh0FH8XbhY8EsX9A4Przc9qLG8kXybIGInPvqCzi8= + + + Resources/core/icons/cloud-upload.svg + + hash2 + + rI2u2Vz9RRv9Dw1YRP9JLeu3s861BRlr8uFlZD/yhAw= + + + Resources/core/icons/cloud.svg + + hash2 + + t8LyzIHPP127a0Umwv9BJo05tBNiOraT4dX5fIJvdyA= + + + Resources/core/icons/clouds-fill.svg + + hash2 + + eOE6SUrTTB3IiOqp2rKnLlAclYNnjOePGBvsrsBuaBo= + + + Resources/core/icons/clouds.svg + + hash2 + + kagr5JCzE9zJpG3L42UKvpg2Ppo6OAZ7TjEP57sHoLw= + + + Resources/core/icons/cloudy-fill.svg + + hash2 + + aP4+Xcl5r/w+uJPkcOAPbmLo3hEyiQf22m8UBJtc/iE= + + + Resources/core/icons/cloudy.svg + + hash2 + + ncpLRv3N3JPMZRuVn1QlVdHrD5QcefmOfkD+x7/LAtQ= + + + Resources/core/icons/code-slash.svg + + hash2 + + 2O2xhiSyqSDpu8hm8EBOP+6njXkWbJLzFa2v5Fe9bKc= + + + Resources/core/icons/code-square.svg + + hash2 + + y1Ibtt6clzOey7xeb6z2Sen3Xkn4zIhj2eQ2Z04Qgy0= + + + Resources/core/icons/code.svg + + hash2 + + +ErDuaMV7EYOwZ3xMkuVAndn6MgWs+6IfKQy5f+/c+Y= + + + Resources/core/icons/coin.svg + + hash2 + + OIWLETD3OgvbHhZ4LOivI4dUZFjTkNY2PtzTie2bSBk= + + + Resources/core/icons/collection-fill.svg + + hash2 + + JhTqMkpuiy2lRlX44bOY1pBHhIcxe+YGN2w4XbVA69A= + + + Resources/core/icons/collection-play-fill.svg + + hash2 + + oax9lpztJQuLSLKoOiLMIWTFXA6f/H0Ys6g6I4ec85Y= + + + Resources/core/icons/collection-play.svg + + hash2 + + vr1Weht/Nu6BBfmqiBUWz9B1GvHpSnVrr92wv8vlX2g= + + + Resources/core/icons/collection.svg + + hash2 + + c00Mh/Xirnmgb/fATxnQrCHWxrC6DWP76MYosgXLdXQ= + + + Resources/core/icons/columns-gap.svg + + hash2 + + VFbVa0GOG01D9Jx7RvcQdoDWF/gxxNUAYxTAu6KKQMI= + + + Resources/core/icons/columns.svg + + hash2 + + i2U5OmCaoFrzNLEW0LZ6BFLxklqS50ABtydcoBc+o3Y= + + + Resources/core/icons/command.svg + + hash2 + + uZewz6iJ3OcTMD386+5XmBKp7wG+cmXZdxKIillo2nc= + + + Resources/core/icons/compass-fill.svg + + hash2 + + +UwYQftA+wJFI8otRFrhIqDbF8eOLGiDQZzPUzt9Pvo= + + + Resources/core/icons/compass.svg + + hash2 + + FnUWNQEKNqI3JJHZ3WyODrdsopvFpL6empZetgkE4V0= + + + Resources/core/icons/cone-striped.svg + + hash2 + + RjkkO8rO9ZoQb0AD6p4GNKB0AJ9yJrbA8r5Yn7QS7zo= + + + Resources/core/icons/cone.svg + + hash2 + + BOkCdeIbDPN+a2coIOnF2YlhNxkH1His35X3dR2+FmM= + + + Resources/core/icons/controller.svg + + hash2 + + py7OW+wRST451ypwmKRSjH52dNhFaGVO7get2ALNjE8= + + + Resources/core/icons/cookie.svg + + hash2 + + 9QDrIKcUC3sVBsfTFHrHqyal0G37Miui0TuINee5Oqk= + + + Resources/core/icons/copy.svg + + hash2 + + LnqralNWWRpTmjXb677cECMZ+PZ/IgVEVEiWpWiw+jE= + + + Resources/core/icons/cpu-fill.svg + + hash2 + + 03d8ex8Rj3uWh757pweZwsmPU3Vv7sgMpP4+R2+L2LM= + + + Resources/core/icons/cpu.svg + + hash2 + + GtWPIqRh2fjPpZJegoxSWRGTjQ/nIgwDu/oVTpitie0= + + + Resources/core/icons/credit-card-2-back-fill.svg + + hash2 + + U54ZWGnKTykn8mFCwEj6grEYUpanSaUot/8ai/hkFlM= + + + Resources/core/icons/credit-card-2-back.svg + + hash2 + + oJfD+cDXG7F+HE7C8k3ifDtXWvtSXIXm3bu3FiLfs4E= + + + Resources/core/icons/credit-card-2-front-fill.svg + + hash2 + + xDlJL1obN8luAUewDjR0mbjFFV8k40G+FS0VfHjJUhE= + + + Resources/core/icons/credit-card-2-front.svg + + hash2 + + FoXSQgksjpzWl8R8T4tVX2QfZOtGe8Kj4dl8G4uqtqs= + + + Resources/core/icons/credit-card-fill.svg + + hash2 + + rntM7jEgIQJZX4Zd+p5oDrHhvEVqxHUK7ag1sMztTac= + + + Resources/core/icons/credit-card.svg + + hash2 + + 68LKYt/QPPG/NwURqRe8vtvk5Kmo0QZSIF9k6BoztCI= + + + Resources/core/icons/crop.svg + + hash2 + + EOGo4zmFtc59NcWvFglkAktVo/Yz+/sT2AxjQU+yyvM= + + + Resources/core/icons/crosshair.svg + + hash2 + + XjDMq5EChcaU8taMCo5RY9LxE9iUd8sV/D6rGv1T7js= + + + Resources/core/icons/crosshair2.svg + + hash2 + + nLh3c5pjSJ43jxj1Uc5vncheyE9K5r+3wzI1B9EeZz8= + + + Resources/core/icons/css.svg + + hash2 + + 7kgVqUswZTHqyD0P9kICN0gDCW8fccDaUZ+e4UIiemA= + + + Resources/core/icons/cup-fill.svg + + hash2 + + pQc0BhYD1h1YHkPATdxsyDrsbhIWLe3Q1dHKpd2f238= + + + Resources/core/icons/cup-hot-fill.svg + + hash2 + + nleBDMpFSXQtQMn4CSwTdO4b3EWYcYGZKBR788asFNA= + + + Resources/core/icons/cup-hot.svg + + hash2 + + GFlwVGTGZaGsdneX1VfMxpQGhH9MwOzhHOotY+wGnRM= + + + Resources/core/icons/cup-straw.svg + + hash2 + + lPVFylqfwjLd3Vc0Ry9OIzHBLNodbDx6gHF87NAVO9U= + + + Resources/core/icons/cup.svg + + hash2 + + 1L1tS6mc1D0HLbQ1qde7kqg7aV2YtYWN5va9p/4guOc= + + + Resources/core/icons/currency-bitcoin.svg + + hash2 + + imjkHZKA/NUu0RDh0fWSrXHf9R1IKRjPiwMbhb2esRA= + + + Resources/core/icons/currency-dollar.svg + + hash2 + + 4mBtlAmkaXzaELxTtwE8xZKE9HuPOeYeD7CBd2mFY/Q= + + + Resources/core/icons/currency-euro.svg + + hash2 + + /DIORCHrs3hivrqcQNfjPXzWThU85OULlRSj6v3L8Fk= + + + Resources/core/icons/currency-exchange.svg + + hash2 + + 1K32ZEw17XA+oUsHoviRocrlYiP/NBAhiEguTKtmJOE= + + + Resources/core/icons/currency-pound.svg + + hash2 + + Z2Zr/d+FETP+OAFTZvTVDjaPCv9Kx4B95Vcq+RE8pNE= + + + Resources/core/icons/currency-rupee.svg + + hash2 + + gsoK1iedqzj/F65Vvt3Z6wA7JktewsAR0qK+tBABO00= + + + Resources/core/icons/currency-yen.svg + + hash2 + + uZcyJIGN/R6qD//xarHVOI4BrGbcQprC8eZFfrmR0Qw= + + + Resources/core/icons/cursor-fill.svg + + hash2 + + r2uFnSTdT2L3wNCS3cYkYD2UZHGCklnN1zBVbiZIyE0= + + + Resources/core/icons/cursor-text.svg + + hash2 + + h/btxODpTpIKeXYaEeZ7S1GtHFsfK5nD2uJq47isPVc= + + + Resources/core/icons/cursor.svg + + hash2 + + +YZnYRRE/i4gOw21DGJ8MHiHjAwJK4rjq78uMLYo/uk= + + + Resources/core/icons/dash-circle-dotted.svg + + hash2 + + 7L1jpeBdE1Qpr8mc3U0vS+27xruvV2wsnZmCVfDjYo8= + + + Resources/core/icons/dash-circle-fill.svg + + hash2 + + dEmdLLkzj5MmMsMaj6uqlSAbmcEpMVq/8CGvfeVaCFo= + + + Resources/core/icons/dash-circle.svg + + hash2 + + VRpXBTYyDm6eH9aWJDogZclyAhJM29Z/svrLn1nh6cM= + + + Resources/core/icons/dash-lg.svg + + hash2 + + z7cea6KodI3iAsAf1Y8P9fQJoI9ybcKqacVE3abuEjI= + + + Resources/core/icons/dash-square-dotted.svg + + hash2 + + /Zl9GmRLctkVL1f+UCZEtnwqRYegUJpC+9ahkCW6SAU= + + + Resources/core/icons/dash-square-fill.svg + + hash2 + + ZY++GhZ5Pwfpzy46xe7UXzWuPsVlgqDvWK9wU2GSTJM= + + + Resources/core/icons/dash-square.svg + + hash2 + + u7t/fHDZXWkY7TvA9iOrO3KpeV7E4ND1KBCmHdvzXPY= + + + Resources/core/icons/dash.svg + + hash2 + + HlpFfqUhiXPjlP6nfVu2vmMws1DRjosdijtnB/pki7Y= + + + Resources/core/icons/database-add.svg + + hash2 + + sHByL8/Pg4qcvEWdnNmRw7mTuaftLGqBOnFcNwgDb4s= + + + Resources/core/icons/database-check.svg + + hash2 + + tHD3vCJeQ3It0fBlqIfLzUDecZVHrLPDn84GUdYXUnk= + + + Resources/core/icons/database-dash.svg + + hash2 + + cCmjDGZHTxCGh6q3ZKCbnJvy07GYWz1uk0ojMW8vVOo= + + + Resources/core/icons/database-down.svg + + hash2 + + /T1wq1ooxOgigGoIKChwcV/8wlaR+T8ieO1p+4fj0bQ= + + + Resources/core/icons/database-exclamation.svg + + hash2 + + ihcFD092NL1cYwv9ZJDN36y4jq/L+tHt0oRrE43go/k= + + + Resources/core/icons/database-fill-add.svg + + hash2 + + yXUHIgnsZIHIeoQR7P8cvUjYuAsPLwCvq0OGSFEk0mU= + + + Resources/core/icons/database-fill-check.svg + + hash2 + + /8Jq7Rn4UgBNyo5sEJ84UUOnD38OcFLLyIrQAO0ay+I= + + + Resources/core/icons/database-fill-dash.svg + + hash2 + + ClKrk4ngfW6ZvyD6qB/xXrAJz/6h7d1YvIhscd3pWpA= + + + Resources/core/icons/database-fill-down.svg + + hash2 + + oPXpcjw43sDQACjdp/31a+jyvd5Vv7YRmdexMv58EKQ= + + + Resources/core/icons/database-fill-exclamation.svg + + hash2 + + boWJuS4sHD4febrG6/z+S276GAhB5EmQn9iqeDPTgqo= + + + Resources/core/icons/database-fill-gear.svg + + hash2 + + 20/GIRj1SgGkb4MpG1R4xY2hj3LFtvE/NWPj0uSFRcs= + + + Resources/core/icons/database-fill-lock.svg + + hash2 + + SYn8QZjMpAyOt5XxZXFZDyG++AhumSGBSy69Lq0VFXI= + + + Resources/core/icons/database-fill-slash.svg + + hash2 + + 1Pfy1DLg8gYU2KuYX91RfbHDyz8Hd/A+zFDDZ5M5o/4= + + + Resources/core/icons/database-fill-up.svg + + hash2 + + 1H2RwmSVQ/krB5vCZ35A6CxdY6PsPnsEHUWk4b6G9tY= + + + Resources/core/icons/database-fill-x.svg + + hash2 + + zN2DLF8nHJn9/stXphmz37S/Y6Nr/7vbljPgopHed6w= + + + Resources/core/icons/database-fill.svg + + hash2 + + AJJZq0oI2//jt2THAXTMPfCFxwZtBqiyVwOL35OitOU= + + + Resources/core/icons/database-gear.svg + + hash2 + + qY8EWe327vwqvJTBsWXxVj12KhnHbmRdk9UVHHRWpag= + + + Resources/core/icons/database-lock.svg + + hash2 + + oYHoRRtp3OFOSN1rzZiTaE9QzklijqHBDWwQQIehrtU= + + + Resources/core/icons/database-slash.svg + + hash2 + + qKzBw1je+9ha9rHhrmMQ1SRywwLkMnj1rvTvLeDmQRc= + + + Resources/core/icons/database-up.svg + + hash2 + + xCS9X8yI9hma7Ki6IlyzPMA8GSBX7tf55HwaF7Wa0PA= + + + Resources/core/icons/database-x.svg + + hash2 + + L6s71hGBxPt+VV30lBmIimpVXjPOLzGXSiE6gxuruM4= + + + Resources/core/icons/database.svg + + hash2 + + RHF6Nmqo4W4p68pA6hkefvKbyFX0vJB58QztwfGjEew= + + + Resources/core/icons/device-hdd-fill.svg + + hash2 + + G4bc6lPmrTFeIiQIYlxh4s51Dgl8kJubFvG1jLEz7kI= + + + Resources/core/icons/device-hdd.svg + + hash2 + + z4pAowvgjLrEfqpb58Gx7X5O+9ItewOTVTNi4+b9bYE= + + + Resources/core/icons/device-ssd-fill.svg + + hash2 + + sia5ojAC4HomsXhKD0ok2iZWfP+u2XW5JwAAZavR4Es= + + + Resources/core/icons/device-ssd.svg + + hash2 + + An4vBWCHfQ9JTdI/UAvfOxqiHY6KFDzTPt7V2B3YthU= + + + Resources/core/icons/diagram-2-fill.svg + + hash2 + + B8EBCVBrCkwVIUQR6hBwzzxXoeLlZYJsu/yZjjlqYZs= + + + Resources/core/icons/diagram-2.svg + + hash2 + + NxSWIZkbfS+fT+8kXIsOGB4W3mWLZu7Oa/cKEEgfnCA= + + + Resources/core/icons/diagram-3-fill.svg + + hash2 + + 96ivliN78lTed2VuThvalqSyDCh01W6YbfZh/ZFrxMM= + + + Resources/core/icons/diagram-3.svg + + hash2 + + 6f2LgwtPkcsupzIJ7uBp3LctMbMgt0zqGy3WGMN6fz8= + + + Resources/core/icons/diamond-fill.svg + + hash2 + + Sm3RAx1dfu/ywTui+Fyl6dn6kgeJLi0hlaUugl3uzo4= + + + Resources/core/icons/diamond-half.svg + + hash2 + + 2F6SkmRvA0zI187+5/dNefLJQVUgSA2sTiCtCf85yF8= + + + Resources/core/icons/diamond.svg + + hash2 + + 1BAh8gLpo+plYBsz5Z83jYqXaMoPu8jncngQBJ4bvss= + + + Resources/core/icons/dice-1-fill.svg + + hash2 + + JHzh3KCOF/Nx+GVUgtGItara6hzqHVVx0Cy6Acvozng= + + + Resources/core/icons/dice-1.svg + + hash2 + + P8xFNyC7KIlr/mz58ICJ3LgZ+YeDLjYusb3pVGT9YQc= + + + Resources/core/icons/dice-2-fill.svg + + hash2 + + Mn9O0sA/ftsYixEn/8i8h27B2qHu6yLSsEsRvunHbKc= + + + Resources/core/icons/dice-2.svg + + hash2 + + 6x5EjMH2e3FAPSlb+wudkRjYd5tnxd+H1GsrPHPdKtM= + + + Resources/core/icons/dice-3-fill.svg + + hash2 + + GDGshZvGwmReBsqvO+qSvrw/VEm9OAEc7OOEYTokVH4= + + + Resources/core/icons/dice-3.svg + + hash2 + + aOJ7lkHRHqmqDIjp20TyQL2Xxqm+8R1VOwG0b8sEnNc= + + + Resources/core/icons/dice-4-fill.svg + + hash2 + + zIFz4QAsf+gFou6z7i0D2DY+hZnXvJIKTBjgh6mWLZA= + + + Resources/core/icons/dice-4.svg + + hash2 + + xuvkyNoZbXiZU9b2zq2VBgbq23LUlSWrm8q4Id5YCrg= + + + Resources/core/icons/dice-5-fill.svg + + hash2 + + 1dVp4PG/LOdowDymP3jfQvIeCmnxMa/8kEHmP0iIv84= + + + Resources/core/icons/dice-5.svg + + hash2 + + o4FUBqd7BgGUDMDSquLMOQDB+QdoGsJPG5jW3zfEf2A= + + + Resources/core/icons/dice-6-fill.svg + + hash2 + + g580zEQVDcTG42O3o7W9hRFjDIelLmYe8un3FP17A/w= + + + Resources/core/icons/dice-6.svg + + hash2 + + m5FS7nekT+UNYW0bwf/bmavYrnMFL5QjciPUhQulQ9U= + + + Resources/core/icons/disc-fill.svg + + hash2 + + +fdSbCHdU/Jgl3TcHV3DrH0rn4HhjWBm+j4MQN5m+MM= + + + Resources/core/icons/disc.svg + + hash2 + + VJ/y/n8E9j+XB+0M8FQ8GUYq1fKBfxBXwZtDT5Rx7x8= + + + Resources/core/icons/discord.svg + + hash2 + + MxpDdABvG9es+9j34nuvmQktynhn9gnZr8nwyGnylgo= + + + Resources/core/icons/display-fill.svg + + hash2 + + A2QuQDub9pRp7oxmjqGNw1roEisoOAAlydAtZ/NWLkU= + + + Resources/core/icons/display.svg + + hash2 + + SjS738L6Bf21uIr0KtNaI3OY25BtjpULXzG7PivgZzM= + + + Resources/core/icons/displayport-fill.svg + + hash2 + + ApDuQOxGRPe6JY+npmrx/RMUr35JPdwpiIaJ9QN0S0o= + + + Resources/core/icons/displayport.svg + + hash2 + + B7OZWB/bz/PoYffQMVtyAaVQRPj4e7RBu65qzHDi7gc= + + + Resources/core/icons/distribute-horizontal.svg + + hash2 + + 7RkYOzjAFx+HSL6ZgdhSzzjkYy7vsH7IG3XFipJlYi0= + + + Resources/core/icons/distribute-vertical.svg + + hash2 + + /rEJ1jbJeKE+9SB0r3JGrbAaO36o1cNXli1kEbnvbsI= + + + Resources/core/icons/door-closed-fill.svg + + hash2 + + BLpuQoCzO6MPlYxep5dufRy/t6cPQqpS5EMWN2J5Jsk= + + + Resources/core/icons/door-closed.svg + + hash2 + + 5Op5ODmP2MC7fTCRZBBKJcIFmFJMkF/iq2kmK4PgdUk= + + + Resources/core/icons/door-open-fill.svg + + hash2 + + tmExnZFcwxmLFLgMBFc7xn3j9qMfaPa0rmO71bVvko4= + + + Resources/core/icons/door-open.svg + + hash2 + + gpU+4GDAvXE4ZhAqdKJCG8oEDMhH9v9cIatDnPhexlg= + + + Resources/core/icons/dot.svg + + hash2 + + qiBUu1GvAo7UiEs/1nu3WTDnpRUJ+WpoiVFCpbpwBmI= + + + Resources/core/icons/download.svg + + hash2 + + wobzZ9mlK+TA4CGQ3JUJJFuu8AzmnlaSc6wpMuWoo4k= + + + Resources/core/icons/dpad-fill.svg + + hash2 + + RJcAhrHGgpxfsUxZEAWy9jMU96tRTM/D5qlGFPO8n+w= + + + Resources/core/icons/dpad.svg + + hash2 + + xUf/j6qD9Jlg/mYvbWHrPr5Wm8NQ/UrmbgKP1dn/FrQ= + + + Resources/core/icons/dribbble.svg + + hash2 + + o4on7pzAB/K6NpOev8vsH0/9lzJ83YYlHAqVPZ64/lU= + + + Resources/core/icons/dropbox.svg + + hash2 + + whv2x3eZ2Ds2JWCFd4LOU13MBcKQiQAfN7T28r0PWmc= + + + Resources/core/icons/droplet-fill.svg + + hash2 + + 0cHfWaPtkTJ93aIjQzcCFRTSbt2CsBeQU7JOQOlWVoo= + + + Resources/core/icons/droplet-half.svg + + hash2 + + PMHfkueJppo01gCxY+FQX0coFDPw45m1WhvpAnXYkOs= + + + Resources/core/icons/droplet.svg + + hash2 + + 6fQ//W4FXH4/isPY3CHBaS5gckwZSAqvTmej8Xr8IQ4= + + + Resources/core/icons/duffle-fill.svg + + hash2 + + UKBWlDNzbW+JFb7tPcpbzK4KH2sHr2h7yilExbBXQLc= + + + Resources/core/icons/duffle.svg + + hash2 + + 2UpGa0aOR3wah9M0XNF5lsbwjGZgd9RAk10j4ZlZkhU= + + + Resources/core/icons/ear-fill.svg + + hash2 + + BWMDkDhmqcHng2bgGunqfzoYRXKpKHvH//OFzXyaG7w= + + + Resources/core/icons/ear.svg + + hash2 + + fSCGQVgKr1aQYHD7A/r9ZQ+rEmyQdKYqQUBsMrlE6ko= + + + Resources/core/icons/earbuds.svg + + hash2 + + HKLGeo0nkV87BfAtVouxaBKxmj1B/4YAxou+M66ZMDk= + + + Resources/core/icons/easel-fill.svg + + hash2 + + I29aKhApYp2wV+bezh1c/gDXSdrysybT4xi8SFBuLlM= + + + Resources/core/icons/easel.svg + + hash2 + + h3N/6nbme6fgBQRxE0UvNJno9jOsWMxisAS6johSZN0= + + + Resources/core/icons/easel2-fill.svg + + hash2 + + xSP4mUowFj2gONP+mLMtbBSSJbVXShkpieALN5vNzSE= + + + Resources/core/icons/easel2.svg + + hash2 + + qaXnyq1yWXWBCx/fpNN1xPysd6YrKDNcW62JrlVZOFM= + + + Resources/core/icons/easel3-fill.svg + + hash2 + + Uh59W9KXlgxUdTRrbHBUo6eQo2oRY5zesJPHAl01+vI= + + + Resources/core/icons/easel3.svg + + hash2 + + kOpFtBrhGKiKeJEsq1pv219W2lCws3ugkBXfRVW5ab0= + + + Resources/core/icons/egg-fill.svg + + hash2 + + /mLDl1dDnN8/nz65DWUTBAA8Zotb4WUA9V8LA+zS7ao= + + + Resources/core/icons/egg-fried.svg + + hash2 + + SVuNAcprVVzYUVggR+nBXvxLuxhaHgJc0Eh7XFHGiQk= + + + Resources/core/icons/egg.svg + + hash2 + + Dvff9ovFnLLR1PWA6pE3szlob8aswk1JfDB6mkWqkSo= + + + Resources/core/icons/eject-fill.svg + + hash2 + + XfZ5SqSElsR/+DoKgLbnVsCpbEbzUzwbicQHA5RzHxI= + + + Resources/core/icons/eject.svg + + hash2 + + CbNKTJF9LoSeG+Zzx1qxbss+RDey/eELZuiaWXPV44s= + + + Resources/core/icons/emoji-angry-fill.svg + + hash2 + + TMfAgGKAf1DAPnhSCf3wCYlAhXMdqvc/Z0N/Fpal5dY= + + + Resources/core/icons/emoji-angry.svg + + hash2 + + knpfpFZAhFwMyWdLTQTZ4x99WSO1pAI30Qh+EHvo/l0= + + + Resources/core/icons/emoji-astonished-fill.svg + + hash2 + + qYhbLD+sRnxG+JosLxOzYaaGiY8F3jA6R7qBlMgVYXk= + + + Resources/core/icons/emoji-astonished.svg + + hash2 + + ZDRrG7a0PcIBSGUDTXT6jnAjxYc2O4QsUsS1Ow4Gxtg= + + + Resources/core/icons/emoji-dizzy-fill.svg + + hash2 + + 3E3DOZNa0Y5KQ5Fecqe7yhbo96yhozIv2CoK8C7VbsU= + + + Resources/core/icons/emoji-dizzy.svg + + hash2 + + cvum8MwDhsSiCJCzcJO+U98gaVr0REoOUM6whQTp6Bg= + + + Resources/core/icons/emoji-expressionless-fill.svg + + hash2 + + po40sct7d1rXLxoLctXVzuLFHAkDE9YxkE6JDByOvio= + + + Resources/core/icons/emoji-expressionless.svg + + hash2 + + peFVqWS41hSjWH/p3b6YFr+Ggc4B3h5VeC1wMvVK5gI= + + + Resources/core/icons/emoji-frown-fill.svg + + hash2 + + j/Cxt2kCShA9skAociwlFOrgi0ZMnME4a77Tk9Ei22A= + + + Resources/core/icons/emoji-frown.svg + + hash2 + + 31jjeQeOP3tWE79QOM1PieXG/Q4kohY4Q/OmaJuGLNA= + + + Resources/core/icons/emoji-grimace-fill.svg + + hash2 + + Ak9DHoW91qHXnoohGCEhWw6LqHuiWSyMD3c+gTWnboo= + + + Resources/core/icons/emoji-grimace.svg + + hash2 + + IjJ5aRX7+3FSGu4f/yQkejTuxxmUiuE/f4k+8f4Il4w= + + + Resources/core/icons/emoji-grin-fill.svg + + hash2 + + V4Jd70kpvGRw7O8XVGpezP2C6BnkeW5+Nd8UUzwFHpE= + + + Resources/core/icons/emoji-grin.svg + + hash2 + + ybaeWJ9uLvYDDG0vRXJ0i5cUQbgoQsjKJ8St5bJ4yLI= + + + Resources/core/icons/emoji-heart-eyes-fill.svg + + hash2 + + Z7GhS1ERwhcqnqHGEZ2BDWqfx/o9tsgjnJ44ZVMoPmc= + + + Resources/core/icons/emoji-heart-eyes.svg + + hash2 + + dGOY3nnpfS7Riyy69yeY+eYfrh/jWlRxnWuGXy9foIk= + + + Resources/core/icons/emoji-kiss-fill.svg + + hash2 + + SRN61ByMUjxQLzlppt/IKHoSnnU92+M/PG9+nNlq1gs= + + + Resources/core/icons/emoji-kiss.svg + + hash2 + + mPCstvnGbLm8M20pxfif0qGQRF5fOST331wEeQi8N5g= + + + Resources/core/icons/emoji-laughing-fill.svg + + hash2 + + iq0DGIDYYhMLPZ78bSfk1637bGMhedc2p15bIBAW6DM= + + + Resources/core/icons/emoji-laughing.svg + + hash2 + + 1zg3oRt4SckY7ZSpJv+yFvQeKzFW3b6xKeMZzYgu7fk= + + + Resources/core/icons/emoji-neutral-fill.svg + + hash2 + + CedD/4REFf9BzQZQrPpW1vDCOeLALYQ3MKjhSYnyLI8= + + + Resources/core/icons/emoji-neutral.svg + + hash2 + + TlZCkG2rxyGgTWAnfsWmVN3iyVdu+gti+PbE8RO8sK8= + + + Resources/core/icons/emoji-smile-fill.svg + + hash2 + + AlNMmaOozrqc8oK61UJMAtuXK4pvzQ1ypCQJm9v7goM= + + + Resources/core/icons/emoji-smile-upside-down-fill.svg + + hash2 + + NTGnKNHRjRCDHDiRW9s4uipYXgWBob8QRAL9We0zVoQ= + + + Resources/core/icons/emoji-smile-upside-down.svg + + hash2 + + BOV4gLCxZvUpt0XhIMrDRbo8SP1wGU1aZsLCPadsxIE= + + + Resources/core/icons/emoji-smile.svg + + hash2 + + Wqgza8fCiyJohcqOHwkdLXv+4Qv2W4ztBgwwmHcYsZw= + + + Resources/core/icons/emoji-sunglasses-fill.svg + + hash2 + + vDWgjZJHqW0b3W93QZpcr3LJAAkJJJbjlOLh0QqB8P0= + + + Resources/core/icons/emoji-sunglasses.svg + + hash2 + + Vii3vzQ11zG9ahDQWEp4spkeMXd1DPAc3GRtROsIM2E= + + + Resources/core/icons/emoji-surprise-fill.svg + + hash2 + + TkYKGicEOd3gHHzzhXYCu8YcrXuQqATVJFKJaV5MeVU= + + + Resources/core/icons/emoji-surprise.svg + + hash2 + + PTlbf6uifkV+O+lzfdCiUXQRCyHxrM4q+1zLx+09y0c= + + + Resources/core/icons/emoji-tear-fill.svg + + hash2 + + fP8quLX/LVAERevOC5PQzpNuRj6VowGV1pW+fIG9kXM= + + + Resources/core/icons/emoji-tear.svg + + hash2 + + 7U9+/i4BldVBn8uA+sl0aJikjca8/awJzHIHYMbMoXc= + + + Resources/core/icons/emoji-wink-fill.svg + + hash2 + + /ghMIRLDyNL6kYbXBn5nlz4AYRosUI9fULgKVogv0e4= + + + Resources/core/icons/emoji-wink.svg + + hash2 + + sLBjjOGjYxLCfJkeuUFIbWVE6LbqPC+of83Iu3GYA4Y= + + + Resources/core/icons/envelope-arrow-down-fill.svg + + hash2 + + +bTPf8cKapb/ulM6FJhjDiPogzP2K+ldvUKHWO+aWaA= + + + Resources/core/icons/envelope-arrow-down.svg + + hash2 + + g2zK+6afdgB+9Xo4a84puTyat6edyKr2+L2CeW8ULu4= + + + Resources/core/icons/envelope-arrow-up-fill.svg + + hash2 + + ozAGVBGdr+QGDPMMtMAgWLxIh3kOAE8lrQYaPz8tSV4= + + + Resources/core/icons/envelope-arrow-up.svg + + hash2 + + sKKH1WENcqx9+A4nCA8dBqoqJCZRBtM0A5GgJbz1F7I= + + + Resources/core/icons/envelope-at-fill.svg + + hash2 + + ZoKZhc9830tdVIiOFirFzgUWFVlFnu7bKfuOGth378s= + + + Resources/core/icons/envelope-at.svg + + hash2 + + 1lngnbfSeyjF0na2KeTRrpaIAinuZpvW9QYIxI1zx1g= + + + Resources/core/icons/envelope-check-fill.svg + + hash2 + + 2pMCpQLfcXBSuLY+cNdWsNIVl/HNwXQBXLsv1I0PT2U= + + + Resources/core/icons/envelope-check.svg + + hash2 + + ZZrO6DFeTPZ5ILlmjEOX3LmFndNonOnIDEjnzzMThvk= + + + Resources/core/icons/envelope-dash-fill.svg + + hash2 + + aX0YpuKs+KqmcLRqY/gXe98GOmR2GRjXuIh1+dU0tKM= + + + Resources/core/icons/envelope-dash.svg + + hash2 + + Risza7JZKG1xM3wu839dKyWrb8KgVVRIXzCe/wrRbH8= + + + Resources/core/icons/envelope-exclamation-fill.svg + + hash2 + + N6byatIGWMpahxW83zJWq7/fPCjghWLEKPlDmkYlIAk= + + + Resources/core/icons/envelope-exclamation.svg + + hash2 + + ct98hBwqLTMZob4CxVl5qDS92ipyo7oTmOzz0Zt2nlY= + + + Resources/core/icons/envelope-fill.svg + + hash2 + + 5O5EhlLZlPfznRIVH2HUy6HUv30Ar3VYSh9MMVcviSg= + + + Resources/core/icons/envelope-heart-fill.svg + + hash2 + + DsY36QiYMqO//KgQTGea0RqebAsKLuYqGv098tP5pkQ= + + + Resources/core/icons/envelope-heart.svg + + hash2 + + KuV4rFnAmUu2TKjKIFNBQabuB/vsGbnuc0Psp2m13ZA= + + + Resources/core/icons/envelope-open-fill.svg + + hash2 + + FFaGczdXkk8B2Tu5n21tVxTt2d2gt0bwNghZnDq8IOo= + + + Resources/core/icons/envelope-open-heart-fill.svg + + hash2 + + 0Ejp5es5qN8B2UI4zF5viDF0oaMY+tzgVXr744v8qz4= + + + Resources/core/icons/envelope-open-heart.svg + + hash2 + + 8roFPEepYqFSmC4AYOcrF0rG8OiU7Kr0NPpGohBU9I0= + + + Resources/core/icons/envelope-open.svg + + hash2 + + nUK8kznRAKjbGhW8CCkkyvA/4YS9sJbGxL/VQqqhXyM= + + + Resources/core/icons/envelope-paper-fill.svg + + hash2 + + KJOtjp1D0XXTHm9H9ldsJeQp4P8cYwBzsk7aRwbCkh8= + + + Resources/core/icons/envelope-paper-heart-fill.svg + + hash2 + + SzZQ76pB+x/2E8ADDPyC+Sak1eQ2e6bOQtY7TX/pA1I= + + + Resources/core/icons/envelope-paper-heart.svg + + hash2 + + aJopLZSaHJOhcOYsZceq2ookzQJMMVofdPxAvZaoCSw= + + + Resources/core/icons/envelope-paper.svg + + hash2 + + gty+RViP18QFdAO8X7PZFTPXO8AXewR8+ZdL0/0JY6c= + + + Resources/core/icons/envelope-plus-fill.svg + + hash2 + + 3Ay5XAPKC5tfTrRQKBLs2daKAx92OrzY5v+nmavcXlg= + + + Resources/core/icons/envelope-plus.svg + + hash2 + + HxuOcCoT4rpgNw07x3ezOpOtPUBT7mqZ3gcA8DpJSAc= + + + Resources/core/icons/envelope-slash-fill.svg + + hash2 + + fRAGLLNde2cDauTcI/GOJmaXZGtn0kGAMbvxHUtgaVs= + + + Resources/core/icons/envelope-slash.svg + + hash2 + + 7d6hLNjQ2rBESlohHL1hm4MR8XDpMQmT9b8+LMiUyEI= + + + Resources/core/icons/envelope-x-fill.svg + + hash2 + + 0l0FIif/exImDklwnLykdoCw2OlO0DSrWVTIu3wUy6Q= + + + Resources/core/icons/envelope-x.svg + + hash2 + + PH+cWSrDEYJGoeq44AL9bVi0vJbWUbWjpSNhIxLQ9eE= + + + Resources/core/icons/envelope.svg + + hash2 + + R/Ye/j4erhWQL5jcVDKMXyEs9s6tGMUOUKxfLtgs5wY= + + + Resources/core/icons/eraser-fill.svg + + hash2 + + 9Ssc4AlCU1VUlK/dkLbavXfQwYHrqJ9qH9exLPUX2qo= + + + Resources/core/icons/eraser.svg + + hash2 + + AGEQN5STqdRiqqtj/Ur7TLd/GLfyL5pB0NslEJd9My8= + + + Resources/core/icons/error.svg + + hash2 + + xYqDUkOX4vH3Vk0LHhceux5QaYPJcSw978OxGdP7yzY= + + + Resources/core/icons/escape.svg + + hash2 + + QnAUm5k9dGTrs7egKTM3ABYflKzxvKvveoPvyIvhPLU= + + + Resources/core/icons/ethernet.svg + + hash2 + + 9fsHShUGZiLFtNqNmgHbBLYBxABqCtFcxwLNiQSjUQ8= + + + Resources/core/icons/ev-front-fill.svg + + hash2 + + NCtpSf7Ft1Trwb++a13PrWzi/816roe1km1zT2YVlpQ= + + + Resources/core/icons/ev-front.svg + + hash2 + + CMxF+iPQO5omgmbTcOZdXKMdoJSmXA0nv7a97NcK9uc= + + + Resources/core/icons/ev-station-fill.svg + + hash2 + + 1FCOPKuv7mBNzs9BauhCBq85JV+oUaSYJRRlPpHBmeo= + + + Resources/core/icons/ev-station.svg + + hash2 + + AdexyfgNatGqmwaD2X+UFSjAg+bEJ4H18EjI127O6qw= + + + Resources/core/icons/exclamation-circle-fill.svg + + hash2 + + D7X6e3ON1qKRu6fabqxuvMErKZboUVdQFMXhTPR7Ma0= + + + Resources/core/icons/exclamation-circle.svg + + hash2 + + ofYmUGSJSRF8ErZsD+LBg/wF7V2j5/Dy2vfvaRF6KVg= + + + Resources/core/icons/exclamation-diamond-fill.svg + + hash2 + + R2ArBFSO1ftnjAHFMSulxRRRrSx5Zy2T7E5MJXzJptU= + + + Resources/core/icons/exclamation-diamond.svg + + hash2 + + DpAmcrcIlZ5KFBN4bMWy9aLgbv0svcKVgpe4VCYU45Q= + + + Resources/core/icons/exclamation-lg.svg + + hash2 + + sdAXkaYl4gRN/wFu688E390ZHV8xeLeX4BHsJ69Io1U= + + + Resources/core/icons/exclamation-octagon-fill.svg + + hash2 + + 3eAApzJ3nrYjjUGCl0lFFsp8u8PVi16bdSlqiMPDlfs= + + + Resources/core/icons/exclamation-octagon.svg + + hash2 + + jFYMLxZ0C8lz9PtLUvCvwu/jiwA2cRKAmDJTHwJB5rU= + + + Resources/core/icons/exclamation-square-fill.svg + + hash2 + + lpAphU4FAkrwP9bjaxGoMcrFTCCv1qYGrdV4Yphqf5U= + + + Resources/core/icons/exclamation-square.svg + + hash2 + + yc4tRp0wsZMF7ST/2t6xdHsIkwjImqCwohbBO7GlXCE= + + + Resources/core/icons/exclamation-triangle-fill.svg + + hash2 + + 5aBTvhlegy+pSta1+gLPGhs+6b+FjhQSCyX6xID+WKk= + + + Resources/core/icons/exclamation-triangle.svg + + hash2 + + w4baJG5Td0kYV7Xw22+k8l+4KLlVzBmUh37jPJhxrgU= + + + Resources/core/icons/exclamation.svg + + hash2 + + /z4ScYvlF1SCkM/wuHCYuNOLemoEiPXbualDk/sScng= + + + Resources/core/icons/exclude.svg + + hash2 + + sGeF9zDquxrnXBuydW5jgVWi/nX8eTZ20W2rQz02ybs= + + + Resources/core/icons/explicit-fill.svg + + hash2 + + 3RWy6Csrdetjo94CA94h889XR4Xldm0oJjaEYqJpyBY= + + + Resources/core/icons/explicit.svg + + hash2 + + KJguhBP5pCgYffm49PLXnOSitesyXV+vuarKGntwHuI= + + + Resources/core/icons/exposure.svg + + hash2 + + vHtldK9EEmgu9ZQRIwI0PU6PEHc84l3ikfsIXtmXoK0= + + + Resources/core/icons/eye-fill.svg + + hash2 + + xJsiiDDo7i1aQraid0lBla8C77tkyCXoTOWn0QLAfWA= + + + Resources/core/icons/eye-slash-fill.svg + + hash2 + + bvh1fZcDvC6zlyBaApQrtgVnxnFH5Kgulyu8YBOGpb8= + + + Resources/core/icons/eye-slash.svg + + hash2 + + NO7ljo7DuDCTHbNzCxXxrow13xr4HTRiLiiCBdNo/Mg= + + + Resources/core/icons/eye.svg + + hash2 + + xYb6iODQBiXIrzq/A9vVTY3Na8zLEB4DRwNHm5wa2qQ= + + + Resources/core/icons/eyedropper.svg + + hash2 + + +D3/MaZBTSVBhrVLYDO56zD20j0KUTXkXRpxQb8aFOw= + + + Resources/core/icons/eyeglasses.svg + + hash2 + + xdPWDfNwLKUYUMA5qxMAjIBRqdq0QeJnJY2hSg8/Hwg= + + + Resources/core/icons/facebook.svg + + hash2 + + NIGhyJLUXxLFnFyKwkdpbUiO0z6g8wJ/jXNsVHvVpFY= + + + Resources/core/icons/fan.svg + + hash2 + + IkfexssVgn4I0dOMhUKqkutdqDQmrqebu30I7WCL59I= + + + Resources/core/icons/fast-forward-btn-fill.svg + + hash2 + + H5yh6DpWGC8/K1sslLji45G/mzHgycx6wm6ms6jxMCk= + + + Resources/core/icons/fast-forward-btn.svg + + hash2 + + hKLSbKMS6LytpZvyfkbgk6TaclY5HdOt5Jrnh5E1Rj0= + + + Resources/core/icons/fast-forward-circle-fill.svg + + hash2 + + V/fV2lFCsK4GkEnPPGCi53t+/AEb7+AG1u+KR0mgWs8= + + + Resources/core/icons/fast-forward-circle.svg + + hash2 + + PDhdOdQJ0+v3hkxSO5lV6O6h8EVIxgqAR8b5/NDkgVQ= + + + Resources/core/icons/fast-forward-fill.svg + + hash2 + + La8zbIx3z5g3vClqRNo/vBNPfOt3kQqASt8t3F9R2Yc= + + + Resources/core/icons/fast-forward.svg + + hash2 + + kr+Tio7GA5LyjUocV/bVEY8bLj1hYFN8Et7OikOfli4= + + + Resources/core/icons/feather.svg + + hash2 + + 7boTxvFySApzFeWEOBL8esq/dfFTV5yjWGoHfr3K1g4= + + + Resources/core/icons/feather2.svg + + hash2 + + 1NEGT5psNU/6foF2hCd298+7U/QARgQxHXhItd8OTCE= + + + Resources/core/icons/file-arrow-down-fill.svg + + hash2 + + 05gXQewYoKfCwX8d8QRKQF/Rc6sO7ixFKf3UozxX9R4= + + + Resources/core/icons/file-arrow-down.svg + + hash2 + + VX+qfY/5/7q8qta4btpIOdurnHQLeG3kRDdIo8kyiR8= + + + Resources/core/icons/file-arrow-up-fill.svg + + hash2 + + iKsgjGfchVWLP6WHV5vuxqXIMMbt80Y4h/+LHF9WKTo= + + + Resources/core/icons/file-arrow-up.svg + + hash2 + + 2zEJQDL8iAzHfzFQA0ckvivjjAnv1ERcr8at9E1z1Ss= + + + Resources/core/icons/file-bar-graph-fill.svg + + hash2 + + IBbYZ3dJk+UPdoYM+lEgt0XJbPcoIr6liT8zShMkzkY= + + + Resources/core/icons/file-bar-graph.svg + + hash2 + + h6UjyFsvs5K63xF0LGRgNjEAjYUR3cfGKaCe2C8mP9s= + + + Resources/core/icons/file-binary-fill.svg + + hash2 + + TB88xHMIoxyqqMuajGit8UAu/CzB5Bv8jAbFJj7s3wU= + + + Resources/core/icons/file-binary.svg + + hash2 + + M+znkeIE0Kb8XRzuanU3ITUhcFhHTXJlykG+IAjI9QE= + + + Resources/core/icons/file-break-fill.svg + + hash2 + + 7WsoUXq9dgiDItiI8rKJtUx9SAe7DEGCTF/O8zSHSU8= + + + Resources/core/icons/file-break.svg + + hash2 + + +Wim0hjdrtqZYUYT2vic5tZv6FQNgquC3d9XYHNBoK8= + + + Resources/core/icons/file-check-fill.svg + + hash2 + + 1VXOgHbU40i5Z70m7PvtJQl/XtKc6uM/sRsbQ9CuoQI= + + + Resources/core/icons/file-check.svg + + hash2 + + j49dZkm58t32Ont/KZ171/94C/gSCOwMi5L5R2QfxbY= + + + Resources/core/icons/file-code-fill.svg + + hash2 + + lbwK+OyU2xaPtPJzv0INVwcHreG72ZNgymwpdwIN0q0= + + + Resources/core/icons/file-code.svg + + hash2 + + qrFmjGpexeCDcQtNYWfzU1L1hxubUVjZrspCJPkyC6I= + + + Resources/core/icons/file-diff-fill.svg + + hash2 + + 3uy0ddzuoc429n0jVRMBQD4WWKzkjfNGmxSuOt92o/0= + + + Resources/core/icons/file-diff.svg + + hash2 + + WpHsNUKNog4G0WfhxrBTz9/x+dtKr6lYwaWSK8ZfTH4= + + + Resources/core/icons/file-earmark-arrow-down-fill.svg + + hash2 + + RM6rNZPLdBpXEUzfD/lh1fnXuNpDgWFVmvCapqfZw8g= + + + Resources/core/icons/file-earmark-arrow-down.svg + + hash2 + + RkO4tm2Jis/MEl7/f9wkHYilUNqcd8BsOEzTqVsdq+4= + + + Resources/core/icons/file-earmark-arrow-up-fill.svg + + hash2 + + MZdfx5m9dve0suDPRfQuyVqxCRzbL8nM8tU0W1GGrJc= + + + Resources/core/icons/file-earmark-arrow-up.svg + + hash2 + + nlHgP0ofwMtDwbiT4N0GyDQc3iXxHEJx2Da0DMwdB04= + + + Resources/core/icons/file-earmark-bar-graph-fill.svg + + hash2 + + y69MBaYeOEwMa1oGtm1Xm2fBI2Vg71cDT5YtePlqY1Y= + + + Resources/core/icons/file-earmark-bar-graph.svg + + hash2 + + c1Ng4zeGNY2aAgMYaRmlGdrO5iSxDIueGR9o9NAtToo= + + + Resources/core/icons/file-earmark-binary-fill.svg + + hash2 + + Ri2/SED30W0yUeTEhKAsa3kfQ7KGJbf+WEvDpDujU6Q= + + + Resources/core/icons/file-earmark-binary.svg + + hash2 + + v1VjsflhceS38QFHzu3Vy4xD+PTbv3L/w1+3yMcxarY= + + + Resources/core/icons/file-earmark-break-fill.svg + + hash2 + + 9FzJbe3pqLdzWDwSMNiPNBUL11oCR5DAfihjhCNWMZo= + + + Resources/core/icons/file-earmark-break.svg + + hash2 + + if1Ci7ST46p2uAHd3xcFaUeGTdyNjma6ZzPT3Ri0SWM= + + + Resources/core/icons/file-earmark-check-fill.svg + + hash2 + + 2pL0BFBRVdFNyFmKGVc4GbWRsaGWiOtted9kYG7QYvU= + + + Resources/core/icons/file-earmark-check.svg + + hash2 + + jeJtnkuzlKZqWS8bqVXeuDyK+lwJeqc9KDaaZOom+p4= + + + Resources/core/icons/file-earmark-code-fill.svg + + hash2 + + ZXp6UuVgvvBq2HUKICiIgnDmmoTYbz1bC78iGlxksIE= + + + Resources/core/icons/file-earmark-code.svg + + hash2 + + HaiCfNSySrcli4jjFWigpITsmN4BoAMimrspeMl0N/g= + + + Resources/core/icons/file-earmark-diff-fill.svg + + hash2 + + 7uAoC38J0jYPhz4Y0YiUVoJ9Y9IoAOB9LPzcdopJP+A= + + + Resources/core/icons/file-earmark-diff.svg + + hash2 + + LIR+464in2yzhK8hH697/wtggO9Wd8eUm3ONVeGgqpQ= + + + Resources/core/icons/file-earmark-easel-fill.svg + + hash2 + + 2sCwnBNxRQD/q+fm7/aVNKUgW/bsIYIeEvLkUYtvMO0= + + + Resources/core/icons/file-earmark-easel.svg + + hash2 + + 1U4qJSY43s1pdFS7l5HqTIto6+ejaz1x8847isdNiWM= + + + Resources/core/icons/file-earmark-excel-fill.svg + + hash2 + + 5o2PqI1llIVWUIVex9583AQJVgdb0Aa+fagteh5q7PE= + + + Resources/core/icons/file-earmark-excel.svg + + hash2 + + i9I7oe2t2yXUFM1PQI4srNirCTGidkC5WLpspq2zHk0= + + + Resources/core/icons/file-earmark-fill.svg + + hash2 + + jLI/bm/8/fb+JBwxpMcU4Znpk4qlLX8uHrm2ZdC+zqw= + + + Resources/core/icons/file-earmark-font-fill.svg + + hash2 + + RyT9Qai4m13x3F7aS1r9t3lHtCByQGw9SMdFwZz38Iw= + + + Resources/core/icons/file-earmark-font.svg + + hash2 + + awV/blYGJYFiraF61edAwR50LUfvbFRxpyDsSCJ1m8c= + + + Resources/core/icons/file-earmark-image-fill.svg + + hash2 + + EBm2ycAr8C5Chbszc4xQqd1CZ1ftbL9B9iD3i2zMvcU= + + + Resources/core/icons/file-earmark-image.svg + + hash2 + + xvkTI+AL6RcRCuwA/YKY4E1q3pxfeTgWI0VAW4L96Ho= + + + Resources/core/icons/file-earmark-lock-fill.svg + + hash2 + + FiE914yT3ogdCY3rVlw/rrtUxwKEXGbq19CDpAhffuM= + + + Resources/core/icons/file-earmark-lock.svg + + hash2 + + j2islIPHYRvmZCExsmtUhFek5ei18Imc+gqZLujkDaQ= + + + Resources/core/icons/file-earmark-lock2-fill.svg + + hash2 + + I7AINXgXxBP6tmyQuLZYSPkFVSjBiw1xM8jtl5RCic8= + + + Resources/core/icons/file-earmark-lock2.svg + + hash2 + + bzkQqdY5OUFf7InSy998TpQHjnPDRqq7KDLi7Ip818g= + + + Resources/core/icons/file-earmark-medical-fill.svg + + hash2 + + glMVuB0AHt3d4SDDU7VXZ8TzMCSkUktRqurc61XEPCQ= + + + Resources/core/icons/file-earmark-medical.svg + + hash2 + + RDBSjrLqdQE25Qor4fYmp6yngtivChebPB39M9qLNXA= + + + Resources/core/icons/file-earmark-minus-fill.svg + + hash2 + + tVsqvXVEokSHKW7GacwsNkNu3/oJg2oAt3JXytwPdo0= + + + Resources/core/icons/file-earmark-minus.svg + + hash2 + + KejDhFr0rL2qWMZpWqPc/ns0A90UitUyv9kpvUEqeBw= + + + Resources/core/icons/file-earmark-music-fill.svg + + hash2 + + xC8jOH6+eIKn3r7ZcE4GmrE3NwSfLoG6zkqdIODgWtE= + + + Resources/core/icons/file-earmark-music.svg + + hash2 + + LkmNApQanp88vsvxnSlYDz6o9D5vuCbUrZDuc1+7lHo= + + + Resources/core/icons/file-earmark-pdf-fill.svg + + hash2 + + Qm2OAjDyiMCHBsmEhxbWfHtnL0FTEHdWuXsjcbFze64= + + + Resources/core/icons/file-earmark-pdf.svg + + hash2 + + ldDxvvSyMjI3Pi4Eo67fKjX3oAVBXOp6TC8mE8if4gE= + + + Resources/core/icons/file-earmark-person-fill.svg + + hash2 + + 0MSwQBforNwhm6tiHHbJbjiIEnQ1bxnXkbRzJjSDlws= + + + Resources/core/icons/file-earmark-person.svg + + hash2 + + z2xp6vE3kXjF7gr0mq7XKtye0Qddb+WDSeBSOYEiB8Q= + + + Resources/core/icons/file-earmark-play-fill.svg + + hash2 + + bha6b/wGc+gKZDT1G2LLwGgrHPqYCNBN9WxzMzUOSMU= + + + Resources/core/icons/file-earmark-play.svg + + hash2 + + p2y/u3PhuYwJ7tV2PmhA7HebFGNZqbuDWgM7XmxKSPo= + + + Resources/core/icons/file-earmark-plus-fill.svg + + hash2 + + tBuWOaU4+ahl8JVCD+h3+e/JJbzd09Pmki1lq9fqDW0= + + + Resources/core/icons/file-earmark-plus.svg + + hash2 + + TE3Z+I/X4j9+pcHiElrwAztuI398OZH8jLbPPc5V4uw= + + + Resources/core/icons/file-earmark-post-fill.svg + + hash2 + + hQCT768Wuf7sVgVbd9+mpCfS28wR7s2vZlnq5rmbKcQ= + + + Resources/core/icons/file-earmark-post.svg + + hash2 + + 6qAn0ZBaw0hD4TKntf0IgWOmko31iv2huRHep1qxt88= + + + Resources/core/icons/file-earmark-ppt-fill.svg + + hash2 + + J4MsZkRTBC6Tsv/OotbsnI2ghcDzjtj59NQ2DlEw9a0= + + + Resources/core/icons/file-earmark-ppt.svg + + hash2 + + 0b3vxuf769p2DyIrq2NATQWtR7i7lGLVxS6Hp3vgtaE= + + + Resources/core/icons/file-earmark-richtext-fill.svg + + hash2 + + xcesvXlt2zYHa87+B0UOSkgee5HvGT9REFyVgTmzJ04= + + + Resources/core/icons/file-earmark-richtext.svg + + hash2 + + jANFSoXZH7bZHWk8DT47OCOKjHIoLjkNJlcaO03iViQ= + + + Resources/core/icons/file-earmark-ruled-fill.svg + + hash2 + + knZ7rrp1PV0b8s1ZYII61EJsJE313Mp5lGsZ+uGT3IU= + + + Resources/core/icons/file-earmark-ruled.svg + + hash2 + + 7a9iuPtDcLenH83/rz+InhccWIToyvwbumwJKrRgGQA= + + + Resources/core/icons/file-earmark-slides-fill.svg + + hash2 + + LGwvK6gFLm+KdxqIEsGNdPUED3hHrnkWd5GAkHuQbK0= + + + Resources/core/icons/file-earmark-slides.svg + + hash2 + + iRk6j33WciRHx0F9nYA+ZLS2KeOAfdy2zcPfDEF5kgc= + + + Resources/core/icons/file-earmark-spreadsheet-fill.svg + + hash2 + + epShc0/zAy21x0aQ8Inmy7BrvzlfTKctYVrD47MrrgY= + + + Resources/core/icons/file-earmark-spreadsheet.svg + + hash2 + + +HmDn3nje+NqYPKiAH23gq/PajcHdmoFVy3dflsD3RI= + + + Resources/core/icons/file-earmark-text-fill.svg + + hash2 + + PJ9lZ0FiXMUh0POY0DwSCuv2A8Zhibxk5r4YpXcMmE8= + + + Resources/core/icons/file-earmark-text.svg + + hash2 + + CTuBzLZfXJWBz9wrh1ptUyZNtEkI9jI09Ecq+MmpDTk= + + + Resources/core/icons/file-earmark-word-fill.svg + + hash2 + + 7weQI/aFk2//xSQ9wy/W/pcMbce1MOtkFKvgCRjGCiM= + + + Resources/core/icons/file-earmark-word.svg + + hash2 + + EyyUaET3+/WrK9FNfU7JyHjVyyPuRwh/yPNF2qhkqjo= + + + Resources/core/icons/file-earmark-x-fill.svg + + hash2 + + 8Qi6HxcibLd1Ek7WfiZihZiJJn+G0qc8sxgt3+H6GBs= + + + Resources/core/icons/file-earmark-x.svg + + hash2 + + f6w3nNP5/ogqkvGqA/iT53V/vtdn8/DMJU+tqhhN0Sw= + + + Resources/core/icons/file-earmark-zip-fill.svg + + hash2 + + vBD5SxCBUy7Myy4i5lHWO0zJHPKY0QpXJSda1bqu7Ys= + + + Resources/core/icons/file-earmark-zip.svg + + hash2 + + MEARtGmLopTjdkYBmMwt3SiM0KUHeo59uLlnjsxFrmg= + + + Resources/core/icons/file-earmark.svg + + hash2 + + wOsZTmXsgaXo3EUoT2onyK81QiQo1dNlluwX+xHVs+M= + + + Resources/core/icons/file-easel-fill.svg + + hash2 + + kggOE7GO/CkLsArRYmDM+EYEPKfTtVzUbRqqBkbmetE= + + + Resources/core/icons/file-easel.svg + + hash2 + + qQTwYo0fHGRIcu4fryWxIugOiDIw5MC2C72e6qITo3w= + + + Resources/core/icons/file-excel-fill.svg + + hash2 + + OfaoVI9Dz5648xsUx//gU2mbxLQE0R5lmjfgE6JKUu4= + + + Resources/core/icons/file-excel.svg + + hash2 + + 3IgiCpdCkeemwM1avbzEZo2uN3IxrnPkSKESGX/DeJY= + + + Resources/core/icons/file-fill.svg + + hash2 + + p/HDTfEEjDTkY4XU2spDKLevDMHm9cHo4yqPjjXfwWo= + + + Resources/core/icons/file-font-fill.svg + + hash2 + + /3czDO140vJlYudt4FDRlO4LsZUAR12GVyQZSxb5q1A= + + + Resources/core/icons/file-font.svg + + hash2 + + ophA/bZpTn0AmZr6nAMYKi09SpJsHW+xQfHmwIwNFWc= + + + Resources/core/icons/file-image-fill.svg + + hash2 + + FgyPVQWpxHz/MRaWsIgJAS8WdT3hecx0mu/wq7d8ntk= + + + Resources/core/icons/file-image.svg + + hash2 + + yoEQR+k5E5DTqzYcvpjgn6+b8buuscHf9V7KUOx5NBk= + + + Resources/core/icons/file-lock-fill.svg + + hash2 + + 8+oYYgCuX2bXrFWmD26hlKr1psu27EX5mMgAD8YAv7U= + + + Resources/core/icons/file-lock.svg + + hash2 + + BnCq00Rh7l8gXuvctwYdUKA7T6lYYylijUYTC+vICho= + + + Resources/core/icons/file-lock2-fill.svg + + hash2 + + Tln/QnF8YeRigK3K+0k2xE2qH86HLtQusi/BCIYFiv4= + + + Resources/core/icons/file-lock2.svg + + hash2 + + efwm+B0ke0JXMUkuFHSHHGPvuTVE893q/9sqFxpRsco= + + + Resources/core/icons/file-medical-fill.svg + + hash2 + + dGKMzOILs6WmqCfFJ4XsH1Y6l+vZFeJgiFrV80rT41k= + + + Resources/core/icons/file-medical.svg + + hash2 + + XYRyjYUgLGc0FkLDzbWBF84lskgyK7HS+2p3lVSFb04= + + + Resources/core/icons/file-minus-fill.svg + + hash2 + + nbbDuYi7zb73cE5x12GL7fAdt3t16hfFK9XnhfdYWz4= + + + Resources/core/icons/file-minus.svg + + hash2 + + usR8opOHcFNInVGvbh5E+doNOv395bRDN6KhFbKqM/g= + + + Resources/core/icons/file-music-fill.svg + + hash2 + + Gqr8soFRyAJazC7uCJgYh0GgDi8K7J1U+34sgGLK6jY= + + + Resources/core/icons/file-music.svg + + hash2 + + FXc1R/+FW8qUaWrDP96UbU5AnEQ/vBukIubtmLJBaRU= + + + Resources/core/icons/file-pdf-fill.svg + + hash2 + + kjnAJbLVyKpQzt7APDWW1c96e3tYBqKeHs93JXxdjfc= + + + Resources/core/icons/file-pdf.svg + + hash2 + + IVPn2NxFR7dr/KyxXPghK8PZUDnUxtk02CK3AfscEEU= + + + Resources/core/icons/file-person-fill.svg + + hash2 + + /4FLrQzX6mVAAehIlEdhYxXEw8UKRY3oVdDRHzwCmmw= + + + Resources/core/icons/file-person.svg + + hash2 + + pN/3nl9tkNzRT/MfOQizolYGhnJhV8zP74whD22wKMI= + + + Resources/core/icons/file-play-fill.svg + + hash2 + + cKPv8G/SSGU+HDfYxFQpg67Fltkwz7nZ7Lxdav11JyA= + + + Resources/core/icons/file-play.svg + + hash2 + + 79qIm1g0MF/i+p9cIEt6Wq5+AXOlFE/tDuaCGddJyeU= + + + Resources/core/icons/file-plus-fill.svg + + hash2 + + 4vOE4YNulBg3EKvr3uZALSklwehuZ9mj10pTbj9Vkz8= + + + Resources/core/icons/file-plus.svg + + hash2 + + clgpNuRyK1RV3pV+HwsIxy8XlHmrmIJ1OxRsrCga6FA= + + + Resources/core/icons/file-post-fill.svg + + hash2 + + h5jG7jLZE61iYf8VztZtA5r9X/TRMCTdIDSUquBRwFg= + + + Resources/core/icons/file-post.svg + + hash2 + + KwQ0uDS7F8sS2mN7aUD7lp5QJypKZXOPzRjfSRp//HQ= + + + Resources/core/icons/file-ppt-fill.svg + + hash2 + + tf0wJozCvXAw8zS7pupjonBUh6qNVJzYTSu7kA1aGE8= + + + Resources/core/icons/file-ppt.svg + + hash2 + + ID+33REbM8Oik3auTfQLOFjWnXoqdsiJ3HOtVNjvomY= + + + Resources/core/icons/file-richtext-fill.svg + + hash2 + + 6ZSkOXtxDCihNOcCJiELx3wwAOZMEHGqBzxQ3HJsM2E= + + + Resources/core/icons/file-richtext.svg + + hash2 + + brJ84ICXVpKbhoU4w2Uc4K4JN4PN79DRoPuCEQVW2pM= + + + Resources/core/icons/file-ruled-fill.svg + + hash2 + + XbHJWm/G3Zgxpvdk+OFBM8VBK57+cBZuHo27thNCsOQ= + + + Resources/core/icons/file-ruled.svg + + hash2 + + fj8FmkRuBDDGfST9rez12ybP6v3XwvNU7nSagyaVAJw= + + + Resources/core/icons/file-slides-fill.svg + + hash2 + + Mxju6z8pUiF1lj+GgMbxaI2t8DiSjxlTqTjbo8HAtlE= + + + Resources/core/icons/file-slides.svg + + hash2 + + aZ0aH+ypAqZ25xl8Em1LKJgY3qPPyS7pZz035ej2xXI= + + + Resources/core/icons/file-spreadsheet-fill.svg + + hash2 + + eboeFUOLAvEnj5ggSX5s4lH2Rh2tVP3xuO0X5YpK0bI= + + + Resources/core/icons/file-spreadsheet.svg + + hash2 + + Mlg6k7zLZX2EU/DKJFiOCICpiBw9DJ8t7KaZiz3Vsc4= + + + Resources/core/icons/file-text-fill.svg + + hash2 + + QUrWIO7ia9PBl24/3MFeHL1odhT+uY0ke2hUE2cB6ZM= + + + Resources/core/icons/file-text.svg + + hash2 + + 7AqEeCPoymZkk+HWN7WTYTy9Ye5ZdjHolBQtX95GHF8= + + + Resources/core/icons/file-word-fill.svg + + hash2 + + aA3g6KCTTrpOWoWJxlSgy+5fhQouQ9YH/SXoPCKdgOM= + + + Resources/core/icons/file-word.svg + + hash2 + + SMC4/P1ZAXk5vgzd5Vq3JhI0cKQc8s5ei/465oPP3u8= + + + Resources/core/icons/file-x-fill.svg + + hash2 + + mb5lSHGtVmR5qzHL9FPzPsU7eBqNMCu1ZxhTp9hPs+U= + + + Resources/core/icons/file-x.svg + + hash2 + + u2NQzneJU75sKJXBRD5bRaiT3opPG8pSHTScppZrBE8= + + + Resources/core/icons/file-zip-fill.svg + + hash2 + + NUoXc3e9Pwg+jx3oY+5jHeW/xcG8EjgbQNYexn35mks= + + + Resources/core/icons/file-zip.svg + + hash2 + + y+S54H8gKHA4Ve50I2m14FoVH421U6dsH0i6F2Vi22Q= + + + Resources/core/icons/file.svg + + hash2 + + fC8Oyud81Tul96s/g53VsX0I/wJ6Y6gpG2FjbBnvnWo= + + + Resources/core/icons/files-alt.svg + + hash2 + + qOtlx/XsNPhr6yorvYWq1L5Rw62kuuy58WVnd7N3Kgs= + + + Resources/core/icons/files.svg + + hash2 + + 6qlFgaGfIZ2kOXAe5fvTEGYGKVnsocTYImAxWWBmP5c= + + + Resources/core/icons/filetype-aac.svg + + hash2 + + 9hE4qKq7N/j09FJMxvExVNi5evGxRcr5DJVa7Wq5TPk= + + + Resources/core/icons/filetype-ai.svg + + hash2 + + 1eRkud9GjS1ajeVXvHJJi7iY2pizaEQCQg7CyDTIDJE= + + + Resources/core/icons/filetype-bmp.svg + + hash2 + + 3UChRpElUyLZUxXf8wrIL0iMVZ6InJyF0SUfHBe4FB8= + + + Resources/core/icons/filetype-cs.svg + + hash2 + + naOxZSgP7Bc6cKajHBuN02ycRxdrfYikKj/ccsZSLKk= + + + Resources/core/icons/filetype-css.svg + + hash2 + + UlpFjkfKQsCy+eTuN2VPyLplNX28ynEQsui0VZvtqRM= + + + Resources/core/icons/filetype-csv.svg + + hash2 + + l01DxPDiEOPdTwOcdHFv1EIYy+a6N3w4RuSdgxoDnr0= + + + Resources/core/icons/filetype-doc.svg + + hash2 + + bo03S5JZDCCQEZziqr17S7NQc6BzSBrws/qqN0uNL2I= + + + Resources/core/icons/filetype-docx.svg + + hash2 + + iwACzJF3Ati4Lx1QIfNXbxkRMcMgA2jGjRaiSjyqSgw= + + + Resources/core/icons/filetype-exe.svg + + hash2 + + uMl/65shfsFCRvqEdCXgzVr0Lg6KR9423QFv3M8GTNQ= + + + Resources/core/icons/filetype-gif.svg + + hash2 + + n36vEASCabGawux6Il6fJx8BuImZ0ApR5i7AQKPbblY= + + + Resources/core/icons/filetype-heic.svg + + hash2 + + vLLiZtHo9GVdVko/liGdap1gE3SqIUwOoP1s+w4yD8g= + + + Resources/core/icons/filetype-html.svg + + hash2 + + uFOK4q9sU8L0byM2hdBuplz4TvhvoxsDSZGBNfF4Grg= + + + Resources/core/icons/filetype-java.svg + + hash2 + + 142uiMkoGBm3mLkAM+EjoTmsXwGO3GGcwovwT6YxOr8= + + + Resources/core/icons/filetype-jpg.svg + + hash2 + + ysCjyONUbT1LWozkvMoFmxs6sG4BkT0A7J8ZMHsHDyc= + + + Resources/core/icons/filetype-js.svg + + hash2 + + QeGeaIdKBxNUPtJF3rern9z3F7JTqUwTXqiqtHdKEoo= + + + Resources/core/icons/filetype-json.svg + + hash2 + + hYXSafhWDlAi7x84Mgq88/WnSLt+bHVm3OqFaw1R1Vo= + + + Resources/core/icons/filetype-jsx.svg + + hash2 + + KVVxTKGJmXfGXMp/ZFcuYjF/FPnXQPLqiBWF+3tlM5M= + + + Resources/core/icons/filetype-key.svg + + hash2 + + AOg/VkaO3HtQ9SEP9B3sCyWUQTBiR50Q99ZcvC0Erps= + + + Resources/core/icons/filetype-m4p.svg + + hash2 + + fMFM5y+HVsDUXNzFWFOG6OCrsQ1wh5NJjl6Z3chU5fE= + + + Resources/core/icons/filetype-md.svg + + hash2 + + No9o3/yoiH2LweFFyznu7WtCYNdfzpaT4+x6Iy4l2mY= + + + Resources/core/icons/filetype-mdx.svg + + hash2 + + hMuULM1oFS6HxK20DKcK/rNNA58/szJf5gcXjfPZlsg= + + + Resources/core/icons/filetype-mov.svg + + hash2 + + pN4wTAiVW688IbGZaIe7mMGYMjIMuCXRPGw13oy9Qg0= + + + Resources/core/icons/filetype-mp3.svg + + hash2 + + pZ9OmRh6ERUvdocKyhHzkrkD8vJrBKjJBUnALgxfKJ8= + + + Resources/core/icons/filetype-mp4.svg + + hash2 + + 9vxglaVEF+m7EhxX1JMlzYr62W6sKvbDh6O74kc3xZc= + + + Resources/core/icons/filetype-otf.svg + + hash2 + + /ITc7PHSRuaHtxyTkWNNdOPxspeyW6xeJ98XrJWXxOg= + + + Resources/core/icons/filetype-pdf.svg + + hash2 + + xxv4M9046iOIk6m8nWG6obBGIiHZRThS/XC/zuzhRlA= + + + Resources/core/icons/filetype-php.svg + + hash2 + + ccV/ewXUbO+aUt4KGL0ZDSQiGt5V5TV4HPXwKb7AqpU= + + + Resources/core/icons/filetype-png.svg + + hash2 + + BCd1obG6HlBZnZO2NH2RJBDbVjpnsrh8s+Yf71kHTKE= + + + Resources/core/icons/filetype-ppt.svg + + hash2 + + iVb77FqHy17QlxLSMISPX/tVXwwSkZrIdf4fF+0PT+8= + + + Resources/core/icons/filetype-pptx.svg + + hash2 + + C764vK/HANUgSRuSFmEFdPiqE74CfmxnqkSkt3s8O7I= + + + Resources/core/icons/filetype-psd.svg + + hash2 + + PDK6YxNVfNKXczuMgV6amUJnrVxRHQW9+TZj4l0E240= + + + Resources/core/icons/filetype-py.svg + + hash2 + + 2z+uE3+A+WtYHuAFotCCcKOD+/bW0XpcSxpiGogOOug= + + + Resources/core/icons/filetype-raw.svg + + hash2 + + tPaXkh24GE3DzlkvlnovDjBGL0tqibx1FIWtKsS1jGw= + + + Resources/core/icons/filetype-rb.svg + + hash2 + + US3H1Ng4dvididSJ1JpT1cLCJs0/Ys7UD4uSEoDJ7ZY= + + + Resources/core/icons/filetype-sass.svg + + hash2 + + RqDrdYPNu2OPbrLSkEHbtwHa12tCVTwH501rs5WosCQ= + + + Resources/core/icons/filetype-scss.svg + + hash2 + + 4U3Ncg9xwLBrfSCXQipAPDMblxmE09830xg3l6b5P40= + + + Resources/core/icons/filetype-sh.svg + + hash2 + + 9jvZYYwd+2FsWzfrjB3beOwNsTfKyth1R+IeRjVcsuI= + + + Resources/core/icons/filetype-sql.svg + + hash2 + + HpEDeLKWV9IW1MSxpyZeZdnX4c9LG9AF7/kBvHOUJNQ= + + + Resources/core/icons/filetype-svg.svg + + hash2 + + 9i4SvtV4CfvT3gLPZuCfP6I6KQpDmUB76LKztW/BKtw= + + + Resources/core/icons/filetype-tiff.svg + + hash2 + + guQ+MLiJEwwZ/zjTkbHDQiYxcyGpymJKlPp46mLEegk= + + + Resources/core/icons/filetype-tsx.svg + + hash2 + + krgSZr8OJRx9e0iNS/InxzZ7N82JugCFWC0yY3n3r4A= + + + Resources/core/icons/filetype-ttf.svg + + hash2 + + Vcu3obCGcf1bbaCd4UoUDIIJH0844lbzWK+AeacLikE= + + + Resources/core/icons/filetype-txt.svg + + hash2 + + TcQlWJPzwrgLURcfinmZdgUqfZoPs8yi56W+0LUH25w= + + + Resources/core/icons/filetype-wav.svg + + hash2 + + R6Be4mK43qKhkL/8zNKx659jeBYqC1G20t+78xI+uNs= + + + Resources/core/icons/filetype-woff.svg + + hash2 + + H5C4Zd3+kXwnLzWjwI8hF83NxEuJGxXbwtEY22pDYaE= + + + Resources/core/icons/filetype-xls.svg + + hash2 + + PNJD641UeSR4JAVBjZIEM9d6CgWaUJStDmdrVHUVs3s= + + + Resources/core/icons/filetype-xlsx.svg + + hash2 + + AUjlIxX0WmE/GHQygy1KT4iEFEg+26h3T93t2Enbg9k= + + + Resources/core/icons/filetype-xml.svg + + hash2 + + TuEa87i6yo7E+g/l20ncw9Y1UidbpDEKy6vISeHor14= + + + Resources/core/icons/filetype-yml.svg + + hash2 + + cCeKSBbi7i9Cz4OsbhEA6Apq+SvrX+hzMfHgRYr6m5g= + + + Resources/core/icons/film.svg + + hash2 + + qh04XMqn1q3wBS/y8SCko1zM2S93pTNPbxMpc+BAgbY= + + + Resources/core/icons/filter-circle-fill.svg + + hash2 + + NPgGSBuAILg/J62rxhNWfmcufmsOnsMSN+Al/r8M+Vs= + + + Resources/core/icons/filter-circle.svg + + hash2 + + zbDBRKCMLUBbM4WYmoYp8Q5NL9oNLonbaIsDpSvlxzM= + + + Resources/core/icons/filter-left.svg + + hash2 + + Q0xP0WXtgx6TaGsKcR2ghNEK7ZK9xjqJ4mGQ4W/oNcs= + + + Resources/core/icons/filter-right.svg + + hash2 + + gbQIEoX0jFbIgI3gf5bJGeZIMbLF8D9xr5mZQ2136Rg= + + + Resources/core/icons/filter-square-fill.svg + + hash2 + + fi3TpGoSLm2EzkhJd1bEhBv2vNUHc5aO7fsEuWmdAGo= + + + Resources/core/icons/filter-square.svg + + hash2 + + AZwUAZ/8FRAFGZXI3GIAiNwu/tIcbBBbUis4aS0GV3s= + + + Resources/core/icons/filter.svg + + hash2 + + 6o4BibjA2AgxcrB/DgvGi4r0fzmvO+jdjPqEfTT2V3E= + + + Resources/core/icons/fingerprint.svg + + hash2 + + v6qr3xjU6uImGBjWBhTtVwWMw/uHeH6raYTsjxPlv/o= + + + Resources/core/icons/fire.svg + + hash2 + + XJuKN2Ws7bjefBmj0wYDMa/hGJOmgQillBm0nqKOh3I= + + + Resources/core/icons/flag-fill.svg + + hash2 + + 4CSwAh4CKZ3rRSFUn08EVoy8Z+zLMsWnVsXFMuh77K8= + + + Resources/core/icons/flag.svg + + hash2 + + gAWPq2YOmFX2N2x3st0f00PBQ5h49N8bt8Xaj6jEBRM= + + + Resources/core/icons/flask-fill.svg + + hash2 + + 9rAe5ZFWPNH5D3yBEIVRTeGQOUGSeAyNmJR79pArMGU= + + + Resources/core/icons/flask-florence-fill.svg + + hash2 + + ldCxOInT7KWKWR2H37ac4yYhNqEeKBGmxXTM2z3x3R4= + + + Resources/core/icons/flask-florence.svg + + hash2 + + 5f7A+46i1GI02/bIX1RyolH+gyFrNobJLMpMi2MAd1w= + + + Resources/core/icons/flask.svg + + hash2 + + ercH0VkNqjfOyEYUZV0QJ+YQMDHgFMHApXtY9dtZfIw= + + + Resources/core/icons/floppy-fill.svg + + hash2 + + f8LTuRfqdgO1TQVjMcZr2GR79wVySNHQQw3SbmSeFXs= + + + Resources/core/icons/floppy.svg + + hash2 + + ImTaMu8sW6s93YgjS32oKiejg/GPHLp643T2u8z+PRg= + + + Resources/core/icons/floppy2-fill.svg + + hash2 + + pOu+TLtOWpylN9gxG9GoePO6wxJfclcEVD+2Ys9LscQ= + + + Resources/core/icons/floppy2.svg + + hash2 + + Zcn82QBWwzGyjyFtnDCbK6kTGEtYYKKu0QpIigrAXD4= + + + Resources/core/icons/flower1.svg + + hash2 + + Qnu4OowEfm9xnouZxtNjg99UO7zUS5m2GtbJRBlcW7w= + + + Resources/core/icons/flower2.svg + + hash2 + + LVLtJJF0cAzf64SXzwyr8NNp+iGwUvrteejsdVrcprE= + + + Resources/core/icons/flower3.svg + + hash2 + + DCmbHLnZePBMPV8K2F1fAkWlS56v92lUfv/dYOjY1jc= + + + Resources/core/icons/folder-check.svg + + hash2 + + c+/HDKCY+iHuqgkfSattKgb4d1l36LwPO6d/gtyqOwU= + + + Resources/core/icons/folder-fill.svg + + hash2 + + irz59uU3GpiVTj3IVbYYLWbBNHiOxCx+B3VdG+bP50c= + + + Resources/core/icons/folder-minus.svg + + hash2 + + vg82TN2gRiKUdqOhc1th6ssrabt4nGIWUsfOlbTBStI= + + + Resources/core/icons/folder-plus.svg + + hash2 + + TR/C3qFvOgEWL6GGd1HEmJU99gk8vJ54NgYne6J3beM= + + + Resources/core/icons/folder-symlink-fill.svg + + hash2 + + jNV6vLEPItLsCwSYuiC9E2foTcvm9Q0QVcf1oUC1ZdU= + + + Resources/core/icons/folder-symlink.svg + + hash2 + + F/qOB35BXt87iPx+wXj++fdsU6utF0iF66x8WIWN0KQ= + + + Resources/core/icons/folder-x.svg + + hash2 + + kDbF80R6ZU6zIZSeWlcoHAhXUuA+zTUCCtvNEzYs5KI= + + + Resources/core/icons/folder.svg + + hash2 + + 3jJd1wsBDaimnTZ1yIdHVDRUK9iHmVxZUpQ2KDg7b70= + + + Resources/core/icons/folder2-open.svg + + hash2 + + a39CO6UFoDSR5sahUZ2gF2zb6KiZ9UPenNQOjDibbjs= + + + Resources/core/icons/folder2.svg + + hash2 + + s5hk18oTeFH7Ymnk7BMj5uQYN0XJ6W0iMNAYwxX1R4g= + + + Resources/core/icons/fonts.svg + + hash2 + + vzzqjbbzslcwZ8Vrov/ljVXl1L741JMHRBC/F1VsEuI= + + + Resources/core/icons/fonts/bootstrap-icons.woff + + hash2 + + 9VUTt7WRy4SjuH/w406iTUgx1v7cIuVLkRymS1tUShU= + + + Resources/core/icons/fonts/bootstrap-icons.woff2 + + hash2 + + bHVxA2ShylYEJncW9tKJl7JjGf2weM8R4LQqtm/y6mE= + + + Resources/core/icons/fork-knife.svg + + hash2 + + p5UzTkZzIGZ0DXCuadeXUEvO8TZBsoK6KtYPYj3C/KQ= + + + Resources/core/icons/forward-fill.svg + + hash2 + + MXo1+LYubSwK2RUYUPyFge58ai/YdziYl1ZUZj3mN6w= + + + Resources/core/icons/forward.svg + + hash2 + + fYqrvyOaX87OOglicsQVLXGZcg7AzpPf/HGcEjQiYmE= + + + Resources/core/icons/front.svg + + hash2 + + 2hOF/22lkuvrv2kD53anGJo+dmonk0jMlXrnT5lsKI4= + + + Resources/core/icons/fuel-pump-diesel-fill.svg + + hash2 + + KfwVguFx8ewZ1gmI1jBsQtXA2Qtye2ypQ5YBgdI1+Eg= + + + Resources/core/icons/fuel-pump-diesel.svg + + hash2 + + i2Vq4X1x5/zb9WXb9giOHVVfFPx9DcM+2Ev0lwlN/xs= + + + Resources/core/icons/fuel-pump-fill.svg + + hash2 + + wUyFPOtoXiRqCW4v63igQSJ1wtez6R+5p0FnRdR1aXg= + + + Resources/core/icons/fuel-pump.svg + + hash2 + + CfVe0RB/eEpDgvxuf0EaiHC5rslmKSWgdMQttLdFvdA= + + + Resources/core/icons/fullscreen-exit.svg + + hash2 + + IDLuBASwTBnVMy8dqQrTxzqNy7omPlRtDX292Fw8K7A= + + + Resources/core/icons/fullscreen.svg + + hash2 + + Ei8hV0hUZVwH1hlk5zRJ/TdbfHAlIaxVjHd7LLnSdBs= + + + Resources/core/icons/funnel-fill.svg + + hash2 + + IWJOQBj1UiGbrfJjG9POSYO/8puWsov0XlfMTnFTimk= + + + Resources/core/icons/funnel.svg + + hash2 + + HH2Xxtj+vW+gKpRdY6Y+2frV/xFl+mKAIZj28f0xOTU= + + + Resources/core/icons/gear-fill.svg + + hash2 + + BMktqBs/bjxtN07+JJo+IDmx8GLGVzJj/hRaQDYTPXI= + + + Resources/core/icons/gear-wide-connected.svg + + hash2 + + KvpY3ZhyHZcviQ+WJl43BLFX2E0lwhVreH/O08EaSrA= + + + Resources/core/icons/gear-wide.svg + + hash2 + + 3xS0KLA33fvGnsyrJqM+VJqe6SIjzWgmrlsj+Kwc4y0= + + + Resources/core/icons/gear.svg + + hash2 + + wQs7ADd1lzwZlm8OdKpW2OYEist80woloWurIkocJ3U= + + + Resources/core/icons/gem.svg + + hash2 + + zRlTdO7KlXRTI8Q0AHTrsrLFHiUG66cjhTXM2wVz2HM= + + + Resources/core/icons/gender-ambiguous.svg + + hash2 + + SDCH0KyVura1c8eC8k0vR2eKn1N/tCzHdaiRHStuiMg= + + + Resources/core/icons/gender-female.svg + + hash2 + + F5gxRSTidofKAqgzfF+HNig2KmW0u2pDR7qckK1y3vE= + + + Resources/core/icons/gender-male.svg + + hash2 + + lNgmUyqGwL3SJOoXEyvQLk++9HSWTQVYJcL8ZmI65Y0= + + + Resources/core/icons/gender-neuter.svg + + hash2 + + mresbCvm7a9LSgz9VgZZ2qg6Rdu72kRMSjP6hOoaheA= + + + Resources/core/icons/gender-trans.svg + + hash2 + + 2vRiNkJtxM8fTBRWzhn3TEyI3GMLjXzq2pGCR6KUGTQ= + + + Resources/core/icons/geo-alt-fill.svg + + hash2 + + 7ZTwX8gVYVr2Wyv5zkQkgsODCj4AhYxUyYaeP7l16vA= + + + Resources/core/icons/geo-alt.svg + + hash2 + + WTUdWY1foZonXZ5yFH+Cpn+loukrhcolRniBTi3iAWs= + + + Resources/core/icons/geo-fill.svg + + hash2 + + GO3uZUJ2Kwf121UTskRWIAYXxbtTYi+GY+fYxabKkZY= + + + Resources/core/icons/geo.svg + + hash2 + + kPuJtf+PSuWsOMQVOSZZpgSTQjYC+0mDqXZxWO5vBls= + + + Resources/core/icons/gift-fill.svg + + hash2 + + apucXcild0oGCsQtY4tpfy70EqKCltxvcO6pS1HuikU= + + + Resources/core/icons/gift.svg + + hash2 + + ADy6iMsW7S/U+S8xwojf0fsxBYPoGxCNZ6n2YRKcCfI= + + + Resources/core/icons/git.svg + + hash2 + + gUoZJ/n8//4N9eDW/myXDb/n3Q87RsUfekvjQKn5I2g= + + + Resources/core/icons/github.svg + + hash2 + + PcEmZ/DECtEWhs2RPEKFF9oj3VJg8qBlUMcRgapbsq8= + + + Resources/core/icons/gitlab.svg + + hash2 + + Ry1m3LVLKBaoazFauSxCl/4VPMg8BjnGoSYxip20gKU= + + + Resources/core/icons/globe-americas-fill.svg + + hash2 + + xmA2jJLYbSO15Vj/veGosEvixDvvLJynMfn7pUplKck= + + + Resources/core/icons/globe-americas.svg + + hash2 + + MNfz+vo3B7BTcXXlLw5Y0h6TdctkYXnEItaYtjkrT08= + + + Resources/core/icons/globe-asia-australia-fill.svg + + hash2 + + UCA/2XdfmlR2GNgkjNGNpwpCFWIBknLadk29IYJsJP4= + + + Resources/core/icons/globe-asia-australia.svg + + hash2 + + sKkwUvJOUwfy9jkPS3MnudUKdShqcpcR+h4JN8Z0v8E= + + + Resources/core/icons/globe-central-south-asia-fill.svg + + hash2 + + h5BFSyks+Ilc/BbNBwsCtgDsWH70i86uKSQjCTIAATE= + + + Resources/core/icons/globe-central-south-asia.svg + + hash2 + + 7+/Jt1pYEgb85FVAXyUtRVpBLxSZu1BW/lock2EQAqc= + + + Resources/core/icons/globe-europe-africa-fill.svg + + hash2 + + fvtJSzjC3BoJGic9zhPvqjNUXwQ2dK6tVWheXSU8mww= + + + Resources/core/icons/globe-europe-africa.svg + + hash2 + + c/haZi/268nE+TtZ0X0vWNBG3bWmmS6yuly4yGdFR7I= + + + Resources/core/icons/globe.svg + + hash2 + + IdVjPaBZoNwzWvK6Z8ER7j/P3IK3DH3kl/d3CID+1Mg= + + + Resources/core/icons/globe2.svg + + hash2 + + rb1DjZCgVcya6Yo0Y0tmGpkJuVVyNp5LMQYHNYK3T5c= + + + Resources/core/icons/google-play.svg + + hash2 + + DG1stdf18PHTl8G4db6WAcd6DkxwEubzoVHjL8EJeI8= + + + Resources/core/icons/google.svg + + hash2 + + 35bZd1Q7KJIWcPHVBuZlt9lslos+SkVYd/aG07W5MWc= + + + Resources/core/icons/gpu-card.svg + + hash2 + + 3SGx1yn1MXM792JW+/iTakBJCcx4C3qUOOWhU5t0g84= + + + Resources/core/icons/graph-down-arrow.svg + + hash2 + + 1sU9O0f6Kp993w9cNSKK1PF6hE5BUOwtb1T+yD8hla0= + + + Resources/core/icons/graph-down.svg + + hash2 + + pXQMOU2I0fXE6PajMtvIhh/7Y/3tin70wQFDk/ktZzs= + + + Resources/core/icons/graph-up-arrow.svg + + hash2 + + TTOmJua1YnGkleJ/FgMQjgHmupqFubLAMEpvczLPguc= + + + Resources/core/icons/graph-up.svg + + hash2 + + XRP7pohJ0AqPkMp6R5R3e+ZfzzaHX9VCmaXa5q+Fw3g= + + + Resources/core/icons/grid-1x2-fill.svg + + hash2 + + yQ7vVqGvaFWw0LmvdhCizMPRsdBqk9Y26JCvM3JMFME= + + + Resources/core/icons/grid-1x2.svg + + hash2 + + CM1mgJBO7A5cIoVbSeUi+zHd3dDfR0dBnioY5uI8BlA= + + + Resources/core/icons/grid-3x2-gap-fill.svg + + hash2 + + +W57fhGqMLWZ/4uTSf7d5H4k3PsBuvb6C7eVnqfLz0w= + + + Resources/core/icons/grid-3x2-gap.svg + + hash2 + + BCSIkij1Fwh/wvsETF/Ieyx2Edh5vW+ocfLG7J4SIys= + + + Resources/core/icons/grid-3x2.svg + + hash2 + + IYl/lrgCUHddl5SEVbpAfHQ3siOkDNHfJKehi+gfMuk= + + + Resources/core/icons/grid-3x3-gap-fill.svg + + hash2 + + TbpvBSP+PQNHHjMPdL/RfLg6/FpT4bkrGDthn5oUQEs= + + + Resources/core/icons/grid-3x3-gap.svg + + hash2 + + l2IfsFPRCARn6rMWl5TILsouYNrx1/Le+AkuPBS5Ack= + + + Resources/core/icons/grid-3x3.svg + + hash2 + + toPdQcTYPegEPSo5yG6yORJz5+SlrOjEB6d5D9z2UGc= + + + Resources/core/icons/grid-fill.svg + + hash2 + + i3welr3h3v00dli4ZuZral37z+PK3kazbWddQy+Pu70= + + + Resources/core/icons/grid.svg + + hash2 + + goW3c6L/HNJZLEqO0K4yEME8SAWjxUoE0Y1zsWIx0Lg= + + + Resources/core/icons/grip-horizontal.svg + + hash2 + + aze7Puw0ZN0hmO25azhIPmeDG0VntlDpzQsq7SrLKdc= + + + Resources/core/icons/grip-vertical.svg + + hash2 + + 3+N9MLVIRKnkMIdkkCgPwrpRMjT5oJEjw7Yrw6DE2e8= + + + Resources/core/icons/h-circle-fill.svg + + hash2 + + 3Ws8LMsYsaTePyWdY4YBtktqkVk4KveUB5G2PzMmsig= + + + Resources/core/icons/h-circle.svg + + hash2 + + JUMygW8mHpS8JkvYKldICMoUz7JJVGxaEdlqszJpjFM= + + + Resources/core/icons/h-square-fill.svg + + hash2 + + gh/OfMcf85p0WPOIxp54ZvhyuhbWeJgPFFP9LTCdJUo= + + + Resources/core/icons/h-square.svg + + hash2 + + c5YySf4/at8RDMtfvU0nnQtLHYQDnFU7U7fuhj6H+Hs= + + + Resources/core/icons/hammer.svg + + hash2 + + y11xjOeMBofAZnDo3pREkceTg8aHkkn7nBCpNn8PYjA= + + + Resources/core/icons/hand-index-fill.svg + + hash2 + + wA2+I9IHaXLfyJqFXAOH7K8lIys6GFkkiE6AivEJqsc= + + + Resources/core/icons/hand-index-thumb-fill.svg + + hash2 + + Kdz+6frZyeGS7YokCoh9zGjyfovVyIjrNL+YEkEjwpE= + + + Resources/core/icons/hand-index-thumb.svg + + hash2 + + KTubhuSLz1Exkjo+j56goLjK50d4WQ+GzPoOGuNUPjQ= + + + Resources/core/icons/hand-index.svg + + hash2 + + Hah6Yh87cpeP/M/O9iD1Ng+QEDvHyKJT29BDQkbDsrU= + + + Resources/core/icons/hand-thumbs-down-fill.svg + + hash2 + + Zbx38GDO5pr/XWqFtP09IY727Jdy3qmhBrKiJBH2Od4= + + + Resources/core/icons/hand-thumbs-down.svg + + hash2 + + NBWw/3ZGyHQ4oIa4Wafy4hkxFvCxbppBAV6hhJtREQg= + + + Resources/core/icons/hand-thumbs-up-fill.svg + + hash2 + + SEFjvWmgd4qYOCjNj0ifGwptFGkE4a9i2HiCMcv+vxQ= + + + Resources/core/icons/hand-thumbs-up.svg + + hash2 + + pS2yrvJs+7uNCmEFDtdVm7Wv/aCJPlm5me9w2+SMRco= + + + Resources/core/icons/handbag-fill.svg + + hash2 + + pN2Q6fuJ2gplR537jkqHuql9pILukiLS/tQCT1v4dQQ= + + + Resources/core/icons/handbag.svg + + hash2 + + hJrJcxC2NC1js+yzDSJJbZcmwUe+v51oyjNw6Pyhchc= + + + Resources/core/icons/hash.svg + + hash2 + + uL62FMV1AoRhdtz1I2fZZBLSS8ly8S4IJfkjUsEK0rc= + + + Resources/core/icons/hdd-fill.svg + + hash2 + + TyN1PfZKtkJxdfpam8HV0wqrVx0m8jnDJNfej7QVtOk= + + + Resources/core/icons/hdd-network-fill.svg + + hash2 + + Vcchch3oIIjoockifZn9YWl6dpf57nTXSLuGZVkc6SY= + + + Resources/core/icons/hdd-network.svg + + hash2 + + StHn2ETRgA3l9U618ttH/8vj+DTGUuEjNtMZ7vWEJbg= + + + Resources/core/icons/hdd-rack-fill.svg + + hash2 + + Ql3K4QqJw6IrAf0/HNS3sGymHDujfy/CaPLF5PhAJ4E= + + + Resources/core/icons/hdd-rack.svg + + hash2 + + HKHIdPw7HkrRi5nhCsY4s8QpBOBI8XOkkKFBR6cLccY= + + + Resources/core/icons/hdd-stack-fill.svg + + hash2 + + rwsOUsvCDdFj5xJR1hxEEl0SGFmoR9ypqSnR5uU+LtM= + + + Resources/core/icons/hdd-stack.svg + + hash2 + + ZKZuwAfdy2OmOokmoXqDyB/u5H6UiRTA7GQNIdJUztM= + + + Resources/core/icons/hdd.svg + + hash2 + + 8fnjStV+HalRROXBR8BYX9MNpTc/z/XioAYTplQQSq8= + + + Resources/core/icons/hdmi-fill.svg + + hash2 + + lIge+5G1n1MNKVJO+p0kiYhUkQaRdkkkzTDTPY4a0L0= + + + Resources/core/icons/hdmi.svg + + hash2 + + u0ntsDGlvuUSncYYhywu4glBgmFRS3ZdTc+7Lp5/YGU= + + + Resources/core/icons/headphones.svg + + hash2 + + 4ThW6HnnXs2G/s7x/tdjxL6wNmGRxNtVkJXD63QCD+0= + + + Resources/core/icons/headset-vr.svg + + hash2 + + 8b06dGWNtQxjkhFvDIKDthXCrq8o7pljTkjg8JJHnrM= + + + Resources/core/icons/headset.svg + + hash2 + + W67hQk0bwwh8DeOgB0limHnBxi3EnCMiOXNLot3pcEI= + + + Resources/core/icons/heart-arrow.svg + + hash2 + + uCeilNcSUy2P0nBe55XmM5NIuEmOjNAUI4u0iQ3Ho2M= + + + Resources/core/icons/heart-fill.svg + + hash2 + + 5rO1MAy5tvhhQcRuxDScdfGj34fX4uKQ7ZgDKdGP2hI= + + + Resources/core/icons/heart-half.svg + + hash2 + + iXut7MpR9KGIvdFbmsZJSo6D7arpjdtuY3COImLf+qo= + + + Resources/core/icons/heart-pulse-fill.svg + + hash2 + + HKmxSgIE4QsluLgcyqBg6uuKNjNs0DLCCxDcHnNLnbM= + + + Resources/core/icons/heart-pulse.svg + + hash2 + + QVeH6+EpfbLsdv2qfSxevAjITGeoNub4+xxSORgWBAk= + + + Resources/core/icons/heart.svg + + hash2 + + Q4hvG0Llsgb2i1Cc+n4Oxm43/UxT6/c0Bz850TutRPU= + + + Resources/core/icons/heartbreak-fill.svg + + hash2 + + OqN3Xd3zOaR68JCxnSaRYLo4tHy5AUhM49bwTDnjaFQ= + + + Resources/core/icons/heartbreak.svg + + hash2 + + bzRWoL1vZm1iIZLkeEk2pm4We4LDoUtYkods5NA1Rks= + + + Resources/core/icons/hearts.svg + + hash2 + + nIDGaA3NbO9VR9WtACHAJMsFCp1PPqfS6UVY2LtrY8A= + + + Resources/core/icons/heptagon-fill.svg + + hash2 + + ee3NON14825a8qziZSu8h7CpeOLjHeAui6gOuI6C2oA= + + + Resources/core/icons/heptagon-half.svg + + hash2 + + WHIwbpQ2IvkVOO4HtPI/yvpGYttuKcV+EJuQ4UQCOiI= + + + Resources/core/icons/heptagon.svg + + hash2 + + kQ+0B8Mzn6cIVfSBt0nOBNoY4qk747KacGL80o79/Oo= + + + Resources/core/icons/hexagon-fill.svg + + hash2 + + KyCqZo3cNrowLodqo395ctod0Oei70ixIylGzf4WvjM= + + + Resources/core/icons/hexagon-half.svg + + hash2 + + yag5wf+l3JFHVjfmY8xRlVsZ9sn7xpJCkIfWbOsQ1o4= + + + Resources/core/icons/hexagon.svg + + hash2 + + CP17Iz4NN3JYX4YR8V125/uUkmrzyp8M0IUBQubDAqM= + + + Resources/core/icons/highlighter.svg + + hash2 + + iTy+D5sRiZ24Hk0zqeGXFY21o4MACAFMnM1oMGFPAZU= + + + Resources/core/icons/highlights.svg + + hash2 + + hvOtJF7ibp9g3KhhQ6nSI2ZbrYSMW68ItmfJPfPVldw= + + + Resources/core/icons/hospital-fill.svg + + hash2 + + hMS4CqXMWg0G3zQep62cfjZDwzzcdGkX20EZZGZbx3U= + + + Resources/core/icons/hospital.svg + + hash2 + + qbj1x6itp8dph1/o33xarMXf8pW+CcnIwgq830psrKI= + + + Resources/core/icons/hourglass-bottom.svg + + hash2 + + cwXWjvofCih/IUfIjRKF7pNCSc6KMXBh8hhWQrTlipA= + + + Resources/core/icons/hourglass-split.svg + + hash2 + + cIy8DUv7fIUrbkKMklq2uY8Ngj0MwVQ1Gi0gUNjii68= + + + Resources/core/icons/hourglass-top.svg + + hash2 + + 0TOc6K+DzS8bIrdid1+i1/GXCaSQnwaHlFL4nFb0vjw= + + + Resources/core/icons/hourglass.svg + + hash2 + + vtv12NVrPM4eOY+O6UkdinH58XPyR8+dpmKKA9hm92I= + + + Resources/core/icons/house-add-fill.svg + + hash2 + + uhsSIuqWmG7MjUHWoKFxd/Uml/N9Kwf2xg2XEsg+qpE= + + + Resources/core/icons/house-add.svg + + hash2 + + 4PuWHDI4Z+9mg3IpPODZQvwABhMSyo/2BsquspZzQZ4= + + + Resources/core/icons/house-check-fill.svg + + hash2 + + V0219j+XgmmU1qvlPXBIxkp/s1Iph4XQU49dk4VkPxo= + + + Resources/core/icons/house-check.svg + + hash2 + + MlPCR7BlOQ5+e3s3YITwPq74WJBC/5FAuhaxZUK3OrM= + + + Resources/core/icons/house-dash-fill.svg + + hash2 + + geFqFb17MRekSRauOWgj81BeWA8OnfnlhWMaCOPygik= + + + Resources/core/icons/house-dash.svg + + hash2 + + ISoBukaRDCKHL6ZhNCqq/W68mbu1R6+STZcUvOuakTw= + + + Resources/core/icons/house-door-fill.svg + + hash2 + + PaIX0RL3564ipRk6Bbr9nzUcBakBZML499DDhjpKuAU= + + + Resources/core/icons/house-door.svg + + hash2 + + YLB3pXAzmB7UJM4YsbVC8dXk+FpHjBiFfKEP8fd8Ih8= + + + Resources/core/icons/house-down-fill.svg + + hash2 + + imYMTlCphAyBng1kgphR1oXN5cn7U8WpF2OdWw2v7Eg= + + + Resources/core/icons/house-down.svg + + hash2 + + UU/uZYEyP7WhbMBMrehODn3nu0Ra5Aydxj6T6qUfxMY= + + + Resources/core/icons/house-exclamation-fill.svg + + hash2 + + 3xA5k3yUhy74Hgqp1Q0i2tTn5VSmFr6oVToloSvapPE= + + + Resources/core/icons/house-exclamation.svg + + hash2 + + W7XYWyHPJzH9aTEvp/0cL2ewYp5qZt8u7kuihUR0YtI= + + + Resources/core/icons/house-fill.svg + + hash2 + + uLeZAlCw3fDmcnTfswhb+ZE2FQOLhXmy8f+Gx5KVgg8= + + + Resources/core/icons/house-gear-fill.svg + + hash2 + + DwOueVW6AZthN2kXGJKsUKJQGFGIuXu7Z5pq/NNhWKA= + + + Resources/core/icons/house-gear.svg + + hash2 + + 4uzUcmeyoqARfyKmgOsf/FP9q4i/vsftsU42C8M3aYs= + + + Resources/core/icons/house-heart-fill.svg + + hash2 + + WMA+kHUVyVzqNJBjKn4rH3pd268SI/euq1kAeupLt+E= + + + Resources/core/icons/house-heart.svg + + hash2 + + zORZ1WQUx+kk2UqiZa5+FtD+Xz2zNWx/7dgeSlrYfaM= + + + Resources/core/icons/house-lock-fill.svg + + hash2 + + Hc8KJYEqW/DKBGSPTuWQOPk1twAd+/LCjnKwGxdne38= + + + Resources/core/icons/house-lock.svg + + hash2 + + 0AO5GVtu1rzDxgxuCdBiK0haLOQB5nZbb0H37VEUPb4= + + + Resources/core/icons/house-slash-fill.svg + + hash2 + + fcNyRKpNgHPop2np4rS+8TCoLIVAqCm/viym9isr13g= + + + Resources/core/icons/house-slash.svg + + hash2 + + 72a3vPy2iEC3x+4tzL9EoXIJHw0bj1MpzvQPrHnxZzo= + + + Resources/core/icons/house-up-fill.svg + + hash2 + + 9cgsOtRhWbRWlIA7fO7gObyULAgBI2dKz3HCDKUdZn4= + + + Resources/core/icons/house-up.svg + + hash2 + + MVKgJ3OwVcp7VL/ft7pE5MzwTdl3IkjwtlWAcQ2OyhQ= + + + Resources/core/icons/house-x-fill.svg + + hash2 + + 3Qwz7GsmNrEB4RDHKEdSdse8cxAb7w50Gv/DwGhuC6E= + + + Resources/core/icons/house-x.svg + + hash2 + + WP2Prg2ePv7CK0vjoltNYHUN6M0SSqYxSSCcDcQ2/OU= + + + Resources/core/icons/house.svg + + hash2 + + 3qXLhii0Z4XZNJ2eEBr7mrSfEVepEPv1cMiGCM3NOTM= + + + Resources/core/icons/houses-fill.svg + + hash2 + + +/VutUYtNXLZJGywXbi+D8hZx0jpVXXjjJJNthIYcpY= + + + Resources/core/icons/houses.svg + + hash2 + + Yeq1XjBRTwVZjextpoCOdHu1F0XGFXRECAt6aJ/QLG8= + + + Resources/core/icons/hr.svg + + hash2 + + SkSCickqNoGY6Xj3Y/dAXhYoQ+rNr3zb2hqmE+bR7bk= + + + Resources/core/icons/hurricane.svg + + hash2 + + PJzg44WNjOco4bpVFJGYZ37BZeYECvqR+hBV5e2JzS4= + + + Resources/core/icons/hypnotize.svg + + hash2 + + d3uXBB56dJqD0LDp118FT4KX/dNnA3Gk5C0UgWn1TUI= + + + Resources/core/icons/image-alt.svg + + hash2 + + gdujLXUjLc+f/LuRMsavxbr7SWLainxARoKWqXV3oC8= + + + Resources/core/icons/image-fill.svg + + hash2 + + 6AMza9UwpA5UnMyNAa3GO97hFn46DZy5/19aLJZvAcs= + + + Resources/core/icons/image.svg + + hash2 + + yDEeRHahvTZQ5MWi5bL4qOM+GbI5GIPctraBmmgQMTw= + + + Resources/core/icons/images.svg + + hash2 + + 0bL3eXXSXFuAEHAQolWe7YB642MM3XGcDVXevh9T7dA= + + + Resources/core/icons/inbox-fill.svg + + hash2 + + YyKCcJIOyWfsNhNpjr68WPVQnjcnw2A1zIdcqO77GQ8= + + + Resources/core/icons/inbox.svg + + hash2 + + LwNPKgFdRf/G0SmhzaeVEDzq9+NpAqOacXmo5Nw4qsg= + + + Resources/core/icons/inboxes-fill.svg + + hash2 + + +aFfW1YFtLIMP1NYMVBX4o/575J+Aq10K4S0VYew91c= + + + Resources/core/icons/inboxes.svg + + hash2 + + JbsD1fbimDASStfw5FPm9V88auHwp1Fb26tmdZxcYlc= + + + Resources/core/icons/incognito.svg + + hash2 + + xBAh4iM86Bohxa8Jq1aI2DaXyY9a8kRS7CrGblCiZFo= + + + Resources/core/icons/indent.svg + + hash2 + + ZqlSAsdHCnucIekd8FOTXGF10IxlUnGzTFNIAYboDXM= + + + Resources/core/icons/infinity.svg + + hash2 + + Flc97q8cnEIEC21U1pIi0yDK86lrptA/bVbOsLnFzP0= + + + Resources/core/icons/info-circle-fill.svg + + hash2 + + eOSaCJxmJuZFNgDQKvdVDXnNdUtcSSLtC8/x44cPfy4= + + + Resources/core/icons/info-circle.svg + + hash2 + + SPyxbmxefVVVtiTByzqb+OfiXHyKRxrtABI3qwGJz4E= + + + Resources/core/icons/info-lg.svg + + hash2 + + YpK9XziDF/u10MxY1ZUNoM2OSVDXHbsFjWfW+lcsW9c= + + + Resources/core/icons/info-square-fill.svg + + hash2 + + Ij8EWhEz0Kqzco3IPlm8bVq44oumgu1mIBzOZEbuQr8= + + + Resources/core/icons/info-square.svg + + hash2 + + YC2td+61h3KoP40/eT4vbvRlks26nkHwFwR9lIl/+lI= + + + Resources/core/icons/info.svg + + hash2 + + wnx4CWS1BCZF5PMdpw6XN6/xBvJf+pyUIoWFromd1zQ= + + + Resources/core/icons/input-cursor-text.svg + + hash2 + + 2SkBKOVQdArpsav/MMyAfkeOlg2AT1rtjljlVL+nsvs= + + + Resources/core/icons/input-cursor.svg + + hash2 + + fNvohFON2w2aOzacmRd3CUp8Fk3AEGebApg5gfjFOx8= + + + Resources/core/icons/instagram.svg + + hash2 + + vd0ARYT9zqCpXJCVsU1pEWkKiUxOcyV6/0QGa7uhlz8= + + + Resources/core/icons/intersect.svg + + hash2 + + s/FaYmuLofZSJbWKWsWf0+M3vJ3rqRhlDqtkmZX9zU0= + + + Resources/core/icons/javascript.svg + + hash2 + + meCiyQzZE/c6KLm/H8eXj/kOsenbJVMOWMWQBIsPKv8= + + + Resources/core/icons/journal-album.svg + + hash2 + + OEdD8tiJsms1+9eiNiWtZv4A6uoodWUGa6nc+1+/Vh0= + + + Resources/core/icons/journal-arrow-down.svg + + hash2 + + NaTYKddWKFpYfIWj60u5W4lGtgyxYAb0Up4N+6tKQYA= + + + Resources/core/icons/journal-arrow-up.svg + + hash2 + + ffmq7/Ckr1mTW9QUovZ1Wgpn1kiI0dgJhjsIgAd2AKk= + + + Resources/core/icons/journal-bookmark-fill.svg + + hash2 + + kKkmWjhgUEAqTnm/hk0e+/vOc9wgdLxJuSGClmAwLGY= + + + Resources/core/icons/journal-bookmark.svg + + hash2 + + hcfUo8UAcnxtdKlMmBo+vQd1VIlu/3mL9KqOskQajCU= + + + Resources/core/icons/journal-check.svg + + hash2 + + DKOgJQs1oMbBGg37tJ5G7qHLgoSdN4/xruznGXFYhKg= + + + Resources/core/icons/journal-code.svg + + hash2 + + 9bHc/d6tIt8Fp8yHao6Z+a9J8/fCPG5PFbhJ/lFm5X8= + + + Resources/core/icons/journal-medical.svg + + hash2 + + bSzXjKxiDUDagmeaIkiGIc3iJ0Ei6p2IDHwCj9ZRR44= + + + Resources/core/icons/journal-minus.svg + + hash2 + + 6h7xswNQy7QEUYogs/bpT9zsT+Xit9ZVj3+YBouJXBg= + + + Resources/core/icons/journal-plus.svg + + hash2 + + W520L22W2rIcs67Hglx9ivkxMcAHS+rNe5Or1BHdygA= + + + Resources/core/icons/journal-richtext.svg + + hash2 + + vGIysLzd/RUklnRJL6zBza2ZKlqe7UeDrtCnnJ/hVrg= + + + Resources/core/icons/journal-text.svg + + hash2 + + jpHYkV+ZmqslDZD7eFosr8BX/LyDCLTmUWiPEALfegY= + + + Resources/core/icons/journal-x.svg + + hash2 + + IfUs4JPR4lKFmcq4yKGQn6+k0D2h54ihfewNFa0epP8= + + + Resources/core/icons/journal.svg + + hash2 + + ktwryIHL8aFGBZa+aLiCDV2tGtB4lP/8NtxmiT0jkZY= + + + Resources/core/icons/journals.svg + + hash2 + + 0zq2aIQBT4NODCvxGxlQKd4i4tOymLvLslEQiKZCI4o= + + + Resources/core/icons/joystick.svg + + hash2 + + 6GrV2oXqJjjHDQ/NzUIJ0NKZ5p3AoEjHIEWRGUaYDak= + + + Resources/core/icons/justify-left.svg + + hash2 + + kIxM+9+49J2n/NJYMX62Qgi9kynynai2N06G+7wiiqA= + + + Resources/core/icons/justify-right.svg + + hash2 + + HEm9sneV3elNG0/DirWZryTomRrHUzJbHB8lwmWwhfE= + + + Resources/core/icons/justify.svg + + hash2 + + 95mBcQGfR5S5IQk8gnETohcBJYX6znvueU2BBIXs7jI= + + + Resources/core/icons/kanban-fill.svg + + hash2 + + lpFjgKPNT21mBoqICON1Ys5u07IofToVP5RP5dj6FkU= + + + Resources/core/icons/kanban.svg + + hash2 + + OxR7TJJHpqxvSDVXKCC+U+Ih6GG4c86LopIL8a5UUSI= + + + Resources/core/icons/key-fill.svg + + hash2 + + NIRuUb0C0tAp/s0zVsNPZxNpo4be3AqPJaPnmV9y400= + + + Resources/core/icons/key.svg + + hash2 + + vwQQ7bAWTx/1m2vZhoQNazgUFaUMRsdYAvmJb9X+M7w= + + + Resources/core/icons/keyboard-fill.svg + + hash2 + + wmQi9tpp8sazQVNZXJds93YTvFSAi+kqTqQck855k4w= + + + Resources/core/icons/keyboard.svg + + hash2 + + kGyIzmzYERBSDj7NftZa/yHdLx1kdWefvacE3G4Z6kw= + + + Resources/core/icons/ladder.svg + + hash2 + + sqBJATKaQj1ZStSNYtl4zygu8Irl4q+hKG3QD6PValc= + + + Resources/core/icons/lamp-fill.svg + + hash2 + + wczo1iQuePUIiAIf2twvNibQVSGmUB+BxrldM8V8yTg= + + + Resources/core/icons/lamp.svg + + hash2 + + LdUMgD+0V2YS5R2NW9dcbP2VgZAvxeX6zgVrg5lMFtE= + + + Resources/core/icons/laptop-fill.svg + + hash2 + + 4BQO8l1t1cB/upWbGq5Dx40zrdL6WDa9bqazr8gGQAE= + + + Resources/core/icons/laptop.svg + + hash2 + + OTF/0z/MI4wUYnsEXH4qW4dR+YipQBW2GyRfLMWHPGs= + + + Resources/core/icons/layer-backward.svg + + hash2 + + flE/hoC9GIQIYIKE4GysnT/GNbp2/qQ3DUEJalmTk8Q= + + + Resources/core/icons/layer-forward.svg + + hash2 + + g8ys5tcLZjy/foPWHvWeSd7F54cmuCHRl7kqvotpX18= + + + Resources/core/icons/layers-fill.svg + + hash2 + + 6/BPJsriUWoGP1g18SzpsGRQ6upn8Uaw1TGrY9yX7e0= + + + Resources/core/icons/layers-half.svg + + hash2 + + FL8mDYlIchOJtCpwzKXjdxT6uSFxT3E11P1LQNdq89g= + + + Resources/core/icons/layers.svg + + hash2 + + Ag2QP5CuFcsvCf+Agr0jy76YNxr7xSld18PHmq01tjk= + + + Resources/core/icons/layout-sidebar-inset-reverse.svg + + hash2 + + YNVNcBxpKovJbkQ1x1jthfWav2Spg0UGcU+fZr3LOR0= + + + Resources/core/icons/layout-sidebar-inset.svg + + hash2 + + 6bl36rKwv/JF23B2QoRz9iIv6Vcp5PGdVCtIMspbWH8= + + + Resources/core/icons/layout-sidebar-reverse.svg + + hash2 + + WX7fzY6IN2Jp9WIOaG3szaTXUL//E4uGWKlYJw29kDw= + + + Resources/core/icons/layout-sidebar.svg + + hash2 + + slZimtRZHNgXuWLDgdimzrRF8dOorbfc43GMj3uKh88= + + + Resources/core/icons/layout-split.svg + + hash2 + + YqWQpXb2lLUN7jS3f3Ht5hHbWlAdQPgpGtiPwPgdees= + + + Resources/core/icons/layout-text-sidebar-reverse.svg + + hash2 + + 12KVtnnVjpNuAoFVJoxieCIDQewsVOndSGv63DW9ivo= + + + Resources/core/icons/layout-text-sidebar.svg + + hash2 + + yOpPyvenuC1N+knA8sYPYFnZQ4PYoJHB42bKLcKNk3A= + + + Resources/core/icons/layout-text-window-reverse.svg + + hash2 + + Adq+K8QUHwrk611a/+hGE0fyJ1E3zel3ZmUWyp3B4Kc= + + + Resources/core/icons/layout-text-window.svg + + hash2 + + U5EhqEWOhqQKCyxOXz0O9oWMfVBkAtwVoMBLEqhGsYA= + + + Resources/core/icons/layout-three-columns.svg + + hash2 + + AB/QOBcLq5Wm778fHftg6j821ZPIN1xuGpfId2w5ykc= + + + Resources/core/icons/layout-wtf.svg + + hash2 + + LQRoHFguJhcG8fcMpfx+tYOSwSUi/NCN0vYE9YuVwg8= + + + Resources/core/icons/leaf-fill.svg + + hash2 + + bWtOQuzGEJB+snu0RZiaOOgpxhAVG4uGwUzFclDLBsM= + + + Resources/core/icons/leaf.svg + + hash2 + + /GgiyE3nWnOIeZ5Ut/raWJk/3INMS1BvL0brTJNzMeg= + + + Resources/core/icons/life-preserver.svg + + hash2 + + PFQm8581VuGAzk/QdZv8wAIGPcvNTvUseGoiayRHJYY= + + + Resources/core/icons/lightbulb-fill.svg + + hash2 + + LgdiM97CcBdR7VoR6xCOsW4Ay3mko1MidAreLWk8+xo= + + + Resources/core/icons/lightbulb-off-fill.svg + + hash2 + + g/JtBp+iz1TMjBHYjdbmbIUv9GOLHg+Ar7sbLGxlPgs= + + + Resources/core/icons/lightbulb-off.svg + + hash2 + + VYJvnbbERiZBMQGl2WDVM+LH/PumtOVUUyvrK6RlHnA= + + + Resources/core/icons/lightbulb.svg + + hash2 + + aUaG8OCMCaVWbR/kX5Uc9Xrik60eK7RXBVEFqhTmXuQ= + + + Resources/core/icons/lightning-charge-fill.svg + + hash2 + + D7PA2mF3Uo+7685KdHvwtHx1P1PRgZIAAIcDatKtPTw= + + + Resources/core/icons/lightning-charge.svg + + hash2 + + laTIeNpAYpBXNAepZqVwhLXInnh+UExrE+JPc+tGbMg= + + + Resources/core/icons/lightning-fill.svg + + hash2 + + cRKA1SX2BItKP5RqiV8znZJqTGm80FYPpXWGnZnZIIU= + + + Resources/core/icons/lightning.svg + + hash2 + + LirFRc7ZPPibm1XrhH7QTZon5s0DjyMbAcIzyzrvD9Y= + + + Resources/core/icons/line.svg + + hash2 + + vcFI0iYGK09/F1tflo5MjuIRf/jffAhX/VnuLXAJbxo= + + + Resources/core/icons/link-45deg.svg + + hash2 + + pCgMtkorjnkP8ukZSibMBIKN5i2FASe/CXj+uLL/yi0= + + + Resources/core/icons/link.svg + + hash2 + + 0oEVX9GDANhbT68RDI7gp7AWf+N2TTB4uiztXG/Fnv8= + + + Resources/core/icons/linkedin.svg + + hash2 + + pqClbcDuH2PNynobQUDeOj74vop01EH0UCkCep7vreY= + + + Resources/core/icons/list-check.svg + + hash2 + + 92vdHnGDfG+WfHkreUWePyR5c1mw15ffKAmBVIx0xUM= + + + Resources/core/icons/list-columns-reverse.svg + + hash2 + + Ns+EXdruPOGm8gFxDeRwfq8hzdYmU4LLNkdYxmK6k7c= + + + Resources/core/icons/list-columns.svg + + hash2 + + N3YkA2CN3I8QwApPsFTT/hc4BM+wOiC0fgDSAueksg4= + + + Resources/core/icons/list-nested.svg + + hash2 + + f06UQfiumFrkdUn5OKmY7SdFWsLxrsPfuBv/0vIHw7o= + + + Resources/core/icons/list-ol.svg + + hash2 + + d5n7c55gQUfjhfhZOR5TOAMNQNSGZYqdsoVYK6esuMI= + + + Resources/core/icons/list-stars.svg + + hash2 + + NkZ++lIfaMjzCzN0GVwe9iffHIP4Nu7KCS0jsb5d6bY= + + + Resources/core/icons/list-task.svg + + hash2 + + aM8nJvRjaxNkOTFjvNPtlIpoHJ2OVBuIXPHwGGR9PI0= + + + Resources/core/icons/list-ul.svg + + hash2 + + +QDebNVwAQyZBxAQz1v2rDeLVha7ftzkiqOVyKHErXo= + + + Resources/core/icons/list.svg + + hash2 + + bFUPlza1WxQhcttKW4KnXmD+bHMxnYx6E3wc9Ssqfmo= + + + Resources/core/icons/lock-fill.svg + + hash2 + + Z8sSfvWzYsMAasvklcCHbZxQef+kuXjxcOq8iYLXc9Y= + + + Resources/core/icons/lock.svg + + hash2 + + Igl1lujQpMVdFVcA2RIn1uh811Wtad0iLIXeSNhKO6I= + + + Resources/core/icons/luggage-fill.svg + + hash2 + + ulwTwTI2fz/jPt9EMNjeqnXgsUpn8zUHYjluOb20PXg= + + + Resources/core/icons/luggage.svg + + hash2 + + Mut71SZVzMDdv5MeF6Ai/rU1J6nk9sN7YFLYrExgnik= + + + Resources/core/icons/lungs-fill.svg + + hash2 + + 9swrCVo7/xMQAZknHcPriB+wr5zorG55BwQunRxnShg= + + + Resources/core/icons/lungs.svg + + hash2 + + XyQ26T+dik99ZZcAH8B4obL8RQKDymefBcoLzv0Y9nc= + + + Resources/core/icons/magic.svg + + hash2 + + LA5Km72xwxi7AKfPSZqURKcZfe2MFWfgUzE7pleaaKk= + + + Resources/core/icons/magnet-fill.svg + + hash2 + + wOXX8WrKikgLj7K/VGGnMxM3amwyb2aj+NuB0p7BIIM= + + + Resources/core/icons/magnet.svg + + hash2 + + +yB6/b1DNo3gUtS99NLBSjgvUHdFIwEhUMwxXgXep0o= + + + Resources/core/icons/mailbox-flag.svg + + hash2 + + 2piDELOICV92JvNOhZ1CgvlGITKhthaEiP/Wu802MKw= + + + Resources/core/icons/mailbox.svg + + hash2 + + yavvkXWsrbyx8t47/bh17+TzUXaXLMAZS49Bdi6qyuo= + + + Resources/core/icons/mailbox2-flag.svg + + hash2 + + qS7Gzxv+0sKs8TmXJZnfCQay4TFrsfttjdDN75wWLaA= + + + Resources/core/icons/mailbox2.svg + + hash2 + + 3m4fXHPPqQiG168tCLzHpGYNziUvlobY1C0s2XEv+M4= + + + Resources/core/icons/map-fill.svg + + hash2 + + 48SBLnmE53HHUbdJCpO4yIiRZ7EmOJkp9I3omQdlxXo= + + + Resources/core/icons/map.svg + + hash2 + + Sm9kD8FjrmtFyelRlUOW6E1rADRWD4Mlso2RApb5prI= + + + Resources/core/icons/markdown-fill.svg + + hash2 + + P+IKQMw/Rb4XjNSgtYjuXdgd0YlARlexqk6FHednsD0= + + + Resources/core/icons/markdown.svg + + hash2 + + wqoyET5gbF+mkXI2wrM9OMcQDVVZOGjBQBnSBcp250Q= + + + Resources/core/icons/marker-tip.svg + + hash2 + + 8agT14ZokPfTRiU1sSRd9i/10Mc7zHljJrpW7hX8BJs= + + + Resources/core/icons/mask.svg + + hash2 + + +VO+qvOev1Zj6FKIrC8/g0x82amMblpPjOJBEQ1xDBo= + + + Resources/core/icons/mastodon.svg + + hash2 + + /7zjjsaxeB0HYQxeAS6z0lAVHY/toRmjVBaNWcgtW6I= + + + Resources/core/icons/measuring-cup-fill.svg + + hash2 + + 1vzWdniliLxuoDUNwMQ1DvEeIMrgMvWIQfkvrYIimD0= + + + Resources/core/icons/measuring-cup.svg + + hash2 + + Ayp8euC/EBU8vPuwpSq51pV6hPE3SqeAp7WCH3PIBUY= + + + Resources/core/icons/medium.svg + + hash2 + + +7wDOwjt7jdX8ZZ4DOcgJv1iOH3rDklLzRZUwPZ8jA0= + + + Resources/core/icons/megaphone-fill.svg + + hash2 + + onTnvLTwl7R0ZlvoBwWDsCMZfwn9zle6GJh0pCDHVWU= + + + Resources/core/icons/megaphone.svg + + hash2 + + cQF0AU14TnKUpVkx/D97dtuTGfsI0NBD+t9BuEMR7is= + + + Resources/core/icons/memory.svg + + hash2 + + asvgSnMos99fCDWuLcU0znKrU5rjgasHMXUeqLJyjyQ= + + + Resources/core/icons/menu-app-fill.svg + + hash2 + + m1DPZOyaIxGD5WdwDFzAvhYuWcEk2txNSa5j8S1oCV8= + + + Resources/core/icons/menu-app.svg + + hash2 + + 4I0bK+QaRX3XivE978DntrCglLKiCZPVlYq5hKoHFeA= + + + Resources/core/icons/menu-button-fill.svg + + hash2 + + MsoweoRftKh0PVf2Dzct+zkk0Q29un+76LBgzdpbm/w= + + + Resources/core/icons/menu-button-wide-fill.svg + + hash2 + + Nn724cgUlv15vGrNXL5IzY6Kati2CfGzDiys3O/ln6c= + + + Resources/core/icons/menu-button-wide.svg + + hash2 + + U5/Vf8Ufsix/MPocpEGC2ZUHF8p0lPZTw43HwM3LKzU= + + + Resources/core/icons/menu-button.svg + + hash2 + + a9+bKDA6mcps6gtZfx318k50EvD0O21OKxMGyT1ha5g= + + + Resources/core/icons/menu-down.svg + + hash2 + + tbnyx2kMQNdNgtcXxro8A9zewbxCXSfEjEtR15whJQ0= + + + Resources/core/icons/menu-up.svg + + hash2 + + ImYYbgQjF6EqXyxpMO0Ou+Yt/ug49o1XNPJSR1a3yQw= + + + Resources/core/icons/messenger.svg + + hash2 + + hxLlyP9dd/ussOg1HznQOcjDM9CFwVN1tpFBduFSFjQ= + + + Resources/core/icons/meta.svg + + hash2 + + W/bSTTNvj1lCfmf5M8wjgfOMS9R4aCdO34H5vMEQtoc= + + + Resources/core/icons/mic-fill.svg + + hash2 + + KGNdPTeRzkPGgN4JVAlzJhnnq4+SPvahJO/1hxvxofA= + + + Resources/core/icons/mic-mute-fill.svg + + hash2 + + L89tuVj2lftW26GfQ5WS5Jfl0OC3S+50TnwjpvyxFmw= + + + Resources/core/icons/mic-mute.svg + + hash2 + + enxnPwdvDOBpEOG+9/Bnusm4hjs6ciIER42W8pUDU4s= + + + Resources/core/icons/mic.svg + + hash2 + + jDEK4wwi3/RlOqVaoUr97C0EFWH053UaFBQCHjai28w= + + + Resources/core/icons/microsoft-teams.svg + + hash2 + + T4b532DqhrmAciHPJJJZ7xyj6NI6jwL9F9i+gOnunKg= + + + Resources/core/icons/microsoft.svg + + hash2 + + Z4C0964KSLSpl4sd3/uq0RmNXpqCnTFGrVY4JU19/qM= + + + Resources/core/icons/minecart-loaded.svg + + hash2 + + 40zTcmji3NSc8DODU6WPtDeV30rA3dOl5td7xu+SyfU= + + + Resources/core/icons/minecart.svg + + hash2 + + QLeTRnOqD+18axsrfmf+6nxPDGaFZT10ZMW66mveG1U= + + + Resources/core/icons/modem-fill.svg + + hash2 + + 3EquJl4lqN1b+aEhWojyQlI423i0jkxX/h65IoizAAw= + + + Resources/core/icons/modem.svg + + hash2 + + ul01xRgPxpwrJthFLGihxnOKbBxxUewAR+hb0Ij2aNI= + + + Resources/core/icons/moisture.svg + + hash2 + + d4smP1MLJAcFTVQXHETSQFeP2L1NZJd/rJufDbXjSEs= + + + Resources/core/icons/moon-fill.svg + + hash2 + + 5U3Djn//Wbr6PM8GDn63Zbu+s3C27SkHnNvaAZqMulc= + + + Resources/core/icons/moon-stars-fill.svg + + hash2 + + lcTTdaNeTePRRm2rawJALwTRBElRip5VGaE3ed2N0VQ= + + + Resources/core/icons/moon-stars.svg + + hash2 + + 0WbEpX5EWPD7bGq5RhUYdvveyAyWgcTHDhRAp9r75WU= + + + Resources/core/icons/moon.svg + + hash2 + + jmOVbTIgz28pyzFJTvmnBfNNLjosh0fmnPw+rsLq3oU= + + + Resources/core/icons/mortarboard-fill.svg + + hash2 + + hKJGEEi39rESbt2LsKBzlLYlWGzBGBOkYGuSkXqg1ec= + + + Resources/core/icons/mortarboard.svg + + hash2 + + Yd30fknCwcf5BNR0HF/UNl8oxw1fiXPDb0Ubp0S6MvE= + + + Resources/core/icons/motherboard-fill.svg + + hash2 + + PGi7n5K6MyNesH9tgmjms8k5W1NuyQ0SkWY/ZgcteRk= + + + Resources/core/icons/motherboard.svg + + hash2 + + b7KQ+GIIRkWNZEG3T1j7EB+F3awq9X+hYszCDQ++lGM= + + + Resources/core/icons/mouse-fill.svg + + hash2 + + KY+hdKHLp50aRYtYS1H7zDXLBZYIlswDUYYyjveqbK0= + + + Resources/core/icons/mouse.svg + + hash2 + + t+U2RvxGAxnrVTEMDIK2v3++/htnW05Xyrl7k/JrtFo= + + + Resources/core/icons/mouse2-fill.svg + + hash2 + + QbPkYzIl4+op+uRtzlH1LdSOhCZfylqI1RkydCdn9DA= + + + Resources/core/icons/mouse2.svg + + hash2 + + O9osWTtyQK4M1oVpp5zIaGjM9maoODDQvkK1xV/7WZw= + + + Resources/core/icons/mouse3-fill.svg + + hash2 + + Hc4Ypn1fLYSZp05Gr9NVXCTm+ONcu1bSgBckipW3Ap8= + + + Resources/core/icons/mouse3.svg + + hash2 + + if9juMFWyKDlFe6w6u05R4iL7yu72b0u1SyCTFyYZZ4= + + + Resources/core/icons/music-note-beamed.svg + + hash2 + + juh8kXOMe650/8W3+mV8M9ncVVzFbuL3d5S+L3jFcyk= + + + Resources/core/icons/music-note-list.svg + + hash2 + + ECbogi+VjBqymkS2GLnX+9TfzGOolAXaMcZMHXLUoFI= + + + Resources/core/icons/music-note.svg + + hash2 + + 54Men/9EQz2LgF0x/fM2F4JR0rpejH7PaPL5Y3v2vgE= + + + Resources/core/icons/music-player-fill.svg + + hash2 + + Qng7Gzl4zxUlOW5RkgGbOUQgS8yvz37Jyub8dqWzgPo= + + + Resources/core/icons/music-player.svg + + hash2 + + Gm87XbZPuZtiM2xFvYr+ZIWAUHEJXKvQANoApnZ5tnc= + + + Resources/core/icons/newspaper.svg + + hash2 + + j8U0cnZ8Xf4TgG+ZvRzAWfZ0185iOujW8l2E1Vr7JnM= + + + Resources/core/icons/nintendo-switch.svg + + hash2 + + NUlvQWEJlgIjwpGtfCgGoQCqbQT6HnnLKexokJmaWMQ= + + + Resources/core/icons/node-minus-fill.svg + + hash2 + + 5dz1TJRvtzzNPLUyuaFJR8h0RUVnlTrWLezichQhW5Y= + + + Resources/core/icons/node-minus.svg + + hash2 + + 79sLqOWzwaRR2Trjtmf4urvYX6VI+xpylUj6PO6no90= + + + Resources/core/icons/node-plus-fill.svg + + hash2 + + r3FksYPmsp9NNRgHtoUMS9Dnbcm854+bACRT7cM4a0M= + + + Resources/core/icons/node-plus.svg + + hash2 + + 5bkSGKkr5SgfStlraW2EWopDhozic3XqCDmIEYZuFcw= + + + Resources/core/icons/noise-reduction.svg + + hash2 + + TBeNP6rfGj5ya4367lPlYp7nRyurHaTFPi0mmjhbzqo= + + + Resources/core/icons/nut-fill.svg + + hash2 + + hHDgt4A6BPxectw1rSj0bdZxsCs4L1aO3EgG6yXtjJA= + + + Resources/core/icons/nut.svg + + hash2 + + P2BLePyM7EQm3tYPJCwWd8w79qzPTKC1hf0iUoNrb7Q= + + + Resources/core/icons/nvidia.svg + + hash2 + + kLV8+1IRkilt3P1gLKRKrHyEC8A/nRYXRqCrzIk/ras= + + + Resources/core/icons/nvme-fill.svg + + hash2 + + URKnQwmQRrZhU+JY/5cUlyNNl5UwidJfSlxvSYv8Erw= + + + Resources/core/icons/nvme.svg + + hash2 + + nilX6MlEIXEerAQxiNiT02HIbjcDiIbYie6TTU2ujMg= + + + Resources/core/icons/octagon-fill.svg + + hash2 + + DRq+zNhRn7fFfOzP0+OY6KAG518aPWa1dERbFuNsZIw= + + + Resources/core/icons/octagon-half.svg + + hash2 + + lcjnQ3QGpC8IlX8o1ueegP0Q2YFgYIlye3USIfISs2g= + + + Resources/core/icons/octagon.svg + + hash2 + + 2tfTPHu493B7cIGfPgT7kFpWtxOZ3o4Y2XwTKU4eI+M= + + + Resources/core/icons/openai.svg + + hash2 + + G6yUHGNxGiBaN6Bcn9rDoeB2G15LRlRcxJntdbq+NxY= + + + Resources/core/icons/opencollective.svg + + hash2 + + Yk7V0vFYi9Lww2+C3g08zLOAzzQ+pGuBTZ93G/SlQLE= + + + Resources/core/icons/optical-audio-fill.svg + + hash2 + + XJfvjxIGJTgnJoMuDeWLbDg5OVbEreU68rU8urb+Idc= + + + Resources/core/icons/optical-audio.svg + + hash2 + + sTyvSb8hJ2SHDru2GeMAg63sWik06W429Znr8hwCiDs= + + + Resources/core/icons/option.svg + + hash2 + + /nZEMC42HHNSXjGE4bFatUMacqbFi4/DyuRPkINN6wM= + + + Resources/core/icons/outlet.svg + + hash2 + + R9NHwkSE28I0NtxkKy5ZXNFUFMqxI+Tnu6Nqg1ExeBw= + + + Resources/core/icons/p-circle-fill.svg + + hash2 + + heX2N9rWNJWtDV0FvTjiTx5z/mY9s/HbF6LlyBsUlQQ= + + + Resources/core/icons/p-circle.svg + + hash2 + + GgIt9U5tq9FTWlSdMggKbbb+i/OToV+Ki89CigeJAys= + + + Resources/core/icons/p-square-fill.svg + + hash2 + + K6baMhzDe1aQv87sn6pFsdTGK8v89t1J99XBZAbYRHE= + + + Resources/core/icons/p-square.svg + + hash2 + + loE2biiO9sy3VrI9rLXuyx3HItih9Vs74vXppQSPMcM= + + + Resources/core/icons/paint-bucket.svg + + hash2 + + zm0ZCiJWutFCsGP6GqGrb0YnOAD6G5JD4B1RB/vu7SU= + + + Resources/core/icons/palette-fill.svg + + hash2 + + D/9J9BYbGsxejXiT7RWXhs4njyr15fx8rpWmkQiYFW4= + + + Resources/core/icons/palette.svg + + hash2 + + Mqi5Ab/UugUlNujBn9zwm6TGQZlbS0S9UBFSueMf4eU= + + + Resources/core/icons/palette2.svg + + hash2 + + xKYqQ7BmKbB+HX/qxuRHcH5tC4rWhc2dPpH+VzfpkxQ= + + + Resources/core/icons/paperclip.svg + + hash2 + + lbfgVObC8SvCmpyf5IJrFpxwnUjd1SQWZASoyk/nZ/U= + + + Resources/core/icons/paragraph.svg + + hash2 + + Q30f3IVTsU/NGI3J9z9ghgZuqB3zH37tE+B7iV7Dboo= + + + Resources/core/icons/pass-fill.svg + + hash2 + + n42pgvIFX+UdLVWfFUewuelrUy59KuE7o9/Uit6tuOk= + + + Resources/core/icons/pass.svg + + hash2 + + ZOMe+G4kYEZCv/ri4rYjisNAjZHgP0RJdPtGuhvreK0= + + + Resources/core/icons/passport-fill.svg + + hash2 + + QK8KkQCuYD1BJFoLH0dK7JwgiScmNJoaFgAalLgCqLc= + + + Resources/core/icons/passport.svg + + hash2 + + f30KUxatEhGiiV2So4d0sYaNNKyNjuIyhg6/0CMtcNA= + + + Resources/core/icons/patch-check-fill.svg + + hash2 + + cYc/HOk4Z6ngdTBnQFneQ1WAAJjKYH+8IfiZ1AFzlCQ= + + + Resources/core/icons/patch-check.svg + + hash2 + + NSaN5+55k7B+tEYF4uOWYr/29yiy0nGVVH/Xv7F3Pps= + + + Resources/core/icons/patch-exclamation-fill.svg + + hash2 + + TBXuDxvJwTwU2teIXFLg0vvtLuacayXc06kvvJjrcqo= + + + Resources/core/icons/patch-exclamation.svg + + hash2 + + y3b+yLkXwzQr1jE6a3J7F5X3rF2DVpl7PkxmFo0yHC8= + + + Resources/core/icons/patch-minus-fill.svg + + hash2 + + cm+oDuXv0yUjqoUN6sU2f1srmNDTJlkqPAJnKypPJxU= + + + Resources/core/icons/patch-minus.svg + + hash2 + + d6uKVqmwmW27ux8DjchqQR0U3cMNSoFlE14r0SK1zTg= + + + Resources/core/icons/patch-plus-fill.svg + + hash2 + + KwOSjGxTkbw1yYyH4+7WPGl80VaQDL9zjMKvmUpBHuE= + + + Resources/core/icons/patch-plus.svg + + hash2 + + KFhym3h/iX+ipEO+JMsziJDJCe/M5Fetzgr+KumAu0g= + + + Resources/core/icons/patch-question-fill.svg + + hash2 + + BQIi+R8AG5eh4AZm5J9TWCaRtFgS43tJzSZ/fphav+A= + + + Resources/core/icons/patch-question.svg + + hash2 + + 6AwTBMsCr7dlDTy083dzmlZIoOhJjvNTV4fMyJry5zQ= + + + Resources/core/icons/pause-btn-fill.svg + + hash2 + + iWtw6GbLUNKuXWoopCOjsBMNWqsuncWSmDMOT1KMPPo= + + + Resources/core/icons/pause-btn.svg + + hash2 + + cqjYB0G01Rw/qd9H279GJ9MuMHQtcSG1n2ryh7Imq6s= + + + Resources/core/icons/pause-circle-fill.svg + + hash2 + + N2AK4WjSVRCzzdiN/RQf6Tzsf38EJpZY9+stHyfOqfk= + + + Resources/core/icons/pause-circle.svg + + hash2 + + AgsXiRdqSeA7CM9xsn3e/+0MjiEkM1OxhRpits6GX1Q= + + + Resources/core/icons/pause-fill.svg + + hash2 + + nOhF615V8GZY2ZO9+4drJP0Hz7GvVuVGva6I7+/vSVw= + + + Resources/core/icons/pause.svg + + hash2 + + zWbrkM1uVC9C7jWlbkkvF8DzS+A0KQZHdDuHLd6j7/I= + + + Resources/core/icons/paypal.svg + + hash2 + + eUbP43qWgx76FHPtCgCMIFXFJ3Eo1OCxoMJYjnvIzQQ= + + + Resources/core/icons/pc-display-horizontal.svg + + hash2 + + IUEBsZfLld52BWUUvBrPQ3ljuOhFkbbv8fZENK6ZL7E= + + + Resources/core/icons/pc-display.svg + + hash2 + + RZhVxTiFk18+jJoXqFN7wV7lj5tob2KYHQZ7AXJrQQQ= + + + Resources/core/icons/pc-horizontal.svg + + hash2 + + r1cAxm50RFVkV5577NpEy6Ij0CaCJxHUSZYXkOPS8fQ= + + + Resources/core/icons/pc.svg + + hash2 + + n56giTOmt9wEha+zr6wHvFcIxGbiFgRAKxocCHk8JE8= + + + Resources/core/icons/pci-card-network.svg + + hash2 + + L3MoCaZH+xIUkRPTbi6QMfv+SfZgsc/8r8WTVm1Dpyw= + + + Resources/core/icons/pci-card-sound.svg + + hash2 + + bXKlSbzarjCiQ0aTXwjX+WK3sHl2oKdhHhPEeD1wd/0= + + + Resources/core/icons/pci-card.svg + + hash2 + + oR3l2PqdztyttlrCLM+E9b1XRD3KG9vzqdYO80svUTU= + + + Resources/core/icons/peace-fill.svg + + hash2 + + FTNxaKFMhdPb5Khrk8M0+NUaQsg5imEEOpinH3TM4XI= + + + Resources/core/icons/peace.svg + + hash2 + + 8vAGcOULeMjD/PzvXLjPF2NQYp6B9wNwsPOYjZ1PcJ0= + + + Resources/core/icons/pen-fill.svg + + hash2 + + LmKSFSZHMnrzl0GEmxJoZd7R+W0jyPH8J78YYqd6xJs= + + + Resources/core/icons/pen.svg + + hash2 + + YCe6t2QauJcM6TcOtTLVQfjbmApcBiyk5+P0m8DTnCw= + + + Resources/core/icons/pencil-fill.svg + + hash2 + + jAoYt66do0UchNng6ImNmFtcOB630BS9Pfuuib4LkKU= + + + Resources/core/icons/pencil-square.svg + + hash2 + + Ia9nQW4efXxcCheSVdUdA+W8Fc5Yt6vlNk4sFuSNfEc= + + + Resources/core/icons/pencil.svg + + hash2 + + 3xm6yRSg1xpZoZsvCxPZSHH+CWaBNfMMrD52ocOcVxI= + + + Resources/core/icons/pentagon-fill.svg + + hash2 + + mm0Y9rqNuSQRRwTeFsf3nIqoHnn3ZI+9PVSYmVz1DhQ= + + + Resources/core/icons/pentagon-half.svg + + hash2 + + +LuYC9S/wlkRv+8xoTiccbFRox4Xc+2DmiJo4q7faVg= + + + Resources/core/icons/pentagon.svg + + hash2 + + uqGEdJPLatdn05MW+44Qx7DFbULA3kMLIrFDucLBz1I= + + + Resources/core/icons/people-fill.svg + + hash2 + + pb87Dzz9UQYq4MHP5c+inXajrg96V7EOpcXd/9Zy5eg= + + + Resources/core/icons/people.svg + + hash2 + + XGT4Kc2LxR6H5eSxDY6sGVGRvIQFu1uYb+nKpLZwBBg= + + + Resources/core/icons/percent.svg + + hash2 + + bt8i0VxZvAKURHOfGUEZNtdB9QclSgV+a69FsBmb62Q= + + + Resources/core/icons/perplexity.svg + + hash2 + + hKmcVit33+1DD4fOwmhwpwe9v/u58RIe8y7A45h0nLg= + + + Resources/core/icons/person-add.svg + + hash2 + + qrcoL3NFKUiSaSqLyFYT7rxPhWRey2ztR2Yh8F/8rzo= + + + Resources/core/icons/person-arms-up.svg + + hash2 + + JrDEwXPLQX2ii1V7aUvXY9j3oXEeB0kAUCTjYO17Mf8= + + + Resources/core/icons/person-badge-fill.svg + + hash2 + + ZxNL27MzOQ2c3A5YSzxczRWhtCZ5csn36uDxB+Zr5K4= + + + Resources/core/icons/person-badge.svg + + hash2 + + /l2EbzgIrOlilUvfiK+vAR3/YAyLsFOUqa7PW8V/OAM= + + + Resources/core/icons/person-bounding-box.svg + + hash2 + + 6xZaYpIkuIybw7zM7IKufkOirBd890srbauDSuj8L68= + + + Resources/core/icons/person-check-fill.svg + + hash2 + + cYQJmMRjxERq0/iNjY0l/huRuSYhYh4Y2sf1z/tQ0lQ= + + + Resources/core/icons/person-check.svg + + hash2 + + V1bqCs6ug3FOmild9kbfc33srIi5m9ReXyjyVMMaSe8= + + + Resources/core/icons/person-circle.svg + + hash2 + + ZwT/QkgKlmUwSM439jSV2hz/ezUu/r0b+HBXZu9HJEc= + + + Resources/core/icons/person-dash-fill.svg + + hash2 + + UQjctUdungu/ZIBXHwZJby7wmeA1jTSn9zyBv+Up9MQ= + + + Resources/core/icons/person-dash.svg + + hash2 + + YdCBfOFtj49s74wL0Peg5i8fW27U3EWr3YLUmV43ars= + + + Resources/core/icons/person-down.svg + + hash2 + + PaT8++6R5bP17Ft6Ghy5arzb/E70kvVZ18o+6NsDd68= + + + Resources/core/icons/person-exclamation.svg + + hash2 + + cLwtoyDQWdMvpkjwbgZG5LkstsnB0RIWZtf4DsQf8Eo= + + + Resources/core/icons/person-fill-add.svg + + hash2 + + KgkgYUd0gY8jiqyunkxCbjc+Zxa6WbJ1k6OXFGdwHug= + + + Resources/core/icons/person-fill-check.svg + + hash2 + + d6+LR9v5yrjXWGitth76TKcNwOjq1dhiTob3lrbC1zw= + + + Resources/core/icons/person-fill-dash.svg + + hash2 + + 93pHWuJtlwc4re3tJmtEJFaFByqOctr0Rq/52V0Oe3Q= + + + Resources/core/icons/person-fill-down.svg + + hash2 + + 1/9bFwBmNnHWy5iyBZHsgNxys8Q2akwatWtVYRbJoIY= + + + Resources/core/icons/person-fill-exclamation.svg + + hash2 + + FtCQyJfnG+vEuB13JvxZCBFN726b/mnZE4Vi3Uh22/w= + + + Resources/core/icons/person-fill-gear.svg + + hash2 + + l9AeypOpOZ7F34yky2B8FvPvjt0xjMZg5uxKLJ16jW8= + + + Resources/core/icons/person-fill-lock.svg + + hash2 + + TFya1C5lT7SxObWdijKCpwUYslurAubl01o6s4IHP1s= + + + Resources/core/icons/person-fill-slash.svg + + hash2 + + H5FM9C6+nivNwJ6buR7SxBKuxZNJxhIMlCCHQqcD4Wk= + + + Resources/core/icons/person-fill-up.svg + + hash2 + + 6KNVXiEqDSBsleRprvO+hmY826c/u9SkfD2IXysiXu4= + + + Resources/core/icons/person-fill-x.svg + + hash2 + + ymcwV+fHp7bcFfKRoTtZfa9KMGNT49oNti7jXy4/rzY= + + + Resources/core/icons/person-fill.svg + + hash2 + + qiZMf1iC2AsSSRviicvWwA+mWFF0M9w+MzAuIpFqplE= + + + Resources/core/icons/person-gear.svg + + hash2 + + eDmr8Cl1uvAaXfa5hvXTHX57HLATC8bh7ITs1ETA72Q= + + + Resources/core/icons/person-heart.svg + + hash2 + + eNg/cDTp2mfU6GHX/cU6LTQqs4cN2LwZjAGBij3emmo= + + + Resources/core/icons/person-hearts.svg + + hash2 + + EgGrH0+31uQMS5NijPNGsNCepW7cH4d2uHr+0aV7fuo= + + + Resources/core/icons/person-lines-fill.svg + + hash2 + + +Y0G64BFoUhR7lOF5qXYgDri6qI35wVsIZuKN0F3i3w= + + + Resources/core/icons/person-lock.svg + + hash2 + + 8Axi7WwTwCNlgT8NzrTG7LfQEKKyQb0ZmTsTLRLd3bU= + + + Resources/core/icons/person-plus-fill.svg + + hash2 + + 57ym4ns394gQ7w2DVTXKkIBNA079LrbtXjsXHwQJCrQ= + + + Resources/core/icons/person-plus.svg + + hash2 + + 8ODEMz2lHlhXxE33rNwgb41vKeOVSbktslZXVEgWSp8= + + + Resources/core/icons/person-raised-hand.svg + + hash2 + + zq7ATvzIHbc0g1wyUYWrIX0TwdQ/ZayiUQ/IAUoqkUs= + + + Resources/core/icons/person-rolodex.svg + + hash2 + + jV45MDo4WwtxIHyFsIEhj70Y9flEhCs6LyHrxr9XBMo= + + + Resources/core/icons/person-slash.svg + + hash2 + + FwkLaCkCc7ch2Ogang9cBwMJw6KMFXjGcFP2GxIAU+s= + + + Resources/core/icons/person-square.svg + + hash2 + + 4KaVoAL/HKJNrntKGZSo1peHCuuuFAutJ4flmvrmq4k= + + + Resources/core/icons/person-standing-dress.svg + + hash2 + + XkZKtabrpMLdk8WbQJsfeFrBe36HWwQQz+AdQD7KKSc= + + + Resources/core/icons/person-standing.svg + + hash2 + + UCkYZlH5ALmQRZWmAllzvqJAxnqWN/xEVy7lWonAdh0= + + + Resources/core/icons/person-up.svg + + hash2 + + njIn7RUHJeANR5qbeqs3RuUuv+c4HRY3LctPqpEX9EA= + + + Resources/core/icons/person-vcard-fill.svg + + hash2 + + 2VgJ2AR3r3gQJXeA/+u8b7o4jFVAHbF88KQikGmj3Gs= + + + Resources/core/icons/person-vcard.svg + + hash2 + + nIEy4Wj3qNgXTrrE2CIebVLyBT2dDXHB8niNkw6nMeg= + + + Resources/core/icons/person-video.svg + + hash2 + + ARqgv7O5PMHptitj9Xx+c2mSUX4B06ijUqWMRIV+Bhs= + + + Resources/core/icons/person-video2.svg + + hash2 + + KuVz4fNG4Vhu1n/AxBvT3+6epnXDnQf8iJ46wtPGTCY= + + + Resources/core/icons/person-video3.svg + + hash2 + + W/uphTrByhq/E/tbgfuWBPnjjR2ry6cYDh1IB4nYfgY= + + + Resources/core/icons/person-walking.svg + + hash2 + + vXpW72VOQnlC65e2OaxtIeFd8xSAgSBz6dMckJdGAz8= + + + Resources/core/icons/person-wheelchair.svg + + hash2 + + 5fPUExa6U+NOtuCqW+h1ookcQvkmRm3v+CNMjnayeYI= + + + Resources/core/icons/person-workspace.svg + + hash2 + + akEPb1uy8THRM5ie5Gd7enT0Pqf47AO+qY9LTKtV0U4= + + + Resources/core/icons/person-x-fill.svg + + hash2 + + tmJRWfGSVyhPuZGQyO2zhEUQkqt7htex/ofLg8OvwyI= + + + Resources/core/icons/person-x.svg + + hash2 + + gJVEzYThrqQ9a1vWIENpzbKbEBC7o0s7s+5PTUfdlK0= + + + Resources/core/icons/person.svg + + hash2 + + 02k7s0dCVDB7oWGfL0h3Mjdpt8cYbOxVC7ZZKoFhfno= + + + Resources/core/icons/phone-fill.svg + + hash2 + + OYjBn9X5GBdEd4Gq8ThWjdPX0hCaniUamIkTZgRx1vE= + + + Resources/core/icons/phone-flip.svg + + hash2 + + CgIQMpS/dUiIkdztRWIB35UlcKk6buq6HbiVkEZkl+o= + + + Resources/core/icons/phone-landscape-fill.svg + + hash2 + + U4VtvkZJs6Xu63RjEomRvxxa39b2SduYfBAWsQZCa6U= + + + Resources/core/icons/phone-landscape.svg + + hash2 + + EBDQsUotbGfzwqUN+T1INYOg9ryKq/IeEd97fT8uFLs= + + + Resources/core/icons/phone-vibrate-fill.svg + + hash2 + + 02yQAvif71bJ9J6SAXeh6mkjzK7F4NS2qpFiCetK798= + + + Resources/core/icons/phone-vibrate.svg + + hash2 + + TFTmsmph50pH5svuZ0dRwGX0nJwxdOhFLyjfY8QffPg= + + + Resources/core/icons/phone.svg + + hash2 + + vxjEwy6ja3A3hNruMduPzG2ctlekx3qxJv0g+EloSKI= + + + Resources/core/icons/pie-chart-fill.svg + + hash2 + + ew5Cc/m8/jNv7MeYXxyVS90VEoM2LmbfhCesV74jTPg= + + + Resources/core/icons/pie-chart.svg + + hash2 + + lJvHe2Evp6NW5KIF3FNrHDF3gZ9zCCJjhQWhUO0yamI= + + + Resources/core/icons/piggy-bank-fill.svg + + hash2 + + jtp4Lcr6mNkgWZy11AF5ZacbCVaImRVZyLqot9Ux91s= + + + Resources/core/icons/piggy-bank.svg + + hash2 + + oiguLPY8HfRUtNCUzAUOFFvp213HCNwhl6zH9Oi8jCg= + + + Resources/core/icons/pin-angle-fill.svg + + hash2 + + 6SwsqpseBgFAmapEWD86YU1uWj0mDQ678zMp02sw8Tk= + + + Resources/core/icons/pin-angle.svg + + hash2 + + YGn9olP5BMlwafHYIKwNbWt0j9UoMIUfiqFOrRBgLns= + + + Resources/core/icons/pin-fill.svg + + hash2 + + BTG4uoP6rzYJ2yLdiAA3Wzl0IiXbErwBa7q1SBR3vhg= + + + Resources/core/icons/pin-map-fill.svg + + hash2 + + bONq2Ce99HcXTU0HQHeCZVrLDe5JVuaLuoH/m1kCme0= + + + Resources/core/icons/pin-map.svg + + hash2 + + RSfQcRMftxWWfVPPd8QJoEIpb+C6LZP6SMIZQOc+7mk= + + + Resources/core/icons/pin.svg + + hash2 + + 45OZto4tjzUQNQvl67DD+bKAbRLsmIciUGV02S7BsJI= + + + Resources/core/icons/pinterest.svg + + hash2 + + Mh+1VH75OmRYF604TbNP+iY3K6jFWAQYVRiOE8G9wzw= + + + Resources/core/icons/pip-fill.svg + + hash2 + + ilVVhW3bP+WTvxx8eX8aRvb0y3IBLXrcwkxYDTtpYNo= + + + Resources/core/icons/pip.svg + + hash2 + + U9Ya5DhYjztwpFrPDi/n+7mq79yMXNFQeshWkY2U+j0= + + + Resources/core/icons/play-btn-fill.svg + + hash2 + + LzTTUF9OcEQQC9zZn0dYzYkIA0vwVANVQC0S9Jkou8Q= + + + Resources/core/icons/play-btn.svg + + hash2 + + e7zEZdBhf1MQHCLFVQnAoUg3JI8J18cLvEgbqKGpIo8= + + + Resources/core/icons/play-circle-fill.svg + + hash2 + + 77cuMKZZA0DBiQ01KUhvyqrbOjFxrWiN/Y/02SsTMk0= + + + Resources/core/icons/play-circle.svg + + hash2 + + wntBPEdzc3pBe4w9E0ZnjYu4pvqbsEIN+sP/LRPobUo= + + + Resources/core/icons/play-fill.svg + + hash2 + + PWpMJUtwuPElwJ9WFC6mX5wICfQqEm/F77BuWKa3zLU= + + + Resources/core/icons/play.svg + + hash2 + + OvDlXdl4uyckJmzltYLly8ZR+kWno7ArplS4Cq2N4+s= + + + Resources/core/icons/playstation.svg + + hash2 + + IQ3ldsy9u5YPZxLqgkm45a7k5Ly3g36ZUjdDwrWgnmY= + + + Resources/core/icons/plug-fill.svg + + hash2 + + zGBk4aeezR60OyzVfivjwXhXqp0vG1sgoYGPYzCL5WU= + + + Resources/core/icons/plug.svg + + hash2 + + U6VYw9L/WwqYrddsNp0htp2/UhwJQmV/8nZ/AYhzxPM= + + + Resources/core/icons/plugin.svg + + hash2 + + 8L9DwkgSZNVuf4/Go3aLVLr5CaQY3PiNNDhRGE6iOOY= + + + Resources/core/icons/plus-circle-dotted.svg + + hash2 + + tk4AzeIMmcqk8MpzHS+mvNPjKKO+hugJJVdXr0ePqx8= + + + Resources/core/icons/plus-circle-fill.svg + + hash2 + + uxWKMRdtrYMOhJq9v+RJqMcgE/FtUfhsObUl3nkuamY= + + + Resources/core/icons/plus-circle.svg + + hash2 + + opWfAJzlBsRHPBXnES8lYgUJEJxZ7TzE1z91jCD+Q58= + + + Resources/core/icons/plus-lg.svg + + hash2 + + lDJdI43Bzk8unmHYovmdWVcpZ6VVUwcu0Of/PMtzZAw= + + + Resources/core/icons/plus-slash-minus.svg + + hash2 + + GmEEzRoE69qZTGZdNddQDglsvMtEkEwbGDzEeOc7zcE= + + + Resources/core/icons/plus-square-dotted.svg + + hash2 + + 8o0Z3yZ5PAfBCmGN7EIQpSqSeJv+b0GXLI8clj+Bk44= + + + Resources/core/icons/plus-square-fill.svg + + hash2 + + XglAMZy9Uk68FcZhIa4OY1hM1aO2L5e+QnW/J1rx5SU= + + + Resources/core/icons/plus-square.svg + + hash2 + + qyd6N9iu/K6cFyPgMc/lTCo1+vJMqujnEhj/xssy/B8= + + + Resources/core/icons/plus.svg + + hash2 + + QM9QlieelCVLbuTgHfoqNmoX5wmOGq0QhT3YL1kB2ao= + + + Resources/core/icons/postage-fill.svg + + hash2 + + htXrraT6luXHvSPXUVODOg9E1ofQuPphsojimpyjd54= + + + Resources/core/icons/postage-heart-fill.svg + + hash2 + + f6HvAfcLPd5POjLRMoskKvJFM0JlY7o3XICZudXGp64= + + + Resources/core/icons/postage-heart.svg + + hash2 + + y/e9Wec0hwotknV2bXAE3FQpq4107buW+dbfdky5cwk= + + + Resources/core/icons/postage.svg + + hash2 + + 96DLTfbEXO0S7VtBkWohvwpf6bBDuDW7zh+yQNhTAc8= + + + Resources/core/icons/postcard-fill.svg + + hash2 + + +bZEFh7F+qBZNNnJey1eLbFboNGqxh6aYUjRlHZjoE0= + + + Resources/core/icons/postcard-heart-fill.svg + + hash2 + + 5ALCNhkoNPms1OQwxh1NmW7NEikZMFyMFB6MWT0Pr3U= + + + Resources/core/icons/postcard-heart.svg + + hash2 + + 1xwxqVhCu7YOzaNLXWBmmsRLBwplhCGIgi1YCEbQSzw= + + + Resources/core/icons/postcard.svg + + hash2 + + zPnDawBzsNPnJkiMsW951QQX/NU8R1CTNwvcg7whdkw= + + + Resources/core/icons/power.svg + + hash2 + + bYt9IKSEyef+6v0Qg5/FokKg1u2mwaqIFd/4wHxdxyU= + + + Resources/core/icons/prescription.svg + + hash2 + + gNQfUXa5kDnYvBtOTZ+F88Cqh7mqqFFdcKx32tglPSQ= + + + Resources/core/icons/prescription2.svg + + hash2 + + QhYJSspY/0D9y5sdmb+aSHpN8ym1jtXP76a57pPWJFM= + + + Resources/core/icons/printer-fill.svg + + hash2 + + yGB+v8w9xAUBIPhcqKMhBv7uJuTYZI1mrcqxNCdAdm4= + + + Resources/core/icons/printer.svg + + hash2 + + R/HdtT4YFI/c7CMS7n9H8cmM+Rg1fGBQ4sCeMuhF+II= + + + Resources/core/icons/projector-fill.svg + + hash2 + + bF34MI9dZvGpLPYSEUPc+ZBHOV/nbqtHqZtOg3xFmH4= + + + Resources/core/icons/projector.svg + + hash2 + + d9ulTR/rzbop5OzI86WolnxG9B89etXblqDhCntvHHY= + + + Resources/core/icons/puzzle-fill.svg + + hash2 + + ibkNTDMg9vqpmqD+CWRqb0K2CM/p2LgEZ589uD3osz8= + + + Resources/core/icons/puzzle.svg + + hash2 + + DXNWcslr8eNxlyxfOrLhWezUCLhf1WKQc6j9uXfjp4w= + + + Resources/core/icons/qr-code-scan.svg + + hash2 + + uNQieIakoFkjjRrUc1ruYJwMhrEdaL0C8y/yoTovITI= + + + Resources/core/icons/qr-code.svg + + hash2 + + kp23zCrOB3c3Da0/7Lo6ReIEeBTcD0y+tNevAJoRoHg= + + + Resources/core/icons/question-circle-fill.svg + + hash2 + + UVt1pUGgHoWOFmBOJoQOxBmClrS2zS0e/D9K5rRLR/0= + + + Resources/core/icons/question-circle.svg + + hash2 + + iNkIqNAW3pGOZm7FOWt4q+V2XhXxwbKLjQ42Zh1mioA= + + + Resources/core/icons/question-diamond-fill.svg + + hash2 + + 2Sj8jwsLFwusP2J05Kqv4rT3PAJqvA/hBhJvgD5Lc+Y= + + + Resources/core/icons/question-diamond.svg + + hash2 + + +TGcmlN/1Nm5au8oap6+PQ7Rv0t84zjei3gi6YGWxI0= + + + Resources/core/icons/question-lg.svg + + hash2 + + fijQldedPzx/IHxuwC/sCpUzf+TVCZhkfXNlbRfCTZk= + + + Resources/core/icons/question-octagon-fill.svg + + hash2 + + BnAp+x26Yyr0i7OJKc88Q+1pMHwpz3uQlD6OjNO8/3s= + + + Resources/core/icons/question-octagon.svg + + hash2 + + WOAkyIPSGqehMH7pOJHJOa3JCRIKIBkfRGLa++YRDw8= + + + Resources/core/icons/question-square-fill.svg + + hash2 + + O8dTtKb2/FY84GpBgaguJUtDZGgGAEbciM5fKmCXTpE= + + + Resources/core/icons/question-square.svg + + hash2 + + wv7IIQLuOglFDXA3eIpHz9MvtpHdrcGEGvo4jG6yAqY= + + + Resources/core/icons/question.svg + + hash2 + + OlundJV6sE7UjWOR/bKs3KJ3EvLogDO64lF9mXscpj4= + + + Resources/core/icons/quora.svg + + hash2 + + /YI0fAPfd7B4SAGHv+InAKagDazBCIGeUn5vROFqr6k= + + + Resources/core/icons/quote.svg + + hash2 + + PnqGAbQZjo76/Y8nE/Vu1tR7Ac9+FJDbGd++9LH8s98= + + + Resources/core/icons/r-circle-fill.svg + + hash2 + + FLmBtqtqvoyMClKf8Sk4NY48oMY4MjQ1PVE5l08CEPM= + + + Resources/core/icons/r-circle.svg + + hash2 + + pH8+fiCvgCKfQBYRPxq9LaVbaq4jFjeSc6SZ34k+C1M= + + + Resources/core/icons/r-square-fill.svg + + hash2 + + fvhMB+afO9vnbiDH7IXDa5DZ3H2HNRoyBwryX4ZzbP8= + + + Resources/core/icons/r-square.svg + + hash2 + + OeuTLfIyM6JgfqvEOfeVPnQBVj1bfgIcUVUTAhoEZL4= + + + Resources/core/icons/radar.svg + + hash2 + + rfGhFUdfxrPnHZeEdpHUJ38L0LXISP8eLk2GhSA/UcQ= + + + Resources/core/icons/radioactive.svg + + hash2 + + tdBzI06zO0xMRPADBqCwHmzzSw6F28d6JUQ5AQ1KIcY= + + + Resources/core/icons/rainbow.svg + + hash2 + + Z/shWIpVEYktQcg39Z96O53ZUQzEaT+/ZmC9IGOkDb8= + + + Resources/core/icons/receipt-cutoff.svg + + hash2 + + Nrt6hekCrx1n0cWDCTma3pelKxgqzaUR4GjvrebVC18= + + + Resources/core/icons/receipt.svg + + hash2 + + 3OIyMfcwf2ceCC5NSiIaKVALGTDi05KnGrBu3r6mlIc= + + + Resources/core/icons/reception-0.svg + + hash2 + + qo3yN5MMxqDcVnARQzhFA7eK0Y8qTD89r5WcpTOVtOo= + + + Resources/core/icons/reception-1.svg + + hash2 + + s0Z5XH4HbUVAdr1suLBdhw6Cc/YVoXHHupp4h7CWIZE= + + + Resources/core/icons/reception-2.svg + + hash2 + + ZkMuPA9WRhyRqYkZL51WpuT3FcLXlrsdeCH6OKf1nN4= + + + Resources/core/icons/reception-3.svg + + hash2 + + hVle2Uellv8NsmMYk6v1RIVaUMjTfTPl+YRRbWNVewY= + + + Resources/core/icons/reception-4.svg + + hash2 + + kPC4jIhpNwPlQLR4oTJTr96A6Dw584go5KNQfuVWVzo= + + + Resources/core/icons/record-btn-fill.svg + + hash2 + + tHU1+PGtt/QHseGU1Lo6BuZ0TXCsqoGfRmJdj6swMVo= + + + Resources/core/icons/record-btn.svg + + hash2 + + OV6dmUjU2bX/eSAWYXOtgyp0pV+d+BDSubnY31S0kLo= + + + Resources/core/icons/record-circle-fill.svg + + hash2 + + 3IRdCwq+uX9WoQx0bEbnMQeSUbFZQsUmnPCGUNLr3ro= + + + Resources/core/icons/record-circle.svg + + hash2 + + 1hUJsB3jtiVNnIx9rsnkBPGgOC6aad3KJn5JqDPfWCU= + + + Resources/core/icons/record-fill.svg + + hash2 + + ApdDo2Ph5UNCtmSC7d5iprTYYR5oUTXczaMubkPBX3U= + + + Resources/core/icons/record.svg + + hash2 + + 620DhDq54olayf0Q3drz8F7CUzmFcMxInLuCvPMn1OQ= + + + Resources/core/icons/record2-fill.svg + + hash2 + + /7w4MWsW7Weri9xnf647J1pQJ9w+kaABqPJld1B3Fug= + + + Resources/core/icons/record2.svg + + hash2 + + l2zT4ethZ7s3agFgrkw4K2m1GC6+XT8xKWHqS50C1Wc= + + + Resources/core/icons/recycle.svg + + hash2 + + +jpT1s71J6e16re/+h9pJvCNTPhwuqcgfcfOJP7PRAI= + + + Resources/core/icons/reddit.svg + + hash2 + + /m0M3rw1H4R443dPNVGIijzf1sI4pW6I6KbgzCcmssw= + + + Resources/core/icons/regex.svg + + hash2 + + fEmb4KfiYLVYKSf7w0ZGZ1INaj7Zhyvwg2YUJGgupn0= + + + Resources/core/icons/repeat-1.svg + + hash2 + + s6FtzJEhpDwEVtefNiQ0DSUXuvKpFVYcQgKVuFltZ1I= + + + Resources/core/icons/repeat.svg + + hash2 + + XRk7KFcZzxPTd8tzLsVtJqQ/GjC9R1uYL7LGmIGIGE4= + + + Resources/core/icons/reply-all-fill.svg + + hash2 + + 3sqQ+N4lZdqkRkvQjZZ1lnZpB2XmqK4jdh9e07jwxRU= + + + Resources/core/icons/reply-all.svg + + hash2 + + bQBNQQNvwJxW9auf9cbDOkLq2NWTFEDCkhEMNll6U3U= + + + Resources/core/icons/reply-fill.svg + + hash2 + + iAW2Ykj89cha+0hcppI3f+jcCU+Ln4EtNU7PtjteTMQ= + + + Resources/core/icons/reply.svg + + hash2 + + XSMuTR9HgCvo6KBBlEzgmRf6+84+tyhbiOIgY8DJ5LI= + + + Resources/core/icons/rewind-btn-fill.svg + + hash2 + + Dz2l213o8A1+oGbJhRruAj9jT77fUUU0xRmu7/+mzr0= + + + Resources/core/icons/rewind-btn.svg + + hash2 + + 5kVHHK9ZPTdhjzZHi8+UOeG8pTkrTmwMpd57k7xiCR8= + + + Resources/core/icons/rewind-circle-fill.svg + + hash2 + + yW+CuABJT8lq5Zdnx1shXM0iLAavwSvj9/C1oECd/wk= + + + Resources/core/icons/rewind-circle.svg + + hash2 + + /M/Wq0VB+yf7AQLc5Dpm+DKey/GMjiaJGGFwqR7e+c0= + + + Resources/core/icons/rewind-fill.svg + + hash2 + + Zs+CqNiUAid32xvrd9zH47n/b19Aw3W/UTWiJLnjeLY= + + + Resources/core/icons/rewind.svg + + hash2 + + TkDGROce+/Ntv7W/boiJr6FX3tHDlL7+I7RbaJKQTHc= + + + Resources/core/icons/robot.svg + + hash2 + + N3WH1wB+mGZMTP9atHDuPwCkXBBnmfvzHXS+6lagj8s= + + + Resources/core/icons/rocket-fill.svg + + hash2 + + ik5NUheONyiRs7tcxr8I1QjbcDcT4pTkzw+E2yH16Go= + + + Resources/core/icons/rocket-takeoff-fill.svg + + hash2 + + qkjXAyLj54SfAxIurIic6Bd4FwwIFOH3ez20df0lMro= + + + Resources/core/icons/rocket-takeoff.svg + + hash2 + + Nqx5YihQ9MqxayXgs1RWUEs6qgZwDNp5SWil988Dh8w= + + + Resources/core/icons/rocket.svg + + hash2 + + Fipc9KicWpwNoGPLyzamk2lo9tk89eXpD/GbNJ3miNk= + + + Resources/core/icons/router-fill.svg + + hash2 + + BEC5AB/DikYFh14+91VEprDYiy2eOMCQ7BAag2mMRXk= + + + Resources/core/icons/router.svg + + hash2 + + xSGunS60kAEqmdjqtd2aNmS6FtmiHT75dHt9p3CviM4= + + + Resources/core/icons/rss-fill.svg + + hash2 + + /5VmUxW6oozrqpY9JS0r05OiVMKUqsg1mDthFYIBWbI= + + + Resources/core/icons/rss.svg + + hash2 + + DeTD5+h0OoV9uhn7ngO3Dv5Oxmwq4+qPeAnFT5yQl44= + + + Resources/core/icons/rulers.svg + + hash2 + + BEPZtW6eQ4IkcDlkmiSdtbUkAL9ZXJXYLv2wpdzvODs= + + + Resources/core/icons/safe-fill.svg + + hash2 + + 9Iyes9CtREV980GDLujp4z4mvj6zv2CDuqjHzeUbdlI= + + + Resources/core/icons/safe.svg + + hash2 + + MUnGu75xsfi6zxirtr0a+jyJHhXvApLKfCofrcujcW0= + + + Resources/core/icons/safe2-fill.svg + + hash2 + + Zd+QbcYVBkbtkW8EJcBKK1I9Ex6ZrfrhvLu0YWAqrKM= + + + Resources/core/icons/safe2.svg + + hash2 + + XJOfeGwcGN2BVO7E+N1nDq6S3TpNwGnSpC1diqoeZUw= + + + Resources/core/icons/save-fill.svg + + hash2 + + rCfkvdafXsNnlXVk4hXjJsjdKGVpr8LIfRNrOvRavEw= + + + Resources/core/icons/save.svg + + hash2 + + B4VP4XJwemlW8EFL8HbWKwzAJHwSRmG9SQAIL3n/+OM= + + + Resources/core/icons/save2-fill.svg + + hash2 + + fZzPBP4NqRNsPPgegMmx4N1yNmMORui67fJfCxu8PkU= + + + Resources/core/icons/save2.svg + + hash2 + + 8pccoqy/UyoILH1jnXn4+Dy16QMIh8tosZvbo06ooOs= + + + Resources/core/icons/scissors.svg + + hash2 + + FNxI17c0iUWZcnas/CC+E8nQwMn4gegcjeHJ/wykJ3Q= + + + Resources/core/icons/scooter.svg + + hash2 + + pkOyXSBpPLzAKidqza0Y0vfBRQU8rJedrc1wm8I/Rr0= + + + Resources/core/icons/screwdriver.svg + + hash2 + + qY63bFsz5juxf+UROYbGGuBgNMfkOSKh2zxSaDjIvUw= + + + Resources/core/icons/sd-card-fill.svg + + hash2 + + 3txC5USV6dpQIk5kRfy9k8YJ0RomXurwR/3INiWsWJA= + + + Resources/core/icons/sd-card.svg + + hash2 + + Kpy03BxnKWXBzvrgEnVA0Unt/k8+F+fxul89HmO7dQs= + + + Resources/core/icons/search-heart-fill.svg + + hash2 + + ovhXtk43i9nWG0T+8pJ87U/4DcuxVz6kC3zD5Rj4NzQ= + + + Resources/core/icons/search-heart.svg + + hash2 + + HA1/QgV1zovzznAU+LZhv2BaK9NX3fgfESmgV/BZPxY= + + + Resources/core/icons/search.svg + + hash2 + + jWwowHDs9IsfEKTtZc894o/JuVnGs5PFR0wIGvQOcnA= + + + Resources/core/icons/segmented-nav.svg + + hash2 + + E6w7Hgwom09Ihx4b6CAk2mbWLz98B5rkZl5cjYBYQR8= + + + Resources/core/icons/send-arrow-down-fill.svg + + hash2 + + e41fZoPh/gllEQJqvbd7nuRnXnBRRpOysqYqzCtQp4E= + + + Resources/core/icons/send-arrow-down.svg + + hash2 + + 9nh04JsPSTEXZ4m/ZGdqWzcCUJ41mpofaS1HbsT/9rU= + + + Resources/core/icons/send-arrow-up-fill.svg + + hash2 + + hTJzchNNl1zcEoHdtLEJ5NQiF8S6eGESesLJ62ajD+0= + + + Resources/core/icons/send-arrow-up.svg + + hash2 + + HW8Y986Uzd4z9cPmznuGwdsABDhME5tKuyMR40cqdMs= + + + Resources/core/icons/send-check-fill.svg + + hash2 + + 4zwfRDEgG6xzoCfVimG9dguLyteq5DPJa3Zz4Swkq4w= + + + Resources/core/icons/send-check.svg + + hash2 + + 7hLb0Ormj/B1ByMvfU7gWGktSqPjTrnjT2ZWJPkV0hs= + + + Resources/core/icons/send-dash-fill.svg + + hash2 + + WRiY6Y8HqS8i3WfX/RjdM9QVqbbbrvprq/a/PO7uVz4= + + + Resources/core/icons/send-dash.svg + + hash2 + + hxHNd2WQacq5jPyIlbZ3wuWn+H0cGSYQuK3sdpPoyYw= + + + Resources/core/icons/send-exclamation-fill.svg + + hash2 + + gZuSO4AXwQ+4riPG72lE4s4iurrnYjOaufhysH7IWV8= + + + Resources/core/icons/send-exclamation.svg + + hash2 + + l6Zvu6+WR4bn392iOqKKj74J0LMLvNqrEc+Z5a1kljk= + + + Resources/core/icons/send-fill.svg + + hash2 + + SzRnTleWs61tF7nGz94RW3OQ5zzCCLhf0quPF/RXbfI= + + + Resources/core/icons/send-plus-fill.svg + + hash2 + + Pj3bXrx59EQWDDvhtLjdIvb5qAhwo/XyEQNe0ZkuLy4= + + + Resources/core/icons/send-plus.svg + + hash2 + + ic2j9D8Ce4KW99T8QfhlYC+P6Zyu9oaq2/NP7d0Twfk= + + + Resources/core/icons/send-slash-fill.svg + + hash2 + + eLNcm68Ey7KGbLopIlcGDvMo9sL3WFZvcJtlnzJKyp8= + + + Resources/core/icons/send-slash.svg + + hash2 + + UneTFpK/Jnr15FN0/70RbWPgsBAP3EqmP76FehO4yFQ= + + + Resources/core/icons/send-x-fill.svg + + hash2 + + w4eHcj/dHonBbLR2UmNfsdS0LOOJYbNQIwr+QV4fzDs= + + + Resources/core/icons/send-x.svg + + hash2 + + cbQgGxIphXOoWbxWuJ940RFJ0wHo47u6b9T2gyNGsAs= + + + Resources/core/icons/send.svg + + hash2 + + KPZGKObM1w3Rk8sfPYXUyJ6j6nIQ9XUUNvISlIgJc+A= + + + Resources/core/icons/server.svg + + hash2 + + 8LjRSgt7v2954HQhW10TgRTlNZ9aBDTxe3CeofsDMOY= + + + Resources/core/icons/shadows.svg + + hash2 + + xPI7SSVshMWQToqpu20UInJFcOSzscuDj4nJyPNWWHk= + + + Resources/core/icons/share-fill.svg + + hash2 + + Xe3t/r+qiAkM+Utoyjx9JCnOgfr599j7uaB1cC1v6yw= + + + Resources/core/icons/share.svg + + hash2 + + cnTkWO6lqKbTb5rX7gIOXfWSqmQZ0G7b3J9k49+6IIU= + + + Resources/core/icons/shield-check.svg + + hash2 + + V9WAqwcEl3MSYGvDdIk9GhqsGYnJIlLYH1JnkSAeU4I= + + + Resources/core/icons/shield-exclamation.svg + + hash2 + + 7jPbOixS/TePSmTfmpgZTLg2GG7A7ezC6Rfh1ppqCDA= + + + Resources/core/icons/shield-fill-check.svg + + hash2 + + EDUjeLPR0qXKgFVQqRfRlZRnN/0EaeTT/J+3DvbqkUg= + + + Resources/core/icons/shield-fill-exclamation.svg + + hash2 + + NVESrfGQUnbz+XaDYbBnJuOJZhT2SVC2DP0lu/Qgg+Q= + + + Resources/core/icons/shield-fill-minus.svg + + hash2 + + ZLHXUZyQ8T9pm15OZF3Sv8XWSfHIDSXxIqJDnZRBGEg= + + + Resources/core/icons/shield-fill-plus.svg + + hash2 + + 3DEZImkceDZNKvf51YFXsNds+f5BiFO667pl/MoWD5I= + + + Resources/core/icons/shield-fill-x.svg + + hash2 + + bjSJaYZ8OnvbyCE36J7TO/QAK+ltWntLEx67SuaXKJw= + + + Resources/core/icons/shield-fill.svg + + hash2 + + snTzXqIXqpmvLEbJivWsbkaSNP/CIrXK6b+a2T7ZocQ= + + + Resources/core/icons/shield-lock-fill.svg + + hash2 + + NQ6C9Q1bgZzk53Ds7vExD/lS4RzrRYRbQevjJ2DRx2s= + + + Resources/core/icons/shield-lock.svg + + hash2 + + uDqEn5+kS+qYmqZKGoaChB+8UeVOxEyKex3sx+0ZdqM= + + + Resources/core/icons/shield-minus.svg + + hash2 + + TNtZcpS9EXGGmk+Rl6I38DqqlQV65rAKRna33II/Qmk= + + + Resources/core/icons/shield-plus.svg + + hash2 + + 3QbGj4KjkCXHxuXze+8dsheOg46WzvV1vi+/apK8FCk= + + + Resources/core/icons/shield-shaded.svg + + hash2 + + lwYDlAIZOcmYkYKhOzFV4RJJMRVgbhkO9adVeQS4Gk0= + + + Resources/core/icons/shield-slash-fill.svg + + hash2 + + TPsKHrm9xFAeNGPm7rQTrrVaN/iW1zlc3T5EAqGdkRc= + + + Resources/core/icons/shield-slash.svg + + hash2 + + tHwLw01sMbQgAXpyZ3QxOXQ8sla9DsrSHOjWGAbnoes= + + + Resources/core/icons/shield-x.svg + + hash2 + + kmIscV3IvLZz9wDTeN4rvsBXUl/BpVH3BCxhnLzkyBE= + + + Resources/core/icons/shield.svg + + hash2 + + H3uzjdgGiAsTdpNu5s+3ZQV9utrxjZAqTo7ItM4iBr4= + + + Resources/core/icons/shift-fill.svg + + hash2 + + 0H7NPJBYcq7MIoN8N/RAz2qqIREkNctJ/KvAOeGRQHc= + + + Resources/core/icons/shift.svg + + hash2 + + iPXlmJNLCdltAh+RcY4hw+S7GhwcCmVCK9m6Wg7k6S8= + + + Resources/core/icons/shop-window.svg + + hash2 + + y1v/RCO/oLJ+SzhJphvlurOWlDnohyKBZpxCZzbGl40= + + + Resources/core/icons/shop.svg + + hash2 + + Ov/BuElvsbuocnOxO4sl11BqMAdnUv9D3LC2ISX5kXQ= + + + Resources/core/icons/shuffle.svg + + hash2 + + Gpe2yJbh0YUNfQ8vF3vFhxSPUfWHRbqbkSNIKKCmIhQ= + + + Resources/core/icons/sign-dead-end-fill.svg + + hash2 + + 63lfgyb+nS+SRfV3IV22BFPQNfGo9zp9FRcVx3Fw2tc= + + + Resources/core/icons/sign-dead-end.svg + + hash2 + + /KTiCXhCNBSqA0SNYFQIjblAdUTXpobdCAySflWTWYs= + + + Resources/core/icons/sign-do-not-enter-fill.svg + + hash2 + + 1OmG2pDlfMZR/+RcrdJH1h1HErB4C6kIy9j9Ud7x404= + + + Resources/core/icons/sign-do-not-enter.svg + + hash2 + + MMF5ijI7p2lme9K/Smi0CTICD9nOezZiNpdjGSWiL0c= + + + Resources/core/icons/sign-intersection-fill.svg + + hash2 + + aY98wGEF1nbdsb7UBewrQKkumdxwqMIlB0CKUJQyzMM= + + + Resources/core/icons/sign-intersection-side-fill.svg + + hash2 + + hKWbbe5C161fe9vskoVqME3MNN+20671T1hGYQ5I6c8= + + + Resources/core/icons/sign-intersection-side.svg + + hash2 + + m4iQk0hKQxMLEeeUO70kVNrCvJ/BPmzxzVMjBxQ2vFg= + + + Resources/core/icons/sign-intersection-t-fill.svg + + hash2 + + FIHlfiDTTrd2uBMQ+axjB/gw8RMbtnS0j3HxvPI5TS0= + + + Resources/core/icons/sign-intersection-t.svg + + hash2 + + 3mX8nBvHpQbzl+zYj/xejCa3Upex+vrMzrzYA5rH4uY= + + + Resources/core/icons/sign-intersection-y-fill.svg + + hash2 + + 8/w1jX2nbX5gIAdMUMK7FQzueCE4CNiCLsaI13yrZeQ= + + + Resources/core/icons/sign-intersection-y.svg + + hash2 + + UROhb99bozOKo7a3lVaj4Opr2xpeKheQvpvnOGaiGRw= + + + Resources/core/icons/sign-intersection.svg + + hash2 + + maANQg2CR3/V2Uj0dXQTB4MPDbrGgBKikonqLkTzxxs= + + + Resources/core/icons/sign-merge-left-fill.svg + + hash2 + + g9++ALTKpPZJJFZJ+fWLNDmAqvw7vnIVB1yj0vKmg+Y= + + + Resources/core/icons/sign-merge-left.svg + + hash2 + + 5DMJ7hYg5ywZWSduoEQ35bTcn8/i1rAcyVv4+zbUwhE= + + + Resources/core/icons/sign-merge-right-fill.svg + + hash2 + + hLi31I4ngyhN2cVwZy5tZp1ZX5q2smRLbBXvjrQTpsU= + + + Resources/core/icons/sign-merge-right.svg + + hash2 + + RPcE7XcLnilgitpRi9V+wkb7YVLJIYF3tgRRHbPC7L0= + + + Resources/core/icons/sign-no-left-turn-fill.svg + + hash2 + + SCiP7lO78r2AqupdftcFuQUuT6T8vL3gY4jcxnviUpo= + + + Resources/core/icons/sign-no-left-turn.svg + + hash2 + + z+i9XMpeuE6fizmx4W48hG5uY4Nx0PFtQ8Cten/IP8Y= + + + Resources/core/icons/sign-no-parking-fill.svg + + hash2 + + hhXlwWCBvNnUn8scHbGsdjx3oE+zeyPktDM6XqDDxoU= + + + Resources/core/icons/sign-no-parking.svg + + hash2 + + 6gIVuee+DBwYiP2ppOhFt0j2mCQKYiEbehvGDl/LEqY= + + + Resources/core/icons/sign-no-right-turn-fill.svg + + hash2 + + RB7g3kYnuytsXBxJ/qyDjV5lfxw1/mB4Q7aaGBvJIZs= + + + Resources/core/icons/sign-no-right-turn.svg + + hash2 + + lAxgNMTuIFk0SOIe8u4qJa5sqvv6mfMm6JvnrQUF9F4= + + + Resources/core/icons/sign-railroad-fill.svg + + hash2 + + U+GwzUs4Xq0JXRhT7Bnzzgiiyxy5n5I/hGzhanWKa3E= + + + Resources/core/icons/sign-railroad.svg + + hash2 + + EkEgzpM8Ee/UpmlUMWANMVSJJ4O6LgnchHdvH3D1JYU= + + + Resources/core/icons/sign-stop-fill.svg + + hash2 + + C20XHTL02fT7bWK0uHPYrnaeuDrkNW6EdszTtmves2I= + + + Resources/core/icons/sign-stop-lights-fill.svg + + hash2 + + CapwdU75PfTvFh012Czqul6mdkHH1WGHSlzn0v4ek/k= + + + Resources/core/icons/sign-stop-lights.svg + + hash2 + + 04SBTfmMpy2ozA8BtwpffAWQKuKRPkEaipNdt47cxSY= + + + Resources/core/icons/sign-stop.svg + + hash2 + + bQdg60KNX/CjeYQ4PzgQ9OkjHK1i5xu7y3bylgGrVCo= + + + Resources/core/icons/sign-turn-left-fill.svg + + hash2 + + VPAFEyGsEvP6sP6064SeqySkJ1+xXJ+9SyUnWLedTz0= + + + Resources/core/icons/sign-turn-left.svg + + hash2 + + dvFILa0QL7kWIMwUrwFkMfvgHLw5Tu/Ozaljscnx4X0= + + + Resources/core/icons/sign-turn-right-fill.svg + + hash2 + + Fp+gxMAuZ/2gUfFIThiZQ3Tr/MwhSwcMZRW4JiMEVaw= + + + Resources/core/icons/sign-turn-right.svg + + hash2 + + GagKQUgII8yrNzBq9rVsDA+y/GpOwiUPDmxTrJQTFWo= + + + Resources/core/icons/sign-turn-slight-left-fill.svg + + hash2 + + 38zAkODrMNnWDTXQpvjXKBAFttgckX/DHTA+5ee0wBE= + + + Resources/core/icons/sign-turn-slight-left.svg + + hash2 + + jN/ZgG7ICBdwHiabKEX6WLitxLrCTJ+pNccux+IQWq0= + + + Resources/core/icons/sign-turn-slight-right-fill.svg + + hash2 + + wyGdoPL9MIsg3h9kHezIhnEzdmGvEPJH/AKpQt7chOk= + + + Resources/core/icons/sign-turn-slight-right.svg + + hash2 + + +z7F8JC1heCYQDGopI2F5dw6exronhLrS8VQYqc0Cig= + + + Resources/core/icons/sign-yield-fill.svg + + hash2 + + wUfbMnhdkZAtH5pWOeTRulf1+bHOjHnDbp/8EO5Rz24= + + + Resources/core/icons/sign-yield.svg + + hash2 + + 2gFWln+le40w18WX6TJlo8lsyIZU2gkW4fIPEmwVbnA= + + + Resources/core/icons/signal.svg + + hash2 + + ZouNG8gVUhCXGH1Eh18tAOIOetfAezIpLZFW8FLYHBI= + + + Resources/core/icons/signpost-2-fill.svg + + hash2 + + W1nzg9h40m/u1mVAJ5A3oevndWnHUixE9H2j6naalTE= + + + Resources/core/icons/signpost-2.svg + + hash2 + + 2gyPleNWgr+fwq/aVH/KAiZ5HBlFae8qQUdhhbJ/KEk= + + + Resources/core/icons/signpost-fill.svg + + hash2 + + vlB6ZkwGSxY1RiWeZ2PgWeu8b+5t2cxwaWXLMlroki4= + + + Resources/core/icons/signpost-split-fill.svg + + hash2 + + +pUUAA07gyqID2h5/2TbUg3JeZOW97RTg9RiyGke/kg= + + + Resources/core/icons/signpost-split.svg + + hash2 + + hy23exHcUH/0AUZ/etMlRxXiam1v3wmI+vOoYmVvP0c= + + + Resources/core/icons/signpost.svg + + hash2 + + hryfDIMAX5y3roSMal5raEZr9JSnihIJ6EUJMmjX4W0= + + + Resources/core/icons/sim-fill.svg + + hash2 + + ey/pGxXxMDJRKr13StCtWyH1vW6EMWSgbBFj+bjInc4= + + + Resources/core/icons/sim-slash-fill.svg + + hash2 + + O4uQN6/Jm2a6Yquahb8M2ik4mt8AM+Q3j8qX4zaWpKY= + + + Resources/core/icons/sim-slash.svg + + hash2 + + SWQ0XjW9tTHlnOippdVal2KL4rkdyluSc3V4Z4EROBI= + + + Resources/core/icons/sim.svg + + hash2 + + c8pinxyeRT0DvzOtPdseeAckFJxyXK0U5EtqtWS3+3g= + + + Resources/core/icons/sina-weibo.svg + + hash2 + + iud1DLQLpv0UVNYzni3h0oZsCAh0Kaz/xogpTRDphJg= + + + Resources/core/icons/skip-backward-btn-fill.svg + + hash2 + + HSveeKt3z9TDzyVf2pAfPqFfI4V7EMvxTonxV27IXbg= + + + Resources/core/icons/skip-backward-btn.svg + + hash2 + + LE7K+f4NIHxTQ7JoH548W38DpD4USk2KHXGVqDIL+GU= + + + Resources/core/icons/skip-backward-circle-fill.svg + + hash2 + + vvnQwXx62KgguwnQH/37/vvNl6/7KT7LP9T+HOftKVM= + + + Resources/core/icons/skip-backward-circle.svg + + hash2 + + uqGFq6t5LIZmqrqZKHSelFoKcG/CIBUQoPGSV3RQWMo= + + + Resources/core/icons/skip-backward-fill.svg + + hash2 + + Viq0hg3jo32v5kJRla7h3egSDsur3eQUYzYcqH5mrGQ= + + + Resources/core/icons/skip-backward.svg + + hash2 + + D4FqEGXZG8qPEEo3VQVWAwCiJJaP97/1h7P2VMo/33c= + + + Resources/core/icons/skip-end-btn-fill.svg + + hash2 + + gcLwymc/FY8t2cPJOfdciBD1ebyRPVnm9zUfcCYd3GI= + + + Resources/core/icons/skip-end-btn.svg + + hash2 + + yV7OwXF26lQY9JVLKB6UlqrvNkkdY9E0pJuCYpn4TkM= + + + Resources/core/icons/skip-end-circle-fill.svg + + hash2 + + B598aY6PbCj4IXh5P97G4/xAn6MiFRJObp6XaKHahHQ= + + + Resources/core/icons/skip-end-circle.svg + + hash2 + + ydw2ONlQv95SNLrgyAeFK7JeWISCeaBBrtbsBfbtWtw= + + + Resources/core/icons/skip-end-fill.svg + + hash2 + + nUR7Tz7K0fv9GCGmU7XKb6a8jrlj1FAfeuCOTh3D2bc= + + + Resources/core/icons/skip-end.svg + + hash2 + + NoJkrBMgLh7V7uXBCl7xvYHSkFSS42Gk2d9RojkXydY= + + + Resources/core/icons/skip-forward-btn-fill.svg + + hash2 + + bEopG+J/JhFX8aCGmh+3LFalIlvduuuKuBhudp2ihrQ= + + + Resources/core/icons/skip-forward-btn.svg + + hash2 + + 7E0NNtPK/dre7uy1Ka+vZgpAFGbh/0RCUYKLpJqdVeA= + + + Resources/core/icons/skip-forward-circle-fill.svg + + hash2 + + FxERyq/jCylRvROuQeJHH3Nb28WjUG/fP1YL+AY1+44= + + + Resources/core/icons/skip-forward-circle.svg + + hash2 + + qPWAdMknlUmmpPzuVgGcXP3+qA9P1ZK1vaq2xwzH8FE= + + + Resources/core/icons/skip-forward-fill.svg + + hash2 + + Bmm0if40UcS3MdDBFPZL0cYjrxjFO9spx2J7GY5xToE= + + + Resources/core/icons/skip-forward.svg + + hash2 + + dtCJ0jy0aA8+lXHWpsoy7voPd0KLXBYkPeilvDsM5Dc= + + + Resources/core/icons/skip-start-btn-fill.svg + + hash2 + + RggYcA88yylZcR1/eLk0YJ0XDePYYt9uhwMqJl071co= + + + Resources/core/icons/skip-start-btn.svg + + hash2 + + St6pymndDG7mjusvQGsrVjSVK3LaUN9RoNZ97Af2ba8= + + + Resources/core/icons/skip-start-circle-fill.svg + + hash2 + + 1u6Wsv/TZsgV15PfpckCy9B4kHJL7DfKxH5NUSvZZgA= + + + Resources/core/icons/skip-start-circle.svg + + hash2 + + 7YXyyKNf0U4A+iZNYzb/yHlL/oLWGK5wH2lKGPgC7JM= + + + Resources/core/icons/skip-start-fill.svg + + hash2 + + EN0waKj9x6f4OqKaaFjgWJPRlmoTjXSy6xEM/k/h+IE= + + + Resources/core/icons/skip-start.svg + + hash2 + + bLOqailtCQbkc14dhIx4cZJl2Q6IRs6KhTvTtAkavv8= + + + Resources/core/icons/skype.svg + + hash2 + + b382VZxnuHnKrE1uZ9Nns5XWZyL1Nwcjh+9m81vjBNc= + + + Resources/core/icons/slack.svg + + hash2 + + GYZ8DRCfrmmppEKFwjLDwmAc8/PXK0AbDsugP/1UCgI= + + + Resources/core/icons/slash-circle-fill.svg + + hash2 + + hHZY+2TuOdw1rax0EXoQkchg1R6U4JiFP7TyQmhCrcE= + + + Resources/core/icons/slash-circle.svg + + hash2 + + wWnSayjrGotKxhQHOp0h4pc8WOc4QrJS7+TBbhkNSVo= + + + Resources/core/icons/slash-lg.svg + + hash2 + + VjCub5JJ6o8iSad+z4N7Fgpe+snAAQt7z0JXCgD9JY0= + + + Resources/core/icons/slash-square-fill.svg + + hash2 + + 5k5XnWCNpAgUAnhsxjJnYHV5Za13P88kRoNiE5YWbyM= + + + Resources/core/icons/slash-square.svg + + hash2 + + dJi4rVigDw7Mzs8F5K0+lPoyMsyKJYm1k/o++/oP0Oc= + + + Resources/core/icons/slash.svg + + hash2 + + FpDp3FQxVEDtXX976kt6snGDgBW96iHKmdkGEuLE3Ss= + + + Resources/core/icons/sliders.svg + + hash2 + + XaUiBHQaV8K+yLSGPf2rwzWkwcBAGDkq/yZ7kKedU6I= + + + Resources/core/icons/sliders2-vertical.svg + + hash2 + + LDQSpwqtxVNwZcwhcJWXJqhjIbJ1ovK53taiHZsMuiU= + + + Resources/core/icons/sliders2.svg + + hash2 + + 4DriwWvRGqGuyajc0GRzkeVcvL1V8f2y4L+w5Pddtz8= + + + Resources/core/icons/smartwatch.svg + + hash2 + + CwwI4jf3fN5g0vAYdtUrD5QgrLT7Ly/tBgqPcjRPKHs= + + + Resources/core/icons/snapchat.svg + + hash2 + + CPyz0QWBvxOY9DVq1uHVFNWtBeWEq8fEkg2J3ZeYXZY= + + + Resources/core/icons/snow.svg + + hash2 + + 7JRxL/9aw0W7bNeBn6UPPQvaNMcazpTw6hfSGugm/qk= + + + Resources/core/icons/snow2.svg + + hash2 + + 8A++SrFl8WPBjj/kLENL5HO9uSo30QtHhHmN8QsPB7w= + + + Resources/core/icons/snow3.svg + + hash2 + + 4+yxQ7ymUzu45aLT/HLW4d+WFHyfIXWxYgsqmLzzn38= + + + Resources/core/icons/sort-alpha-down-alt.svg + + hash2 + + cRAxvrU9cROCfKYCngL557jFsOzAuR9b+7JZjL4OhpI= + + + Resources/core/icons/sort-alpha-down.svg + + hash2 + + gwtSej5eKyY4B/uiM8AXaSIKsyOPeGp2EEgbnNYhB2g= + + + Resources/core/icons/sort-alpha-up-alt.svg + + hash2 + + C8ubOFmWZip4zFPaMAdr45bUJzTuS+jxdstJ+ZYjBbc= + + + Resources/core/icons/sort-alpha-up.svg + + hash2 + + AnsmJjumrwzLg9fnE69UFvTEnD/4GGlQqfrvX7TOZc0= + + + Resources/core/icons/sort-down-alt.svg + + hash2 + + 6cEr0WTcTQHb+PkirgIkuUpmWYL1TlXDecKlvAsfIfI= + + + Resources/core/icons/sort-down.svg + + hash2 + + d40cc2eYLDd+lAnaehiqhjfSoMUBgDxnCCyDCxNyYoE= + + + Resources/core/icons/sort-numeric-down-alt.svg + + hash2 + + rWMhvApsJQHhhlQjA62vIDyWnQswF/aTC7l0xcbhlzo= + + + Resources/core/icons/sort-numeric-down.svg + + hash2 + + lF9WDWm4hS73wN49NEAoJeaNmkhzStvXfG2oPFval0o= + + + Resources/core/icons/sort-numeric-up-alt.svg + + hash2 + + LUlaHydNNiKx1Fbs7RRP9Fj4XmbO34a+rayH4JOO1nY= + + + Resources/core/icons/sort-numeric-up.svg + + hash2 + + MxhWyE6Svzv6EnzE7V3EkidNJ1YjPF27WBohl0Td+1k= + + + Resources/core/icons/sort-up-alt.svg + + hash2 + + K/Dmz9esY4czCkA5GE7Pz9ktaL/8Gsax6H0oZ3y0+4g= + + + Resources/core/icons/sort-up.svg + + hash2 + + ca+lgJpdL5wk/OYgyyPbn/U4ieSY2tQaoOJZvkPW0H0= + + + Resources/core/icons/soundwave.svg + + hash2 + + pL0wO2zot80LyUZ13TsR0cOLp3WN1Jk3t2iIdLylAQQ= + + + Resources/core/icons/sourceforge.svg + + hash2 + + CnH6rbHNFxQhhlf6Rd6CkZGmI4fKMhXC3sH2vYFL7gk= + + + Resources/core/icons/speaker-fill.svg + + hash2 + + Mp6tm4MNJaizzqcRWWepKXnbL5G8mF+hnuGy1LXQRlg= + + + Resources/core/icons/speaker.svg + + hash2 + + 8pVnTgFObl5+Kka+j8DVmCH90yC+CP93+jzjj7dHdr0= + + + Resources/core/icons/speedometer.svg + + hash2 + + YdJR/cFG36Z0vRBaykE2lbk5Sy/55VMbFUeC07Ma7vU= + + + Resources/core/icons/speedometer2.svg + + hash2 + + paqimoUsWaHocJ889kCcUx3qmECK0Vw+bHxZR+Tp/pk= + + + Resources/core/icons/spellcheck.svg + + hash2 + + DNGLU/Y0N0BFUSboRFL2YVroKK91Fu/X5P0p/ApEZL8= + + + Resources/core/icons/spinner.svg + + hash2 + + NhQXgMYaJk9N8KLfH4cm+t2B22OvDesla1DMsBcjtAU= + + + Resources/core/icons/spotify.svg + + hash2 + + bm6/RPNAaLnGPBioSOmKxIgDlJA4I11rP5WwRDSJs4w= + + + Resources/core/icons/square-fill.svg + + hash2 + + 0WHtLcSFlx90hYjOCVwOGbn+wUtyFMi6rDO5ydTcuUU= + + + Resources/core/icons/square-half.svg + + hash2 + + SQGdzYN3GNe9ZYeHleiQHcOIgpCFtPl/NHY0JXNvIVI= + + + Resources/core/icons/square.svg + + hash2 + + 4qrwj5CWUP232zazKlxP1efCIrVOiF9eyCGvdraBddA= + + + Resources/core/icons/stack-overflow.svg + + hash2 + + 7nWa0t6LToKFdO7umzUspVXKcXWre6m8GqOse5L8WOk= + + + Resources/core/icons/stack.svg + + hash2 + + HMrbC803NrSatjLkx97aQutDQAptyWTWIH9p+BEnsp0= + + + Resources/core/icons/star-fill.svg + + hash2 + + 7dW9krSW9Z1z9xBin0m4J7+s+mK8M6zwmAb2mrP7UdM= + + + Resources/core/icons/star-half.svg + + hash2 + + QOqzEu/wQgUls1Z5T+bQ462yj3rNLqpA0L0qcnsFCaI= + + + Resources/core/icons/star.svg + + hash2 + + XXkd3ACH1MmIHhE0tss0/c3GsJcb7AGYraKjvI/FFRI= + + + Resources/core/icons/stars.svg + + hash2 + + DYiy2E9EcZ3dVNba53BYxBhh7OSqpckoVpOZweAMsCk= + + + Resources/core/icons/steam.svg + + hash2 + + 7Wndc3hyJf4W8RcW3TsTaloCNIY71auXlgKaw/YNVJA= + + + Resources/core/icons/stickies-fill.svg + + hash2 + + P4kUlzeCE6E1Ac6xFVk15QRakbC+ivZAgLX4tmufVUs= + + + Resources/core/icons/stickies.svg + + hash2 + + rEhf9gwo3gcqc+pmpHYPwQpoz9ThcnMkzFIScnHmLNQ= + + + Resources/core/icons/sticky-fill.svg + + hash2 + + +r/u1C1c8RmiDmT6dxX+TbfD7Tb297uDKMKOldgwhyk= + + + Resources/core/icons/sticky.svg + + hash2 + + c5vxaRV5QBzWxUaZ8VzxzMCuzMpnNSTWvFujXdbtUhU= + + + Resources/core/icons/stop-btn-fill.svg + + hash2 + + Y3ppsb/X3iV15sJ6atJJm2KH5PPJHze1jAH/pYCImTQ= + + + Resources/core/icons/stop-btn.svg + + hash2 + + 8xu0WXV6I0xz1NMPZ3dQZpuR2YAgYSpTr7M2MsYW66U= + + + Resources/core/icons/stop-circle-fill.svg + + hash2 + + vNAS+bERObe2i50yeEeLMeNxANevxnxTCgOUHz6DzlQ= + + + Resources/core/icons/stop-circle.svg + + hash2 + + j5zbcGoK+JgNEw59EXfBoKDhs+2YASfJjhzapxY0XgA= + + + Resources/core/icons/stop-fill.svg + + hash2 + + AeGVBa9wRpdVaWOJ0qV8AhcBXEbY6tVGonqlqhtGrYI= + + + Resources/core/icons/stop.svg + + hash2 + + XvAyDHlHRUZP64o4aRs6Nz5dtiWXOI//1VGvEwdOlBY= + + + Resources/core/icons/stoplights-fill.svg + + hash2 + + Y+zyBQEUnZUnMjMhZviyAdgf4MUvh0/l+s6ai07T2hw= + + + Resources/core/icons/stoplights.svg + + hash2 + + clsqtRbvwG/jqXPGvf31a8AgIWdxZSZA11IdFW/Tjpw= + + + Resources/core/icons/stopwatch-fill.svg + + hash2 + + BzJw8xxXQhH8Eq2bAkDMDFuf65Opw4t3ysrQs3OtkyU= + + + Resources/core/icons/stopwatch.svg + + hash2 + + TwnfAWn54Fm9VGfFKcr3HIokIHaziERB84Nu3D/Vh0c= + + + Resources/core/icons/strava.svg + + hash2 + + bEnOdq9X4/MhI4CCfy5jAMk/6g8yrD7QCDxNJgOGyKY= + + + Resources/core/icons/stripe.svg + + hash2 + + njmfa2kYQko7RZOOOmlJXHUPMT75wsyF/a1sMTGklSk= + + + Resources/core/icons/subscript.svg + + hash2 + + OkrAQRzxY9FyNZDo7aasICVuefpX75v7h7XYPVPOu/w= + + + Resources/core/icons/substack.svg + + hash2 + + 2F/JKI38rFbRHxXAIJ6EvBHmVkYOQMAvCulU5Nb3EZQ= + + + Resources/core/icons/subtract.svg + + hash2 + + jwXEleW0lK7vwfqqhffb6o6KioasLRdaLkR5XSNy5zI= + + + Resources/core/icons/success.svg + + hash2 + + 6x6/ryeqU9YNv1omBK5nOINYH+mrsOfW8Qz7hLs+fzg= + + + Resources/core/icons/suit-club-fill.svg + + hash2 + + mOrJAO/8PjFaU1xRvzuP0OcApT0tADbFOeanTUrjMvY= + + + Resources/core/icons/suit-club.svg + + hash2 + + pWkWPBO9K2iOYffTZ1ONd56MIFbwzaF/MnKR95YMZnU= + + + Resources/core/icons/suit-diamond-fill.svg + + hash2 + + peR/9Paq+ikul+wVc1YKnKMiOsMGXa4KGS68DdGZNRo= + + + Resources/core/icons/suit-diamond.svg + + hash2 + + HU+XjE3P2VGO4waqo+aoJO1OoveMoypPqH0o9RcnQqg= + + + Resources/core/icons/suit-heart-fill.svg + + hash2 + + cHA4u/0MPeIAe4QyhFw1WWLyi3byutRy/0ikaJ42MyY= + + + Resources/core/icons/suit-heart.svg + + hash2 + + DmE4MrHFe/4dksoSlqX952+w9XdeIz0KzEHRtWcBbec= + + + Resources/core/icons/suit-spade-fill.svg + + hash2 + + tmWWVj2n7Q3B37ffSxfB2swcCIB9+GARIsuAnkoqXRI= + + + Resources/core/icons/suit-spade.svg + + hash2 + + vTuun5IUxuleKkL0zs0j2ziF3baAisK2+lwG8clBADU= + + + Resources/core/icons/suitcase-fill.svg + + hash2 + + hoq5RaSwxVi4fwQOSMbli4Lmxd1RNWn1BK/dp+6B94Q= + + + Resources/core/icons/suitcase-lg-fill.svg + + hash2 + + 82VNjxRMw+qzyBDhOadEbT+DSprW1WZ3pXlssR1wGWU= + + + Resources/core/icons/suitcase-lg.svg + + hash2 + + UnatnHnOw0Yoz4fonVH2xfBlqQm51Ug2Io00SwYvc9A= + + + Resources/core/icons/suitcase.svg + + hash2 + + aigrj6hTKHLGHrS4PXk734fXeZVFemW+JZ4xQ8PRStQ= + + + Resources/core/icons/suitcase2-fill.svg + + hash2 + + eD2htzpsq642CsqDIZjkVpgEnMPy/am11ovk9wTGwEI= + + + Resources/core/icons/suitcase2.svg + + hash2 + + 4wvQLpj5dOjClRsvJA9Glp2RpyEbeSg7o+ycMMtXyLU= + + + Resources/core/icons/sun-fill.svg + + hash2 + + afyzDYADqVXfGJD9AOOQoT+ZZHDEP2lHIOgjoEiRCyg= + + + Resources/core/icons/sun.svg + + hash2 + + +Km9dBfiihVvhhF1yxYwcn7sDAM/RKTxwvUMxQ12Pu4= + + + Resources/core/icons/sunglasses.svg + + hash2 + + ITCTnuklcxHLr31/dH4OaPvM76ap1dttUil3Rf0KZoI= + + + Resources/core/icons/sunrise-fill.svg + + hash2 + + jXaXjSSGPMjgEqDH2M8LlyssYqqALsxONcnuPIROBzA= + + + Resources/core/icons/sunrise.svg + + hash2 + + 6HSLD+rOX7NgEpC/o14e3HF53YT3nEh0A5u4q+xwceU= + + + Resources/core/icons/sunset-fill.svg + + hash2 + + BJ0H6P0zpnh7qGQm7yod7M2Z3ibUFvyKLUzQ/JY4Alw= + + + Resources/core/icons/sunset.svg + + hash2 + + /qCpshFGyw0shN4ZV6G01AFDv6SJ+ioqNFoXQxcF2bA= + + + Resources/core/icons/superscript.svg + + hash2 + + zKFRpLxUdItj7meyTEyr7zvhE7Ddmo0BXj6tBTcDqh8= + + + Resources/core/icons/symmetry-horizontal.svg + + hash2 + + bwlFocaZjMMqE9RUIWPpV6kb531ujS+SXd/MnPzNdcg= + + + Resources/core/icons/symmetry-vertical.svg + + hash2 + + OdrG2Rb3VT/2sQJ1WooX16ZxguCiNQ6Y1y5KE2GwKV0= + + + Resources/core/icons/table.svg + + hash2 + + bBI7U2PXfquUdbL8Nc4rnC/dQumBm75GCRrm/cUe+18= + + + Resources/core/icons/tablet-fill.svg + + hash2 + + q/DnUyrFsCkU88cbrKXnWQF6V9j+2eCnzk8XAI7T5oo= + + + Resources/core/icons/tablet-landscape-fill.svg + + hash2 + + 2gfTF2LkaYAuQlsc2AzO43DDygU67YAz67BpdhP9XeI= + + + Resources/core/icons/tablet-landscape.svg + + hash2 + + iMI/GRuSzfbJfh2rO/Fctn+U3Rx4Hj1AVArpsJ2WdAQ= + + + Resources/core/icons/tablet.svg + + hash2 + + XX6D1/e+JKRjGdggJp04Gl4sMyge4cF4A0Stbn3eMqg= + + + Resources/core/icons/tag-fill.svg + + hash2 + + SWaQ1tk8Zo7mMdZPv/f2Z0yscyn6JxV8i8CBj+cdG+Q= + + + Resources/core/icons/tag.svg + + hash2 + + qFA3Bjf38dsDg/D+FIILBkITDREbHBHkfwRjQ4cFjVg= + + + Resources/core/icons/tags-fill.svg + + hash2 + + kgQVJiqZm7F7V1usrbTJkfvibXX1RAxnqVU3JxdF0iY= + + + Resources/core/icons/tags.svg + + hash2 + + iFMRtr8MY8xfN3+yjvHw0pKfFI/gKFRNZx3p3/iQ4ds= + + + Resources/core/icons/taxi-front-fill.svg + + hash2 + + 9Gp2sVZSsHSkh1UNoqpZP78ImHLBkxGpgE0PE3j5lhw= + + + Resources/core/icons/taxi-front.svg + + hash2 + + D+zQOBONJOpt+qTfsbXSq2H1cWd5sBitw1x2ofjT0KM= + + + Resources/core/icons/telegram.svg + + hash2 + + jvToEHRyTRvIi9Y42rKgTWCoLzPgWc3YqLv7qKRkSYA= + + + Resources/core/icons/telephone-fill.svg + + hash2 + + fTtTSSQbsESQ9E3ZC8fwExcanYQpVcKQXgdHq6nknxg= + + + Resources/core/icons/telephone-forward-fill.svg + + hash2 + + iFiY7nkbnSw5LnRACI3m4IID1eCmI59hoi0oIygewnE= + + + Resources/core/icons/telephone-forward.svg + + hash2 + + l7mDs6IRZPUghn2BGDcXVGZmmaquAro6n7KGlEHzpwc= + + + Resources/core/icons/telephone-inbound-fill.svg + + hash2 + + ZDaBpNKaOIjqP+TOYoZ6v1ouRdNstNwblaHGpPTi4hU= + + + Resources/core/icons/telephone-inbound.svg + + hash2 + + H9kkBdD7XOYLsP5HyBtFh2Pp9cTtbEeenMiwG31z0PM= + + + Resources/core/icons/telephone-minus-fill.svg + + hash2 + + 90ZKvDz3B4hH69P1ym6BqV7oFXU6styM6UA9slW4EcY= + + + Resources/core/icons/telephone-minus.svg + + hash2 + + x1Tj6xqxIghmRcSJwfF9F1RkWPByZ9yB4GAY1wnh08Q= + + + Resources/core/icons/telephone-outbound-fill.svg + + hash2 + + hQiPS6KCTn+aRlvLKxU124eYI6gyREOP/tBVamNVziQ= + + + Resources/core/icons/telephone-outbound.svg + + hash2 + + 9YKSa4BTSxSURBSFjiDw/Mi6Na91HCuQ1I51quWD6LI= + + + Resources/core/icons/telephone-plus-fill.svg + + hash2 + + hid8lSBQSJBRA17PK2qw6Qz3nSbzNvIULHhWymB7+ls= + + + Resources/core/icons/telephone-plus.svg + + hash2 + + n8CgdP5ilQ9AGO5/XbmccqMmXzksk8NarDs19aPO51g= + + + Resources/core/icons/telephone-x-fill.svg + + hash2 + + bcNVBAtK1dtjQeC9qecB/hpuyF95KPfS0gommYTmU8M= + + + Resources/core/icons/telephone-x.svg + + hash2 + + P1gz1/hz95XFIQ7ZCcBXTD1DwtPy1v1dGHwqln+oMd8= + + + Resources/core/icons/telephone.svg + + hash2 + + tsChVJUksCArBJdKmI8ldrdy2MUC8Gl/WAFko07Xl7w= + + + Resources/core/icons/tencent-qq.svg + + hash2 + + 5g/XPG/Z//vsYCkBtO4JzvWy4khjWBX+62Aihoio7Ns= + + + Resources/core/icons/terminal-dash.svg + + hash2 + + 642wjWkuqhjAr1TbNt2urCoM6CogI7YPljyRYprYkjM= + + + Resources/core/icons/terminal-fill.svg + + hash2 + + WBqWciJIpzUJUapnF68mZwjNd7lPCsCCUnWpTFZSLd0= + + + Resources/core/icons/terminal-plus.svg + + hash2 + + GDE9lyuHR86wCTbWQ8l4gQw9q8diA3Vjck3akr/mDL8= + + + Resources/core/icons/terminal-split.svg + + hash2 + + nKB24zSdmx0dTtk7PhUE5y78XN0+yMChEITJQYGq+hk= + + + Resources/core/icons/terminal-x.svg + + hash2 + + OW+NUZy/3ZCqiVBMXe43o0gb6FWs3XIlqoYT7nEQbj4= + + + Resources/core/icons/terminal.svg + + hash2 + + 1d+wePuQaMfrsj7aAh+3jVo8A1CFcGRXuGEdQOG1r4M= + + + Resources/core/icons/text-center.svg + + hash2 + + Jglon9skrAyK/fUlPBQuVzu/ZqC8WHlOBppN6szfXXw= + + + Resources/core/icons/text-indent-left.svg + + hash2 + + tTnyumbJlQJA1+OGO/9G8feAUDLBkN81g8rX9ggH5So= + + + Resources/core/icons/text-indent-right.svg + + hash2 + + X7DizOjI9F5yt02b29LIagE5DiBrU8BKuutVel8TwU4= + + + Resources/core/icons/text-left.svg + + hash2 + + cOfeVsxGQqHt8MJbpDsfijG5zA+oFlrBENT87Nxf2Vs= + + + Resources/core/icons/text-paragraph.svg + + hash2 + + qa5tjdbU6k7WKVjTLtF51Uh2uF0zxNC095ediq4TGak= + + + Resources/core/icons/text-right.svg + + hash2 + + lfVgIhnaWjTmqInXTDzyuaOqDG3bIU0by0Aw73p+1gE= + + + Resources/core/icons/text-wrap.svg + + hash2 + + inz/hxSNtw4bW+wp0UP1chHJXlxd0VASdX+84c+n3Wo= + + + Resources/core/icons/textarea-resize.svg + + hash2 + + Ra5+r7G8NopondzYUJ8vOgJV/1vFlD9jW0oMHPgwAKU= + + + Resources/core/icons/textarea-t.svg + + hash2 + + RTwzeRK/o4BfqawQ1xS6kGHSB+mGL4gbWRWbvrWGhSw= + + + Resources/core/icons/textarea.svg + + hash2 + + GiEhbV+wgIfQDVY2u3QOEaZBdXeWfzbYqow1MFbM7uc= + + + Resources/core/icons/thermometer-half.svg + + hash2 + + AJrArTalBAv+svYcjj+n0j6l6N6B3OKjMOwPvbTH+MQ= + + + Resources/core/icons/thermometer-high.svg + + hash2 + + OQWk+j5lVrM/2APcKguOzKCFbh5ZIpKyi6+P37N84hw= + + + Resources/core/icons/thermometer-low.svg + + hash2 + + Vq340e08tgU6zIiVOtUqL2+RxrJPlYNIrc4sZBsarlM= + + + Resources/core/icons/thermometer-snow.svg + + hash2 + + IYhIP5L81qUiL60kqx3chW3DR+ecb1mYhCCFVqw19fI= + + + Resources/core/icons/thermometer-sun.svg + + hash2 + + mOXNskwB9cJVhstgk4ku9Jwzyf7sjLAO/9NytzEivkU= + + + Resources/core/icons/thermometer.svg + + hash2 + + C3L6UKBaRdmwHFdtKcBqJmjzz7LSf6tKH5MXJNXfD3s= + + + Resources/core/icons/threads-fill.svg + + hash2 + + tNbb6JqfVnKRJzzdHIjgryyH5npWQ18zSW0Yw+RBkWg= + + + Resources/core/icons/threads.svg + + hash2 + + UgFXuolZqfYy3RKm6oDvOUluyPNlTmNhcBYHJl5kcoI= + + + Resources/core/icons/three-dots-vertical.svg + + hash2 + + GxcQtV4co4EaCFQp+TMyP+/MIUWZ4hF297IGHuXAfyc= + + + Resources/core/icons/three-dots.svg + + hash2 + + I/0zYes/GqDx6QaBE4KS1QOhY+5+enzECdzHQ/xIcq4= + + + Resources/core/icons/thunderbolt-fill.svg + + hash2 + + i6xJij+QlPCZUPETfYLwc8aDO1b7LG6OjLvvTkyScSg= + + + Resources/core/icons/thunderbolt.svg + + hash2 + + V2b7nm4CZTQuotiFxPdKChgnKNCyxHxaXygoaGSddTk= + + + Resources/core/icons/ticket-detailed-fill.svg + + hash2 + + f06V8tOC7eTfYF8u1FMspHKfcKC8w8ekP8cdni+xxCU= + + + Resources/core/icons/ticket-detailed.svg + + hash2 + + rxDnwtBeNHTLKjaFXiV2olWMAR7LdiJVX1eOdif5wH4= + + + Resources/core/icons/ticket-fill.svg + + hash2 + + jLon+crNGxXyRgYC3lUOq+UFF4WU4z3pck+ovGbAqlI= + + + Resources/core/icons/ticket-perforated-fill.svg + + hash2 + + TlW9vSQPNEpOBKN/mUwF9LZh5bvCumxywjjWmdApkKc= + + + Resources/core/icons/ticket-perforated.svg + + hash2 + + CsgPS/KdYs1q9jlCpgKkdBdAcQw56cbvdBccXC6/uM4= + + + Resources/core/icons/ticket.svg + + hash2 + + 9OKGbUGSeW+AKEEZZvrZEXbW6E1zDNgZ7Oy+FbqysW0= + + + Resources/core/icons/tiktok.svg + + hash2 + + 3yXtV1/PDQ2W+nCMKgf8R9RRjlQsaPa7HvfVdEc2FTM= + + + Resources/core/icons/toggle-off.svg + + hash2 + + BQHIOm1TdDzGwbW+XoN7sLcgNMI+28TyxqZgwOjCgcc= + + + Resources/core/icons/toggle-on.svg + + hash2 + + qWaupG1BX6a7ZXF4sYw3gTeLReiAw3jiShkEqlKCPoQ= + + + Resources/core/icons/toggle2-off.svg + + hash2 + + FNCOzRpSGQCgT9Kgeu7US118XKgr7lVJ05xHIXQAhBQ= + + + Resources/core/icons/toggle2-on.svg + + hash2 + + RD7mRjxEQ+PT09OkWpVpCwrkIBmhrqwusx+VdIRjzck= + + + Resources/core/icons/toggles.svg + + hash2 + + qg6pf9BI2ZE9Rt8vFqURH2vma1UTTfyCwmHcx2/2Sg0= + + + Resources/core/icons/toggles2.svg + + hash2 + + J80NITB7jKw6Sb6LCjIWGH3SJXHf6xGOwYOQh+DIPII= + + + Resources/core/icons/tools.svg + + hash2 + + ritJcoQT1/MuIqpkw9SQ2yqgJLoE/fYBf4UxreoljUs= + + + Resources/core/icons/tornado.svg + + hash2 + + A1Md+Z/7jRzFAO9S/Sh+jk3ljLRLpnriitdJ2K2u3q0= + + + Resources/core/icons/train-freight-front-fill.svg + + hash2 + + yV8NAOtw7q859m0k3Ik5FwiXqsGJDyGg2IsUPiYwylk= + + + Resources/core/icons/train-freight-front.svg + + hash2 + + fDRALrU6kqug8dvamo3lsB75fvzkbNryAnpv3bYNf28= + + + Resources/core/icons/train-front-fill.svg + + hash2 + + HIEwcowQCHrU0DEnQK66baCpfWlf/yTBJtGQIEvTWkQ= + + + Resources/core/icons/train-front.svg + + hash2 + + 8hVBF+lp8qBdP7+IzM8yFOoFTbwL1UIc620sJw3C9w0= + + + Resources/core/icons/train-lightrail-front-fill.svg + + hash2 + + RFMNiGZnGHZHUQcIg141tM/j/HRIa/NmsBkaVsISyn0= + + + Resources/core/icons/train-lightrail-front.svg + + hash2 + + RfyLY9Ptkq9unfR//KBMnLx3mpQlSBkcSg43nmB2L2Y= + + + Resources/core/icons/translate.svg + + hash2 + + 0cx9TzgBSygChWY1g1O8a29jIWDRsU9JTM7A9y/03Is= + + + Resources/core/icons/transparency.svg + + hash2 + + Xyz322VGS9gSpF3FUE7R3g7/qloydYfwKoYE7Y7Zp5k= + + + Resources/core/icons/trash-fill.svg + + hash2 + + B6ypAIwim3jPa7XMWvPp/ODJf4PO+x4D9KeXJqH3gwc= + + + Resources/core/icons/trash.svg + + hash2 + + 3VdvRuGQub8wjL8UOq9vxWQS/7HkV6eIktS+9iTfjx8= + + + Resources/core/icons/trash2-fill.svg + + hash2 + + JbKhFWnDu3VhTmxtEIv3xALh8OcacEJZx4BYrWx/4ug= + + + Resources/core/icons/trash2.svg + + hash2 + + bmkOmqK4uCSbUQwX7Hx+837FiK84U+lwBDt8wLmRZss= + + + Resources/core/icons/trash3-fill.svg + + hash2 + + UPh4IPcuHcKEsoiROrepBRIcsszmNZLUjklzacd7RRM= + + + Resources/core/icons/trash3.svg + + hash2 + + gpXgRLW6I90ZOT4a+XxCggtse5+vh7JHHFdxdSnkuZw= + + + Resources/core/icons/tree-fill.svg + + hash2 + + /d8BR/vQz5PF5krK+1wRHnDy+4YHOfNe5di9/pflThU= + + + Resources/core/icons/tree.svg + + hash2 + + 3knrqaFRFIrXuKh1vVKxT4UiE4YlDF5wdkYAXLfXNPY= + + + Resources/core/icons/trello.svg + + hash2 + + HLQhbTt7lsB1QtIgh73o/93zT59r8PQKnMFdhCeH0RU= + + + Resources/core/icons/triangle-fill.svg + + hash2 + + iq0UnZkXMn6isPYjBuhHy97o7cL+0XyQawq3KwyWZRo= + + + Resources/core/icons/triangle-half.svg + + hash2 + + SLd+6Tqd2TtNCMbifLlRm9u1kCfl+3uxp4JlmJrVmDA= + + + Resources/core/icons/triangle.svg + + hash2 + + JDfGkpnIA9TRnV9Jkxgl+5XPpyZrDGSIed/0Z3X9Vyw= + + + Resources/core/icons/trophy-fill.svg + + hash2 + + TkPk0FL8cv8/4jIb4g3RNKbzZe4zn0gYCamEuzYfih4= + + + Resources/core/icons/trophy.svg + + hash2 + + lx2IHu1TnJHrt3bvTfYJ5AMhSn2Af3TSaCmKsEVPRCc= + + + Resources/core/icons/tropical-storm.svg + + hash2 + + GFOU4yIz9/qmED0h4+TKo6VBLIUM8jlJiGfU1O0hO2M= + + + Resources/core/icons/truck-flatbed.svg + + hash2 + + 2P57TxOfy2mqGDGMzMk1rOgNUpqmA3V7zOqBfF1BmPc= + + + Resources/core/icons/truck-front-fill.svg + + hash2 + + l5TFD9+VjesH6E68GzELlrE3MdQCojUFceXpkTZp5zo= + + + Resources/core/icons/truck-front.svg + + hash2 + + HOR/GVwMAD9RJajkAeM/+N7cLN4z2+aMALeVXNa9Ul4= + + + Resources/core/icons/truck.svg + + hash2 + + JXcRJESPE5fFDNfzVwDVsozInI/Uf6uVSyDwut6YMq0= + + + Resources/core/icons/tsunami.svg + + hash2 + + yf0HhXJ70YD047vHJwzZv54Ig5vbXr7/E2pwKLp+6bU= + + + Resources/core/icons/tux.svg + + hash2 + + NCdKKF9wjVODB0c+XXHpl6tfGWtdyypB8wnsyfKEIvk= + + + Resources/core/icons/tv-fill.svg + + hash2 + + drchedezZnenUuyqaSFQF2IG2FkIWQHfLd7io3YZKm8= + + + Resources/core/icons/tv.svg + + hash2 + + 6iLdSsfdUYuqx0XcQ8p8MFah8dbgiIy6yoa6dyndbv4= + + + Resources/core/icons/twitch.svg + + hash2 + + XuVkJF+8maCA764SSfBryZe7kkPA2k8Xlnz2OXuK1g0= + + + Resources/core/icons/twitter-x.svg + + hash2 + + gSl/5NLMrhIVSQmNVhSrpYHlI8W35oPdzsXQNm9Ays8= + + + Resources/core/icons/twitter.svg + + hash2 + + g5prgSUq85Bd+1LR84PelPfomeM4h5fVTD6ILTp/Gog= + + + Resources/core/icons/type-bold.svg + + hash2 + + 2sKDRmuWDmtrh+8MZu3FNc4jupqvCdPz0BYUKDKCfnY= + + + Resources/core/icons/type-h1.svg + + hash2 + + WHEiqa2CfUzgQEgXEQ2wGM0DyTCJLFFZVJMN+5QCIrc= + + + Resources/core/icons/type-h2.svg + + hash2 + + IPwgCm+qk9XhHUAdkUhzedz3t+FtzdTVWg4+nWSPDYk= + + + Resources/core/icons/type-h3.svg + + hash2 + + 8N4S4u7fKtIcE+FIpHfNwru/vT1VYE4wFiyXXQ/pneY= + + + Resources/core/icons/type-h4.svg + + hash2 + + 9wjedQ38a+qv1twbtxxQ/AoMPI/g/bani26AlGAgLxc= + + + Resources/core/icons/type-h5.svg + + hash2 + + LmhtvHSDwLn9P0fkHr53PPv+x4i0ItAdjTtxq+3Euds= + + + Resources/core/icons/type-h6.svg + + hash2 + + c8FSl2mVUXoPenDCHQsbhSMAIETsDS8KoocDDzET+X4= + + + Resources/core/icons/type-italic.svg + + hash2 + + gFj5Na6eUvdtRDaR8xOwmiRKHZbnYd3h/NUpH1DEzDA= + + + Resources/core/icons/type-strikethrough.svg + + hash2 + + l1rxkJFqd8teLobDTBo8wpIVX/v8048PQWtvdkuzE+A= + + + Resources/core/icons/type-underline.svg + + hash2 + + i0Z9vImrvcD+IBj1f3TTjhueGA9zp6SaYhQiuurc8+E= + + + Resources/core/icons/type.svg + + hash2 + + n/oJp75lm5nu8SJNhQUYQUxo7NzuQk0qFPYbV97n9no= + + + Resources/core/icons/typescript.svg + + hash2 + + zXTjLTOoOBHsZAwrWF9NVZjgXitPm5lROEBcIwvG76M= + + + Resources/core/icons/ubuntu.svg + + hash2 + + 5f0ugkKllI8qJWV/F1+o3yrBB6UO5IAXp5Odkir4yUs= + + + Resources/core/icons/ui-checks-grid.svg + + hash2 + + +Al2z2eFh/FBM4QcopsClYR3Md4yKaYPeY4G/Yg983s= + + + Resources/core/icons/ui-checks.svg + + hash2 + + 24J1puvtiHHhzAKH4j2UUvQYUGasSpFpLTpNCNjwNf0= + + + Resources/core/icons/ui-radios-grid.svg + + hash2 + + 0Yq/61ySh+adZas2u0tR1REKq7HWB9Yq60fEslYULN0= + + + Resources/core/icons/ui-radios.svg + + hash2 + + tfz0en8lLW9Z33lWVC8rC5/aS4oyuDymV+yEmRcEvhc= + + + Resources/core/icons/umbrella-fill.svg + + hash2 + + 7ax7Ohgf5RZ1I+ojNV7Oe6Q6FtT1t706AViFGl8cpu8= + + + Resources/core/icons/umbrella.svg + + hash2 + + 8DbXfko9/rku6cRz1sUXAfM1Nnk+zQWlv4ZPEhhWqyM= + + + Resources/core/icons/unindent.svg + + hash2 + + kAAJDreqO/QrqaiGcWhB3e0ehGVsFT6Spz9KkX8ney4= + + + Resources/core/icons/union.svg + + hash2 + + eGpFPGwTYAo+1V/IgXCNMAnfMyoklyK//rat3C+6jkQ= + + + Resources/core/icons/unity.svg + + hash2 + + qfWkhyj4qj9koU9/rfh0AdAYDH6y8WoJYqMYzPoJcDk= + + + Resources/core/icons/universal-access-circle.svg + + hash2 + + l+/xgUhXBC/KovXpzqYNuk5I0XgJaetecgE8vVo7DSc= + + + Resources/core/icons/universal-access.svg + + hash2 + + nPfVWfGdRpMJydiIcWxcUHyngIeqZg+hiBrDQbwRB5Q= + + + Resources/core/icons/unlock-fill.svg + + hash2 + + 1kqXRX92PkDRu3gMKIUpX0+3teuPfzDYK6xQYWssa6Q= + + + Resources/core/icons/unlock.svg + + hash2 + + NzQgw7IlYZijZZh++U4xeUHnXAxNkVCDa+NRrIao/jQ= + + + Resources/core/icons/unlock2-fill.svg + + hash2 + + KpSVULGnVNnuSQiAan4q85KNg4BbFZDZ0PIIEx81Iq8= + + + Resources/core/icons/unlock2.svg + + hash2 + + yEzfLG9ApW8vdB/qY5APK/2iEBQom/HmtbR0V3Pav4g= + + + Resources/core/icons/upc-scan.svg + + hash2 + + 9tHf8WPJFUga7SI9T1ECp/XsI0JSY/lAlNcVo8yeAek= + + + Resources/core/icons/upc.svg + + hash2 + + cBlKzA8uRjgH1/2lpsXD47wx5Lr+g9JAumXBqeG3znM= + + + Resources/core/icons/upload.svg + + hash2 + + yuE5SYmBIbFAiMSzpvPgZ1XY+FQD/QVktpbTpFVIw7s= + + + Resources/core/icons/usb-c-fill.svg + + hash2 + + C82lAKFd9vK8u7BJ6tjw+zGYQAJGz/+W9X4YeeXejzA= + + + Resources/core/icons/usb-c.svg + + hash2 + + N56PgZ+jb1G707rj3H4LeTlYBMn2vWm6ljOQmjlegKw= + + + Resources/core/icons/usb-drive-fill.svg + + hash2 + + W9E7aOpdSKtmaBdK9CpeY1Teb3ZRocYPRvWvp/PibGg= + + + Resources/core/icons/usb-drive.svg + + hash2 + + TgCge1a2wEI1UbkaR4h5KLxYjMDqsICM+CkQP8VqWy4= + + + Resources/core/icons/usb-fill.svg + + hash2 + + rq84924ifO5Hig4BPmuMocreaSGuhq9s2pYWTeT4rAk= + + + Resources/core/icons/usb-micro-fill.svg + + hash2 + + heXnSCfWti806MlFZOacK+JhNMCKhL/MGoIOLSnCQJ8= + + + Resources/core/icons/usb-micro.svg + + hash2 + + LUcvYZubVk96wQ6tqzeOfPHk7vKvP8ripiRT9B6JtaE= + + + Resources/core/icons/usb-mini-fill.svg + + hash2 + + J0/PbNM34g/ihLPu4/fNYwIRg3hffpmAqhPL+/YL+Fk= + + + Resources/core/icons/usb-mini.svg + + hash2 + + Q/gIlJvkcJaZGBT9KjXmZQH7abAs0PJDLVfodCj+8jA= + + + Resources/core/icons/usb-plug-fill.svg + + hash2 + + LESlFOJb45jOi+CxVXSMcFex3QeQHWHtqAZqSKRX7Cw= + + + Resources/core/icons/usb-plug.svg + + hash2 + + Q45TIQnE+KgVT/Zk6g++oHMND7L847mR5ImHHoBqEJs= + + + Resources/core/icons/usb-symbol.svg + + hash2 + + xrOSsoqAUOYbpv2Fxxw4eBpJ++xY5jwi6JDgiDZF1yU= + + + Resources/core/icons/usb.svg + + hash2 + + By1SwgXJc1km7jFekiDaBef6YOB7WF1wgYjf0tg0zgs= + + + Resources/core/icons/valentine.svg + + hash2 + + Z0NsIX201Qwf4PHJpjg0GlhpQldXEdzCg8J8WNhwzgc= + + + Resources/core/icons/valentine2.svg + + hash2 + + puQzUPRH7LPAbW6e4qtubwjHO0cX2Z0Yw0UiRjX9a2s= + + + Resources/core/icons/vector-pen.svg + + hash2 + + w68Aj5NIx79tRc4iJnrfiTmPU576ZOnWhZGrt0My3Xs= + + + Resources/core/icons/view-list.svg + + hash2 + + ilk/7wTSYwgaU1JOhZwzpp7zWegWIPQTTK5S4MDjZQI= + + + Resources/core/icons/view-stacked.svg + + hash2 + + 9YyHVXIcfzncnKrLbSbsTpiMNQ8nJsCflvKCQ3CB29g= + + + Resources/core/icons/vignette.svg + + hash2 + + b2VTLdyrNZ4EBmwkvG0SHkHWnaOhxUCwUPrrAAHWAgg= + + + Resources/core/icons/vimeo.svg + + hash2 + + j0RHU8EmA7QV2W6FHh2DUZl5150N8IHSnPHCrYd8LnU= + + + Resources/core/icons/vinyl-fill.svg + + hash2 + + m0pwBhKWKP/D4mof4TwcPYZ/0+8gWWfGPd6a2dzObWQ= + + + Resources/core/icons/vinyl.svg + + hash2 + + w9qT86AXndKfFZWACVzKfEJdyOhZxPDgrUQcMGu7x48= + + + Resources/core/icons/virus.svg + + hash2 + + rbn5ji5IjNdzKVQxJxutDuowlfcCUXyAOxwSCvWvqU0= + + + Resources/core/icons/virus2.svg + + hash2 + + eZxDvUhdD1WAATzOMfz8pgrpD9o/vEYAbDQVbX4nKmo= + + + Resources/core/icons/voicemail.svg + + hash2 + + lcYIF5VVl70aoJH3kyYruNW6vKya42Z4aP9StmdWLK8= + + + Resources/core/icons/volume-down-fill.svg + + hash2 + + fppCNMJZCkR4jqrxDXUbvgHuetUKA+bU1bRV3F+zVQM= + + + Resources/core/icons/volume-down.svg + + hash2 + + ydQM5aH+DmZfIpFRi9vN0JmqrFSDrza85G9FMG1f+B8= + + + Resources/core/icons/volume-mute-fill.svg + + hash2 + + HsHbuuuD8pQkXX/XOMdHvq7nymst0eDiCt2tFMCGvXU= + + + Resources/core/icons/volume-mute.svg + + hash2 + + gYplDwUHsqgK5wNpQwcMN6cgSBDxLNbg4o5YjUTarIU= + + + Resources/core/icons/volume-off-fill.svg + + hash2 + + sIxNLGvvcHYQXxHNoqOSIPwu9u8I9xNKMnnEXAA5d4E= + + + Resources/core/icons/volume-off.svg + + hash2 + + SFBPv7s3N5njgR1R4U8/HdbWAUOyI/oA+u/q56hN2Dc= + + + Resources/core/icons/volume-up-fill.svg + + hash2 + + 2wjAracBVju4yTf4NE2RnjEMl7RPaPpT4R+Bd//BZPw= + + + Resources/core/icons/volume-up.svg + + hash2 + + jg01TIPwNxf9ZCPwDaoecscjv/rGvJV8EF3sI+Mbm6A= + + + Resources/core/icons/vr.svg + + hash2 + + i5yAPy1LDoLJUUxb5B8KqDobqjCXwm7DHgU2aqhfbGs= + + + Resources/core/icons/wallet-fill.svg + + hash2 + + 5dGPTCDDpHwT1I7LgRG7+N6rZC/+cQ4UQfGwulS25D4= + + + Resources/core/icons/wallet.svg + + hash2 + + ns3JwMr+DoNHa9r3tcsiFHMSxmXuoImduP+9CNnKipY= + + + Resources/core/icons/wallet2.svg + + hash2 + + sTyaFnssg8B22ZolSA6+HSSEeviJIZfQRjJIm/EPjNM= + + + Resources/core/icons/warning.svg + + hash2 + + /t9fnMtadSzwb8wiEBJ3MSDA376XmgUYSU5IXLpkhdg= + + + Resources/core/icons/watch.svg + + hash2 + + U6EqBL0cYiBK8zV0xg6JyDC1sTcBYJ5y9/fheompMqw= + + + Resources/core/icons/water.svg + + hash2 + + 2IuXTOX/Bi0/CzOhy962n1ni82Xbz4OKZ8Jp4vgLfTc= + + + Resources/core/icons/webcam-fill.svg + + hash2 + + 3O4mH12RDbRDAq5k/l9pkAuZzYIiyHP2kZ+7UkgeD4c= + + + Resources/core/icons/webcam.svg + + hash2 + + Nq5yawYOTfgBpg0FH+JEjcmGyQo3/Ic7nc9VQmsJWiw= + + + Resources/core/icons/wechat.svg + + hash2 + + PxhxzLyuWAGolmdTpJHTzjfaVs3FLsiSbOVSn5RWGZ8= + + + Resources/core/icons/whatsapp.svg + + hash2 + + Pw64xBxMwIy0x21Im4j1l9XColt8F6wcfJwrRiOpufM= + + + Resources/core/icons/wifi-1.svg + + hash2 + + 7rI92SB9JmWC2XeYgpFbEFaMT+4E5JxfF5a9vPSEDoU= + + + Resources/core/icons/wifi-2.svg + + hash2 + + ghrQB4Fs3oxSTP9bhwbCtxJusaq86MXRg13pV1QHSWc= + + + Resources/core/icons/wifi-off.svg + + hash2 + + yfKhH8TwQEN/y0LCqXAmTBBRnf1RwcPjBgx89/+d7wY= + + + Resources/core/icons/wifi.svg + + hash2 + + WkCupqVkg6+iTk2fJzmI3iNPXrobH4jyQwxgsiV9Eig= + + + Resources/core/icons/wikipedia.svg + + hash2 + + Q8gMjgBbpVvQyTV4wAFlHrm/gtgygL69UOm1zGf4dT8= + + + Resources/core/icons/wind.svg + + hash2 + + NB57DLfvWqsEzpQ2cSd4Ch6FCsZMzU3nvkHIK9s0w6o= + + + Resources/core/icons/window-dash.svg + + hash2 + + IjpfxlfqLFZ8NTOGtM8OJu2Eva9CwOqD2YqkhQ9UoDo= + + + Resources/core/icons/window-desktop.svg + + hash2 + + O0KER51+jF21k8amcbqqZdtz93zH/jNG4DrZnS+5gMM= + + + Resources/core/icons/window-dock.svg + + hash2 + + EvgV5lWFGaoCP8bPaK0SZWne7ot/1cSP5lTHcnHIgEI= + + + Resources/core/icons/window-fullscreen.svg + + hash2 + + pv9bvF2Saz7D+ajqvgA7CoBym0n7bdD/tSNUTqE/Dag= + + + Resources/core/icons/window-plus.svg + + hash2 + + doXFJRWsDS0P0ZU33NFZWhsFdsY7EExgBd5krbU3FxY= + + + Resources/core/icons/window-sidebar.svg + + hash2 + + H6kqJT6SWc9kPVDylaJHruTIWOOVUeV1X/2jwbFRiWk= + + + Resources/core/icons/window-split.svg + + hash2 + + LJH1OpAXOknCb4ud7tUb6m7RYpAMsLD0rrXQ4+pVg1s= + + + Resources/core/icons/window-stack.svg + + hash2 + + U4+Xd3LHFrXzIvTjRAah6L0VqFQmPEfGKtxeJB6eU2A= + + + Resources/core/icons/window-x.svg + + hash2 + + lAivcliPiqUlf4Njj97nHtNPe9+NrrLegSQL7y9TBHI= + + + Resources/core/icons/window.svg + + hash2 + + R98nPnIpJpQREk7wlKs2n5qpCtB1D49OtPuDa69z4nE= + + + Resources/core/icons/windows.svg + + hash2 + + nwZcbpXZ08JapCLzdOglnDU6gcYgovIcXhH6FlOnOVE= + + + Resources/core/icons/wordpress.svg + + hash2 + + txhunxNrHAJ5iuNznnmztcisUmWU/Yn4lwqcZGn/s0I= + + + Resources/core/icons/wrench-adjustable-circle-fill.svg + + hash2 + + LHmw0tm+gNsNKp4WYwXkO7AA8Srejs9P8tL6FVWbRq0= + + + Resources/core/icons/wrench-adjustable-circle.svg + + hash2 + + KtguPqmPlFEvFa7NdG9UP8s5W6tfU/ZjJENTxqjQyaw= + + + Resources/core/icons/wrench-adjustable.svg + + hash2 + + NFzHXV7rljJ4IffmPRZd7Dyd5zakpG3vMbV2LriIci8= + + + Resources/core/icons/wrench.svg + + hash2 + + AdRhV0pw3AwcabtU3GRWSs9EO++AmvgwbPJHD8xElEM= + + + Resources/core/icons/x-circle-fill.svg + + hash2 + + 6ORfnWR1Qaqtiv87jwwJ2enNnJBgdFxMMYxqqnUEsnM= + + + Resources/core/icons/x-circle.svg + + hash2 + + TCM0sPjYJDQxDJ2BFsF+khUAFeyOpj8NcHAQo7/YfPE= + + + Resources/core/icons/x-diamond-fill.svg + + hash2 + + Q7K0F7AX9OTJ6N86eZ+RyokwVqezLBv9hfPLMYE4p2Y= + + + Resources/core/icons/x-diamond.svg + + hash2 + + 3B7f4v2sJca2RjNqhXVRrlBnuiuxA8gUhyOarZEy8o0= + + + Resources/core/icons/x-lg.svg + + hash2 + + MkbMK31MBPlESCmXRsljJ8sAEW7BQR7DbLs7ecBlLHA= + + + Resources/core/icons/x-octagon-fill.svg + + hash2 + + 2dbUzpA3u81kN6AYFWZX62ZgHdNOPHBoDIVSMaGqjVs= + + + Resources/core/icons/x-octagon.svg + + hash2 + + nX5WMI+NxpGjIE3um0g81gju00IsCHmZTaA6qYFOEus= + + + Resources/core/icons/x-square-fill.svg + + hash2 + + hMBCS6elOQYO0afRUATQk5zBGnjNVo6E11pIlrEgzuY= + + + Resources/core/icons/x-square.svg + + hash2 + + Dv3Y0BStD57waKAc0dnWTGHA68kUPxI+t93wOW6SJRo= + + + Resources/core/icons/x.svg + + hash2 + + nGRdhZ7qNt66l1BpHvCb/PT4hXb2OMzVLr+7X+pY3Is= + + + Resources/core/icons/xbox.svg + + hash2 + + Pe9HUc8qBMlLMykBj+gGmAu0PGXSRLB34jMZR+rQhug= + + + Resources/core/icons/yelp.svg + + hash2 + + nkco5H9hl/vrwgCbIQgCIEjAAmWKeQsxX3Rslm0w3e4= + + + Resources/core/icons/yin-yang.svg + + hash2 + + pNBG2IU7kDoUfXIFQ+bVkKUJn6VNJ8f4kY9CKthCpD8= + + + Resources/core/icons/youtube.svg + + hash2 + + /tB0c6Ug90ligAMLLg+j3VFeoHmOAmyjJltr7gARq7Y= + + + Resources/core/icons/zoom-in.svg + + hash2 + + a4QZRtF3JofOg0jpbg6j3uLYxTxG9baWIfq5redza0w= + + + Resources/core/icons/zoom-out.svg + + hash2 + + nS/PsVTPHEvi/HlVCvTOa7/zqKv9gb1vlblnhC1ipyc= + + + Resources/core/log.py + + hash2 + + bkq9ZYaVSyMzRHLrZOkx/1oCb5+M/I9BCehvJFnewoE= + + + Resources/core/network/__pycache__/diagnostic.cpython-311.pyc + + hash2 + + GkdsMaNHqUx8RLGfNYR4nAmK9wePCf7opRxhlC3wKaM= + + + Resources/core/network/__pycache__/diagnostic.cpython-312.pyc + + hash2 + + onv70udQXvnJkKaY0zmXjc1RQU2PUj6CcS3L2NjWOr8= + + + Resources/core/network/__pycache__/tools.cpython-311.pyc + + hash2 + + AGiKl9lU3v6/SIHtqZpCO+r+Myn7+Sfzch8z739hJiw= + + + Resources/core/network/__pycache__/tools.cpython-312.pyc + + hash2 + + 7/lqIoEi9ArUdRHksns/LLluuoNqsvurlwZvORnHaNk= + + + Resources/core/network/diagnostic.py + + hash2 + + +rRiRIy1qzrI2wgKhdvXnVlZ8tz55up4PV8wmePUpgc= + + + Resources/core/network/tools.py + + hash2 + + NH/0OFPnw1srKNYvrmcoN72xR7rN77/4wUdEwXBDDEw= + + + Resources/core/service.py + + hash2 + + RNpM7u+p1lpzlFDEIty/K1yaRHP7TkXwnSJks/9uQ9w= + + + Resources/core/src/bin/nssm/windows/x86/nssm.exe + + hash2 + + RyIyyoIbXC71YqsH9TY4vCzILq6EzqE/vmdNYCK2SBw= + + + Resources/core/src/bin/nssm/windows/x86_64/nssm.exe + + hash2 + + 9onumvlLAOnj8LsHKzTKryB/Mty09Xgvyco1HfmgbJc= + + + Resources/core/styles/style.css + + hash2 + + BuixOG8lj2u55nsAz0cVFGPAb7YGBPlgZIIyV5XaaY0= + + + Resources/core/ui.py + + hash2 + + AMU2ewv+s4v01eAvVCp+7Ay0RzR3uBJ/HUgA6FJiwjM= + + + Resources/core/update.sh + + hash2 + + mRjJbMVVN1xuiopjFUuA5KTVOLcLwW2dWF+z+utMK+g= + + + Resources/icon.icns + + hash2 + + zC8szArVDkE5j6dHG3JJh2teij+70RTxBpcH5I1x3ys= + + + Resources/icons/icon.icns + + hash2 + + zC8szArVDkE5j6dHG3JJh2teij+70RTxBpcH5I1x3ys= + + + Resources/icons/icon.png + + hash2 + + 6L3lWiSILrc0v6HH1kpcLtwZpXq1HQt7Ud88nl7EPmI= + + + Resources/icons/icon.svg + + hash2 + + 4tVGXSBwtlgpDUX2SGbo5Op7k9jD+VIHYgMZxdCv8RI= + + + Resources/libcrypto.3.dylib + + symlink + ../Frameworks/libcrypto.3.dylib + + Resources/liblzma.5.dylib + + symlink + ../Frameworks/liblzma.5.dylib + + Resources/libmpdec.4.dylib + + symlink + ../Frameworks/libmpdec.4.dylib + + Resources/libsqlite3.dylib + + symlink + ../Frameworks/libsqlite3.dylib + + Resources/libssl.3.dylib + + symlink + ../Frameworks/libssl.3.dylib + + Resources/python3.11 + + symlink + ../Frameworks/python3.11 + + Resources/replicator/__init__.py + + hash2 + + 4pdtQs79K4WtyKIx/goMQzCHQCai9gS2W5tlkCL4oac= + + + Resources/replicator/__pycache__/__init__.cpython-311.pyc + + hash2 + + a4jlPbZRcWo2ydglsxnksd7hWQUlxN6CMcBOubTmqbo= + + + Resources/replicator/__pycache__/__init__.cpython-312.pyc + + hash2 + + 7QYywWRlhqHIyrdXkPk/w/03lD6+0gzmZUfXaX4Wxr4= + + + Resources/replicator/__pycache__/job.cpython-311.pyc + + hash2 + + IpSHjE6PCtJJ4O+PB+3BlJVMY1rAOhSJM6jfXp+jGOs= + + + Resources/replicator/__pycache__/job.cpython-312.pyc + + hash2 + + 63bQRpalIvRUM/p32rXYSAfw7cU+auDeaMAS50mpCvk= + + + Resources/replicator/__pycache__/migration.cpython-311.pyc + + hash2 + + PLZvYyAcxm2dtixZHgCQfcRA8/ERsUY6WxWEsADSkTw= + + + Resources/replicator/__pycache__/migration.cpython-312.pyc + + hash2 + + F/1rAfBMFpAayatJRqPmFMp9FSFUVfYtZHozSOW9ssM= + + + Resources/replicator/__pycache__/mount.cpython-311.pyc + + hash2 + + Zaxj1AZVwLdTp5NwQbWm/YvEe1KvR3FE2Jzj8k9hHpU= + + + Resources/replicator/__pycache__/replicator.cpython-311.pyc + + hash2 + + Zd22UhaBDjAmn2zSEgDY2Jb5EaYEXi67XuEkIVIQo8U= + + + Resources/replicator/__pycache__/replicator.cpython-312.pyc + + hash2 + + nqv+8PFnOq1PXuLWvlzBAs3BnbYj73fGXyTCj5bj/Ok= + + + Resources/replicator/__pycache__/ui.cpython-311.pyc + + hash2 + + ETBlRbaTmOUa8X6rJz1QK5THRrGGefbYa7gU8UdhtR4= + + + Resources/replicator/__pycache__/ui.cpython-312.pyc + + hash2 + + aFjnqS9ZGZPJxqfoJAKgy0lvImu4JWLXRBLyeITLV8k= + + + Resources/replicator/job.py + + hash2 + + 7xcjdhJ3qc9gaKMFMt3ZfJ/E0OaWGpf8W7ZqPdjNjuM= + + + Resources/replicator/migration.py + + hash2 + + 60S76qF6yY3T5HboA2J3BWLeB//Hhs+Vf6j29JqAg3c= + + + Resources/replicator/mount.py + + hash2 + + WPDR4GoQg/nRRenmd0MVqrKkVCqKwNHP4QnVWqnFIWg= + + + Resources/replicator/replicator.py + + hash2 + + nnhcAy/M5+8oU8AtHNYs1zU2WDa04EfEFaBqvs/3VMk= + + + Resources/replicator/ui.py + + hash2 + + /0iGoP0eoPYyUbt0ZV2huwdnFXgSTVirz8lPepVCkFA= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/dist/macos/Replicator.dmg b/dist/macos/Replicator.dmg new file mode 100644 index 00000000..f0532992 Binary files /dev/null and b/dist/macos/Replicator.dmg differ diff --git a/dist/windows/Replicator-cli.exe b/dist/windows/Replicator-cli.exe new file mode 100644 index 00000000..b3d181b7 Binary files /dev/null and b/dist/windows/Replicator-cli.exe differ diff --git a/dist/windows/Replicator-cli.lnk b/dist/windows/Replicator-cli.lnk new file mode 100644 index 00000000..e1ce1787 Binary files /dev/null and b/dist/windows/Replicator-cli.lnk differ diff --git a/dist/windows/Replicator.exe b/dist/windows/Replicator.exe new file mode 100644 index 00000000..cf0f615b Binary files /dev/null and b/dist/windows/Replicator.exe differ diff --git a/dist/windows/Replicator.lnk b/dist/windows/Replicator.lnk new file mode 100644 index 00000000..71251869 Binary files /dev/null and b/dist/windows/Replicator.lnk differ diff --git a/launch.sh b/launch.sh new file mode 100755 index 00000000..9eea2dbe --- /dev/null +++ b/launch.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Replicator dev launcher (macOS/Linux + Windows Git Bash) +# - Creates a virtualenv if missing +# - Installs runtime deps (prefers requirements.txt if present) +# - Runs src/main.py + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$ROOT_DIR" + +VENV_DIR=".venv" +REQ_FILE="requirements.txt" + +# Detect Windows Git Bash (MSYS/MINGW/CYGWIN) +UNAME_S="$(uname -s 2>/dev/null || echo '')" +IS_WINDOWS=0 +case "$UNAME_S" in + MINGW*|MSYS*|CYGWIN*) IS_WINDOWS=1 ;; + *) IS_WINDOWS=0 ;; +esac + +# Choose python command +PY_CMD="" +PY_ARGS=() + +# Prefer explicit python3.11 on macOS/Linux +if command -v python3.11 >/dev/null 2>&1; then + PY_CMD="python3.11" +elif [ "$IS_WINDOWS" -eq 1 ] && command -v py >/dev/null 2>&1; then + # Prefer Windows Python Launcher (does NOT require python.exe in PATH) + PY_CMD="py" + PY_ARGS=(-3.11) +elif command -v python3 >/dev/null 2>&1; then + PY_CMD="python3" +elif command -v python >/dev/null 2>&1; then + PY_CMD="python" +else + echo "ERROR: Python not found in PATH. On Windows, install Python 3.11+ and/or ensure the Python Launcher (py) is available." >&2 + exit 1 +fi + +# Resolve venv python/activate paths +if [ "$IS_WINDOWS" -eq 1 ]; then + VENV_PY="$VENV_DIR/Scripts/python.exe" + ACTIVATE_SH="$VENV_DIR/Scripts/activate" +else + VENV_PY="$VENV_DIR/bin/python" + ACTIVATE_SH="$VENV_DIR/bin/activate" +fi + +# Create venv if needed +if [ ! -x "$VENV_PY" ]; then + echo "Creating virtualenv: $VENV_DIR" + # shellcheck disable=SC2086 + "$PY_CMD" "${PY_ARGS[@]}" -m venv "$VENV_DIR" +fi + +# Activate venv +# shellcheck disable=SC1090 +source "$ACTIVATE_SH" + +python -m pip install --upgrade pip wheel + +if [ -f "$REQ_FILE" ]; then + echo "Installing requirements from $REQ_FILE" + python -m pip install -r "$REQ_FILE" +else + echo "Installing minimal runtime deps (PyQt5)" + python -m pip install "PyQt5>=5.15,<6" +fi + +exec python "src/main.py" "$@" diff --git a/launch.vbs b/launch.vbs new file mode 100644 index 00000000..f9b3406b --- /dev/null +++ b/launch.vbs @@ -0,0 +1,26 @@ +' Replicator Windows launcher (no console) +' - Prefers launching the built binary if present +' - Falls back to launching Git Bash + launch.sh if available + +Option Explicit + +Dim shell, fso, scriptDir, exePath, bashPath, cmd +Set shell = CreateObject("WScript.Shell") +Set fso = CreateObject("Scripting.FileSystemObject") + +scriptDir = fso.GetParentFolderName(WScript.ScriptFullName) + +' Try built EXE first +exePath = scriptDir & "\\dist\\windows\\Replicator.exe" +If fso.FileExists(exePath) Then + shell.CurrentDirectory = scriptDir + shell.Run Chr(34) & exePath & Chr(34), 1, False + WScript.Quit 0 +End If + +' Fallback: Git Bash launch.sh (if user is in a dev checkout) +bashPath = shell.ExpandEnvironmentStrings("%ProgramFiles%") & "\\Git\\bin\\bash.exe" +If fso.FileExists(bashPath) Then + cmd = Chr(34) & bashPath & Chr(34) & " -lc " & Chr(34) & "cd \"" & scriptDir & "\" && ./launch.sh" & Chr(34) + shell.Run cmd, 0, False +End If diff --git a/src/bin/nssm/windows/x86/nssm.exe b/src/bin/nssm/windows/x86/nssm.exe new file mode 100644 index 00000000..8faee45b Binary files /dev/null and b/src/bin/nssm/windows/x86/nssm.exe differ diff --git a/src/bin/nssm/windows/x86_64/nssm.exe b/src/bin/nssm/windows/x86_64/nssm.exe new file mode 100644 index 00000000..6ccfe3cf Binary files /dev/null and b/src/bin/nssm/windows/x86_64/nssm.exe differ diff --git a/src/core b/src/core new file mode 160000 index 00000000..f592fc0f --- /dev/null +++ b/src/core @@ -0,0 +1 @@ +Subproject commit f592fc0fd81f8ae66ebed35bab0e088ca6826a03 diff --git a/src/icons/icon.icns b/src/icons/icon.icns new file mode 100644 index 00000000..e1a2c0f7 Binary files /dev/null and b/src/icons/icon.icns differ diff --git a/src/icons/icon.png b/src/icons/icon.png new file mode 100644 index 00000000..e683fe20 Binary files /dev/null and b/src/icons/icon.png differ diff --git a/src/icons/icon.svg b/src/icons/icon.svg new file mode 100644 index 00000000..d29f6262 --- /dev/null +++ b/src/icons/icon.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main.py b/src/main.py new file mode 100755 index 00000000..db2e6e80 --- /dev/null +++ b/src/main.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# src/main.py + +import sys +import os, sys, traceback + +from pathlib import Path +from core.application import Application +from core.cli import CommandLine +from replicator.replicator import Replicator + +# --------------------------------------------------------------------------- +# Customization and start of the application +# --------------------------------------------------------------------------- + +name = "Replicator" + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + +def has_option(): + return any(arg.startswith('--') for arg in sys.argv) + +def runtime_setup(): + try: + if getattr(sys, "frozen", False): + os.chdir(Path(sys.executable).resolve().parent) + else: + os.chdir(Path(__file__).resolve().parent) + + log_dir = Path.home() / "Library" / "Logs" / "Replicator" + log_dir.mkdir(parents=True, exist_ok=True) + log_file = log_dir / "replicator-crash.log" + + def excepthook(t, e, tb): + with open(log_file, "a", encoding="utf-8") as f: + f.write("\n" + "="*80 + "\n") + traceback.print_exception(t, e, tb, file=f) + sys.__excepthook__(t, e, tb) + + sys.excepthook = excepthook + except Exception: + pass + +# --------------------------------------------------------------------------- +# Start of the application +# --------------------------------------------------------------------------- + +def start_app(): + # Perform any runtime setup + runtime_setup() + + # Create application and register it with QApplication + app = Application(name,sys.argv) + + # Create main window and register it with Application + win = Replicator() + app.set_mainWindow(win) + + # All other code gets app via QApplication.instance() + sys.exit(app.exec_()) + +def start_cli(): + # Perform any runtime setup + runtime_setup() + + # Create command line application and register it with QApplication + cli = CommandLine(name,sys.argv) + + # Create main command line handler and register it with CommandLine + handler = Replicator() + handler.cli(cli) + + # All other code gets app via QApplication.instance() + sys.exit(cli.exec()) + +# --------------------------------------------------------------------------- +# Main entry point +# --------------------------------------------------------------------------- + +if __name__ == "__main__": + if has_option(): + start_cli() + else: + start_app() diff --git a/src/replicator/__init__.py b/src/replicator/__init__.py new file mode 100644 index 00000000..7c3a9253 --- /dev/null +++ b/src/replicator/__init__.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# src/core/__init__.py + +from .replicator import Replicator +from .ui import JobDialog, ScheduleDialog +from .job import Schedule, Endpoint, Job, JobRunResult, JobStore +from .migration import Migration +from .mount import RemoteMountError, MountedEndpoint, mount_endpoint_if_remote + +__version__ = "1.0.0" + +__all__ = [ + "Replicator", + "JobDialog", + "ScheduleDialog", + "Schedule", + "Endpoint", + "Job", + "JobRunResult", + "JobStore", + "Migration", + "RemoteMountError", + "MountedEndpoint", + "mount_endpoint_if_remote", +] diff --git a/src/replicator/job.py b/src/replicator/job.py new file mode 100644 index 00000000..56f102e6 --- /dev/null +++ b/src/replicator/job.py @@ -0,0 +1,766 @@ +#!/usr/bin/env python3 +# src/replicator/job.py + +from __future__ import annotations +import json +from dataclasses import dataclass, field +from datetime import datetime, timedelta, timezone, time +from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Tuple, Union +from urllib.parse import urlparse +from .mount import RemoteMountError, MountedEndpoint, mount_endpoint_if_remote + +try: + # corePY SQLite wrapper (preferred) + from core.database.sqlite import SQLite # type: ignore +except Exception: # pragma: no cover + SQLite = None # type: ignore + +JsonDict = Dict[str, Any] + +# --------------------------------------------------------------------------- +# Data models +# --------------------------------------------------------------------------- + +@dataclass(frozen=True) +class Endpoint: + type: str = "local" + location: str = "" + auth: JsonDict = field(default_factory=dict) + + def validate(self, role: str) -> List[str]: + errs: List[str] = [] + if not self.type: + errs.append(f"{role} endpoint type is required.") + if not self.location: + errs.append(f"{role} endpoint location is required.") + t = (self.type or "").lower() + # SMB port validation removed + return errs + + def to_db_fields(self, role: str) -> JsonDict: + t = (self.type or "local").lower() + auth = dict(self.auth or {}) + + guest: int = 1 + username: Optional[str] = None + password: Optional[str] = None + options: JsonDict = {} + + if t == "local": + pass + elif t == "smb": + guest = 1 if bool(auth.get("guest", True)) else 0 + username = auth.get("username") or None + password = auth.get("password") or None + # Optional SMB domain + options["domain"] = auth.get("domain") + # Optional rclone args (applies to all remote types) + if isinstance(auth.get("rcloneArgs"), list): + options["rcloneArgs"] = auth.get("rcloneArgs") + + known_keys = {"guest", "username", "password", "domain"} + for k, v in auth.items(): + if k not in known_keys: + options[k] = v + + return { + "role": role, + "type": t, + "location": self.location, + "port": None, + "guest": guest, + "username": username, + "password": password, + "options": json.dumps(options) if options else None, + } + + @staticmethod + def from_db_row(row: Mapping[str, Any]) -> "Endpoint": + t = (row.get("type") or "local").lower() + auth: JsonDict = {} + + if t == "local": + auth = {} + elif t == "smb": + auth = { + "guest": bool(row.get("guest", 1)), + "username": row.get("username") or "", + "password": row.get("password") or "", + } + # domain is stored in options JSON when present + + opt = row.get("options") + if opt: + try: + extra = json.loads(opt) + if isinstance(extra, dict): + auth.update(extra) + except Exception: + pass + + return Endpoint(type=t, location=row.get("location") or "", auth=auth) + +@dataclass +class Schedule: + enabled: bool = False + intervalSeconds: int = 3600 + windows: Dict[str, Any] = field(default_factory=dict) + + def to_dict(self) -> Dict[str, Any]: + return { + "enabled": bool(self.enabled), + "intervalSeconds": int(self.intervalSeconds or 0), + "windows": self.windows if isinstance(self.windows, dict) else {}, + } + + @staticmethod + def from_dict(d: Optional[Dict[str, Any]]) -> "Schedule": + d = d or {} + enabled = bool(d.get("enabled", False)) + # intervalSeconds can be on the schedule itself, or in per-day window objects + try: + interval_s = int(d.get("intervalSeconds") or 0) + except Exception: + interval_s = 0 + windows = d.get("windows") if isinstance(d.get("windows"), dict) else {} + if interval_s <= 0: + # best-effort: derive from first window on any day + try: + for _k, _v in windows.items(): + if isinstance(_v, list) and _v and isinstance(_v[0], dict): + v = _v[0].get("intervalSeconds") + if v is not None: + interval_s = int(v or 0) + break + except Exception: + pass + if interval_s <= 0: + interval_s = 3600 + return Schedule(enabled=enabled, intervalSeconds=interval_s, windows=windows) + + def validate(self) -> List[str]: + errs: List[str] = [] + if self.enabled: + try: + iv = int(self.intervalSeconds or 0) + except Exception: + iv = 0 + if iv <= 0: + errs.append("Schedule intervalSeconds must be > 0 when schedule is enabled.") + # windows is optional; if provided, validate structure best-effort + if self.windows and not isinstance(self.windows, dict): + errs.append("Schedule windows must be an object/dict.") + return errs + + def _parse_hhmm(val: Any) -> Optional[Tuple[int, int]]: + try: + parts = str(val).strip().split(":") + if len(parts) != 2: + return None + hh = int(parts[0]); mm = int(parts[1]) + if hh < 0 or hh > 23 or mm < 0 or mm > 59: + return None + return (hh, mm) + except Exception: + return None + + try: + for _day, arr in (self.windows or {}).items(): + if not isinstance(arr, list): + errs.append("Schedule windows entries must be lists.") + continue + for w in arr: + if not isinstance(w, dict): + errs.append("Schedule window must be an object.") + continue + if _parse_hhmm(w.get("start")) is None: + errs.append("Schedule window start must be HH:MM.") + if _parse_hhmm(w.get("end")) is None: + errs.append("Schedule window end must be HH:MM.") + if "intervalSeconds" in w: + try: + if int(w.get("intervalSeconds") or 0) <= 0: + errs.append("Schedule window intervalSeconds must be > 0 when provided.") + except Exception: + errs.append("Schedule window intervalSeconds must be an integer.") + except Exception: + # best-effort validation only + pass + + return errs + + def _window_allows_now_local(self, now_local: datetime) -> bool: + # If windows is missing/not-a-dict, treat as unrestricted (legacy). + if self.windows is None or not isinstance(self.windows, dict): + return True + # If windows is an empty dict, treat as "no service window configured" => not allowed. + if not self.windows: + return False + + wd = now_local.weekday() # 0..6 (Mon..Sun) + day_windows = self.windows.get(str(wd)) or self.windows.get(wd) + if not isinstance(day_windows, list) or not day_windows: + return False + + tnow = now_local.time().replace(tzinfo=None) + + def _parse_hhmm(val: Any) -> Optional[Tuple[int, int]]: + try: + parts = str(val).strip().split(":") + if len(parts) != 2: + return None + hh = int(parts[0]); mm = int(parts[1]) + if hh < 0 or hh > 23 or mm < 0 or mm > 59: + return None + return (hh, mm) + except Exception: + return None + + for w in day_windows: + if not isinstance(w, dict): + continue + ps = _parse_hhmm(w.get("start")) + pe = _parse_hhmm(w.get("end")) + if ps is None or pe is None: + continue + sh, sm = ps; eh, em = pe + ts = datetime(2000, 1, 1, sh, sm).time() + te = datetime(2000, 1, 1, eh, em).time() + + if ts <= te: + if ts <= tnow <= te: + return True + else: + # overnight window (e.g. 22:00-06:00) + if tnow >= ts or tnow <= te: + return True + + return False + + def interval_seconds_for_now(self, now: Optional[datetime] = None) -> int: + now_local = (now or datetime.now(timezone.utc)).astimezone() + # Priority: + # 1) per-day window intervalSeconds (first window entry) + # 2) schedule.intervalSeconds + try: + wd = now_local.weekday() + day = None + if isinstance(self.windows, dict): + day = self.windows.get(str(wd)) or self.windows.get(wd) + if isinstance(day, list) and day and isinstance(day[0], dict): + v = day[0].get("intervalSeconds") + if v is not None: + iv = int(v or 0) + if iv > 0: + return iv + except Exception: + pass + + try: + iv = int(self.intervalSeconds or 0) + return iv if iv > 0 else 3600 + except Exception: + return 3600 + + def should_run_now(self, now: Optional[datetime] = None) -> bool: + if not self.enabled: + return False + now_local = (now or datetime.now(timezone.utc)).astimezone() + return self._window_allows_now_local(now_local) + + def next_run_at(self, now: Optional[datetime] = None) -> Optional[datetime]: + # This domain object doesn't store lastScheduledRunAt; caller should decide cadence. + # We return "now + interval" if windows allow now; otherwise the next allowed window start. + if not self.enabled: + return None + + now_utc = now or datetime.now(timezone.utc) + now_local = now_utc.astimezone() + + if self._window_allows_now_local(now_local): + return now_utc + timedelta(seconds=int(self.interval_seconds_for_now(now_utc))) + + # Find next allowed window start within the next 7 days (best-effort). + if not self.windows or not isinstance(self.windows, dict): + return now_utc + timedelta(seconds=int(self.interval_seconds_for_now(now_utc))) + + def _parse_hhmm(val: Any) -> Optional[Tuple[int, int]]: + try: + parts = str(val).strip().split(":") + if len(parts) != 2: + return None + hh = int(parts[0]); mm = int(parts[1]) + if hh < 0 or hh > 23 or mm < 0 or mm > 59: + return None + return (hh, mm) + except Exception: + return None + + base_local = now_local.replace(second=0, microsecond=0) + for add_days in range(0, 8): + day_local = base_local + timedelta(days=add_days) + wd = day_local.weekday() + day_windows = self.windows.get(str(wd)) or self.windows.get(wd) + if not isinstance(day_windows, list) or not day_windows: + continue + # use the first window as the start candidate (UI currently writes a single window per day) + w0 = day_windows[0] if isinstance(day_windows[0], dict) else None + if not w0: + continue + ps = _parse_hhmm(w0.get("start")) + if ps is None: + continue + sh, sm = ps + candidate_local = day_local.replace(hour=sh, minute=sm) + candidate_utc = candidate_local.astimezone(timezone.utc) + if candidate_utc > now_utc: + return candidate_utc + + return None + +@dataclass +class JobRunResult: + ok: bool + started_at: str + ended_at: str + result: str + message: Optional[str] = None + stats: JsonDict = field(default_factory=dict) + +@dataclass +class Job: + id: Optional[int] = None + name: str = "" + enabled: bool = True + mode: str = "mirror" + direction: str = "unidirectional" + preserveMetadata: bool = True + conflictPolicy: str = "newest" + pairId: Optional[str] = None + + sourceEndpoint: Endpoint = field(default_factory=Endpoint) + targetEndpoint: Endpoint = field(default_factory=Endpoint) + + schedule: Schedule = field(default_factory=Schedule) + + lastRun: Optional[str] = None + lastResult: Optional[str] = None + lastError: Optional[str] = None + + def validate(self) -> List[str]: + errs: List[str] = [] + if not self.name.strip(): + errs.append("Job name is required.") + if not self.mode: + errs.append("Job mode is required.") + if not self.direction: + errs.append("Job direction is required.") + + errs.extend(self.sourceEndpoint.validate("source")) + errs.extend(self.targetEndpoint.validate("target")) + errs.extend(self.schedule.validate()) + + d = (self.direction or "").lower() + if d not in ("unidirectional", "bidirectional"): + errs.append("Job direction must be 'unidirectional' or 'bidirectional'.") + + cp = (self.conflictPolicy or "newest").lower() + if cp not in ("newest", "keepa", "a", "keepb", "b"): + errs.append("conflictPolicy must be one of: newest, keepA/a, keepB/b.") + + return errs + + def should_run_now(self, now: Optional[datetime] = None) -> bool: + if not self.enabled: + return False + return self.schedule.should_run_now(now) + + def next_run_at(self, now: Optional[datetime] = None) -> Optional[datetime]: + if not self.enabled: + return None + return self.schedule.next_run_at(now) + + def run( + self, + *, + now: Optional[datetime] = None, + copy_func: Optional[Callable[..., bool]] = None, + bidirectional_func: Optional[Callable[..., Tuple[bool, JsonDict]]] = None, + logger: Optional[Callable[[str, str], None]] = None, + ) -> JobRunResult: + now_dt = now or datetime.now(timezone.utc) + started_at = now_dt.isoformat() + + def _log(msg: str, level: str = "info") -> None: + if logger: + try: + logger(msg, level) + except Exception: + pass + + errs = self.validate() + if errs: + msg = "; ".join(errs) + ended = datetime.now(timezone.utc).isoformat() + self.lastRun = ended + self.lastResult = "fail" + self.lastError = msg + return JobRunResult( + ok=False, + started_at=started_at, + ended_at=ended, + result="fail", + message=msg, + stats={}, + ) + + if not self.enabled: + ended = datetime.now(timezone.utc).isoformat() + return JobRunResult( + ok=True, + started_at=started_at, + ended_at=ended, + result="ok", + message="Job disabled; skipped.", + stats={}, + ) + + preserve = bool(self.preserveMetadata) + allow_del = (str(self.mode or "").lower() == "mirror") + + # Resolve endpoints (mount SMB endpoints to local paths for the duration of the run) + mounted: List[MountedEndpoint] = [] + ok: bool = False + stats: JsonDict = {} + + # Define upfront so logging/error handling can't reference undefined vars. + src = "" + dst = "" + + try: + # Mount endpoints inside the try so a failure mounting target still cleans up source. + src_m = mount_endpoint_if_remote(self.sourceEndpoint, self.id, "source", logger=logger) + mounted.append(src_m) + dst_m = mount_endpoint_if_remote(self.targetEndpoint, self.id, "target", logger=logger) + mounted.append(dst_m) + + src = src_m.local_path + dst = dst_m.local_path + + if (self.direction or "").lower() == "bidirectional": + if not bidirectional_func: + raise NotImplementedError("Bidirectional engine not provided.") + + # IMPORTANT: + # The bidirectional engine historically enforced local endpoints only by checking + # endpoint types. Since remote endpoints are mounted to local paths for the duration + # of the run, we provide a local-view of this job to the engine. + job_local_view = Job( + id=self.id, + name=self.name, + enabled=self.enabled, + mode=self.mode, + direction=self.direction, + preserveMetadata=self.preserveMetadata, + conflictPolicy=self.conflictPolicy, + pairId=self.pairId, + sourceEndpoint=Endpoint(type="local", location=src, auth={}), + targetEndpoint=Endpoint(type="local", location=dst, auth={}), + schedule=self.schedule, + lastRun=self.lastRun, + lastResult=self.lastResult, + lastError=self.lastError, + ) + + _log(f"[Job] Running bidirectional job '{self.name}': {src} <-> {dst}", "info") + ok, stats = bidirectional_func(job_local_view, None) + else: + if not copy_func: + raise NotImplementedError("Copy function not provided.") + _log(f"[Job] Running unidirectional job '{self.name}': {src} -> {dst}", "info") + ok = bool(copy_func(src, dst, preserve_metadata=preserve, allow_deletion=allow_del)) + except NotImplementedError as e: + ok = False + self.lastError = str(e) + _log(f"[Job] Not supported: {e}", "error") + except Exception as e: + ok = False + self.lastError = str(e) + _log(f"[Job] Execution failed: {e}", "error") + finally: + # Always unmount remote endpoints + for m in reversed(mounted): + try: + m.cleanup() + except Exception: + pass + + ended_at = datetime.now(timezone.utc).isoformat() + self.lastRun = ended_at + self.lastResult = "ok" if ok else "fail" + if ok: + self.lastError = None + else: + self.lastError = self.lastError or "Failed" + + return JobRunResult( + ok=ok, + started_at=started_at, + ended_at=ended_at, + result="ok" if ok else "fail", + message=None if ok else self.lastError, + stats=stats or {}, + ) + + def to_row_dicts(self) -> Dict[str, Any]: + job_row = { + "id": self.id, + "name": self.name, + "enabled": 1 if self.enabled else 0, + "mode": self.mode or "mirror", + "direction": self.direction or "unidirectional", + # "allowDeletion" entry removed; will be derived at write time + "preserveMetadata": 1 if self.preserveMetadata else 0, + "pairId": self.pairId, + "conflictPolicy": self.conflictPolicy or "newest", + "lastRun": self.lastRun, + "lastResult": self.lastResult, + "lastError": self.lastError, + } + + endpoint_rows = [ + self.sourceEndpoint.to_db_fields("source"), + self.targetEndpoint.to_db_fields("target"), + ] + + sched_row = { + "enabled": 1 if self.schedule and self.schedule.enabled else 0, + "intervalSeconds": int(self.schedule.intervalSeconds if self.schedule else 3600), + "windows": json.dumps(self.schedule.windows if self.schedule and isinstance(self.schedule.windows, dict) else {}), + } + + return { + "job_row": job_row, + "endpoint_rows": endpoint_rows, + "schedule_row": sched_row, + } + + @staticmethod + def from_db_rows( + job_row: Mapping[str, Any], + endpoint_rows: Iterable[Mapping[str, Any]], + schedule_row: Optional[Mapping[str, Any]] = None, + ) -> "Job": + j = Job( + id=int(job_row.get("id")) if job_row.get("id") is not None else None, + name=str(job_row.get("name") or ""), + enabled=bool(job_row.get("enabled", 1)), + mode=str(job_row.get("mode") or "mirror"), + direction=str(job_row.get("direction") or "unidirectional"), + preserveMetadata=bool(job_row.get("preserveMetadata", 1)), + conflictPolicy=str(job_row.get("conflictPolicy") or "newest"), + pairId=job_row.get("pairId"), + lastRun=job_row.get("lastRun"), + lastResult=job_row.get("lastResult"), + lastError=job_row.get("lastError"), + ) + + src = None + tgt = None + for r in endpoint_rows: + role = (r.get("role") or "").lower() + ep = Endpoint.from_db_row(r) + if role == "source": + src = ep + elif role == "target": + tgt = ep + + j.sourceEndpoint = src or Endpoint() + j.targetEndpoint = tgt or Endpoint() + + if schedule_row: + # Read intervalSeconds and windows as new model, fallback as needed + try: + interval_s = int(schedule_row.get("intervalSeconds") or 0) + except Exception: + interval_s = 0 + # Remove legacy everyMinutes fallback + if interval_s <= 0: + interval_s = 3600 + windows = {} + try: + raw = schedule_row.get("windows") + if raw: + windows = json.loads(raw) if isinstance(raw, str) else (raw if isinstance(raw, dict) else {}) + except Exception: + windows = {} + j.schedule = Schedule( + enabled=bool(schedule_row.get("enabled", 1)), + intervalSeconds=int(interval_s), + windows=windows, + ) + else: + j.schedule = Schedule() + + return j + + + +# --------------------------------------------------------------------------- +# JobStore (DB persistence) +# --------------------------------------------------------------------------- + +class JobStore: + """SQLite persistence for Job domain objects (UI-agnostic).""" + + def __init__(self, db: Any): + self._db = db + if SQLite is None or not isinstance(self._db, SQLite): + raise TypeError("JobStore requires core.database.sqlite.SQLite") + + def _is_core_sqlite(self) -> bool: + return True + + def _select(self, table: str, where: Optional[str] = None, params: Any = None, *, order_by: Optional[str] = None) -> List[Dict[str, Any]]: + return self._db.select(table, where=where, params=params, order_by=order_by) # type: ignore[union-attr] + + def _one(self, table: str, where: str, params: Any) -> Optional[Dict[str, Any]]: + return self._db.one(f'SELECT * FROM "{table}" WHERE {where} LIMIT 1;', params) # type: ignore[union-attr] + + def _insert(self, table: str, data: Dict[str, Any]) -> int: + return int(self._db.insert(table, data)) # type: ignore[union-attr] + + def _update(self, table: str, data: Dict[str, Any], where: str, params: Any) -> None: + if not isinstance(params, dict): + raise ValueError("JobStore._update requires dict params") + self._db.update(table, data, where, params) # type: ignore[union-attr] + + def _upsert(self, table: str, data: Dict[str, Any], conflict_columns: List[str], update_columns: Optional[List[str]] = None) -> None: + self._db.upsert(table, data, conflict_columns, update_columns) # type: ignore[union-attr] + + def _delete(self, table: str, where: str, params: Any) -> None: + self._db.delete(table, where, params) # type: ignore[union-attr] + + def _transaction(self): + return self._db.transaction() # type: ignore[union-attr] + + # ------------------------------- + # Reads + # ------------------------------- + + def fetch_all(self) -> List[Job]: + job_rows = self._select("jobs", order_by="id ASC") + jobs: List[Job] = [] + for jr in job_rows: + jid = int(jr.get("id") or 0) + ep_rows = self.fetch_endpoints_rows(jid) + sched_row = self.fetch_schedule_row(jid) + jobs.append(Job.from_db_rows(jr, ep_rows, sched_row)) + return jobs + + def fetch_by_id(self, job_id: int) -> Optional[Job]: + jr = self._one("jobs", "id = ?", (int(job_id),)) + if not jr: + return None + ep_rows = self.fetch_endpoints_rows(int(job_id)) + sched_row = self.fetch_schedule_row(int(job_id)) + return Job.from_db_rows(jr, ep_rows, sched_row) + + def fetch_endpoints_rows(self, job_id: int) -> List[Dict[str, Any]]: + return self._select("endpoints", "jobId = ?", (int(job_id),)) + + def fetch_schedule_row(self, job_id: int) -> Optional[Dict[str, Any]]: + return self._one("schedule", "jobId = ?", (int(job_id),)) + + # ------------------------------- + # Writes + # ------------------------------- + + def upsert(self, job: Job) -> int: + row_dicts = job.to_row_dicts() + job_row: Dict[str, Any] = row_dicts["job_row"] + endpoint_rows: List[Dict[str, Any]] = row_dicts["endpoint_rows"] + schedule_row: Dict[str, Any] = row_dicts["schedule_row"] + + with self._transaction(): + # --- jobs --- + data = { + "name": job_row.get("name"), + "enabled": int(job_row.get("enabled") or 0), + "mode": job_row.get("mode") or "mirror", + "direction": job_row.get("direction") or "unidirectional", + # mode is the source of truth for deletion behavior + "allowDeletion": 1 if (str(job_row.get("mode") or "mirror").lower() == "mirror") else 0, + "preserveMetadata": int(job_row.get("preserveMetadata") or 0), + "pairId": job_row.get("pairId"), + "conflictPolicy": job_row.get("conflictPolicy") or "newest", + "lastRun": job_row.get("lastRun"), + "lastResult": job_row.get("lastResult"), + "lastError": job_row.get("lastError"), + } + + if job.id: + self._update("jobs", data, "id = :id", {"id": int(job.id)}) + job_id = int(job.id) + else: + job_id = self._insert("jobs", data) + job.id = job_id + + # --- endpoints (unique: jobId+role) --- + for ep in endpoint_rows: + role = ep.get("role") + if role not in ("source", "target"): + continue + ep_data = { + "jobId": job_id, + "role": role, + "type": ep.get("type"), + "location": ep.get("location"), + "port": ep.get("port"), + "guest": ep.get("guest"), + "username": ep.get("username"), + "password": ep.get("password"), + "options": ep.get("options"), + } + self._upsert( + "endpoints", + ep_data, + ["jobId", "role"], + update_columns=["type", "location", "port", "guest", "username", "password", "options"], + ) + + # --- schedule (unique: jobId) --- + s_data = { + "jobId": job_id, + "enabled": int(schedule_row.get("enabled") or 0), + "intervalSeconds": int(schedule_row.get("intervalSeconds") or 0), + "windows": schedule_row.get("windows"), + } + self._upsert( + "schedule", + s_data, + ["jobId"], + update_columns=["enabled", "intervalSeconds", "windows"], + ) + + return int(job.id or 0) + + def delete(self, job_id: int) -> None: + jid = int(job_id) + with self._transaction(): + # Delete dependent rows first to avoid orphan data (and to work even without FK cascades) + try: + self._delete("endpoints", "jobId = ?", (jid,)) + except Exception: + pass + try: + self._delete("schedule", "jobId = ?", (jid,)) + except Exception: + pass + # These tables may exist depending on enabled features; delete best-effort. + for tbl in ("runs", "conflicts", "file_state"): + try: + self._delete(tbl, "jobId = ?", (jid,)) + except Exception: + pass + self._delete("jobs", "id = ?", (jid,)) diff --git a/src/replicator/migration.py b/src/replicator/migration.py new file mode 100644 index 00000000..e4cddada --- /dev/null +++ b/src/replicator/migration.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 +# src/replicator/migration.py + +from __future__ import annotations + +from typing import List, Optional, Sequence, Tuple + +try: + from core.database.sqlite import SQLite + from core.log import Log +except ImportError: + from database.sqlite import SQLite + from log import Log + + +class Migration: + """Database schema creation + migrations for Replicator. + + This class intentionally *does not* re-implement a DB wrapper. + It relies on corePY's `SQLite` for connections/transactions and only + owns Replicator's schema + migration history + small meta KV helpers. + """ + + def __init__(self, db: SQLite, logger: Optional[Log] = None): + self._db = db + self._logger = logger + + # ------------------------------------------------------------------ + # Public API + # ------------------------------------------------------------------ + + def ensure(self) -> None: + """Ensure base tables exist and apply all pending migrations.""" + self._ensure_schema_migrations_table() + self._apply_migrations(self._migrations()) + + def get_meta(self, key: str, default: Optional[str] = None) -> Optional[str]: + """Read a value from the `meta` table. Returns default if missing.""" + try: + row = self._db.one("SELECT value FROM meta WHERE key = ?", (key,)) + if not row: + return default + val = row.get("value") + return default if val is None else str(val) + except Exception: + return default + + def set_meta(self, key: str, value: Optional[str]) -> None: + """Upsert a value into the `meta` table.""" + try: + with self._db.transaction(): + exists = self._db.scalar("SELECT 1 FROM meta WHERE key = ? LIMIT 1", (key,)) + if exists: + self._db.execute( + "UPDATE meta SET value = ?, modified = CURRENT_TIMESTAMP WHERE key = ?", + (value, key), + ) + else: + self._db.execute( + "INSERT INTO meta (key, value) VALUES (?, ?)", + (key, value), + ) + except Exception: + # best effort + pass + + # ------------------------------------------------------------------ + # Internals + # ------------------------------------------------------------------ + + def _log(self, msg: str, *, level: str = "info", channel: str = "migration") -> None: + if self._logger is not None and hasattr(self._logger, "append"): + self._logger.append(msg, level=level, channel=channel) # type: ignore[call-arg] + else: + print(msg) + + def _ensure_schema_migrations_table(self) -> None: + self._db.execute( + """ + CREATE TABLE IF NOT EXISTS schema_migrations ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + name TEXT NOT NULL UNIQUE + ); + """ + ) + + def _is_applied(self, name: str) -> bool: + r = self._db.scalar( + "SELECT 1 FROM schema_migrations WHERE name = ? LIMIT 1;", + (name,), + ) + return bool(r) + + def _apply_migrations(self, migrations: Sequence[Tuple[str, Sequence[str]]]) -> None: + for name, stmts in migrations: + if self._is_applied(name): + continue + + try: + with self._db.transaction(): + for stmt in stmts: + self._db.execute(stmt) + self._db.execute("INSERT INTO schema_migrations (name) VALUES (?)", (name,)) + + self._log(f"[Migration] applied {name}", level="debug") + except Exception as e: + raise RuntimeError(f"Failed to apply migration {name}: {e}") + + def _migrations(self) -> List[Tuple[str, List[str]]]: + return [ + ( + "0001_init", + [ + # jobs + """ + CREATE TABLE IF NOT EXISTS jobs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + name TEXT NOT NULL, + enabled INTEGER NOT NULL DEFAULT 1, + mode TEXT NOT NULL DEFAULT 'mirror', + direction TEXT NOT NULL DEFAULT 'unidirectional', + allowDeletion INTEGER NOT NULL DEFAULT 0, + preserveMetadata INTEGER NOT NULL DEFAULT 1, + pairId TEXT NULL, + conflictPolicy TEXT NOT NULL DEFAULT 'newest', + lastRun TEXT NULL, + lastResult TEXT NULL, + lastError TEXT NULL + ); + """, + "CREATE INDEX IF NOT EXISTS idx_jobs_enabled ON jobs(enabled);", + + # endpoints + """ + CREATE TABLE IF NOT EXISTS endpoints ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL, + role TEXT NOT NULL, + type TEXT NOT NULL, + location TEXT NOT NULL, + port INTEGER NULL, + guest INTEGER NOT NULL DEFAULT 1, + username TEXT NULL, + password TEXT NULL, + options TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """, + "CREATE UNIQUE INDEX IF NOT EXISTS uq_endpoints_job_role ON endpoints(jobId, role);", + + # schedule + """ + CREATE TABLE IF NOT EXISTS schedule ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL UNIQUE, + -- Schedule is controlled via per-day windows and intervalSeconds. + enabled INTEGER NOT NULL DEFAULT 1, + intervalSeconds INTEGER NOT NULL DEFAULT 3600, + nextRunAt TEXT NULL, + lastScheduledRunAt TEXT NULL, + windows TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """, + + # runs + """ + CREATE TABLE IF NOT EXISTS runs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL, + startedAt TEXT NOT NULL, + endedAt TEXT NULL, + result TEXT NOT NULL, + message TEXT NULL, + stats TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """, + "CREATE INDEX IF NOT EXISTS idx_runs_job_started ON runs(jobId, startedAt);", + + # file_state + """ + CREATE TABLE IF NOT EXISTS file_state ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL, + side TEXT NOT NULL, + relPath TEXT NOT NULL, + size INTEGER NOT NULL DEFAULT 0, + mtime INTEGER NOT NULL DEFAULT 0, + hash TEXT NULL, + isDir INTEGER NOT NULL DEFAULT 0, + deleted INTEGER NOT NULL DEFAULT 0, + deletedAt TEXT NULL, + meta TEXT NULL, + lastSeenAt TEXT NULL, + lastSeenRunId INTEGER NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """, + "CREATE UNIQUE INDEX IF NOT EXISTS uq_file_state ON file_state(jobId, side, relPath);", + + # conflicts + """ + CREATE TABLE IF NOT EXISTS conflicts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL, + runId INTEGER NULL, + relPath TEXT NOT NULL, + a_size INTEGER NULL, + a_mtime INTEGER NULL, + a_hash TEXT NULL, + b_size INTEGER NULL, + b_mtime INTEGER NULL, + b_hash TEXT NULL, + status TEXT NOT NULL DEFAULT 'open', + resolution TEXT NULL, + note TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE, + FOREIGN KEY(runId) REFERENCES runs(id) ON DELETE SET NULL + ); + """, + "CREATE INDEX IF NOT EXISTS idx_conflicts_job_status ON conflicts(jobId, status);", + + # meta (simple KV store) + """ + CREATE TABLE IF NOT EXISTS meta ( + key TEXT PRIMARY KEY, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + value TEXT NULL + ); + """, + ], + ), + ( + "0002_schedule_enabled_default_off", + [ + # SQLite cannot ALTER COLUMN defaults directly; rebuild the schedule table so + # new rows default to enabled=0 while preserving existing data. + "PRAGMA foreign_keys=OFF;", + """ + CREATE TABLE IF NOT EXISTS schedule_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + modified DATETIME DEFAULT CURRENT_TIMESTAMP, + jobId INTEGER NOT NULL UNIQUE, + -- Schedule is controlled via per-day windows and intervalSeconds. + enabled INTEGER NOT NULL DEFAULT 0, + intervalSeconds INTEGER NOT NULL DEFAULT 3600, + nextRunAt TEXT NULL, + lastScheduledRunAt TEXT NULL, + windows TEXT NULL, + FOREIGN KEY(jobId) REFERENCES jobs(id) ON DELETE CASCADE + ); + """.strip(), + """ + INSERT INTO schedule_new (id, created, modified, jobId, enabled, intervalSeconds, nextRunAt, lastScheduledRunAt, windows) + SELECT id, created, modified, jobId, enabled, intervalSeconds, nextRunAt, lastScheduledRunAt, windows + FROM schedule; + """.strip(), + "DROP TABLE schedule;", + "ALTER TABLE schedule_new RENAME TO schedule;", + "PRAGMA foreign_keys=ON;", + ], + ), + ] diff --git a/src/replicator/mount.py b/src/replicator/mount.py new file mode 100644 index 00000000..30f3276a --- /dev/null +++ b/src/replicator/mount.py @@ -0,0 +1,317 @@ + +#!/usr/bin/env python3 +# src/replicator/mount.py + +"""Remote mount helpers for Replicator. + +Purpose +------- +Centralize SMB mounting logic so it can be reused by both: + - UI runner (replicator.py) which often works with legacy dict endpoints + - Domain runner (job.py) which uses Endpoint dataclass objects + +Supported +--------- +- SMB (CIFS / Windows shares) + +This module is intentionally thin and delegates to corePY's Share helper: + from core.filesystem.share import Share, ShareAuth + +Notes +----- +- Remote "location" strings are accepted in common forms: + * \\host\\Share\\dir + * //host/Share/dir + * host/Share/dir +- On macOS, `mount_smbfs` expects URL-style paths; the remote part is + percent-encoded (spaces, etc.) while keeping '/' separators intact. +- Secrets are never logged; obvious fields are redacted. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Callable, Dict, Optional, Tuple + +import os +import re +import tempfile +from urllib.parse import quote + +# corePY Share helper (import once at module import time) +try: + from core.filesystem.share import Share, ShareAuth # type: ignore +except Exception as _e: # pragma: no cover + Share = None # type: ignore + ShareAuth = None # type: ignore + _COREPY_SHARE_IMPORT_ERROR = _e +else: + _COREPY_SHARE_IMPORT_ERROR = None + +# --------------------------------------------------------------------------- +# Exceptions +# --------------------------------------------------------------------------- + +class RemoteMountError(RuntimeError): + """Raised when a remote endpoint cannot be mounted or parsed.""" + +# --------------------------------------------------------------------------- +# Logging helpers +# --------------------------------------------------------------------------- + +def redact_secrets(s: str) -> str: + """Best-effort secret redaction for log lines.""" + if not s: + return s + # key=value patterns + s = re.sub(r"(pass=)([^,\s]+)", r"\1***", s, flags=re.IGNORECASE) + s = re.sub(r"(password=)([^,\s]+)", r"\1***", s, flags=re.IGNORECASE) + # CLI flags + s = re.sub(r"(--password\s+)(\S+)", r"\1***", s, flags=re.IGNORECASE) + s = re.sub(r"(--pass\s+)(\S+)", r"\1***", s, flags=re.IGNORECASE) + return s + +class ShareLoggerAdapter: + """Adapter to feed Share's logging into Replicator/corePY style append().""" + + def __init__(self, append_fn: Callable[[str, str], None] | Callable[..., None]): + self._append = append_fn + + def debug(self, msg: str) -> None: + self._append(redact_secrets(msg), level="debug") # type: ignore[misc] + + def info(self, msg: str) -> None: + self._append(redact_secrets(msg), level="info") # type: ignore[misc] + + def warning(self, msg: str) -> None: + self._append(redact_secrets(msg), level="warning") # type: ignore[misc] + + def error(self, msg: str) -> None: + self._append(redact_secrets(msg), level="error") # type: ignore[misc] + +# --------------------------------------------------------------------------- +# Models +# --------------------------------------------------------------------------- + +@dataclass +class MountedEndpoint: + """Represents a mounted (or local) endpoint.""" + + local_path: str + mount_point: Optional[str] = None + share: Any = None # Share instance (only present when mounted) + + def cleanup(self, *, elevate: bool = False) -> None: + """Unmount the share if mounted; best-effort. + + Notes + ----- + Some platforms/targets may require elevation to unmount. We keep the + default as `False` to match current behavior; callers can opt-in. + """ + if self.share is not None and self.mount_point: + try: + self.share.umount(self.mount_point, elevate=bool(elevate)) + except Exception: + pass + +# --------------------------------------------------------------------------- +# Parsing +# --------------------------------------------------------------------------- + +def parse_smb_location(location: str) -> Tuple[str, str]: + """Parse SMB location into (host, remote). + + Accepts forms: + - \\host\\Share + - \\host\\Share\\dir\\sub + - //host/Share/dir + - host/Share/dir + + Returns: + host, remote where remote is "Share" or "Share/dir/sub". + """ + s = (location or "").strip() + if not s: + raise RemoteMountError("SMB location is empty") + + # Normalize to backslashes then split. + s = s.replace("/", "\\") + while s.startswith("\\"): + s = s[1:] + + parts = [p for p in s.split("\\") if p] + if len(parts) < 2: + raise RemoteMountError( + f"Invalid SMB location '{location}'. Expected //host/Share[/path] or \\\\host\\Share[/path]." + ) + + host = parts[0] + remote = "/".join(parts[1:]) + return host, remote + +# --------------------------------------------------------------------------- +# Mounting +# --------------------------------------------------------------------------- + +def _get_mount_point(job_id: Optional[int], role: str, *, unique: bool = False) -> str: + """Compute the local mount point for a job/role.""" + base = Path(tempfile.gettempdir()) / "replicator" / "mounts" / (str(job_id or "new")) / role + if unique: + # Avoid collisions if caller mounts multiple times quickly. + base = base / str(os.getpid()) + base.mkdir(parents=True, exist_ok=True) + return str(base) + +def mount_endpoint_if_remote( + endpoint: Any, + job_id: Optional[int], + role: str, + *, + share: Any = None, + log_append: Optional[Callable[..., None]] = None, + logger: Any = None, + timeout: int = 60, +) -> MountedEndpoint: + """Mount an endpoint if it is remote; otherwise return the local path. + + Parameters + ---------- + endpoint: + Can be either: + - dict-like: {type, location, auth?} or legacy endpoint row fields + - an object with attributes: .type, .location, .auth + job_id: + Job id (used for mount dir structure). + role: + "source" or "target" (used for mount dir structure). + share: + Optional Share instance to reuse. + log_append: + Function compatible with core Log.append(msg, level=..., channel=...). + If provided, used for safe debug messages. + logger: + Backward-compatible alias used by some callers (e.g. job.py). + Can be either: + - an object exposing `.append(msg, level=...)` (core Log-like) + - a callable compatible with `log_append` + If provided and `log_append` is None, it will be used. + """ + + # Share support is optional at import time; raise a meaningful error at runtime. + if Share is None or ShareAuth is None: + raise RemoteMountError( + "Share support not available (corePY missing or failed to import). " + f"Import error: {_COREPY_SHARE_IMPORT_ERROR}" + ) + + # Backward-compatible: allow callers to pass `logger=` instead of `log_append=`. + if log_append is None and logger is not None: + if callable(logger): + log_append = logger # type: ignore[assignment] + else: + append_fn = getattr(logger, "append", None) + if callable(append_fn): + def _append(msg: str, *, level: str = "info") -> None: + # core Log.append may accept (msg, level=..., channel=...) or (msg, level) + try: + append_fn(msg, level=level) # type: ignore[misc] + except TypeError: + append_fn(msg, level) # type: ignore[misc] + + log_append = _append + + def _get(d: Any, k: str, default: Any = None) -> Any: + if isinstance(d, dict): + return d.get(k, default) + return getattr(d, k, default) + + t = str(_get(endpoint, "type", "local") or "local").lower() + loc = str(_get(endpoint, "location", "") or "").strip() + + if t == "local": + return MountedEndpoint(local_path=loc) + + if t != "smb": + raise RemoteMountError(f"Unsupported endpoint type: {t}") + + mount_point = _get_mount_point(job_id, role, unique=False) + + # Build auth dict from endpoint.auth + legacy flat fields + auth: Dict[str, Any] = {} + raw_auth = _get(endpoint, "auth", None) + if isinstance(raw_auth, dict): + auth.update(raw_auth) + + # Backward compatible: top-level fields (as stored in endpoints table) + for k in ("port", "guest", "username", "password", "options", "domain", "workgroup", "read_only", "ro"): + v = _get(endpoint, k, None) + if v is not None and k not in auth: + auth[k] = v + + # Parse host/remote + host, remote = parse_smb_location(loc) + + # Percent-encode remote path (keep '/' separators) + remote_enc = quote(remote, safe="/") + + # Port + port = 445 + try: + if auth.get("port") is not None: + port = int(auth.get("port") or 445) + except Exception: + port = 445 + + # Options + opts: Dict[str, Any] = {} + if isinstance(auth.get("options"), dict): + opts.update(auth.get("options") or {}) + + # ShareAuth (best effort) + share_auth = ShareAuth( + username=auth.get("username"), + password=auth.get("password"), + domain=auth.get("domain") or auth.get("workgroup"), + ) + + # Share instance (reuse if provided). If we create one here, wire it with our adapter. + if share is None: + share_logger = ShareLoggerAdapter(log_append) if log_append is not None else None + share = Share(logger=share_logger) + + # Emit safe debug line + if log_append is not None: + safe_auth = dict(auth) + for k in ("password", "pass"): + if k in safe_auth and safe_auth[k]: + safe_auth[k] = "***" + msg = ( + f"[Replicator][Mount] protocol={t} host={host} remote={remote_enc} " + f"mount_point={mount_point} auth={safe_auth}" + ) + try: + log_append(msg, level="debug") # type: ignore[misc] + except TypeError: + # Some callables accept only positional args. + log_append(msg) # type: ignore[misc] + + # Mount + try: + share.mount( + t, + host, + remote_enc, + mount_point, + auth=share_auth, + port=port, + options=opts, + read_only=bool(auth.get("read_only") or auth.get("ro") or False), + elevate=False, + timeout=int(timeout or 60), + ) + except Exception as e: + raise RemoteMountError(f"Failed to mount SMB endpoint '{loc}': {e}") + + return MountedEndpoint(local_path=mount_point, mount_point=mount_point, share=share) diff --git a/src/replicator/replicator.py b/src/replicator/replicator.py new file mode 100644 index 00000000..208ea9a7 --- /dev/null +++ b/src/replicator/replicator.py @@ -0,0 +1,1424 @@ +#!/usr/bin/env python3 +# src/replicator/replicator.py + +from __future__ import annotations +import os +import json +import shutil +import time +from typing import Optional, Any, Dict, List +from datetime import datetime, timezone, timedelta +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QPixmap +from PyQt5.QtWidgets import ( + QApplication, + QMainWindow, + QWidget, + QVBoxLayout, + QHBoxLayout, + QLabel, + QTableWidget, + QTableWidgetItem, + QHeaderView, + QDialog, +) +from .ui import JobDialog, ScheduleDialog +from .migration import Migration +from .job import Job, Endpoint, Schedule, JobStore +from .mount import RemoteMountError, MountedEndpoint, mount_endpoint_if_remote + +try: + from core.helper import Helper + from core.configuration import Configuration + from core.log import Log + from core.ui import MsgBox, Form + from core.filesystem.filesystem import FileSystem + from core.filesystem.share import Share, ShareAuth + from core.database.sqlite import SQLite +except ImportError: + from helper import Helper + from configuration import Configuration + from log import Log + from ui import MsgBox, Form + from filesystem.filesystem import FileSystem + from filesystem.share import Share, ShareAuth + from database.sqlite import SQLite + +# --------------------------------------------------------------------------- +# Remote endpoints (Share mount) +# --------------------------------------------------------------------------- + +class _ShareLogger: + """Adapter that forwards Share logs into Replicator's logger.""" + + def __init__(self, append_fn): + self._append = append_fn + + def debug(self, msg: str) -> None: + self._append(f"[Share] {msg}", level="debug") + + def info(self, msg: str) -> None: + self._append(f"[Share] {msg}", level="info") + + def warning(self, msg: str) -> None: + self._append(f"[Share] {msg}", level="warning") + + def error(self, msg: str) -> None: + self._append(f"[Share] {msg}", level="error") + +class Replicator(QMainWindow): + + # ------------------------------------------------------------------ + # Initialization + # ------------------------------------------------------------------ + + def __init__( + self, + helper: Optional[Helper] = None, + configuration: Optional[Configuration] = None, + logger: Optional[Log] = None, + ): + super().__init__() + + self._app = QApplication.instance() + if self._app is None: + raise RuntimeError("Replicator must be created after QApplication/Application.") + + helper = helper or getattr(self._app, "helper", None) + configuration = configuration or getattr(self._app, "configuration", None) + logger = logger or getattr(self._app, "logger", None) + + if helper is None or configuration is None: + raise RuntimeError("Replicator requires corePY Helper + Configuration.") + + self._helper: Helper = helper + self._configuration: Configuration = configuration + self._logger: Optional[Log] = logger + + self._fs = FileSystem(helper=self._helper, logger=self._logger) + + # Shared Share instance (for SMB mounts) so we don't recreate it on every job run. + self._share_logger = _ShareLogger(self._log) + self._share = Share(logger=self._share_logger) + + # --- Database path setup --- + # Use Helper.get_data_path to locate data/replicator.db + data_dir = self._helper.get_data_path("data", scope="system") + if data_dir is None: + raise RuntimeError("Could not locate data/ directory via Helper.get_data_path().") + os.makedirs(data_dir, exist_ok=True) + db_path = os.path.join(data_dir, "replicator.db") + + # --- Database (corePY SQLite wrapper) + migrations --- + self._db = SQLite(db_path=db_path) + self._migration = Migration(self._db, logger=self._logger) + self._migration.ensure() + + self._store = JobStore(self._db) + + self._log(f"[Replicator] Database: {db_path}", level="debug") + self._log("[Replicator] Database migrations applied.", level="info") + + # Domain jobs (Job objects) + self._jobs: List[Job] = [] + self._table: Optional[QTableWidget] = None + + # After DB is ready, log a snapshot of DB layout/counts (non-verbose) + self._db_debug_snapshot(verbose=False) + + # ------------------------------------------------------------------ + # Scheduler (service mode) + # ------------------------------------------------------------------ + + def _parse_iso_dt(self, s: Any) -> Optional[datetime]: + if not s: + return None + try: + dt = datetime.fromisoformat(str(s)) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=timezone.utc) + return dt + except Exception: + return None + + def _should_run_scheduled(self, job: Job, *, now_utc: datetime) -> bool: + """Decide if a job should run in SERVICE/SCHEDULED mode. + + Manual 'Run now' intentionally bypasses this. + """ + if not job.id: + return False + + sched = self._db.one( + "SELECT enabled, nextRunAt, lastScheduledRunAt FROM schedule WHERE jobId=?", + (int(job.id),), + ) + if not sched: + # No schedule row => do not auto-run (manual run still works) + return False + + # Schedule must be explicitly enabled in DB + if not bool(sched.get("enabled", 0)): + return False + + # Schedule windows/interval are defined on the Job domain object + if not job.schedule.should_run_now(now_utc): + return False + + # Respect nextRunAt if present + next_dt = self._parse_iso_dt(sched.get("nextRunAt")) + if next_dt and now_utc < next_dt: + return False + + # Respect lastScheduledRunAt + interval + last_dt = self._parse_iso_dt(sched.get("lastScheduledRunAt")) + if last_dt is None: + return True + + interval_s = int(job.schedule.interval_seconds_for_now(now_utc) or 0) + if interval_s <= 0: + interval_s = self._default_interval_seconds() + + elapsed = (now_utc - last_dt).total_seconds() + return elapsed >= float(interval_s) + # Bidirectional sync helpers (local-only for now) + # ------------------------------------------------------------------ + + def _endpoint_local_root(self, ep: Dict[str, Any]) -> str: + """Return the local root path for an endpoint or raise. + This is a simple extractor for the already-mounted path.""" + if not isinstance(ep, dict): + raise ValueError("Endpoint is missing") + loc = (ep.get("location") or "").strip() + if not loc: + raise ValueError("Endpoint location is required") + return loc + + def _scan_local_tree(self, root: str) -> Dict[str, Dict[str, Any]]: + """Return a map relPath -> {isDir,size,mtime} for a local filesystem root.""" + root = os.path.abspath(root) + out: Dict[str, Dict[str, Any]] = {} + if not os.path.exists(root): + return out + + # Walk directories; include dirs as entries so deletions can be propagated. + for dirpath, dirnames, filenames in os.walk(root): + # Normalize and skip hidden special entries if needed (keep simple for now) + rel_dir = os.path.relpath(dirpath, root) + if rel_dir == ".": + rel_dir = "" + + # Record directory itself (except root) + if rel_dir: + try: + st = os.stat(dirpath) + out[rel_dir] = { + "isDir": True, + "size": 0, + "mtime": int(st.st_mtime), + } + except Exception: + # If stat fails, still record directory + out[rel_dir] = {"isDir": True, "size": 0, "mtime": 0} + + for fn in filenames: + full = os.path.join(dirpath, fn) + rel = os.path.relpath(full, root) + try: + st = os.stat(full) + out[rel] = { + "isDir": False, + "size": int(st.st_size), + "mtime": int(st.st_mtime), + } + except Exception: + out[rel] = {"isDir": False, "size": 0, "mtime": 0} + + return out + + def _load_prev_file_state(self, job_id: int, side: str) -> Dict[str, Dict[str, Any]]: + rows = self._db.query( + "SELECT relPath, size, mtime, isDir, deleted, deletedAt, lastSeenAt, lastSeenRunId FROM file_state WHERE jobId=? AND side=?", + (job_id, side), + ) + prev: Dict[str, Dict[str, Any]] = {} + for r in rows or []: + prev[str(r.get("relPath"))] = { + "size": int(r.get("size") or 0), + "mtime": int(r.get("mtime") or 0), + "isDir": bool(r.get("isDir")), + "deleted": bool(r.get("deleted")), + "deletedAt": r.get("deletedAt"), + "lastSeenAt": r.get("lastSeenAt"), + "lastSeenRunId": r.get("lastSeenRunId"), + } + return prev + + def _persist_file_state(self, job_id: int, side: str, cur: Dict[str, Dict[str, Any]], run_id: Optional[int]) -> None: + # Use wrapper transaction; no raw connection needed. + now_iso = datetime.now(timezone.utc).isoformat() + with self._db.transaction(): + # Upsert all current entries + for rel, meta in cur.items(): + is_dir = 1 if meta.get("isDir") else 0 + size = int(meta.get("size", 0) or 0) + mtime = int(meta.get("mtime", 0) or 0) + + exists = self._db.scalar( + "SELECT id FROM file_state WHERE jobId=? AND side=? AND relPath=?", + (job_id, side, rel), + ) + if exists: + self._db.execute( + "UPDATE file_state SET size=?, mtime=?, isDir=?, deleted=0, deletedAt=NULL, lastSeenAt=?, lastSeenRunId=? WHERE jobId=? AND side=? AND relPath=?", + (size, mtime, is_dir, now_iso, run_id, job_id, side, rel), + ) + else: + self._db.execute( + "INSERT INTO file_state (jobId, side, relPath, size, mtime, isDir, deleted, deletedAt, lastSeenAt, lastSeenRunId) VALUES (?,?,?,?,?,?,0,NULL,?,?)", + (job_id, side, rel, size, mtime, is_dir, now_iso, run_id), + ) + + # Mark missing as deleted (single UPDATE) + rels = list(cur.keys()) + if rels: + placeholders = ",".join(["?"] * len(rels)) + self._db.execute( + f"UPDATE file_state SET deleted=1, deletedAt=COALESCE(deletedAt, ?) WHERE jobId=? AND side=? AND deleted=0 AND relPath NOT IN ({placeholders})", + (now_iso, job_id, side, *rels), + ) + else: + # cur is empty: mark all as deleted for this job/side + self._db.execute( + "UPDATE file_state SET deleted=1, deletedAt=COALESCE(deletedAt, ?) WHERE jobId=? AND side=? AND deleted=0", + (now_iso, job_id, side), + ) + + def _ensure_parent_dir(self, path: str) -> None: + parent = os.path.dirname(path) + if parent and not os.path.exists(parent): + os.makedirs(parent, exist_ok=True) + + def _copy_local_path(self, src_root: str, dst_root: str, rel: str, is_dir: bool, preserve_metadata: bool) -> None: + src_full = os.path.join(src_root, rel) + dst_full = os.path.join(dst_root, rel) + + if is_dir: + os.makedirs(dst_full, exist_ok=True) + return + + self._ensure_parent_dir(dst_full) + if preserve_metadata: + shutil.copy2(src_full, dst_full) + else: + shutil.copy(src_full, dst_full) + + def _delete_local_path(self, root: str, rel: str, is_dir: bool) -> None: + full = os.path.join(root, rel) + if not os.path.exists(full): + return + if is_dir: + # Only remove if empty; never rmtree blindly in sync engine. + try: + os.rmdir(full) + except OSError: + pass + else: + try: + os.remove(full) + except Exception: + pass + + def _record_conflict( + self, + job_id: int, + run_id: Optional[int], + rel: str, + a: Dict[str, Any], + b: Dict[str, Any], + note: str = "", + ) -> None: + try: + # Avoid inserting duplicate open conflicts for the same path/note. + existing = self._db.one( + "SELECT id FROM conflicts WHERE jobId=? AND relPath=? AND status='open' AND COALESCE(note,'')=COALESCE(?, '') ORDER BY id DESC LIMIT 1", + (job_id, rel, note or ""), + ) + if existing: + return + self._db.execute( + """ + INSERT INTO conflicts (jobId, runId, relPath, a_size, a_mtime, a_hash, b_size, b_mtime, b_hash, status, note) + VALUES (?,?,?,?,?,?,?,?,?,'open',?) + """, + ( + job_id, + run_id, + rel, + int(a.get("size", 0) or 0), + int(a.get("mtime", 0) or 0), + a.get("hash"), + int(b.get("size", 0) or 0), + int(b.get("mtime", 0) or 0), + b.get("hash"), + note or None, + ), + ) + except Exception as e: + self._log(f"[Replicator][DB] Failed to record conflict for '{rel}': {e}", level="warning") + + def _run_job_bidirectional(self, job: Dict[str, Any], run_id: Optional[int]) -> tuple[bool, Dict[str, Any]]: + """Bidirectional sync using `file_state` as the persistent baseline. + + Currently implemented for local<->local only. + """ + job_id = int(job.get("id") or 0) + if job_id <= 0: + raise ValueError("Job must have an id to run bidirectional sync") + + src_ep = job.get("sourceEndpoint") + dst_ep = job.get("targetEndpoint") + a_root = self._endpoint_local_root(src_ep) + b_root = self._endpoint_local_root(dst_ep) + + # Deletion behavior is derived from mode; mirror allows deletions. + allow_deletion = str(job.get("mode") or "mirror").lower() == "mirror" + preserve_metadata = bool(job.get("preserveMetadata", True)) + conflict_policy = (job.get("conflictPolicy") or "newest").lower() + + # Load previous baseline before scanning/persisting. + prev_a = self._load_prev_file_state(job_id, "A") + prev_b = self._load_prev_file_state(job_id, "B") + + # Scan current trees + cur_a = self._scan_local_tree(a_root) + cur_b = self._scan_local_tree(b_root) + + def _meta_changed(cur: Dict[str, Any], prev: Dict[str, Any]) -> bool: + return ( + bool(cur.get("isDir")) != bool(prev.get("isDir")) + or int(cur.get("size", 0) or 0) != int(prev.get("size", 0) or 0) + or int(cur.get("mtime", 0) or 0) != int(prev.get("mtime", 0) or 0) + ) + + def _changed_set(cur: Dict[str, Dict[str, Any]], prev: Dict[str, Dict[str, Any]]) -> set[str]: + out = set() + for rel, meta in cur.items(): + p = prev.get(rel) + if p is None or p.get("deleted", False): + out.add(rel) + else: + if _meta_changed(meta, p): + out.add(rel) + return out + + def _deleted_set(cur: Dict[str, Dict[str, Any]], prev: Dict[str, Dict[str, Any]]) -> set[str]: + # deleted since last baseline means it existed (not deleted) and now missing + out = set() + for rel, p in prev.items(): + if p.get("deleted", False): + continue + if rel not in cur: + out.add(rel) + return out + + changed_a = _changed_set(cur_a, prev_a) + changed_b = _changed_set(cur_b, prev_b) + deleted_a = _deleted_set(cur_a, prev_a) + deleted_b = _deleted_set(cur_b, prev_b) + + self._log( + f"[Replicator][BiDi] Snapshot A={len(cur_a)} entries, B={len(cur_b)} entries; changedA={len(changed_a)} changedB={len(changed_b)} deletedA={len(deleted_a)} deletedB={len(deleted_b)}", + level="debug", + ) + + # Build unified rel set + all_paths = set(cur_a.keys()) | set(cur_b.keys()) | set(prev_a.keys()) | set(prev_b.keys()) + + actions_copy_a_to_b: list[tuple[str, bool]] = [] + actions_copy_b_to_a: list[tuple[str, bool]] = [] + actions_del_a: list[tuple[str, bool]] = [] + actions_del_b: list[tuple[str, bool]] = [] + + # Helper for newest + def _winner_newest(a: Dict[str, Any], b: Dict[str, Any]) -> str: + am = int(a.get("mtime", 0) or 0) + bm = int(b.get("mtime", 0) or 0) + if am == bm: + # tie-breaker: larger size wins + return "A" if int(a.get("size", 0) or 0) >= int(b.get("size", 0) or 0) else "B" + return "A" if am > bm else "B" + + for rel in sorted(all_paths): + a_cur = cur_a.get(rel) + b_cur = cur_b.get(rel) + + a_exists = a_cur is not None + b_exists = b_cur is not None + + a_changed = rel in changed_a + b_changed = rel in changed_b + + a_deleted = rel in deleted_a + b_deleted = rel in deleted_b + + # If exists only on one side. + # When deletions are enabled and the missing side deleted it since the last baseline, + # deletion should win unless the existing side also changed (conflict). + if a_exists and not b_exists: + if b_deleted and allow_deletion: + if a_changed: + # conflict: B deleted while A changed + self._record_conflict(job_id, run_id, rel, a_cur, {"deleted": True}, note="B deleted, A changed") + winner = "A" if conflict_policy == "newest" else "A" + if winner == "A": + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + else: + actions_del_a.append((rel, bool(a_cur.get("isDir")))) + else: + # propagate deletion (keep B deleted, delete A) + actions_del_a.append((rel, bool(a_cur.get("isDir")))) + elif b_deleted and not allow_deletion: + # If B was deleted and deletions are not allowed, do NOT copy A->B (do nothing) + pass + else: + # no deletion involved: treat as create on A, copy to B + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + continue + + if b_exists and not a_exists: + if a_deleted and allow_deletion: + if b_changed: + # conflict: A deleted while B changed + self._record_conflict(job_id, run_id, rel, {"deleted": True}, b_cur, note="A deleted, B changed") + winner = "B" if conflict_policy == "newest" else "B" + if winner == "B": + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + else: + actions_del_b.append((rel, bool(b_cur.get("isDir")))) + else: + # propagate deletion (keep A deleted, delete B) + actions_del_b.append((rel, bool(b_cur.get("isDir")))) + elif a_deleted and not allow_deletion: + # If A was deleted and deletions are not allowed, do NOT copy B->A (do nothing) + pass + else: + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + continue + + # Missing on both sides: maybe deletion propagation; nothing to do. + if not a_exists and not b_exists: + continue + + # Exists on both: check if identical + if a_exists and b_exists: + same = ( + bool(a_cur.get("isDir")) == bool(b_cur.get("isDir")) + and int(a_cur.get("size", 0) or 0) == int(b_cur.get("size", 0) or 0) + and int(a_cur.get("mtime", 0) or 0) == int(b_cur.get("mtime", 0) or 0) + ) + + if same: + # Maybe propagate deletions if one side deleted previously (should not happen if same exists) + continue + + # Not same: detect changes since baseline + if a_changed and b_changed: + # true conflict + self._record_conflict(job_id, run_id, rel, a_cur, b_cur, note="Changed on both sides") + if conflict_policy == "newest": + winner = _winner_newest(a_cur, b_cur) + elif conflict_policy in ("keepa", "a"): + winner = "A" + elif conflict_policy in ("keepb", "b"): + winner = "B" + else: + winner = _winner_newest(a_cur, b_cur) + + if winner == "A": + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + else: + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + elif a_changed and not b_changed: + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + elif b_changed and not a_changed: + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + else: + # differs but we can't prove which changed vs baseline (e.g., first run with baseline empty) + # Choose newest as default. + winner = _winner_newest(a_cur, b_cur) + if winner == "A": + actions_copy_a_to_b.append((rel, bool(a_cur.get("isDir")))) + else: + actions_copy_b_to_a.append((rel, bool(b_cur.get("isDir")))) + + # Deletions propagation (safe rules) + if allow_deletion: + # If A deleted and B did not change since baseline, delete on B + for rel in sorted(deleted_a): + if rel in changed_b: + # conflict: deleted on A but changed on B + self._record_conflict(job_id, run_id, rel, {"deleted": True}, cur_b.get(rel, {}), note="A deleted, B changed") + continue + pb = prev_b.get(rel) + if pb and not pb.get("deleted", False) and rel in cur_b: + actions_del_b.append((rel, bool(cur_b[rel].get("isDir")))) + + # If B deleted and A did not change since baseline, delete on A + for rel in sorted(deleted_b): + if rel in changed_a: + self._record_conflict(job_id, run_id, rel, cur_a.get(rel, {}), {"deleted": True}, note="B deleted, A changed") + continue + pa = prev_a.get(rel) + if pa and not pa.get("deleted", False) and rel in cur_a: + actions_del_a.append((rel, bool(cur_a[rel].get("isDir")))) + + # Execute actions + try: + # Copy directories first to ensure parents exist + for rel, is_dir in actions_copy_a_to_b: + self._copy_local_path(a_root, b_root, rel, is_dir, preserve_metadata) + for rel, is_dir in actions_copy_b_to_a: + self._copy_local_path(b_root, a_root, rel, is_dir, preserve_metadata) + + # Then copy files (copy method handles both, but ordering helps for deep paths) + # (Already handled in _copy_local_path) + + # Deletions last + for rel, is_dir in actions_del_a: + self._delete_local_path(a_root, rel, is_dir) + for rel, is_dir in actions_del_b: + self._delete_local_path(b_root, rel, is_dir) + + except Exception as e: + self._log(f"[Replicator][BiDi] Execution failed: {e}", level="error") + return False, {} + + # After actions, scan again and persist final file state as baseline + final_a = self._scan_local_tree(a_root) + final_b = self._scan_local_tree(b_root) + self._persist_file_state(job_id, "A", final_a, run_id) + self._persist_file_state(job_id, "B", final_b, run_id) + + stats = { + "copyAtoB": len(actions_copy_a_to_b), + "copyBtoA": len(actions_copy_b_to_a), + "delA": len(actions_del_a), + "delB": len(actions_del_b), + "changedA": len(changed_a), + "changedB": len(changed_b), + "deletedA": len(deleted_a), + "deletedB": len(deleted_b), + } + self._log(f"[Replicator][BiDi] Actions: {stats}", level="debug") + + # Update run stats if possible + if run_id: + try: + self._db.execute( + "UPDATE runs SET stats=? WHERE id=?", + (json.dumps(stats), run_id), + ) + except Exception: + pass + + return True, stats + + # ------------------------------------------------------------------ + # CLI integration + # ------------------------------------------------------------------ + + def cli(self, cli: QApplication = None) -> None: + """ + Called by corePY CommandLine when running in CLI mode. + """ + if cli is None: + return + cli.add("run", "Run all replication jobs.", self.run) + cli.service.add("run", "Run all replication jobs", self.run_scheduled, interval=1) + + # ------------------------------------------------------------------ + # UI + # ------------------------------------------------------------------ + + def show(self): + self.init() + super().show() + + def init(self): + self.setWindowTitle(getattr(self._app, "name", "Replicator")) + self.setObjectName("Replicator") + # Ensure minimum window width for table visibility + self.setMinimumWidth(800) + + central = QWidget(self) + self.setCentralWidget(central) + central.setStyleSheet("background-color: #212121;") + root = QVBoxLayout(central) + root.setContentsMargins(16, 16, 16, 16) + root.setSpacing(12) + + # Logo (top, centered) + logo = QLabel() + logo.setAlignment(Qt.AlignCenter) + + # Use app icon/logo if you have one; otherwise harmless + # Adjust path to wherever you store icons in Replicator + candidate = self._helper.get_path("icons/icon.png") or self._helper.get_path("core/icons/info.svg") + name = getattr(self._app, "name", None) or self._app.applicationName() + if candidate and self._helper.file_exists(candidate) and candidate.lower().endswith(".png"): + pm = QPixmap(candidate) + if not pm.isNull(): + logo.setPixmap(pm.scaled(256, 256, Qt.KeepAspectRatio, Qt.SmoothTransformation)) + else: + logo.setText(name) + logo.setStyleSheet("font-size: 32px; font-weight: 200; opacity: 0.8; padding: 0px; margin: 0px;") + + root.addWidget(logo) + + # Application name (under logo) + app_name = QLabel() + app_name.setText(str(name) if name else "") + app_name.setAlignment(Qt.AlignCenter) + app_name.setStyleSheet("font-size: 32px; font-weight: 200; opacity: 0.8; padding: 0px; margin: 0px;") + root.addWidget(app_name) + + # --- Actions row (top, after logo) --- + actions_row = QHBoxLayout() + # No stretch at start; left-aligned by default + self._add_btn = Form.button(label="", icon="plus-circle", action=self._add_job) + self._add_btn.setToolTip("Add job") + self._edit_btn = Form.button(label="", icon="pencil-square", action=self._edit_job) + self._edit_btn.setToolTip("Edit job") + self._edit_btn.setVisible(False) + self._dup_btn = Form.button(label="", icon="files", action=self._duplicate_job) + self._dup_btn.setToolTip("Duplicate job") + self._dup_btn.setVisible(False) + self._del_btn = Form.button(label="", icon="trash", action=self._delete_job) + self._del_btn.setToolTip("Delete job") + self._del_btn.setVisible(False) + self._schedule_btn = Form.button(label="", icon="calendar-event", action=self._edit_schedule) + self._schedule_btn.setToolTip("Schedule") + self._schedule_btn.setVisible(False) + actions_row.addWidget(self._add_btn) + actions_row.addWidget(self._edit_btn) + actions_row.addWidget(self._dup_btn) + actions_row.addWidget(self._del_btn) + actions_row.addWidget(self._schedule_btn) + actions_row.addStretch(1) + root.addLayout(actions_row) + + # Table + self._table = QTableWidget(0, 6, self) + self._table.setHorizontalHeaderLabels([ + "Name", "Enabled", "Source", "Target", "Last run", "Result" + ]) + self._table.setSelectionBehavior(QTableWidget.SelectRows) + self._table.setEditTriggers(QTableWidget.NoEditTriggers) + + # Hide row numbers + self._table.verticalHeader().setVisible(False) + + # Connect selection change to update visibility of action buttons + self._table.selectionModel().selectionChanged.connect(self._on_selection_changed) + + # Ensure columns never shrink below their content (use scrollbar for overflow) + header = self._table.horizontalHeader() + # Performance: ResizeToContents on every column can get painfully slow. + header.setSectionResizeMode(0, QHeaderView.Stretch) # Name + for i in range(1, self._table.columnCount()): + header.setSectionResizeMode(i, QHeaderView.ResizeToContents) + + # Keep horizontal scrollbar available for overflow + header.setStretchLastSection(False) + + root.addWidget(self._table) + + # --- Bottom row: Service Manager, Configurator and Run now (right aligned) --- + bottom_row = QHBoxLayout() + bottom_row.addStretch(1) + + service_btn = Form.button(label="", icon="hdd-network", action=self._open_service_manager) + service_btn.setToolTip("Service Manager") + + config_btn = Form.button(label="", icon="gear-fill", action=self._configuration.show) + config_btn.setToolTip("Configurator") + + run_btn = Form.button(label="", icon="play-fill", action=lambda: self._run_with_ui_feedback()) + run_btn.setToolTip("Run now") + + bottom_row.addWidget(service_btn) + bottom_row.addWidget(config_btn) + bottom_row.addWidget(run_btn) + root.addLayout(bottom_row) + + self._reload_jobs() + self._on_selection_changed() + + def _on_selection_changed(self, *_args): + has = self._selected_index() >= 0 + if hasattr(self, "_edit_btn"): + self._edit_btn.setVisible(has) + if hasattr(self, "_dup_btn"): + self._dup_btn.setVisible(has) + if hasattr(self, "_del_btn"): + self._del_btn.setVisible(has) + if hasattr(self, "_schedule_btn"): + self._schedule_btn.setVisible(has) + + def _selected_index(self) -> int: + if not self._table: + return -1 + rows = self._table.selectionModel().selectedRows() + if not rows: + return -1 + return rows[0].row() + + def _reload_jobs(self): + self._jobs = self._store.fetch_all() + self._refresh_table() + + def _save_jobs(self): + return + + def _refresh_table(self): + if not self._table: + return + self._table.setRowCount(0) + + for job in self._jobs: + r = self._table.rowCount() + self._table.insertRow(r) + + def _it(v: Any) -> QTableWidgetItem: + item = QTableWidgetItem(str(v) if v is not None else "") + item.setFlags(item.flags() ^ Qt.ItemIsEditable) + return item + + self._table.setItem(r, 0, _it(job.name)) + self._table.setItem(r, 1, _it("On" if job.enabled else "Off")) + + src_str = f"{job.sourceEndpoint.type}:{job.sourceEndpoint.location}" + tgt_str = f"{job.targetEndpoint.type}:{job.targetEndpoint.location}" + self._table.setItem(r, 2, _it(src_str)) + self._table.setItem(r, 3, _it(tgt_str)) + + last_run = job.lastRun + self._table.setItem(r, 4, _it(last_run if last_run else "Never")) + + self._table.setItem(r, 5, _it(job.lastResult or "")) + + def _default_interval_seconds(self) -> int: + """Return the configured default interval in seconds (service.defaultInterval), fallback to 3600.""" + try: + v = self._configuration.get("service.defaultInterval", 3600) + iv = int(v) + return iv if iv > 0 else 3600 + except Exception: + return 3600 + + def _default_schedule_dict(self) -> Dict[str, Any]: + interval = self._default_interval_seconds() + windows: Dict[str, Any] = {} + for wd in range(7): + windows[str(wd)] = [{"start": "00:00", "end": "23:59", "intervalSeconds": interval}] + return { + "enabled": False, + "intervalSeconds": interval, + "windows": windows, + } + + def _schedule_interval_seconds_for_now(self, sched: Dict[str, Any]) -> int: + # Kept for backward compatibility with existing log formatting. + # Prefer the Job/Schedule domain helpers where possible. + try: + j = self._job_from_legacy_dict({"schedule": sched, "name": "_tmp", "enabled": True, "sourceEndpoint": {"type": "local", "location": "/"}, "targetEndpoint": {"type": "local", "location": "/"}}) + return int(j.schedule.interval_seconds_for_now(datetime.now(timezone.utc)) or 0) or self._default_interval_seconds() + except Exception: + return self._default_interval_seconds() + + def _job_from_legacy_dict(self, d: Dict[str, Any], *, existing_id: Optional[int] = None) -> Job: + src = d.get("sourceEndpoint") or {"type": "local", "location": d.get("source", ""), "auth": {}} + tgt = d.get("targetEndpoint") or {"type": "local", "location": d.get("target", ""), "auth": {}} + + # Schedule defaults: + # - enabled + # - every day, all day + # - interval 3600 seconds (1h) + sched = d.get("schedule") + if not isinstance(sched, dict): + sched = self._default_schedule_dict() + + default_interval = self._default_interval_seconds() + + # Normalize intervalSeconds (no everyMinutes support) + try: + iv = int(sched.get("intervalSeconds") or 0) + except Exception: + iv = 0 + if iv <= 0: + iv = default_interval + sched["intervalSeconds"] = iv + + # Ensure windows exist; if missing, make it "every day, all day" with per-day interval + windows = sched.get("windows") + if not isinstance(windows, dict) or not windows: + windows = {} + for wd in range(7): + windows[str(wd)] = [{"start": "00:00", "end": "23:59", "intervalSeconds": iv}] + sched["windows"] = windows + else: + # Ensure each enabled day window includes intervalSeconds (per-day) for the upcoming scheduler logic + for k, v in list(windows.items()): + if isinstance(v, list) and v and isinstance(v[0], dict): + if "intervalSeconds" not in v[0]: + v[0]["intervalSeconds"] = iv + + j = Job( + id=existing_id, + name=str(d.get("name") or ""), + enabled=bool(d.get("enabled", True)), + mode=str(d.get("mode") or "mirror"), + direction=str(d.get("direction") or "unidirectional"), + # Deletion behavior is derived from mode; mirror allows deletions. + allowDeletion=(str(d.get("mode") or "mirror").lower() == "mirror"), + preserveMetadata=bool(d.get("preserveMetadata", True)), + conflictPolicy=str(d.get("conflictPolicy") or "newest"), + pairId=d.get("pairId"), + lastRun=d.get("lastRun"), + lastResult=d.get("lastResult"), + lastError=d.get("lastError"), + ) + + j.sourceEndpoint = Endpoint( + type=str(src.get("type") or "local"), + location=str(src.get("location") or ""), + auth=dict(src.get("auth") or {}), + ) + j.targetEndpoint = Endpoint( + type=str(tgt.get("type") or "local"), + location=str(tgt.get("location") or ""), + auth=dict(tgt.get("auth") or {}), + ) + + windows = sched.get("windows") if isinstance(sched.get("windows"), dict) else {} + + j.schedule = Schedule( + enabled=bool(sched.get("enabled", False)), + intervalSeconds=int(iv), + windows=windows, + ) + + return j + + def _add_job(self): + # Pass configured service.defaultInterval into the dialog so Schedule defaults match user config + dlg = JobDialog(self, default_interval_seconds=self._default_interval_seconds()) + if dlg.exec_() == QDialog.Accepted: + new_job_dict = dlg.value() + if "schedule" not in new_job_dict or not isinstance(new_job_dict.get("schedule"), dict): + new_job_dict["schedule"] = self._default_schedule_dict() + job_obj = self._job_from_legacy_dict(new_job_dict) + job_id = self._store.upsert(job_obj) + job_obj.id = job_id + self._reload_jobs() + + def _edit_job(self): + idx = self._selected_index() + if idx < 0: + MsgBox.show(self, "Jobs", "Select a job to edit.", icon="info") + return + + current = self._jobs[idx] + # Pass configured service.defaultInterval into the dialog so Schedule defaults remain consistent + dlg = JobDialog(self, current.to_legacy_dict(), default_interval_seconds=self._default_interval_seconds()) + if dlg.exec_() == QDialog.Accepted: + updated_dict = dlg.value() + job_obj = self._job_from_legacy_dict(updated_dict, existing_id=current.id) + self._store.upsert(job_obj) + self._reload_jobs() + + def _duplicate_job(self): + idx = self._selected_index() + if idx < 0: + MsgBox.show(self, "Jobs", "Select a job to duplicate.", icon="info") + return + + orig = self._jobs[idx] + d = orig.to_legacy_dict() + d.pop("id", None) + d["name"] = f"{orig.name} (copy)" if orig.name else "Copy" + + job_obj = self._job_from_legacy_dict(d) + self._store.upsert(job_obj) + self._reload_jobs() + + if self._table: + # Select the newest row (best-effort) + self._table.selectRow(self._table.rowCount() - 1) + + def _delete_job(self): + idx = self._selected_index() + if idx < 0: + MsgBox.show(self, "Jobs", "Select a job to delete.", icon="info") + return + + job = self._jobs[idx] + choice = MsgBox.show( + self, + title="Delete", + message=f"Delete job '{job.name}'?", + icon="question", + buttons=("Cancel", "Delete"), + default="Cancel", + ) + if choice == "Delete": + if job.id: + jid = int(job.id) + try: + with self._db.transaction(): + # Explicitly delete dependent rows to avoid orphans. + self._db.execute("DELETE FROM endpoints WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM schedule WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM runs WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM conflicts WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM file_state WHERE jobId = ?", (jid,)) + self._db.execute("DELETE FROM jobs WHERE id = ?", (jid,)) + except Exception as e: + self._log(f"[Replicator][DB] Failed to delete job {jid} cascade: {e}", level="warning") + # Fallback to store deletion if cascade failed. + try: + self._store.delete(jid) + except Exception: + pass + self._reload_jobs() + + def _edit_schedule(self): + idx = self._selected_index() + if idx < 0: + MsgBox.show(self, "Jobs", "Select a job to edit schedule.", icon="info") + return + + current = self._jobs[idx] + # Pass configured service.defaultInterval into the schedule editor so defaults match user config + dlg = ScheduleDialog(self, job=current.to_legacy_dict(), default_interval_seconds=self._default_interval_seconds()) + if dlg.exec_() == QDialog.Accepted: + d = current.to_legacy_dict() + d["schedule"] = dlg.value() + job_obj = self._job_from_legacy_dict(d, existing_id=current.id) + self._store.upsert(job_obj) + self._reload_jobs() + + def _run_with_ui_feedback(self): + ok = self.run() + MsgBox.show( + self, + title="Replicator", + message="Replication completed successfully." if ok else "Replication finished with errors.", + icon="info" if ok else "warning", + ) + + # ------------------------------------------------------------------ + # Execution + # ------------------------------------------------------------------ + + def run_scheduled(self) -> bool: + """ + Scheduled/service execution entrypoint. + Respects per-job schedule (enabled/windows/interval). + Returns True if all eligible jobs succeeded. + """ + self._reload_jobs() + + verbose_db = False + try: + verbose_db = bool(self._configuration.get("log.verbose", False)) + except Exception: + verbose_db = False + self._db_debug_snapshot(verbose=verbose_db) + + if not self._jobs: + self._log("[Replicator] No jobs configured.", level="warning") + return False + + now_utc = datetime.now(timezone.utc) + + any_ran = False + all_ok = True + + for job in self._jobs: + if not bool(job.enabled): + continue + + if not self._should_run_scheduled(job, now_utc=now_utc): + continue + + any_ran = True + ok = self._run_job(job) + all_ok = all_ok and ok + + # Update schedule bookkeeping for this job + try: + interval_s = int(job.schedule.interval_seconds_for_now(datetime.now(timezone.utc)) or 0) or self._default_interval_seconds() + next_run = (datetime.now(timezone.utc) + timedelta(seconds=int(interval_s))).isoformat() + self._db.update( + "schedule", + { + "lastScheduledRunAt": datetime.now(timezone.utc).isoformat(), + "nextRunAt": next_run, + }, + "jobId = :jobId", + {"jobId": int(job.id)}, + ) + except Exception: + pass + + if not any_ran: + self._log("[Replicator] No jobs due per schedule.", level="debug") + + return all_ok + + def run(self) -> bool: + """ + Run all configured jobs (from DB). + Returns True if all jobs succeeded. + """ + self._reload_jobs() + # After reloading jobs, log a DB snapshot for debugging. + # Only log verbose DB details when log.verbose is enabled. + verbose_db = False + try: + verbose_db = bool(self._configuration.get("log.verbose", False)) + except Exception: + verbose_db = False + + self._db_debug_snapshot(verbose=verbose_db) + jobs: List[Job] = self._jobs + if not jobs: + self._log("[Replicator] No jobs configured.", level="warning") + return False + + all_ok = True + for job in jobs: + if not bool(job.enabled): + self._log(f"[Replicator] Skipping disabled job '{job.name or 'Unnamed'}'.", level="info") + continue + ok = self._run_job(job) + all_ok = all_ok and ok + + # Run DB maintenance at most once per day. + try: + last = self._migration.get_meta("maintenance.lastRunAt") + should = True + if last: + try: + last_dt = datetime.fromisoformat(str(last)) + if last_dt.tzinfo is None: + last_dt = last_dt.replace(tzinfo=timezone.utc) + should = (datetime.now(timezone.utc) - last_dt).total_seconds() >= 86400 + except Exception: + should = True + if should: + self._db_maintenance() + except Exception: + pass + + return all_ok + + def _run_job(self, job: Job) -> bool: + name = job.name or "Unnamed" + if not bool(job.enabled): + self._log(f"[Replicator] Job '{name}' is disabled; skipping.", level="info") + return True + job_id = job.id + src = job.sourceEndpoint.location + src_type = job.sourceEndpoint.type + dst = job.targetEndpoint.location + dst_type = job.targetEndpoint.type + mode = job.mode + # Deletion behavior is derived from mode; mirror allows deletions. + allow_deletion = str(mode or "mirror").lower() == "mirror" + preserve_metadata = bool(job.preserveMetadata) + direction = job.direction + + if not src or not dst: + self._log(f"[Replicator] Job '{name}' invalid: missing source or target path (src='{src}', dst='{dst}').", level="error") + return False + + sched_str = "" + try: + if job_id: + sched = self._db.one( + "SELECT enabled FROM schedule WHERE jobId=?", + (int(job_id),), + ) + if sched and bool(sched.get("enabled", 0)): + interval_s = int(job.schedule.interval_seconds_for_now(datetime.now(timezone.utc)) or 0) or self._default_interval_seconds() + sched_str = f", schedule=Interval {interval_s}s" + except Exception: + pass + logline = f"[Replicator] Running job '{name}': {src} -> {dst} (mode={mode}, direction={direction}, delete={allow_deletion}, meta={preserve_metadata}{sched_str}" + logline += f", srcType={src_type}, dstType={dst_type})" + self._log(logline) + + # Insert a run record at start + started_at = datetime.now(timezone.utc).isoformat() + run_id = None + bidi_stats = None + try: + run_id = None + if job_id: + try: + run_id = int(self._db.insert("runs", {"jobId": int(job_id), "startedAt": started_at, "result": "running"})) + except Exception as e: + self._log(f"[Replicator] Failed to insert run record: {e}", level="warning") + except Exception as e: + self._log(f"[Replicator] Failed to insert run record: {e}", level="warning") + + record_noop_runs = bool(self._configuration.get("db.recordNoopRuns", False)) + + ok = False + try: + # Always build a legacy dict so we can reuse the endpoint records + auth. + job_dict = job.to_legacy_dict() + src_ep = job_dict.get("sourceEndpoint") or {"type": "local", "location": src, "auth": {}} + dst_ep = job_dict.get("targetEndpoint") or {"type": "local", "location": dst, "auth": {}} + + # Mount remote endpoints (SMB only) via Share so BOTH uni + bidi operate on + # local filesystem paths, and we get connectivity debug logs. + mounted: list[MountedEndpoint] = [] + + try: + src_m = mount_endpoint_if_remote(src_ep, job_id, "source", share=self._share, log_append=self._log) + mounted.append(src_m) + dst_m = mount_endpoint_if_remote(dst_ep, job_id, "target", share=self._share, log_append=self._log) + mounted.append(dst_m) + + # Use the mounted/local view for execution + local_src = src_m.local_path + local_dst = dst_m.local_path + + if str(direction).lower() == "bidirectional": + # Local view for the bidirectional sync engine + job_dict["sourceEndpoint"] = {"type": "local", "location": local_src, "auth": {}} + job_dict["targetEndpoint"] = {"type": "local", "location": local_dst, "auth": {}} + ok, bidi_stats = self._run_job_bidirectional(job_dict, run_id) + else: + # Unidirectional copy (mirror) also uses mounted/local paths + ok = self._fs.copy( + local_src, + local_dst, + preserve_metadata=preserve_metadata, + allow_deletion=allow_deletion, + ) + finally: + for m in reversed(mounted): + try: + m.cleanup() + except Exception: + pass + except NotImplementedError as e: + self._log(f"[Replicator] Job '{name}' not supported: {e}", level="error") + ok = False + except RemoteMountError as e: + self._log(f"[Replicator] Job '{name}' failed to mount remote endpoint: {e}", level="error") + ok = False + except Exception as e: + self._log(f"[Replicator] Job '{name}' failed: {e}", level="error") + ok = False + + # If this was a bidirectional run with no actions/changes, optionally drop the run row. + if run_id and bidi_stats is not None and not record_noop_runs: + try: + noop = ( + int(bidi_stats.get("copyAtoB", 0) or 0) == 0 + and int(bidi_stats.get("copyBtoA", 0) or 0) == 0 + and int(bidi_stats.get("delA", 0) or 0) == 0 + and int(bidi_stats.get("delB", 0) or 0) == 0 + and int(bidi_stats.get("changedA", 0) or 0) == 0 + and int(bidi_stats.get("changedB", 0) or 0) == 0 + and int(bidi_stats.get("deletedA", 0) or 0) == 0 + and int(bidi_stats.get("deletedB", 0) or 0) == 0 + ) + if noop: + self._db.execute("DELETE FROM runs WHERE id = ?", (run_id,)) + run_id = None + except Exception: + pass + + # Persist lastRun and lastResult, refresh UI, save to DB + now_str = datetime.now(timezone.utc).isoformat() + job.lastRun = now_str + job.lastResult = "ok" if ok else "fail" + job.lastError = None if ok else (job.lastError or "Failed") + self._store.upsert(job) + if run_id: + try: + self._db.update( + "runs", + {"endedAt": now_str, "result": ("ok" if ok else "fail"), "message": (None if ok else (job.lastError or "Failed"))}, + "id = :id", + {"id": int(run_id)}, + ) + except Exception as e: + self._log(f"[Replicator] Failed to update run record: {e}", level="warning") + if self._table: + self._reload_jobs() + + self._log(f"[Replicator] Job '{job.name}' result: {'OK' if ok else 'FAIL'} (lastResult={job.lastResult})", level="info" if ok else "warning") + return ok + + def _log(self, msg: str, level: str = "info", channel: str = "replicator") -> None: + if self._logger is not None and hasattr(self._logger, "append"): + self._logger.append(msg, level=level, channel=channel) # type: ignore[call-arg] + else: + print(msg) + + def _db_debug_snapshot(self, verbose: bool = False) -> None: + """ + Log a compact snapshot of the current DB layout + row counts. + If verbose=True, also logs the most recent rows for key tables. + """ + try: + # List tables + tables = [r["name"] for r in self._db.query("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name")] + + self._log(f"[Replicator][DB] Tables: {', '.join(tables) if tables else '(none)'}", level="debug") + + # Layout + counts + for t in tables: + try: + cols = self._db.query(f"PRAGMA table_info({t})") + col_names = [c.get("name") for c in cols] + count = int(self._db.scalar(f"SELECT COUNT(*) FROM {t}") or 0) + self._log(f"[Replicator][DB] {t}: columns={len(col_names)} rows={count}", level="debug") + if verbose: + self._log(f"[Replicator][DB] {t}: {', '.join(col_names)}", level="debug") + except Exception as e: + self._log(f"[Replicator][DB] Failed introspecting {t}: {e}", level="warning") + + if not verbose: + return + + for t, order_col in (("jobs", "id"), ("runs", "id"), ("schedule", "id"), ("conflicts", "id")): + if t in tables: + try: + rows = self._db.query(f"SELECT * FROM {t} ORDER BY {order_col} DESC LIMIT 3") + self._log(f"[Replicator][DB] {t}: latest {len(rows)} row(s)", level="debug") + for r in rows: + dr = dict(r) + for k in ("password", "pass"): + if k in dr and dr[k]: + dr[k] = "***" + self._log(f"[Replicator][DB] {t}: {dr}", level="debug") + except Exception as e: + self._log(f"[Replicator][DB] Failed reading latest rows from {t}: {e}", level="warning") + + except Exception as e: + self._log(f"[Replicator][DB] Snapshot failed: {e}", level="warning") + + def _db_maintenance(self) -> None: + """Prune old history and run lightweight SQLite maintenance. + + Safe defaults: + - Keep last N runs per job (db.retention.runs.keepLast) + - Also prune runs older than X days (db.retention.runs.keepDays) + - Keep open conflicts; prune resolved conflicts older than X days + - Optionally VACUUM (off by default) + + This is designed to be called periodically (e.g. daily) by the service loop. + """ + try: + keep_last = int(self._configuration.get("db.retention.runs.keepLast", 500)) + keep_days = int(self._configuration.get("db.retention.runs.keepDays", 30)) + prune_conflict_days = int(self._configuration.get("db.retention.conflicts.keepDays", 90)) + prune_deleted_state_days = int(self._configuration.get("db.retention.fileState.deletedKeepDays", 30)) + do_vacuum = bool(self._configuration.get("db.maintenance.vacuum", False)) + except Exception: + keep_last, keep_days = 500, 30 + prune_conflict_days, prune_deleted_state_days = 90, 30 + do_vacuum = False + + now = datetime.now(timezone.utc) + now_iso = now.isoformat() + + # Runs: keep last N per job + prune anything older than keep_days + try: + job_ids = [int(r.get("id")) for r in (self._db.query("SELECT id FROM jobs") or [])] + with self._db.transaction(): + for jid in job_ids: + if keep_last > 0: + self._db.execute( + """ + DELETE FROM runs + WHERE jobId = ? + AND id NOT IN ( + SELECT id FROM runs WHERE jobId = ? ORDER BY id DESC LIMIT ? + ) + """, + (jid, jid, keep_last), + ) + + if keep_days > 0: + self._db.execute( + "DELETE FROM runs WHERE julianday(created) < julianday('now', ?) ", + (f'-{keep_days} days',), + ) + except Exception as e: + self._log(f"[Replicator][DB] Maintenance: runs prune failed: {e}", level="warning") + + # Conflicts: keep all open; prune non-open older than prune_conflict_days + try: + if prune_conflict_days > 0: + with self._db.transaction(): + self._db.execute( + "DELETE FROM conflicts WHERE status <> 'open' AND julianday(created) < julianday('now', ?) ", + (f'-{prune_conflict_days} days',), + ) + except Exception as e: + self._log(f"[Replicator][DB] Maintenance: conflicts prune failed: {e}", level="warning") + + # file_state: prune deleted entries that have been deleted for a long time + try: + if prune_deleted_state_days > 0: + with self._db.transaction(): + self._db.execute( + "DELETE FROM file_state WHERE deleted = 1 AND deletedAt IS NOT NULL AND julianday(deletedAt) < julianday('now', ?) ", + (f'-{prune_deleted_state_days} days',), + ) + except Exception as e: + self._log(f"[Replicator][DB] Maintenance: file_state prune failed: {e}", level="warning") + + # SQLite maintenance: optimize; optionally vacuum + try: + self._db.execute("PRAGMA optimize;") + if do_vacuum: + self._db.execute("VACUUM;") + self._migration.set_meta("maintenance.lastRunAt", now_iso) + self._log("[Replicator][DB] Maintenance completed.", level="debug") + except Exception as e: + self._log(f"[Replicator][DB] Maintenance failed: {e}", level="warning") + + def _open_service_manager(self) -> None: + """Open the corePY Service Manager dialog (if available).""" + try: + svc = getattr(self._app, "service", None) + if svc is None: + raise RuntimeError("Service is not available on the application instance.") + + # Preferred helper added in corePY Service + if hasattr(svc, "open_manager_dialog"): + svc.open_manager_dialog(parent=self) + return + + # Fallback: if the dialog class exists, try to instantiate it + dlg_cls = getattr(svc, "ServiceManagerDialog", None) + if dlg_cls is not None: + dlg = dlg_cls(parent=self, service=svc) + dlg.exec_() + return + + raise RuntimeError("Service manager UI is not available in this build.") + + except Exception as e: + MsgBox.show(self, "Service", f"Unable to open Service Manager: {e}", icon="warning") diff --git a/src/replicator/ui.py b/src/replicator/ui.py new file mode 100644 index 00000000..e0c96b10 --- /dev/null +++ b/src/replicator/ui.py @@ -0,0 +1,816 @@ +#!/usr/bin/env python3 +# src/replicator/ui.py + +from __future__ import annotations + +from typing import Optional, Any, Dict, List, Tuple + +from PyQt5.QtCore import Qt, QTime, pyqtSignal +from PyQt5.QtWidgets import ( + QWidget, + QVBoxLayout, + QHBoxLayout, + QLabel, + QPushButton, + QDialog, + QFormLayout, + QLineEdit, + QCheckBox, + QComboBox, + QSpinBox, + QTextEdit, + QFrame, + QSizePolicy, + QLayout, + QTimeEdit, + QFileDialog, +) + +try: + from core.ui import MsgBox +except ImportError: + from ui import MsgBox + +# ------------------------------------------------------------------ +# Helpers +# ------------------------------------------------------------------ +class BrowseLineEdit(QLineEdit): + """QLineEdit that emits a signal when clicked (used to open browse dialogs).""" + clicked = pyqtSignal() + + def mousePressEvent(self, event): + try: + self.clicked.emit() + except Exception: + pass + super().mousePressEvent(event) + +# ------------------------------------------------------------------ +# Job Dialog +# ------------------------------------------------------------------ +class JobDialog(QDialog): + def __init__(self, parent=None, job: Optional[Dict[str, Any]] = None, *, default_interval_seconds: Optional[int] = None): + super().__init__(parent) + self.setWindowTitle("Replication Job") + self.setModal(True) + self.setFixedHeight(400) + self.setMinimumHeight(400) + self.setMinimumWidth(1200) + + job = job or {} + self._original_job = job + + # Default interval for new schedules (seconds). Provided by the app (e.g. Configuration service.defaultInterval). + try: + di = int(default_interval_seconds) if default_interval_seconds is not None else 3600 + except Exception: + di = 3600 + if di <= 0: + di = 3600 + self._default_interval_seconds = di + + layout = QVBoxLayout(self) + layout.setAlignment(Qt.AlignTop) + layout.setSizeConstraint(QLayout.SetMinimumSize) + + # ------------------------------ + # Name row + # ------------------------------ + name_row = QHBoxLayout() + name_row.addWidget(QLabel("Name")) + self.name = QLineEdit(job.get("name", "")) + name_row.addWidget(self.name, 1) + layout.addLayout(name_row) + + # Helper to get endpoint dict from job or fallback + def _get_endpoint(key_endpoint: str, key_str: str, default_type: str = "local") -> Dict[str, Any]: + ep = job.get(key_endpoint) + if isinstance(ep, dict): + return dict(ep) + return {"type": default_type, "location": job.get(key_str, ""), "auth": {}} + + self._source_ep = _get_endpoint("sourceEndpoint", "source", "local") + self._target_ep = _get_endpoint("targetEndpoint", "target", "local") + + # ------------------------------ + # Two-column Source / Destination + # ------------------------------ + cols = QHBoxLayout() + cols.setSpacing(20) + cols.setAlignment(Qt.AlignTop) + + src_frame = QFrame() + src_frame.setObjectName("EndpointFrame") + src_frame.setFrameShape(QFrame.NoFrame) + src_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + src_frame.setMinimumHeight(0) + src_frame.setStyleSheet( + "#EndpointFrame { border: 1px solid rgba(255,255,255,0.12); border-radius: 8px; padding: 10px; }" + ) + src_col = QVBoxLayout(src_frame) + src_col.setContentsMargins(10, 10, 10, 10) + src_col.setSpacing(8) + src_col.setAlignment(Qt.AlignTop) + + dst_frame = QFrame() + dst_frame.setObjectName("EndpointFrame") + dst_frame.setFrameShape(QFrame.NoFrame) + dst_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + dst_frame.setMinimumHeight(0) + dst_frame.setStyleSheet( + "#EndpointFrame { border: 1px solid rgba(255,255,255,0.12); border-radius: 8px; padding: 10px; }" + ) + dst_col = QVBoxLayout(dst_frame) + dst_col.setContentsMargins(10, 10, 10, 10) + dst_col.setSpacing(8) + dst_col.setAlignment(Qt.AlignTop) + + src_title = QLabel("Source") + src_title.setStyleSheet("font-weight: 600;") + dst_title = QLabel("Destination") + dst_title.setStyleSheet("font-weight: 600;") + + src_col.addWidget(src_title) + dst_col.addWidget(dst_title) + + ( + self._source_type_combo, + self._source_location_edit, + self._source_port_spin, + self._source_endpoint_row, + self._source_auth_widget, + self._source_auth_widgets, + ) = self._build_endpoint(existing=self._source_ep) + + ( + self._target_type_combo, + self._target_location_edit, + self._target_port_spin, + self._target_endpoint_row, + self._target_auth_widget, + self._target_auth_widgets, + ) = self._build_endpoint(existing=self._target_ep) + + src_col.addWidget(self._source_endpoint_row) + src_col.addWidget(self._source_auth_widget) + + dst_col.addWidget(self._target_endpoint_row) + dst_col.addWidget(self._target_auth_widget) + + cols.addWidget(src_frame, 1) + cols.addWidget(dst_frame, 1) + layout.addLayout(cols) + + # ------------------------------ + # Mode + Direction on same line + # ------------------------------ + self.mode = QComboBox() + # Mode is now a first-class control. + # mirror => allowDeletion=True + # incremental => allowDeletion=False + self.mode.addItems(["mirror", "incremental"]) + + # Backward compatibility: + # - Older jobs may only have allowDeletion without a mode. + # - Some jobs may still have mode="mirror". + mode_val = str(job.get("mode") or "").strip().lower() + if mode_val not in ("mirror", "incremental"): + # Infer from allowDeletion when mode is missing/legacy. + mode_val = "mirror" if bool(job.get("allowDeletion", False)) else "incremental" + + idx = self.mode.findText(mode_val) + if idx >= 0: + self.mode.setCurrentIndex(idx) + + self.direction = QComboBox() + self.direction.addItems(["unidirectional", "bidirectional"]) + direction_val = job.get("direction", "unidirectional") + idx = self.direction.findText(direction_val) + if idx >= 0: + self.direction.setCurrentIndex(idx) + + mode_dir_row = QHBoxLayout() + + mode_wrap = QWidget() + mode_wrap.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + mode_lay = QHBoxLayout(mode_wrap) + mode_lay.setContentsMargins(0, 0, 0, 0) + mode_lay.setSpacing(8) + mode_lay.addWidget(QLabel("Mode")) + mode_lay.addWidget(self.mode, 1) + + dir_wrap = QWidget() + dir_wrap.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + dir_lay = QHBoxLayout(dir_wrap) + dir_lay.setContentsMargins(0, 0, 0, 0) + dir_lay.setSpacing(8) + dir_lay.addWidget(QLabel("Direction")) + dir_lay.addWidget(self.direction, 1) + + mode_dir_row.addWidget(mode_wrap, 1) + mode_dir_row.addWidget(dir_wrap, 1) + layout.addLayout(mode_dir_row) + + # ------------------------------ + # Other options + # ------------------------------ + opts_row = QHBoxLayout() + + # Deletion behavior is controlled by mode now. + # Keep the UI simple: show metadata + enabled toggles here. + self.preserve_metadata = QCheckBox("Preserve metadata") + self.preserve_metadata.setChecked(bool(job.get("preserveMetadata", True))) + self.enabled = QCheckBox("Enabled") + self.enabled.setChecked(bool(job.get("enabled", True))) + + opts_row.addWidget(self.preserve_metadata) + opts_row.addSpacing(16) + opts_row.addWidget(self.enabled) + opts_row.addStretch(1) + + # Schedule button (UI stays here) + self._schedule_btn = QPushButton("Schedule…") + self._schedule_btn.clicked.connect(self._open_schedule) + opts_row.addWidget(self._schedule_btn) + + layout.addLayout(opts_row) + + # ------------------------------ + # Buttons + # ------------------------------ + btn_row = QHBoxLayout() + btn_row.addStretch(1) + cancel_btn = QPushButton("Cancel") + ok_btn = QPushButton("Save") + cancel_btn.clicked.connect(self.reject) + ok_btn.clicked.connect(self._on_ok) + btn_row.addWidget(cancel_btn) + btn_row.addWidget(ok_btn) + layout.addLayout(btn_row) + + # Wire type changes + self._source_type_combo.currentIndexChanged.connect(lambda _i: self._on_type_changed( + self._source_type_combo, + self._source_location_edit, + self._source_port_spin, + self._source_auth_widget, + self._source_auth_widgets, + )) + self._target_type_combo.currentIndexChanged.connect(lambda _i: self._on_type_changed( + self._target_type_combo, + self._target_location_edit, + self._target_port_spin, + self._target_auth_widget, + self._target_auth_widgets, + )) + + # Trigger initial state + self._on_type_changed( + self._source_type_combo, + self._source_location_edit, + self._source_port_spin, + self._source_auth_widget, + self._source_auth_widgets, + initial=True, + ) + self._on_type_changed( + self._target_type_combo, + self._target_location_edit, + self._target_port_spin, + self._target_auth_widget, + self._target_auth_widgets, + initial=True, + ) + + def _open_schedule(self) -> None: + job = self._original_job if isinstance(self._original_job, dict) else {} + dlg = ScheduleDialog(self, job=job, default_interval_seconds=self._default_interval_seconds) + if dlg.exec_() == QDialog.Accepted: + # store schedule back into original job dict so value() preserves it + if not isinstance(self._original_job, dict): + self._original_job = {} + self._original_job["schedule"] = dlg.value() + + # ------------------------------------------------------------------ + # Endpoint UI + # ------------------------------------------------------------------ + + def _build_endpoint(self, existing: Dict[str, Any]): + type_combo = QComboBox() + type_combo.addItems(["local", "smb"]) + idx = type_combo.findText(existing.get("type", "local")) + if idx >= 0: + type_combo.setCurrentIndex(idx) + if idx < 0: + type_combo.setCurrentIndex(0) + type_combo.setFixedWidth(110) + type_combo.setProperty("existing_type", existing.get("type", "local")) + type_combo.setProperty("existing_auth", existing.get("auth", {}) or {}) + + location_edit = BrowseLineEdit(existing.get("location", "")) + + port_spin = QSpinBox() + port_spin.setRange(1, 65535) + port_spin.setFixedWidth(110) + # Ports are not used for local/SMB endpoints. + port_spin.setValue(1) + port_spin.setVisible(False) + + endpoint_fields = QWidget() + fields_lay = QHBoxLayout(endpoint_fields) + fields_lay.setContentsMargins(0, 0, 0, 0) + fields_lay.setSpacing(8) + fields_lay.addWidget(type_combo) + fields_lay.addWidget(location_edit, 1) + fields_lay.addWidget(port_spin) + + def _browse_location(): + try: + typ = (type_combo.currentText() or "").lower() + if typ != "local": + return + start_dir = location_edit.text().strip() or "" + # If the user typed a file path, prefer its directory. + if start_dir and not start_dir.endswith("/") and not start_dir.endswith("\\"): + try: + import os + if os.path.isfile(start_dir): + start_dir = os.path.dirname(start_dir) + except Exception: + pass + selected = QFileDialog.getExistingDirectory(self, "Select folder", start_dir) + if selected: + location_edit.setText(selected) + except Exception: + return + + # Click-to-browse for local paths (no extra button needed). + location_edit.clicked.connect(_browse_location) + + endpoint_row = QWidget() + endpoint_row.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + endpoint_form = QFormLayout(endpoint_row) + endpoint_form.setContentsMargins(0, 0, 0, 0) + endpoint_form.setSpacing(6) + endpoint_form.addRow(endpoint_fields) + + auth_widget = QFrame() + auth_widget.setFrameShape(QFrame.NoFrame) + auth_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + auth_widget.setMinimumHeight(0) + + auth_lay = QVBoxLayout(auth_widget) + auth_lay.setContentsMargins(0, 0, 0, 0) + auth_lay.setSpacing(6) + auth_lay.setAlignment(Qt.AlignTop) + + auth_title = QLabel("Authentication") + auth_title.setStyleSheet("font-weight: 600;") + + widgets: Dict[str, Any] = {} + + # SMB auth + smb_wrap = QWidget() + smb_wrap.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + smb_form = QFormLayout(smb_wrap) + smb_form.setContentsMargins(0, 0, 0, 0) + smb_guest = QCheckBox("Login as Guest") + smb_user_lbl = QLabel("Username (user or user@domain)") + smb_username = QLineEdit() + smb_pass_lbl = QLabel("Password") + smb_password = QLineEdit() + smb_password.setEchoMode(QLineEdit.Password) + + smb_auth = existing.get("auth", {}) if existing.get("type") == "smb" else {} + smb_guest.setChecked(bool(smb_auth.get("guest", True))) + smb_username.setText(smb_auth.get("username", "")) + smb_password.setText(smb_auth.get("password", "")) + + smb_form.addRow(smb_guest) + smb_form.addRow(smb_user_lbl, smb_username) + smb_form.addRow(smb_pass_lbl, smb_password) + + def _smb_guest_update(): + guest = smb_guest.isChecked() + smb_user_lbl.setVisible(not guest) + smb_username.setVisible(not guest) + smb_pass_lbl.setVisible(not guest) + smb_password.setVisible(not guest) + + smb_guest.stateChanged.connect(_smb_guest_update) + _smb_guest_update() + + auth_lay.addWidget(auth_title) + auth_lay.addWidget(smb_wrap) + + widgets["smb"] = { + "wrap": smb_wrap, + "guest": smb_guest, + "user_lbl": smb_user_lbl, + "username": smb_username, + "pass_lbl": smb_pass_lbl, + "password": smb_password, + } + + return type_combo, location_edit, port_spin, endpoint_row, auth_widget, widgets + + def _on_type_changed( + self, + type_combo: QComboBox, + location_edit: QLineEdit, + port_spin: QSpinBox, + auth_widget: QWidget, + widgets: Dict[str, Any], + initial: bool = False, + ): + typ = type_combo.currentText() + + placeholder = { + "local": "Local path (e.g. /data or C:\\Data)", + "smb": "SMB path (e.g. \\\\SERVER\\Share\\Folder)", + }.get(typ, "") + location_edit.setPlaceholderText(placeholder) + # For local endpoints, clicking the location field opens a folder chooser. + # For non-local endpoints, keep normal typing behavior. + if (typ or "").lower() == "local": + location_edit.setCursorPosition(len(location_edit.text())) + # Ports are not used for local/SMB endpoints. + port_spin.setVisible(False) + + if typ == "local": + auth_widget.setVisible(False) + auth_widget.setMaximumHeight(0) + else: + auth_widget.setVisible(True) + auth_widget.setMaximumHeight(16777215) + + # Hide all auth sections + for key in ("smb",): + if key in widgets and "wrap" in widgets[key]: + widgets[key]["wrap"].setVisible(False) + + # Show only the relevant auth section + if typ == "smb": + widgets["smb"]["wrap"].setVisible(True) + + auth_widget.adjustSize() + if auth_widget.parentWidget() is not None: + auth_widget.parentWidget().adjustSize() + self.adjustSize() + + # ------------------------------------------------------------------ + # Validation + # ------------------------------------------------------------------ + + def _on_ok(self): + if not self.name.text().strip(): + MsgBox.show(self, "Job", "Name is required.", icon="warning") + return + + src_type = self._source_type_combo.currentText() + tgt_type = self._target_type_combo.currentText() + + src_loc = self._source_location_edit.text().strip() + tgt_loc = self._target_location_edit.text().strip() + + if not src_loc: + MsgBox.show(self, "Job", "Source location is required.", icon="warning") + return + if not tgt_loc: + MsgBox.show(self, "Job", "Target location is required.", icon="warning") + return + + if src_type == "smb": + w = self._source_auth_widgets["smb"] + if not w["guest"].isChecked(): + # Either Guest is enabled OR both username+password are provided. + # If either field is missing, force Guest and block save. + if not w["username"].text().strip() or not w["password"].text().strip(): + w["guest"].setChecked(True) + MsgBox.show( + self, + "Job", + "For the Source SMB endpoint, either enable Guest or provide BOTH a username and a password.", + icon="warning", + ) + return + + if tgt_type == "smb": + w = self._target_auth_widgets["smb"] + if not w["guest"].isChecked(): + # Either Guest is enabled OR both username+password are provided. + # If either field is missing, force Guest and block save. + if not w["username"].text().strip() or not w["password"].text().strip(): + w["guest"].setChecked(True) + MsgBox.show( + self, + "Job", + "For the Destination SMB endpoint, either enable Guest or provide BOTH a username and a password.", + icon="warning", + ) + return + + self.accept() + + # ------------------------------------------------------------------ + # Value extraction + # ------------------------------------------------------------------ + + def value(self) -> Dict[str, Any]: + def _extract(type_combo: QComboBox, location_edit: QLineEdit, port_spin: QSpinBox, widgets: Dict[str, Any]) -> Dict[str, Any]: + typ = type_combo.currentText() + location = location_edit.text().strip() + auth: Dict[str, Any] = {} + + if typ == "local": + auth = {} + elif typ == "smb": + w = widgets["smb"] + guest = bool(w["guest"].isChecked()) + # If Guest is enabled, credentials are irrelevant; clear them on save. + auth = { + "guest": guest, + "username": "" if guest else w["username"].text().strip(), + "password": "" if guest else w["password"].text(), + } + else: + # Unsupported/legacy types fall back to local + typ = "local" + auth = {} + + return {"type": typ, "location": location, "auth": auth} + + source_ep = _extract(self._source_type_combo, self._source_location_edit, self._source_port_spin, self._source_auth_widgets) + target_ep = _extract(self._target_type_combo, self._target_location_edit, self._target_port_spin, self._target_auth_widgets) + + val: Dict[str, Any] = { + "name": self.name.text().strip(), + "sourceEndpoint": source_ep, + "targetEndpoint": target_ep, + "source": source_ep["location"], # backward compatibility + "target": target_ep["location"], # backward compatibility + # Backward compatible field: allowDeletion derives from mode. + "allowDeletion": bool((self.mode.currentText() or "").lower() == "mirror"), + "preserveMetadata": bool(self.preserve_metadata.isChecked()), + "mode": self.mode.currentText(), + "direction": self.direction.currentText(), + "enabled": bool(self.enabled.isChecked()), + } + + # Preserve schedule (and update if ScheduleDialog was used) + if self._original_job and isinstance(self._original_job, dict): + sched = self._original_job.get("schedule") + if sched is not None: + val["schedule"] = sched + + return val + # Remove any remaining references to self.allow_deletion in this class. + +# ------------------------------------------------------------------ +# Schedule Dialog +# ------------------------------------------------------------------ +class ScheduleDialog(QDialog): + """Schedule editor UI. + + Persists as: + schedule = { + "enabled": bool, + "intervalSeconds": int, # computed fallback (minimum per-day interval if enabled, else default) + "windows": { + "0":[{"start":"22:00","end":"06:00","intervalSeconds":3600}], + ... + } + } + """ + + _DAYS: List[Tuple[int, str]] = [ + (0, "Monday"), + (1, "Tuesday"), + (2, "Wednesday"), + (3, "Thursday"), + (4, "Friday"), + (5, "Saturday"), + (6, "Sunday"), + ] + + def __init__(self, parent=None, job: Optional[Dict[str, Any]] = None, *, default_interval_seconds: Optional[int] = None): + super().__init__(parent) + self.setWindowTitle("Schedule") + self.setModal(True) + + # Default interval for new schedules (seconds). Provided by the app (e.g. Configuration service.defaultInterval). + try: + di = int(default_interval_seconds) if default_interval_seconds is not None else 3600 + except Exception: + di = 3600 + if di <= 0: + di = 3600 + self._default_interval_seconds = di + + job = job or {} + schedule = job.get("schedule") if isinstance(job.get("schedule"), dict) else {} + + # IMPORTANT semantics: + # - schedule.enabled == False => job can be run manually but will NOT be executed by the service. + # - schedule.enabled == True => job may run in the service, but ONLY within selected day windows. + # - enabled with no days selected means "run never" (no service runs). + + if not schedule: + # New schedule default: enabled, every day, all day, default interval + schedule = {"enabled": True, "intervalSeconds": int(self._default_interval_seconds), "windows": {}} + for wd in range(7): + schedule["windows"][str(wd)] = [ + {"start": "00:00", "end": "23:59", "intervalSeconds": int(self._default_interval_seconds)} + ] + else: + # Existing schedule: preserve intent. + # If windows is missing/empty, DO NOT auto-populate days (that would change meaning). + if not isinstance(schedule.get("windows"), dict): + schedule["windows"] = {} + + # Ensure each existing day window has intervalSeconds + try: + for _k, _v in list(schedule["windows"].items()): + if isinstance(_v, list) and _v and isinstance(_v[0], dict) and "intervalSeconds" not in _v[0]: + _v[0]["intervalSeconds"] = int(schedule.get("intervalSeconds") or self._default_interval_seconds) + except Exception: + pass + + self._windows: Dict[str, Any] = schedule.get("windows", {}) if isinstance(schedule.get("windows", {}), dict) else {} + + layout = QVBoxLayout(self) + layout.setAlignment(Qt.AlignTop) + layout.setSizeConstraint(QLayout.SetMinimumSize) + + form = QFormLayout() + layout.addLayout(form) + + self.enabled = QCheckBox() + self.enabled.setChecked(bool(schedule.get("enabled", False))) + + form.addRow("Enabled", self.enabled) + + hint = QLabel("Tip: Enable the schedule to allow service runs. If enabled and no days are selected, the job will not run in the service.") + hint.setWordWrap(True) + hint.setStyleSheet("opacity: 0.75;") + layout.addWidget(hint) + + # Windows editor + win_frame = QFrame() + win_frame.setFrameShape(QFrame.NoFrame) + win_lay = QVBoxLayout(win_frame) + win_lay.setContentsMargins(0, 0, 0, 0) + win_lay.setSpacing(6) + + title = QLabel("Allowed run windows") + title.setStyleSheet("font-weight: 600;") + win_lay.addWidget(title) + + self._day_controls: Dict[int, Dict[str, Any]] = {} + + for wd, label in self._DAYS: + row = QHBoxLayout() + row.setSpacing(10) + + day_enabled = QCheckBox(label) + start = QTimeEdit() + end = QTimeEdit() + start.setDisplayFormat("HH:mm") + end.setDisplayFormat("HH:mm") + start.setTime(QTime(0, 0)) + end.setTime(QTime(23, 59)) + + interval = QSpinBox() + interval.setRange(1, 604800) # 1s .. 7 days + interval.setFixedWidth(130) + interval.setValue(int(schedule.get("intervalSeconds", self._default_interval_seconds) or self._default_interval_seconds)) + + # Load from existing windows if present + key = str(wd) + day_windows = self._windows.get(key) + if isinstance(day_windows, list) and len(day_windows) > 0 and isinstance(day_windows[0], dict): + w0 = day_windows[0] + s = str(w0.get("start", "00:00")) + e = str(w0.get("end", "23:59")) + day_enabled.setChecked(True) + start.setTime(self._parse_qtime(s, QTime(0, 0))) + end.setTime(self._parse_qtime(e, QTime(23, 59))) + try: + interval.setValue(int(w0.get("intervalSeconds", schedule.get("intervalSeconds", self._default_interval_seconds)) or self._default_interval_seconds)) + except Exception: + interval.setValue(int(schedule.get("intervalSeconds", self._default_interval_seconds) or self._default_interval_seconds)) + else: + day_enabled.setChecked(False) + try: + interval.setValue(int(schedule.get("intervalSeconds", self._default_interval_seconds) or self._default_interval_seconds)) + except Exception: + interval.setValue(int(self._default_interval_seconds)) + + # Disable edits when not enabled + def _apply_enabled_state(_=None, *, _day_enabled=day_enabled, _start=start, _end=end, _interval=interval): + en = _day_enabled.isChecked() + _start.setEnabled(en) + _end.setEnabled(en) + _interval.setEnabled(en) + + day_enabled.stateChanged.connect(_apply_enabled_state) + _apply_enabled_state() + + row.addWidget(day_enabled, 1) + row.addWidget(QLabel("Start")) + row.addWidget(start) + row.addWidget(QLabel("End")) + row.addWidget(end) + row.addWidget(QLabel("Interval (s)")) + row.addWidget(interval) + + win_lay.addLayout(row) + + self._day_controls[wd] = {"enabled": day_enabled, "start": start, "end": end, "interval": interval} + + layout.addWidget(win_frame) + + btn_row = QHBoxLayout() + btn_row.addStretch(1) + cancel_btn = QPushButton("Cancel") + ok_btn = QPushButton("Save") + cancel_btn.clicked.connect(self.reject) + ok_btn.clicked.connect(self._on_ok) + btn_row.addWidget(cancel_btn) + btn_row.addWidget(ok_btn) + layout.addLayout(btn_row) + + self._sync_enabled_state() + + self.enabled.stateChanged.connect(lambda _i: self._sync_enabled_state()) + + def _sync_enabled_state(self): + en = self.enabled.isChecked() + for wd, ctrls in self._day_controls.items(): + ctrls["enabled"].setEnabled(en) + # if schedule disabled, visually disable time edits too + if not en: + ctrls["start"].setEnabled(False) + ctrls["end"].setEnabled(False) + ctrls["interval"].setEnabled(False) + else: + # restore per-day checkbox logic + day_en = ctrls["enabled"].isChecked() + ctrls["start"].setEnabled(day_en) + ctrls["end"].setEnabled(day_en) + ctrls["interval"].setEnabled(day_en) + + def _parse_qtime(self, s: str, default: QTime) -> QTime: + try: + parts = s.strip().split(":") + if len(parts) != 2: + return default + hh = int(parts[0]) + mm = int(parts[1]) + if hh < 0 or hh > 23 or mm < 0 or mm > 59: + return default + return QTime(hh, mm) + except Exception: + return default + + def _on_ok(self): + if self.enabled.isChecked(): + any_day = any(bool(ctrls["enabled"].isChecked()) for _wd, ctrls in self._day_controls.items()) + if not any_day: + MsgBox.show(self, "Schedule", "Select at least one day when the schedule is enabled (otherwise the job will never run in the service).", icon="warning") + return + for _wd, ctrls in self._day_controls.items(): + if not ctrls["enabled"].isChecked(): + continue + if int(ctrls["interval"].value() or 0) < 1: + MsgBox.show(self, "Schedule", "Per-day interval must be at least 1 second for enabled days.", icon="warning") + return + + # Basic validation: ensure enabled days have valid times (QTimeEdit ensures format) + # Allow overnight windows naturally (start > end) — that's intended. + self.accept() + + def value(self) -> Dict[str, Any]: + windows: Dict[str, Any] = {} + enabled_intervals = [] + if self.enabled.isChecked(): + for wd, ctrls in self._day_controls.items(): + if not ctrls["enabled"].isChecked(): + continue + s = ctrls["start"].time().toString("HH:mm") + e = ctrls["end"].time().toString("HH:mm") + itv = int(ctrls["interval"].value()) + windows[str(wd)] = [{"start": s, "end": e, "intervalSeconds": itv}] + enabled_intervals.append(itv) + + # Compute fallback intervalSeconds: min per-day interval if enabled, else default + if self.enabled.isChecked() and enabled_intervals: + computed_interval_seconds = min(enabled_intervals) + else: + computed_interval_seconds = int(self._default_interval_seconds) + + return { + "enabled": bool(self.enabled.isChecked()), + "intervalSeconds": int(computed_interval_seconds), + "windows": windows, + } diff --git a/test.sh b/test.sh new file mode 100755 index 00000000..b7ea6c02 --- /dev/null +++ b/test.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +touch tmp/a/file-$(date +%H-%M).txt +touch tmp/c/file-$(date +%H-%M).txt diff --git a/update.sh b/update.sh new file mode 120000 index 00000000..ce091d3c --- /dev/null +++ b/update.sh @@ -0,0 +1 @@ +src/core/update.sh \ No newline at end of file