diff --git a/.github/actions/test-backend/action.yml b/.github/actions/test-backend/action.yml index 47bf1407f..b7946d28c 100644 --- a/.github/actions/test-backend/action.yml +++ b/.github/actions/test-backend/action.yml @@ -9,7 +9,7 @@ runs: steps: - uses: browser-actions/setup-chrome@latest - name: Set up Python 3.9 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: Install Python dependencies @@ -29,7 +29,7 @@ runs: run: sudo systemctl start elasticsearch.service shell: bash - name: Write Google Drive API credentials to file - uses: jsdaniell/create-json@1.1.2 + uses: jsdaniell/create-json@v1.2.3 with: name: "client_secrets.json" json: ${{ inputs.google-drive-api-key }} diff --git a/.github/actions/test-desktop-tool/action.yml b/.github/actions/test-desktop-tool/action.yml index cb9e31506..5a99fed1d 100644 --- a/.github/actions/test-desktop-tool/action.yml +++ b/.github/actions/test-desktop-tool/action.yml @@ -9,14 +9,14 @@ runs: chrome-version: stable - uses: browser-actions/setup-edge@latest with: - edge-version: stable + edge-version: beta # beta version seems to work more consistently for linux CI - name: Fix macOS Chromedriver if: runner.os == 'macOS' run: | rm /usr/local/bin/chromedriver shell: bash - name: Set up Python 3.9 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: Install Python dependencies @@ -26,7 +26,7 @@ runs: pip install -r requirements.txt shell: bash - name: Write Google Drive API credentials to file - uses: jsdaniell/create-json@1.1.2 + uses: jsdaniell/create-json@v1.2.3 with: name: "client_secrets.json" json: ${{ inputs.google-drive-api-key }} diff --git a/.github/actions/test-frontend/action.yml b/.github/actions/test-frontend/action.yml index bc69f7e9c..aca5747b6 100644 --- a/.github/actions/test-frontend/action.yml +++ b/.github/actions/test-frontend/action.yml @@ -4,7 +4,7 @@ runs: using: composite steps: - name: Install npm - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18.15 - name: Compile frontend diff --git a/.github/actions/test-pre-commit/action.yml b/.github/actions/test-pre-commit/action.yml index 141651737..0c72654d9 100644 --- a/.github/actions/test-pre-commit/action.yml +++ b/.github/actions/test-pre-commit/action.yml @@ -4,7 +4,7 @@ runs: using: composite steps: - name: Set up Python 3.9 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: Install pre-commit diff --git a/.github/workflows/auto-author-assign.yml b/.github/workflows/auto-author-assign.yml index 13e671d5d..4087d5340 100644 --- a/.github/workflows/auto-author-assign.yml +++ b/.github/workflows/auto-author-assign.yml @@ -9,4 +9,4 @@ jobs: assign-author: runs-on: ubuntu-latest steps: - - uses: toshimaru/auto-author-assign@v1.6.2 + - uses: toshimaru/auto-author-assign@v2.2.1 diff --git a/.github/workflows/build-desktop-tool.yml b/.github/workflows/build-desktop-tool.yml index df1d7cb9f..621885fd5 100644 --- a/.github/workflows/build-desktop-tool.yml +++ b/.github/workflows/build-desktop-tool.yml @@ -14,8 +14,11 @@ jobs: strategy: matrix: include: - - os: macos-13 # TODO: revert back to macos-latest when https://github.com/actions/setup-python/issues/852 is fixed - TARGET: macos + - os: macos-latest + TARGET: macos-arm + OUT_FILE_NAME: autofill + - os: macos-12 + TARGET: macos-intel OUT_FILE_NAME: autofill - os: windows-latest TARGET: windows @@ -24,10 +27,10 @@ jobs: TARGET: linux OUT_FILE_NAME: autofill steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: browser-actions/setup-chrome@latest - name: Set up Python 3.9 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: Install dependencies @@ -35,7 +38,7 @@ jobs: python -m pip install --upgrade pip pip install -r requirements.txt - name: Write Google Drive API credentials to file - uses: jsdaniell/create-json@1.1.2 + uses: jsdaniell/create-json@v1.2.3 with: name: "client_secrets.json" json: ${{ secrets.GOOGLE_DRIVE_API_KEY }} @@ -43,7 +46,7 @@ jobs: - name: Build with pyinstaller for ${{ matrix.TARGET }} run: pyinstaller autofill.spec - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: ./desktop-tool/dist/${{ matrix.OUT_FILE_NAME }} name: autofill-${{ matrix.TARGET }} diff --git a/.github/workflows/build-frontend.yml b/.github/workflows/build-frontend.yml index 3d87c7301..df40267e7 100644 --- a/.github/workflows/build-frontend.yml +++ b/.github/workflows/build-frontend.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install npm uses: actions/setup-node@v3 with: diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml index e0239745d..d58054dc2 100644 --- a/.github/workflows/test-backend.yml +++ b/.github/workflows/test-backend.yml @@ -23,7 +23,7 @@ jobs: ports: - 5432:5432 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/test-backend with: google-drive-api-key: ${{ secrets.GOOGLE_DRIVE_API_KEY }} diff --git a/.github/workflows/test-desktop-tool.yml b/.github/workflows/test-desktop-tool.yml index 9a04c9564..626aa4f5c 100644 --- a/.github/workflows/test-desktop-tool.yml +++ b/.github/workflows/test-desktop-tool.yml @@ -11,11 +11,11 @@ jobs: strategy: matrix: include: - - os: macos-13 # TODO: revert back to macos-latest when https://github.com/actions/setup-python/issues/852 is fixed + - os: macos-latest - os: windows-latest - os: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/test-desktop-tool with: google-drive-api-key: ${{ secrets.GOOGLE_DRIVE_API_KEY }} diff --git a/.github/workflows/test-frontend.yml b/.github/workflows/test-frontend.yml index d1911db8e..1f8bcfaf5 100644 --- a/.github/workflows/test-frontend.yml +++ b/.github/workflows/test-frontend.yml @@ -9,5 +9,5 @@ jobs: name: Frontend tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/test-frontend diff --git a/.github/workflows/test-pre-commit.yml b/.github/workflows/test-pre-commit.yml index 70230f870..9c51c0fee 100644 --- a/.github/workflows/test-pre-commit.yml +++ b/.github/workflows/test-pre-commit.yml @@ -8,5 +8,5 @@ jobs: name: Formatting and static type checking runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/test-pre-commit diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9c9d47498..39b4ebfcd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -22,7 +22,7 @@ jobs: ports: - 5432:5432 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/test-backend with: google-drive-api-key: ${{ secrets.GOOGLE_DRIVE_API_KEY }} @@ -32,11 +32,11 @@ jobs: strategy: matrix: include: - - os: macos-13 # TODO: revert back to macos-latest when https://github.com/actions/setup-python/issues/852 is fixed + - os: macos-latest - os: windows-latest - os: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/test-desktop-tool with: google-drive-api-key: ${{ secrets.GOOGLE_DRIVE_API_KEY }} @@ -44,11 +44,11 @@ jobs: name: Frontend tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/test-frontend test-pre-commit: name: Formatting and static type checking runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/test-pre-commit diff --git a/desktop-tool/autofill.py b/desktop-tool/autofill.py index 120f0ddf0..8dd62da9d 100644 --- a/desktop-tool/autofill.py +++ b/desktop-tool/autofill.py @@ -14,6 +14,7 @@ from src.pdf_maker import PdfExporter from src.processing import ImagePostProcessingConfig from src.utils import bold +from src.web_server import WebServer # https://stackoverflow.com/questions/12492810/python-how-can-i-make-the-ansi-escape-codes-to-work-also-in-windows os.system("") # enables ansi escape characters in terminal @@ -159,8 +160,12 @@ def main( card_orders = aggregate_and_split_orders( orders=CardOrder.from_xmls_in_folder(), target_site=target_site, combine_orders=combine_orders ) + web_server = WebServer() AutofillDriver( - browser=Browsers[browser], target_site=target_site, binary_location=binary_location + browser=Browsers[browser], + target_site=target_site, + binary_location=binary_location, + starting_url=web_server.server_url(), ).execute_orders( orders=card_orders, auto_save_threshold=auto_save_threshold if auto_save else None, diff --git a/desktop-tool/autofill.spec b/desktop-tool/autofill.spec index 5fd5162bc..44847ff43 100644 --- a/desktop-tool/autofill.spec +++ b/desktop-tool/autofill.spec @@ -6,7 +6,7 @@ block_cipher = None a = Analysis(['autofill.py'], binaries=collect_dynamic_libs('ansicon') + collect_dynamic_libs('enlighten'), - datas=[('client_secrets.json', '.')], + datas=[('client_secrets.json', '.'), ('post-launch.html', '.')], hiddenimports=['colorama', 'jinxed.terminfo.vtwin10', 'wakepy._linux._jeepney_dbus'], hookspath=[], runtime_hooks=[], diff --git a/desktop-tool/post-launch.html b/desktop-tool/post-launch.html new file mode 100644 index 000000000..ba6d64b6a --- /dev/null +++ b/desktop-tool/post-launch.html @@ -0,0 +1,20 @@ + + + + + + + MPC Autofill + + +

Congratulations!

+

+ MPC Autofill has started up successfully, please look back at your terminal + application to answer a few questions so the upload process can begin. +

+

+ If you have more questions about using MPC Autofill, check out + the documentation. +

+ + diff --git a/desktop-tool/requirements.txt b/desktop-tool/requirements.txt index 5b2a67eab..5bcf1d9e4 100644 --- a/desktop-tool/requirements.txt +++ b/desktop-tool/requirements.txt @@ -18,5 +18,5 @@ pytest-retry~=1.5 ratelimit~=2.2.1 requests~=2.31.0 sanitize-filename~=1.2.0 -selenium~=4.19.0 +selenium~=4.23 wakepy==0.6.0 diff --git a/desktop-tool/src/constants.py b/desktop-tool/src/constants.py index f77ba9aef..319ff133c 100644 --- a/desktop-tool/src/constants.py +++ b/desktop-tool/src/constants.py @@ -102,6 +102,9 @@ class TargetSite: default={cardstock: cardstock.value for cardstock in Cardstocks} ) # endregion + # region save states + saved_successfully_text: str = attr.ib(default="Saved successfully") + # endregion def format_url(self, url: str) -> str: return f"{self.base_url}/{url}" @@ -161,6 +164,7 @@ class TargetSites(Enum): base_url="https://www.printerstudio.de", starting_url_route="machen/blanko-spielkarten-63x88mm-personalisieren.html", supports_foil=False, + saved_successfully_text="Speicherung erfolgreich", cardstock_site_name_mapping={ Cardstocks.S30: "Standard (glatt)", Cardstocks.S33: "Super (glatt)", @@ -175,3 +179,5 @@ class TargetSites(Enum): PROJECT_MAX_SIZE = 612 # shared between target sites THREADS = 5 # shared between CardImageCollections + +POST_LAUNCH_HTML_FILENAME = "post-launch.html" diff --git a/desktop-tool/src/driver.py b/desktop-tool/src/driver.py index c237fe8d0..01c046863 100644 --- a/desktop-tool/src/driver.py +++ b/desktop-tool/src/driver.py @@ -18,7 +18,11 @@ ) from selenium.webdriver.common.by import By from selenium.webdriver.remote.webdriver import WebDriver -from selenium.webdriver.support.expected_conditions import invisibility_of_element +from selenium.webdriver.support.expected_conditions import ( + invisibility_of_element, + text_to_be_present_in_element, + visibility_of_element_located, +) from selenium.webdriver.support.ui import Select, WebDriverWait from src.constants import THREADS, Browsers, Cardstocks, States, TargetSites @@ -41,6 +45,7 @@ class AutofillDriver: binary_location: Optional[str] = attr.ib(default=None) # path to browser executable target_site: TargetSites = attr.ib(default=TargetSites.MakePlayingCards) headless: bool = attr.ib(default=False) + starting_url: str = attr.ib(default="data:") # internal properties (init=False) state: str = attr.ib(init=False, default=States.initialising) @@ -59,6 +64,8 @@ def initialise_driver(self) -> None: driver = self.browser.value(headless=self.headless, binary_location=self.binary_location) driver.set_window_size(1200, 900) driver.implicitly_wait(5) + driver.get(self.starting_url) + WebDriverWait(driver, 10).until(visibility_of_element_located((By.TAG_NAME, "body"))) logging.info( f"Successfully initialised {bold(self.browser.name)} driver " f"targeting {bold(self.target_site.name)}.\n" @@ -160,27 +167,36 @@ def switch_to_frame(self, frame: str) -> Generator[None, None, None]: @alert_handler @exception_retry_skip_handler - def wait(self) -> None: + def wait(self) -> bool: """ Wait until the loading circle in the targeted site disappears. + If the frontend locks up while loading, this function will attempt to resolve this + with a page refresh (and the return value indicates if a refresh occurred). """ + wait_timeout_seconds = 30 logging.debug("Waiting until MPC loading circle disappears...") try: wait_elem = self.driver.find_element(by=By.ID, value="sysdiv_wait") # Wait for the element to become invisible while True: try: - WebDriverWait(self.driver, 100, poll_frequency=0.1).until(invisibility_of_element(wait_elem)) + WebDriverWait(self.driver, wait_timeout_seconds, poll_frequency=0.1).until( + invisibility_of_element(wait_elem) + ) except sl_exc.TimeoutException: - logging.debug("Timed out while waiting for the loading circle to disappear.") - continue + logging.info( + f"Waited for longer than {wait_timeout_seconds}s for the {self.target_site.name} page " + f"to respond - attempting to resolve with a page refresh..." + ) + self.driver.refresh() + return True logging.debug("The loading circle has disappeared!") break except (sl_exc.NoSuchElementException, sl_exc.NoSuchFrameException, sl_exc.WebDriverException) as e: logging.debug("Attempted to locate the loading circle but encountered an exception:") logging.debug(e) - return + return False def set_state(self, state: str, action: Optional[str] = None) -> None: self.state = state @@ -367,7 +383,7 @@ def upload_image(self, image: CardImage, max_tries: int = 3) -> Optional[str]: return None @exception_retry_skip_handler - def insert_image(self, pid: Optional[str], image: CardImage, slots: list[int]) -> None: + def insert_image(self, pid: Optional[str], image: CardImage, slots: list[int], max_tries: int = 3) -> None: """ Inserts the image identified by `pid` into `slots`. """ @@ -376,15 +392,28 @@ def insert_image(self, pid: Optional[str], image: CardImage, slots: list[int]) - self.wait_until_javascript_object_is_defined("PageLayout.prototype.applyDragPhoto") if pid: - logging.debug(f"Inserting {image.name} into slots {slots}...") + logging.debug(f'Inserting "{image.name}" into slots {slots}...') for i, slot in enumerate(slots, start=1): logging.debug(f"Inserting into slot {slot}...") - self.set_state(state=self.state, action=f"Inserting {image.name} into slot {slot+1} ({i}/{len(slots)})") - # Insert the card into each slot and wait for the page to load before continuing - self.execute_javascript( - f'PageLayout.prototype.applyDragPhoto({self.get_element_for_slot_js(slot)}, 0, "{pid}")' + self.set_state( + state=self.state, action=f'Inserting "{image.name}" into slot {slot+1} ({i}/{len(slots)})' ) - self.wait() + # Insert the card into each slot and wait for the page to load before continuing + tries = 0 + page_refreshed_while_inserting_image = True + while page_refreshed_while_inserting_image: + self.execute_javascript( + f'PageLayout.prototype.applyDragPhoto({self.get_element_for_slot_js(slot)}, 0, "{pid}")' + ) + + page_refreshed_while_inserting_image = self.wait() + tries += 1 + if tries >= max_tries: + logging.warning( + f"Attempted to insert image {bold(image.name)} {max_tries} times, " + f"but no attempt succeeded! Skipping this image." + ) + break logging.debug(f"All done inserting {image.name} into slots {slots}!") self.set_state(self.state) else: @@ -617,7 +646,20 @@ def save_project_to_user_account(self, order: CardOrder) -> None: project_name_element.send_keys(project_name) self.wait_until_javascript_object_is_defined("oDesign.setTemporarySave") self.execute_javascript("oDesign.setTemporarySave();") - self.wait() + + wait_timeout_seconds = 30 + try: + WebDriverWait(self.driver, wait_timeout_seconds).until( + text_to_be_present_in_element( + (By.ID, "div_temporarysavestatus"), self.target_site.value.saved_successfully_text + ) + ) + except sl_exc.TimeoutException: + logging.info( + f"Waited for longer than {wait_timeout_seconds}s for the {self.target_site.name} page to respond - " + "attempting to resolve with a page refresh..." + ) + self.driver.refresh() logging.debug("Finished saving the project to the user's account!") # endregion @@ -769,7 +811,7 @@ def execute_orders( auto_save_threshold: Optional[int], post_processing_config: Optional[ImagePostProcessingConfig], ) -> None: - logging.info(f"{bold(len(orders))} projects are scheduled to be auto-filled. They are:") + logging.info(f"{bold(len(orders))} project/s are scheduled to be auto-filled. They are:") for i, order in enumerate(orders, start=1): logging.info(f"{i}. {bold(order.name or 'Unnamed Project')}") logging.info(" " + order.get_overview()) diff --git a/desktop-tool/src/web_server.py b/desktop-tool/src/web_server.py new file mode 100644 index 000000000..cc1924afd --- /dev/null +++ b/desktop-tool/src/web_server.py @@ -0,0 +1,41 @@ +""" +This module spins up a simple web server for serving the landing page for the tool +(guiding the user back to the desktop tool to answer another question before it can proceed). +""" + +import logging +import threading +from http import server +from pathlib import Path +from typing import Union + +from src import constants + + +class _Handler(server.BaseHTTPRequestHandler): + def do_GET(self) -> None: + self.send_response(200) + self.send_header("Content-Type", "text/html") + self.end_headers() + self.wfile.write( + Path(__file__).joinpath("../..").joinpath(constants.POST_LAUNCH_HTML_FILENAME).resolve().read_bytes() + ) + + def log_request(self, code: Union[int, str] = "-", size: Union[int, str] = "-") -> None: + # Silence the request log. + pass + + +class WebServer: + def __init__(self) -> None: + self._server = server.ThreadingHTTPServer(("", 0), _Handler) + self._thread = threading.Thread(target=self._server.serve_forever) + self._thread.start() + logging.info(f"Web server started on {self.server_url()}") + + def server_url(self) -> str: + return f"http://localhost:{self._server.socket.getsockname()[1]}/" + + def __del__(self) -> None: + self._server.shutdown() + self._thread.join() diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 1460dc363..80e4f57c3 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1494,9 +1494,9 @@ } }, "node_modules/@next/env": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", - "integrity": "sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==" + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz", + "integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.2.4", @@ -1508,9 +1508,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.4.tgz", - "integrity": "sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", + "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", "cpu": [ "arm64" ], @@ -1523,9 +1523,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.4.tgz", - "integrity": "sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", + "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", "cpu": [ "x64" ], @@ -1538,9 +1538,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.4.tgz", - "integrity": "sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", + "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", "cpu": [ "arm64" ], @@ -1553,9 +1553,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.4.tgz", - "integrity": "sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", + "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", "cpu": [ "arm64" ], @@ -1568,9 +1568,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.4.tgz", - "integrity": "sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", + "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", "cpu": [ "x64" ], @@ -1583,9 +1583,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.4.tgz", - "integrity": "sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", + "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", "cpu": [ "x64" ], @@ -1598,9 +1598,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.4.tgz", - "integrity": "sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", + "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", "cpu": [ "arm64" ], @@ -1613,9 +1613,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.4.tgz", - "integrity": "sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", + "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", "cpu": [ "ia32" ], @@ -1628,9 +1628,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.4.tgz", - "integrity": "sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", + "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==", "cpu": [ "x64" ], @@ -3513,12 +3513,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "devOptional": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -5443,9 +5443,9 @@ "dev": true }, "node_modules/fast-loops": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.3.tgz", - "integrity": "sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.4.tgz", + "integrity": "sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==" }, "node_modules/fast-shallow-equal": { "version": "1.0.0", @@ -5548,9 +5548,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "devOptional": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -8237,11 +8237,11 @@ "dev": true }, "node_modules/next": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/next/-/next-13.5.4.tgz", - "integrity": "sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/next/-/next-13.5.6.tgz", + "integrity": "sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==", "dependencies": { - "@next/env": "13.5.4", + "@next/env": "13.5.6", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -8256,15 +8256,15 @@ "node": ">=16.14.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.5.4", - "@next/swc-darwin-x64": "13.5.4", - "@next/swc-linux-arm64-gnu": "13.5.4", - "@next/swc-linux-arm64-musl": "13.5.4", - "@next/swc-linux-x64-gnu": "13.5.4", - "@next/swc-linux-x64-musl": "13.5.4", - "@next/swc-win32-arm64-msvc": "13.5.4", - "@next/swc-win32-ia32-msvc": "13.5.4", - "@next/swc-win32-x64-msvc": "13.5.4" + "@next/swc-darwin-arm64": "13.5.6", + "@next/swc-darwin-x64": "13.5.6", + "@next/swc-linux-arm64-gnu": "13.5.6", + "@next/swc-linux-arm64-musl": "13.5.6", + "@next/swc-linux-x64-gnu": "13.5.6", + "@next/swc-linux-x64-musl": "13.5.6", + "@next/swc-win32-arm64-msvc": "13.5.6", + "@next/swc-win32-ia32-msvc": "13.5.6", + "@next/swc-win32-x64-msvc": "13.5.6" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -11259,9 +11259,9 @@ } }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "engines": { "node": ">=10.0.0" @@ -12475,9 +12475,9 @@ } }, "@next/env": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", - "integrity": "sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==" + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz", + "integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==" }, "@next/eslint-plugin-next": { "version": "13.2.4", @@ -12489,57 +12489,57 @@ } }, "@next/swc-darwin-arm64": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.4.tgz", - "integrity": "sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz", + "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==", "optional": true }, "@next/swc-darwin-x64": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.4.tgz", - "integrity": "sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz", + "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==", "optional": true }, "@next/swc-linux-arm64-gnu": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.4.tgz", - "integrity": "sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz", + "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==", "optional": true }, "@next/swc-linux-arm64-musl": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.4.tgz", - "integrity": "sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz", + "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==", "optional": true }, "@next/swc-linux-x64-gnu": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.4.tgz", - "integrity": "sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz", + "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==", "optional": true }, "@next/swc-linux-x64-musl": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.4.tgz", - "integrity": "sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz", + "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==", "optional": true }, "@next/swc-win32-arm64-msvc": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.4.tgz", - "integrity": "sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz", + "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==", "optional": true }, "@next/swc-win32-ia32-msvc": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.4.tgz", - "integrity": "sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz", + "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==", "optional": true }, "@next/swc-win32-x64-msvc": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.4.tgz", - "integrity": "sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz", + "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==", "optional": true }, "@nodelib/fs.scandir": { @@ -13962,12 +13962,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "devOptional": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browserslist": { @@ -15392,9 +15392,9 @@ "dev": true }, "fast-loops": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.3.tgz", - "integrity": "sha512-8EZzEP0eKkEEVX+drtd9mtuQ+/QrlfW/5MlwcwK5Nds6EkZ/tRzEexkzUY2mIssnAyVLT+TKHuRXmFNNXYUd6g==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-loops/-/fast-loops-1.1.4.tgz", + "integrity": "sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg==" }, "fast-shallow-equal": { "version": "1.0.0", @@ -15474,9 +15474,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "devOptional": true, "requires": { "to-regex-range": "^5.0.1" @@ -17443,20 +17443,20 @@ "dev": true }, "next": { - "version": "13.5.4", - "resolved": "https://registry.npmjs.org/next/-/next-13.5.4.tgz", - "integrity": "sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==", - "requires": { - "@next/env": "13.5.4", - "@next/swc-darwin-arm64": "13.5.4", - "@next/swc-darwin-x64": "13.5.4", - "@next/swc-linux-arm64-gnu": "13.5.4", - "@next/swc-linux-arm64-musl": "13.5.4", - "@next/swc-linux-x64-gnu": "13.5.4", - "@next/swc-linux-x64-musl": "13.5.4", - "@next/swc-win32-arm64-msvc": "13.5.4", - "@next/swc-win32-ia32-msvc": "13.5.4", - "@next/swc-win32-x64-msvc": "13.5.4", + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/next/-/next-13.5.6.tgz", + "integrity": "sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==", + "requires": { + "@next/env": "13.5.6", + "@next/swc-darwin-arm64": "13.5.6", + "@next/swc-darwin-x64": "13.5.6", + "@next/swc-linux-arm64-gnu": "13.5.6", + "@next/swc-linux-arm64-musl": "13.5.6", + "@next/swc-linux-x64-gnu": "13.5.6", + "@next/swc-linux-x64-musl": "13.5.6", + "@next/swc-win32-arm64-msvc": "13.5.6", + "@next/swc-win32-ia32-msvc": "13.5.6", + "@next/swc-win32-x64-msvc": "13.5.6", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -19592,9 +19592,9 @@ } }, "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "requires": {} }, diff --git a/frontend/src/features/export/finishedMyProjectModal.tsx b/frontend/src/features/export/finishedMyProjectModal.tsx index 17a66e026..0df413141 100644 --- a/frontend/src/features/export/finishedMyProjectModal.tsx +++ b/frontend/src/features/export/finishedMyProjectModal.tsx @@ -111,7 +111,7 @@ function PlatformDownload({ platformName, icon, }: { - downloadURLSuffix: "windows.exe" | "macos" | "linux"; + downloadURLSuffix: "windows.exe" | "macos-intel" | "macos-arm" | "linux"; platformName: string; icon: string; }) { @@ -144,21 +144,28 @@ function DesktopToolDownload() { !

- + - + - + + + +